Initial aurora setup, doesn't build yet
This commit is contained in:
parent
ba0d7ef58c
commit
2509e01125
18 changed files with 430 additions and 9 deletions
30
CMakeLists.txt
Normal file
30
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
project(marioparty4 LANGUAGES C CXX)
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-parameter")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -fsanitize=address -fsanitize-address-use-after-scope")
|
||||||
|
set(CMAKE_PREFIX_PATH /usr)
|
||||||
|
set(CMAKE_LIBRARY_ARCHITECTURE i386-linux-gnu)
|
||||||
|
set(CMAKE_LIBRARY_PATH "/usr/lib32" CACHE PATH "")
|
||||||
|
set(CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX 32)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_subdirectory(extern/aurora EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
add_executable(marioparty4
|
||||||
|
src/game/main.c
|
||||||
|
src/game/init.c
|
||||||
|
# libraries/dolphin_pc/GX.c
|
||||||
|
# libraries/dolphin_pc/vi.c
|
||||||
|
# libraries/dolphin_pc/pad_evdev.c
|
||||||
|
# libraries/dolphin_pc/pad_dinput.c
|
||||||
|
# src/port/byteswap.cpp
|
||||||
|
src/port/imgui.cpp
|
||||||
|
src/port/stubs.c
|
||||||
|
)
|
||||||
|
target_compile_definitions(marioparty4 PRIVATE TARGET_PC VERSION=0)
|
||||||
|
target_include_directories(marioparty4 PRIVATE include)
|
||||||
|
target_link_libraries(marioparty4 PRIVATE aurora::aurora aurora::main)
|
||||||
18
README.md
18
README.md
|
|
@ -59,7 +59,7 @@ Linux
|
||||||
- For non-x86(_64) platforms: Install wine from your package manager.
|
- For non-x86(_64) platforms: Install wine from your package manager.
|
||||||
- For x86(_64), [wibo](https://github.com/decompals/wibo), a minimal 32-bit Windows binary wrapper, will be automatically downloaded and used.
|
- For x86(_64), [wibo](https://github.com/decompals/wibo), a minimal 32-bit Windows binary wrapper, will be automatically downloaded and used.
|
||||||
|
|
||||||
Building
|
Building the game for the GameCube
|
||||||
========
|
========
|
||||||
|
|
||||||
- Clone the repository:
|
- Clone the repository:
|
||||||
|
|
@ -89,11 +89,13 @@ Building
|
||||||
ninja
|
ninja
|
||||||
```
|
```
|
||||||
|
|
||||||
Diffing
|
Building the game for PC
|
||||||
=======
|
=====
|
||||||
|
After you got the GameCube build up and running for `GMPE01_00`:
|
||||||
|
- Generate project files using CMake:
|
||||||
|
```
|
||||||
|
cmake -B build/port -G "Visual Studio 17 2022" -A Win32
|
||||||
|
```
|
||||||
|
Linux and MacOS, and x64 support is coming later.
|
||||||
|
|
||||||
Once the initial build succeeds, an `objdiff.json` should exist in the project root.
|
- Open the solution in Visual Studio and build.
|
||||||
|
|
||||||
Download the latest release from [encounter/objdiff](https://github.com/encounter/objdiff). Under project settings, set `Project directory`. The configuration should be loaded automatically.
|
|
||||||
|
|
||||||
Select an object from the left sidebar to begin diffing. Changes to the project will rebuild automatically: changes to source files, headers, `configure.py`, `splits.txt` or `symbols.txt`.
|
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,7 @@ config.asflags = [
|
||||||
"-mgekko",
|
"-mgekko",
|
||||||
"--strip-local-absolute",
|
"--strip-local-absolute",
|
||||||
"-I include",
|
"-I include",
|
||||||
|
"-I libc",
|
||||||
f"-I build/{config.version}/include",
|
f"-I build/{config.version}/include",
|
||||||
f"--defsym version={version_num}",
|
f"--defsym version={version_num}",
|
||||||
]
|
]
|
||||||
|
|
@ -192,6 +193,7 @@ cflags_base = [
|
||||||
"-fp_contract on",
|
"-fp_contract on",
|
||||||
"-str reuse",
|
"-str reuse",
|
||||||
"-i include",
|
"-i include",
|
||||||
|
"-i libc",
|
||||||
"-i extern/musyx/include",
|
"-i extern/musyx/include",
|
||||||
f"-i build/{config.version}/include",
|
f"-i build/{config.version}/include",
|
||||||
"-multibyte",
|
"-multibyte",
|
||||||
|
|
@ -270,6 +272,7 @@ cflags_musyx = [
|
||||||
"-nodefaults",
|
"-nodefaults",
|
||||||
"-nosyspath",
|
"-nosyspath",
|
||||||
"-i include",
|
"-i include",
|
||||||
|
"-i libc",
|
||||||
"-i extern/musyx/include",
|
"-i extern/musyx/include",
|
||||||
"-inline auto",
|
"-inline auto",
|
||||||
"-O4,p",
|
"-O4,p",
|
||||||
|
|
|
||||||
18
include/port/imgui.h
Normal file
18
include/port/imgui.h
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef _SRC_IMGUI_H_
|
||||||
|
#define _SRC_IMGUI_H_
|
||||||
|
|
||||||
|
#include <aurora/aurora.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void imgui_main(const AuroraInfo* info);
|
||||||
|
void frame_limiter();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -137,6 +137,9 @@ static long DLSize(struct Cell *list)
|
||||||
|
|
||||||
void *OSAllocFromHeap(int heap, unsigned long size)
|
void *OSAllocFromHeap(int heap, unsigned long size)
|
||||||
{
|
{
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
return malloc(size);
|
||||||
|
#endif
|
||||||
struct HeapDesc *hd;
|
struct HeapDesc *hd;
|
||||||
struct Cell *cell;
|
struct Cell *cell;
|
||||||
struct Cell *newCell;
|
struct Cell *newCell;
|
||||||
|
|
@ -297,6 +300,9 @@ void *OSAllocFixed(void **rstart, void **rend)
|
||||||
|
|
||||||
void OSFreeToHeap(int heap, void *ptr)
|
void OSFreeToHeap(int heap, void *ptr)
|
||||||
{
|
{
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
free(ptr);
|
||||||
|
#else
|
||||||
struct HeapDesc *hd;
|
struct HeapDesc *hd;
|
||||||
struct Cell *cell;
|
struct Cell *cell;
|
||||||
|
|
||||||
|
|
@ -310,6 +316,7 @@ void OSFreeToHeap(int heap, void *ptr)
|
||||||
ASSERTMSG1(0x247, DLLookup(hd->allocated, cell), "OSFreeToHeap(): invalid pointer.");
|
ASSERTMSG1(0x247, DLLookup(hd->allocated, cell), "OSFreeToHeap(): invalid pointer.");
|
||||||
hd->allocated = DLExtract(hd->allocated, cell);
|
hd->allocated = DLExtract(hd->allocated, cell);
|
||||||
hd->free = DLInsert(hd->free, cell);
|
hd->free = DLInsert(hd->free, cell);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int OSSetCurrentHeap(int heap)
|
int OSSetCurrentHeap(int heap)
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ void HuSysInit(GXRenderModeObj *mode)
|
||||||
OSInit();
|
OSInit();
|
||||||
DVDInit();
|
DVDInit();
|
||||||
VIInit();
|
VIInit();
|
||||||
|
#if TARGET_PC
|
||||||
|
VISetWindowTitle("Mario Party 4");
|
||||||
|
#endif
|
||||||
PADInit();
|
PADInit();
|
||||||
#if VERSION_NTSC
|
#if VERSION_NTSC
|
||||||
if(OSGetProgressiveMode() == 1 && VIGetDTVStatus() == 1) {
|
if(OSGetProgressiveMode() == 1 && VIGetDTVStatus() == 1) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,13 @@
|
||||||
#include "game/gamework.h"
|
#include "game/gamework.h"
|
||||||
#include "game/sreset.h"
|
#include "game/sreset.h"
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
#include "port/imgui.h"
|
||||||
|
#include <aurora/aurora.h>
|
||||||
|
#include <aurora/event.h>
|
||||||
|
#include <aurora/main.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
extern FileListEntry _ovltbl[];
|
extern FileListEntry _ovltbl[];
|
||||||
u32 GlobalCounter;
|
u32 GlobalCounter;
|
||||||
static u32 vcheck;
|
static u32 vcheck;
|
||||||
|
|
@ -40,8 +47,54 @@ static u32 fi_req;
|
||||||
s32 HuDvdErrWait;
|
s32 HuDvdErrWait;
|
||||||
s32 SystemInitF;
|
s32 SystemInitF;
|
||||||
|
|
||||||
void main(void)
|
#ifdef TARGET_PC
|
||||||
|
#include <stdio.h>
|
||||||
|
void aurora_log_callback(AuroraLogLevel level, const char *message, unsigned int len)
|
||||||
{
|
{
|
||||||
|
const char *levelStr = "??";
|
||||||
|
FILE *out = stdout;
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case LOG_DEBUG:
|
||||||
|
levelStr = "DEBUG";
|
||||||
|
break;
|
||||||
|
case LOG_INFO:
|
||||||
|
levelStr = "INFO";
|
||||||
|
break;
|
||||||
|
case LOG_WARNING:
|
||||||
|
levelStr = "WARNING";
|
||||||
|
break;
|
||||||
|
case LOG_ERROR:
|
||||||
|
levelStr = "ERROR";
|
||||||
|
out = stderr;
|
||||||
|
break;
|
||||||
|
case LOG_FATAL:
|
||||||
|
levelStr = "FATAL";
|
||||||
|
out = stderr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(out, "[%s: %s]\n", levelStr, message);
|
||||||
|
if (level == LOG_FATAL)
|
||||||
|
{
|
||||||
|
fflush(out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
#else
|
||||||
|
void main(void)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef AURORA
|
||||||
|
const AuroraInfo auroraInfo = aurora_initialize(argc, argv,
|
||||||
|
&(AuroraConfig){
|
||||||
|
.appName = "Mario Party 4",
|
||||||
|
.logCallback = &aurora_log_callback,
|
||||||
|
});
|
||||||
|
#endif
|
||||||
u32 met0;
|
u32 met0;
|
||||||
u32 met1;
|
u32 met1;
|
||||||
s16 i;
|
s16 i;
|
||||||
|
|
@ -82,12 +135,33 @@ void main(void)
|
||||||
VIWaitForRetrace();
|
VIWaitForRetrace();
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
const AuroraEvent *event = aurora_update();
|
||||||
|
bool exiting = false;
|
||||||
|
while (event != NULL && event->type != AURORA_NONE)
|
||||||
|
{
|
||||||
|
if (event->type == AURORA_EXIT)
|
||||||
|
{
|
||||||
|
exiting = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++event;
|
||||||
|
}
|
||||||
|
if (exiting)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
retrace = VIGetRetraceCount();
|
retrace = VIGetRetraceCount();
|
||||||
if (HuSoftResetButtonCheck() != 0 || HuDvdErrWait != 0) {
|
if (HuSoftResetButtonCheck() != 0 || HuDvdErrWait != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
HuPerfZero();
|
HuPerfZero();
|
||||||
|
|
||||||
HuPerfBegin(2);
|
HuPerfBegin(2);
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
aurora_begin_frame();
|
||||||
|
#endif
|
||||||
HuSysBeforeRender();
|
HuSysBeforeRender();
|
||||||
GXSetGPMetric(GX_PERF0_CLIP_VTX, GX_PERF1_VERTICES);
|
GXSetGPMetric(GX_PERF0_CLIP_VTX, GX_PERF1_VERTICES);
|
||||||
GXClearGPMetric();
|
GXClearGPMetric();
|
||||||
|
|
@ -95,10 +169,12 @@ void main(void)
|
||||||
GXClearVCacheMetric();
|
GXClearVCacheMetric();
|
||||||
GXClearPixMetric();
|
GXClearPixMetric();
|
||||||
GXClearMemMetric();
|
GXClearMemMetric();
|
||||||
|
|
||||||
HuPerfBegin(0);
|
HuPerfBegin(0);
|
||||||
Hu3DPreProc();
|
Hu3DPreProc();
|
||||||
HuPadRead();
|
HuPadRead();
|
||||||
pfClsScr();
|
pfClsScr();
|
||||||
|
|
||||||
HuPrcCall(1);
|
HuPrcCall(1);
|
||||||
MGSeqMain();
|
MGSeqMain();
|
||||||
HuPerfBegin(1);
|
HuPerfBegin(1);
|
||||||
|
|
@ -106,8 +182,15 @@ void main(void)
|
||||||
HuDvdErrorWatch();
|
HuDvdErrorWatch();
|
||||||
WipeExecAlways();
|
WipeExecAlways();
|
||||||
HuPerfEnd(0);
|
HuPerfEnd(0);
|
||||||
|
|
||||||
pfDrawFonts();
|
pfDrawFonts();
|
||||||
HuPerfEnd(1);
|
HuPerfEnd(1);
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
imgui_main(&auroraInfo);
|
||||||
|
aurora_end_frame();
|
||||||
|
#endif
|
||||||
|
|
||||||
msmMusFdoutEnd();
|
msmMusFdoutEnd();
|
||||||
HuSysDoneRender(retrace);
|
HuSysDoneRender(retrace);
|
||||||
GXReadGPMetric(&met0, &met1);
|
GXReadGPMetric(&met0, &met1);
|
||||||
|
|
@ -116,7 +199,15 @@ void main(void)
|
||||||
GXReadMemMetric(&cp_req, &tc_req, &cpu_rd_req, &cpu_wr_req, &dsp_req, &io_req, &vi_req, &pe_req, &rf_req, &fi_req);
|
GXReadMemMetric(&cp_req, &tc_req, &cpu_rd_req, &cpu_wr_req, &dsp_req, &io_req, &vi_req, &pe_req, &rf_req, &fi_req);
|
||||||
HuPerfEnd(2);
|
HuPerfEnd(2);
|
||||||
GlobalCounter++;
|
GlobalCounter++;
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
frame_limiter();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TARGET_PC
|
||||||
|
aurora_shutdown();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HuSysVWaitSet(s16 vcount)
|
void HuSysVWaitSet(s16 vcount)
|
||||||
|
|
|
||||||
267
src/port/imgui.cpp
Normal file
267
src/port/imgui.cpp
Normal file
|
|
@ -0,0 +1,267 @@
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "port/imgui.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cmath>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <numeric>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
static bool m_frameRate = true;
|
||||||
|
static bool m_pipelineInfo = true;
|
||||||
|
static bool m_graphicsBackend = true;
|
||||||
|
static int m_debugOverlayCorner = 0; // top-left
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
using namespace std::string_view_literals;
|
||||||
|
|
||||||
|
namespace aurora::gfx
|
||||||
|
{
|
||||||
|
extern std::atomic_uint32_t queuedPipelines;
|
||||||
|
extern std::atomic_uint32_t createdPipelines;
|
||||||
|
|
||||||
|
extern size_t g_drawCallCount;
|
||||||
|
extern size_t g_mergedDrawCallCount;
|
||||||
|
extern size_t g_lastVertSize;
|
||||||
|
extern size_t g_lastUniformSize;
|
||||||
|
extern size_t g_lastIndexSize;
|
||||||
|
extern size_t g_lastStorageSize;
|
||||||
|
} // namespace aurora::gfx
|
||||||
|
|
||||||
|
static void SetOverlayWindowLocation(int corner)
|
||||||
|
{
|
||||||
|
const ImGuiViewport *viewport = ImGui::GetMainViewport();
|
||||||
|
ImVec2 workPos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
|
||||||
|
ImVec2 workSize = viewport->WorkSize;
|
||||||
|
ImVec2 windowPos;
|
||||||
|
ImVec2 windowPosPivot;
|
||||||
|
constexpr float padding = 10.0f;
|
||||||
|
windowPos.x = (corner & 1) != 0 ? (workPos.x + workSize.x - padding) : (workPos.x + padding);
|
||||||
|
windowPos.y = (corner & 2) != 0 ? (workPos.y + workSize.y - padding) : (workPos.y + padding);
|
||||||
|
windowPosPivot.x = (corner & 1) != 0 ? 1.0f : 0.0f;
|
||||||
|
windowPosPivot.y = (corner & 2) != 0 ? 1.0f : 0.0f;
|
||||||
|
ImGui::SetNextWindowPos(windowPos, ImGuiCond_Always, windowPosPivot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGuiStringViewText(std::string_view text)
|
||||||
|
{
|
||||||
|
// begin()/end() do not work on MSVC
|
||||||
|
ImGui::TextUnformatted(text.data(), text.data() + text.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string BytesToString(size_t bytes)
|
||||||
|
{
|
||||||
|
constexpr std::array suffixes{"B"sv, "KB"sv, "MB"sv, "GB"sv, "TB"sv, "PB"sv, "EB"sv};
|
||||||
|
uint32_t s = 0;
|
||||||
|
auto count = static_cast<double>(bytes);
|
||||||
|
while (count >= 1024.0 && s < 7)
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
count /= 1024.0;
|
||||||
|
}
|
||||||
|
if (count - floor(count) == 0.0)
|
||||||
|
{
|
||||||
|
return fmt::format(FMT_STRING("{}{}"), static_cast<size_t>(count), suffixes[s]);
|
||||||
|
}
|
||||||
|
return fmt::format(FMT_STRING("{:.1f}{}"), count, suffixes[s]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void imgui_main(const AuroraInfo *info)
|
||||||
|
{
|
||||||
|
|
||||||
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
|
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDecoration |
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize |
|
||||||
|
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||||
|
if (m_debugOverlayCorner != -1)
|
||||||
|
{
|
||||||
|
SetOverlayWindowLocation(m_debugOverlayCorner);
|
||||||
|
windowFlags |= ImGuiWindowFlags_NoMove;
|
||||||
|
}
|
||||||
|
ImGui::SetNextWindowBgAlpha(0.65f);
|
||||||
|
if (ImGui::Begin("Debug Overlay", nullptr, windowFlags))
|
||||||
|
{
|
||||||
|
bool hasPrevious = false;
|
||||||
|
if (m_frameRate)
|
||||||
|
{
|
||||||
|
if (hasPrevious)
|
||||||
|
{
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
hasPrevious = true;
|
||||||
|
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("FPS: {:.1f}\n"), io.Framerate));
|
||||||
|
}
|
||||||
|
if (m_graphicsBackend)
|
||||||
|
{
|
||||||
|
if (hasPrevious)
|
||||||
|
{
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
hasPrevious = true;
|
||||||
|
|
||||||
|
std::string_view backendString = "Unknown"sv;
|
||||||
|
switch (info->backend)
|
||||||
|
{
|
||||||
|
case BACKEND_D3D12:
|
||||||
|
backendString = "D3D12"sv;
|
||||||
|
break;
|
||||||
|
case BACKEND_METAL:
|
||||||
|
backendString = "Metal"sv;
|
||||||
|
break;
|
||||||
|
case BACKEND_VULKAN:
|
||||||
|
backendString = "Vulkan"sv;
|
||||||
|
break;
|
||||||
|
case BACKEND_OPENGL:
|
||||||
|
backendString = "OpenGL"sv;
|
||||||
|
break;
|
||||||
|
case BACKEND_OPENGLES:
|
||||||
|
backendString = "OpenGL ES"sv;
|
||||||
|
break;
|
||||||
|
case BACKEND_WEBGPU:
|
||||||
|
backendString = "WebGPU"sv;
|
||||||
|
break;
|
||||||
|
case BACKEND_NULL:
|
||||||
|
backendString = "Null"sv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("Backend: {}\n"), backendString));
|
||||||
|
}
|
||||||
|
if (m_pipelineInfo)
|
||||||
|
{
|
||||||
|
if (hasPrevious)
|
||||||
|
{
|
||||||
|
ImGui::Separator();
|
||||||
|
}
|
||||||
|
hasPrevious = true;
|
||||||
|
|
||||||
|
ImGuiStringViewText(
|
||||||
|
fmt::format(FMT_STRING("Queued pipelines: {}\n"), aurora::gfx::queuedPipelines));
|
||||||
|
ImGuiStringViewText(
|
||||||
|
fmt::format(FMT_STRING("Done pipelines: {}\n"), aurora::gfx::createdPipelines));
|
||||||
|
ImGuiStringViewText(
|
||||||
|
fmt::format(FMT_STRING("Draw call count: {}\n"), aurora::gfx::g_drawCallCount));
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("Merged draw calls: {}\n"),
|
||||||
|
aurora::gfx::g_mergedDrawCallCount));
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("Vertex size: {}\n"),
|
||||||
|
BytesToString(aurora::gfx::g_lastVertSize)));
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("Uniform size: {}\n"),
|
||||||
|
BytesToString(aurora::gfx::g_lastUniformSize)));
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("Index size: {}\n"),
|
||||||
|
BytesToString(aurora::gfx::g_lastIndexSize)));
|
||||||
|
ImGuiStringViewText(fmt::format(FMT_STRING("Storage size: {}\n"),
|
||||||
|
BytesToString(aurora::gfx::g_lastStorageSize)));
|
||||||
|
ImGuiStringViewText(fmt::format(
|
||||||
|
FMT_STRING("Total: {}\n"),
|
||||||
|
BytesToString(aurora::gfx::g_lastVertSize + aurora::gfx::g_lastUniformSize +
|
||||||
|
aurora::gfx::g_lastIndexSize + aurora::gfx::g_lastStorageSize)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Limiter
|
||||||
|
{
|
||||||
|
using delta_clock = std::chrono::high_resolution_clock;
|
||||||
|
using duration_t = std::chrono::nanoseconds;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
m_oldTime = delta_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sleep(duration_t targetFrameTime)
|
||||||
|
{
|
||||||
|
if (targetFrameTime.count() == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto start = delta_clock::now();
|
||||||
|
duration_t adjustedSleepTime = SleepTime(targetFrameTime);
|
||||||
|
if (adjustedSleepTime.count() > 0)
|
||||||
|
{
|
||||||
|
NanoSleep(adjustedSleepTime);
|
||||||
|
duration_t overslept = TimeSince(start) - adjustedSleepTime;
|
||||||
|
if (overslept < duration_t{targetFrameTime})
|
||||||
|
{
|
||||||
|
m_overheadTimes[m_overheadTimeIdx] = overslept;
|
||||||
|
m_overheadTimeIdx = (m_overheadTimeIdx + 1) % m_overheadTimes.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
duration_t SleepTime(duration_t targetFrameTime)
|
||||||
|
{
|
||||||
|
const auto sleepTime = duration_t{targetFrameTime} - TimeSince(m_oldTime);
|
||||||
|
m_overhead = std::accumulate(m_overheadTimes.begin(), m_overheadTimes.end(), duration_t{}) /
|
||||||
|
m_overheadTimes.size();
|
||||||
|
if (sleepTime > m_overhead)
|
||||||
|
{
|
||||||
|
return sleepTime - m_overhead;
|
||||||
|
}
|
||||||
|
return duration_t{0};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
delta_clock::time_point m_oldTime;
|
||||||
|
std::array<duration_t, 4> m_overheadTimes{};
|
||||||
|
size_t m_overheadTimeIdx = 0;
|
||||||
|
duration_t m_overhead = duration_t{0};
|
||||||
|
|
||||||
|
duration_t TimeSince(delta_clock::time_point start)
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<duration_t>(delta_clock::now() - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
bool m_initialized;
|
||||||
|
double m_countPerNs;
|
||||||
|
|
||||||
|
void NanoSleep(const duration_t duration)
|
||||||
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER freq;
|
||||||
|
QueryPerformanceFrequency(&freq);
|
||||||
|
m_countPerNs = static_cast<double>(freq.QuadPart) / 1000000000.0;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
|
||||||
|
auto tickCount =
|
||||||
|
static_cast<LONGLONG>(static_cast<double>(duration.count()) * m_countPerNs);
|
||||||
|
LARGE_INTEGER count;
|
||||||
|
QueryPerformanceCounter(&count);
|
||||||
|
if (ms > 10)
|
||||||
|
{
|
||||||
|
// Adjust for Sleep overhead
|
||||||
|
::Sleep(ms - 10);
|
||||||
|
}
|
||||||
|
auto end = count.QuadPart + tickCount;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
QueryPerformanceCounter(&count);
|
||||||
|
} while (count.QuadPart < end);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void NanoSleep(const duration_t duration)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static Limiter g_frameLimiter;
|
||||||
|
void frame_limiter()
|
||||||
|
{
|
||||||
|
g_frameLimiter.Sleep(
|
||||||
|
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds{1}) / 60);
|
||||||
|
}
|
||||||
0
src/port/stubs.c
Normal file
0
src/port/stubs.c
Normal file
Loading…
Add table
Add a link
Reference in a new issue