diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d63755..55156d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ endif() # This makes sure that the dynamic library goes into the build directory automatically. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$") +set(PROFILE ON) # Imgui file(GLOB imgui_sources dependency/imgui/*.h dependency/imgui/*.cpp) @@ -25,7 +26,7 @@ add_subdirectory("${CMAKE_SOURCE_DIR}/dependency/minidef") file(GLOB_RECURSE sources_engine engine/*.cpp engine/*.h) add_executable(PuzGameEngine ${sources_engine}) set_property(TARGET PuzGameEngine PROPERTY CXX_STANDARD 17) -target_include_directories(PuzGameEngine PUBLIC) +target_include_directories(PuzGameEngine PUBLIC dependency/tracy/public/) # Game add_custom_command( @@ -41,6 +42,15 @@ add_library(PuzGame SHARED ${sources_game} ${source_singleheader} ${imgui_source set_property(TARGET PuzGame PROPERTY CXX_STANDARD 17) target_include_directories(PuzGame PUBLIC dependency/imgui) +# Profiling +if (PROFILE) + option(TRACY_ENABLE "" ON) + option(TRACY_ON_DEMAND "" ON) + set(TRACY_DELAYED_INIT ON) + set(TRACY_MANUAL_LIFETIME ON) + add_subdirectory("${CMAKE_SOURCE_DIR}/dependency/tracy") +endif() + # SDL add_subdirectory("${CMAKE_SOURCE_DIR}/dependency/SDL" EXCLUDE_FROM_ALL) @@ -50,6 +60,6 @@ SET(BGFX_BUILD_EXAMPLES OFF) add_subdirectory("${CMAKE_SOURCE_DIR}/dependency/bgfx.cmake") # Link -target_link_libraries(PuzGame bx bimg bgfx SDL3::SDL3) -target_link_libraries(PuzGameEngine bx SDL3::SDL3) +target_link_libraries(PuzGame bx bimg bgfx SDL3::SDL3 Tracy::TracyClient) +target_link_libraries(PuzGameEngine bx SDL3::SDL3 Tracy::TracyClient) set_target_properties(PuzGame PROPERTIES OUTPUT_NAME "PuzGame2") diff --git a/src/game/Level.cpp b/src/game/Level.cpp index a7ac29d..a7ceadc 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace Game { @@ -160,6 +161,7 @@ namespace Game void Level::Update() { + ZoneScopedN("Level update"); START_PERF(); PlayerData& player = GetInstance().Player; @@ -237,6 +239,7 @@ namespace Game void Level::Render(uint16_t viewId, const Model* models, const Material* materials) { + ZoneScopedN("Level Render"); auto& shared = GetShared(); float proj[16]; diff --git a/src/game/Setup.cpp b/src/game/Setup.cpp index 5d026cd..91a89fe 100644 --- a/src/game/Setup.cpp +++ b/src/game/Setup.cpp @@ -3,9 +3,12 @@ #include "Instance.h" #include "Log.h" #include "Setup.h" +#include "rendering/Rendering.h" + #include "bx/bx.h" #include "bx/timer.h" -#include "rendering/Rendering.h" +#include +#include namespace Game { @@ -23,6 +26,7 @@ namespace Game void Setup(SharedData& shared) { LOG("Game Setup Start!"); + tracy::StartupProfiler(); if (shared.Game.PermanentStorage == nullptr) { @@ -56,33 +60,35 @@ namespace Game void Update() { - auto& inst = GetInstance(); - int64_t newNowHP = bx::getHPCounter() - inst.Time.StartTime; - inst.Time.DeltaHP = newNowHP - inst.Time.NowHP; - inst.Time.NowHP = newNowHP; - inst.Time.Now = (double)inst.Time.NowHP / bx::getHPFrequency(); - inst.Time.Delta = (double)inst.Time.DeltaHP / bx::getHPFrequency(); - GetShared().Window.PerfCounters[(int32_t)PerfCounterType::GameDelta].Write(inst.Time.DeltaHP, - GetShared().Window.FrameCounter); - - if (GetKeyPressedNow(ScanCode::R)) { - GetInstance().Size = 0; - Shutdown(); - Setup(GetShared()); + ZoneScopedN("TimeUpdate"); + auto& inst = GetInstance(); + int64_t newNowHP = bx::getHPCounter() - inst.Time.StartTime; + inst.Time.DeltaHP = newNowHP - inst.Time.NowHP; + inst.Time.NowHP = newNowHP; + inst.Time.Now = (double)inst.Time.NowHP / bx::getHPFrequency(); + inst.Time.Delta = (double)inst.Time.DeltaHP / bx::getHPFrequency(); + GetShared().Window.PerfCounters[(int32_t)PerfCounterType::GameDelta].Write(inst.Time.DeltaHP, + GetShared().Window.FrameCounter); } + SetupInstance.Rendering.Update(); - auto& win = GetShared().Window; - win.MouseDeltaX = 0.0f; - win.MouseDeltaY = 0.0f; - bx::memCopy(win.LastHeldScanCodes, win.HeldScanCodes, sizeof(win.HeldScanCodes)); - bx::memCopy(win.LastHeldMouseButtons, win.HeldMouseButtons, sizeof(win.HeldMouseButtons)); + { + ZoneScopedN("MouseDeltaUpdate"); + auto& win = GetShared().Window; + win.MouseDeltaX = 0.0f; + win.MouseDeltaY = 0.0f; + bx::memCopy(win.LastHeldScanCodes, win.HeldScanCodes, sizeof(win.HeldScanCodes)); + bx::memCopy(win.LastHeldMouseButtons, win.HeldMouseButtons, sizeof(win.HeldMouseButtons)); + } + FrameMark; } void Shutdown() { LOG("Shutdown"); SetupInstance.Rendering.Shutdown(); + tracy::ShutdownProfiler(); } } // namespace Game diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index 663026c..684a8ce 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -21,11 +21,11 @@ #include #include #include +#include #include "imgui-helper.h" #include "imgui-style.h" #include "imgui.h" -#include "imgui_internal.h" using namespace std::chrono_literals; @@ -333,6 +333,8 @@ namespace Game void GameRendering::Setup() { LOG("--- RENDERING STARTUP ---"); + ZoneScopedN("Setup"); + if (Instance != nullptr) LOG_WARN("old rendering wasn't destroyed!"); Instance = this; SharedData& shared = GetShared(); @@ -407,11 +409,11 @@ namespace Game DitherGen(DitherTextures, DitherRecursion); } - void GameRendering::Update() + void GameRendering::HandleEvents() { + ZoneScopedN("Handle Events"); SharedData& shared = GetShared(); - // Handle events for (uint16_t i = 0; i < shared.Window.SDLEventCount; ++i) { ImGui_ImplSDL3_ProcessEvent(&shared.Window.SDLEvents[i]); @@ -453,218 +455,246 @@ namespace Game } } } + } - // Start Rendering - imguiBeginFrame(20); - ImGui_ImplSDL3_NewFrame(); - ImGui::DockSpaceOverViewport(0, 0, ImGuiDockNodeFlags_PassthruCentralNode); + void GameRendering::RenderDebugUI() + { + ZoneScopedN("DebugUI"); - auto& level = GetInstance().GameLevel; + auto& shared = GetShared(); auto& debug = GetInstance().DebugData; - if (UIVisible == UIVisibilityState::Debug) + auto& level = GetInstance().GameLevel; + + if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) { - if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) + debug.DebugCardRotation++; + if (debug.DebugCardRotation >= 4) debug.DebugCardRotation = 0; + } + if (ImGui::Begin("Rendering")) + { + if (LastShaderLoadTime >= 0.0f) { - debug.DebugCardRotation++; - if (debug.DebugCardRotation >= 4) debug.DebugCardRotation = 0; + ImGui::TextColored({0.2f, 0.9f, 0.2f, 1.0f}, + "Shader loaded %.0f seconds ago", + GetInstance().Time.Now - LastShaderLoadTime); } - if (ImGui::Begin("Rendering")) + else { - if (LastShaderLoadTime >= 0.0f) - { - ImGui::TextColored({0.2f, 0.9f, 0.2f, 1.0f}, - "Shader loaded %.0f seconds ago", - GetInstance().Time.Now - LastShaderLoadTime); - } - else - { - ImGui::TextColored({0.9f, 0.2f, 0.2f, 1.0f}, "Shader load Failiure!"); - } - if (ImGui::Button("Reload Meshes")) - { - LoadModels(Models, ModelCount); - } - ImGui::SameLine(); - if (ImGui::Button("Reload Level")) - { - level = {}; - level.Setup(shared.Game); - } - ImGui::Checkbox("Show ImGui Demo", &debug.ShowImguiDemo); - if (debug.ShowImguiDemo) ImGui::ShowDemoWindow(&debug.ShowImguiDemo); - ImGui::Separator(); - - ImGui::Checkbox("Cubes", &level.Cubes.IsEnabled); - ImGui::Checkbox("Tests", &level.Tests.IsEnabled); - ImGui::Checkbox("PuzzleTiles", &level.PuzzleTiles.IsEnabled); - ImGui::Checkbox("UIQuads", &level.UIQuads.IsEnabled); - - if (ImGui::Button("Dithergen")) - { - DitherGen(DitherTextures, DitherRecursion); - } - ImGui::SameLine(); - ImGui::SliderInt("Recursion", &DitherRecursion, 1, 4); - ImGui::Text( - "%ux%ux%u", DitherTextures.DitherTexWH, DitherTextures.DitherTexWH, DitherTextures.DitherTexDepth); - if (!isValid(DitherTextures.PreviewTex)) - { - ImGui::Text("Invalid Texture"); - } - else - { - ImGui::Image(DitherTextures.PreviewTex.idx, - {(float)DitherTextures.DitherTexWH, - (float)DitherTextures.DitherTexWH * DitherTextures.DitherTexDepth}); - } - if (isValid(DitherTextures.RampTex)) - { - ImGui::Image(DitherTextures.RampTex.idx, {BX_COUNTOF(DitherTextures.BrightnessRamp), 8}); - } - Vec3 quadPos = level.UIQuads.Get({0}).EData.Transform.GetPosition(); - ImGui::Text("%f %f %f", quadPos.x, quadPos.y, quadPos.z); - - if (ImGui::ColorEdit3("Base Color", &DefaultBaseColor.x)) - { - auto& tiles = GetInstance().GameLevel.PuzzleTiles; - for (int32_t i = 0; i < tiles.Count; ++i) - { - tiles.Data[i].EData.BaseColor = DefaultBaseColor; - } - } - if (ImGui::ColorEdit3("Dot Color", &DefaultTileColor.x)) - { - auto& tiles = GetInstance().GameLevel.PuzzleTiles; - for (int32_t i = 0; i < tiles.Count; ++i) - { - tiles.Data[i].EData.TestColor = DefaultTileColor; - } - } - - ImGui::Text("Shader log:"); - ImGui::TextWrapped("%s", GetShared().Dev.ShaderLog); + ImGui::TextColored({0.9f, 0.2f, 0.2f, 1.0f}, "Shader load Failiure!"); } - ImGui::End(); - if (ImGui::Begin("Puzzles")) + if (ImGui::Button("Reload Meshes")) { - if (ImGui::Button("Add")) + LoadModels(Models, ModelCount); + } + ImGui::SameLine(); + if (ImGui::Button("Reload Level")) + { + level = {}; + level.Setup(shared.Game); + } + ImGui::Checkbox("Show ImGui Demo", &debug.ShowImguiDemo); + if (debug.ShowImguiDemo) ImGui::ShowDemoWindow(&debug.ShowImguiDemo); + ImGui::Separator(); + + ImGui::Checkbox("Cubes", &level.Cubes.IsEnabled); + ImGui::Checkbox("Tests", &level.Tests.IsEnabled); + ImGui::Checkbox("PuzzleTiles", &level.PuzzleTiles.IsEnabled); + ImGui::Checkbox("UIQuads", &level.UIQuads.IsEnabled); + + if (ImGui::Button("Dithergen")) + { + DitherGen(DitherTextures, DitherRecursion); + } + ImGui::SameLine(); + ImGui::SliderInt("Recursion", &DitherRecursion, 1, 4); + ImGui::Text( + "%ux%ux%u", DitherTextures.DitherTexWH, DitherTextures.DitherTexWH, DitherTextures.DitherTexDepth); + if (!isValid(DitherTextures.PreviewTex)) + { + ImGui::Text("Invalid Texture"); + } + else + { + ImGui::Image(DitherTextures.PreviewTex.idx, + {(float)DitherTextures.DitherTexWH, + (float)DitherTextures.DitherTexWH * DitherTextures.DitherTexDepth}); + } + if (isValid(DitherTextures.RampTex)) + { + ImGui::Image(DitherTextures.RampTex.idx, {BX_COUNTOF(DitherTextures.BrightnessRamp), 8}); + } + Vec3 quadPos = level.UIQuads.Get({0}).EData.Transform.GetPosition(); + ImGui::Text("%f %f %f", quadPos.x, quadPos.y, quadPos.z); + + if (ImGui::ColorEdit3("Base Color", &DefaultBaseColor.x)) + { + auto& tiles = GetInstance().GameLevel.PuzzleTiles; + for (int32_t i = 0; i < tiles.Count; ++i) { - bool found = false; - for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) - { - auto& puz = level.Puzzles[i].Data; - if (puz.ID == UINT16_MAX) - { - bx::strCopy(puz.PuzzleName, sizeof(puz.PuzzleName), "Unnamed Puzzle"); - puz.ID = i; - found = true; - break; - } - } - if (!found) - { - LOG_ERROR("Too many puzzles!"); - } + tiles.Data[i].EData.BaseColor = DefaultBaseColor; } - ImGui::Separator(); + } + if (ImGui::ColorEdit3("Dot Color", &DefaultTileColor.x)) + { + auto& tiles = GetInstance().GameLevel.PuzzleTiles; + for (int32_t i = 0; i < tiles.Count; ++i) + { + tiles.Data[i].EData.TestColor = DefaultTileColor; + } + } + + ImGui::Text("Shader log:"); + ImGui::TextWrapped("%s", GetShared().Dev.ShaderLog); + } + ImGui::End(); + if (ImGui::Begin("Puzzles")) + { + if (ImGui::Button("Add")) + { + bool found = false; for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) { - auto& puzzleData = level.Puzzles[i].Data; - if (puzzleData.ID == UINT16_MAX) continue; - - bool isSelected = debug.SelectedDebugLevel == i; - ImGui::PushID("selectable"); - if (ImGui::Selectable(puzzleData.PuzzleName, isSelected)) + auto& puz = level.Puzzles[i].Data; + if (puz.ID == UINT16_MAX) { - debug.SelectedDebugLevel = isSelected ? UINT16_MAX : i; + bx::strCopy(puz.PuzzleName, sizeof(puz.PuzzleName), "Unnamed Puzzle"); + puz.ID = i; + found = true; + break; } - ImGui::PopID(); + } + if (!found) + { + LOG_ERROR("Too many puzzles!"); } } - ImGui::End(); - if (debug.SelectedDebugLevel < BX_COUNTOF(level.Puzzles)) + ImGui::Separator(); + for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) { - if (!Puzzle::RenderDebugUI(level.Puzzles[debug.SelectedDebugLevel].Data)) + auto& puzzleData = level.Puzzles[i].Data; + if (puzzleData.ID == UINT16_MAX) continue; + + bool isSelected = debug.SelectedDebugLevel == i; + ImGui::PushID("selectable"); + if (ImGui::Selectable(puzzleData.PuzzleName, isSelected)) { - debug.SelectedDebugLevel = UINT16_MAX; + debug.SelectedDebugLevel = isSelected ? UINT16_MAX : i; } + ImGui::PopID(); } - if (ImGui::Begin("Cards")) + } + ImGui::End(); + if (debug.SelectedDebugLevel < BX_COUNTOF(level.Puzzles)) + { + if (!Puzzle::RenderDebugUI(level.Puzzles[debug.SelectedDebugLevel].Data)) { - Generated::StaticPuzzleData& staticData = Puzzle::GetStaticPuzzleData(); - if (ImGui::Button("Save")) + debug.SelectedDebugLevel = UINT16_MAX; + } + } + if (ImGui::Begin("Cards")) + { + Generated::StaticPuzzleData& staticData = Puzzle::GetStaticPuzzleData(); + if (ImGui::Button("Save")) + { + Puzzle::SaveStaticPuzzleData(); + } + ImGui::SameLine(); + if (ImGui::Button("Reload")) + { + Puzzle::LoadStaticPuzzleData(); + } + + for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i) + { + ImGui::Separator(); + + Generated::StaticPuzzleCard& card = staticData.Cards[i]; + ImGui::PushID(i); + char cardName[64]{0}; + bx::snprintf(cardName, sizeof(cardName), "%i", i); + ImGui::Selectable(cardName); + if (ImGui::BeginDragDropSource()) { - Puzzle::SaveStaticPuzzleData(); - } - ImGui::SameLine(); - if (ImGui::Button("Reload")) - { - Puzzle::LoadStaticPuzzleData(); + Puzzle::DrawCard(card, debug.DebugCardRotation, ImGui::GetCursorScreenPos()); + ImGui::SetDragDropPayload("cardtype", &i, sizeof(i)); + ImGui::EndDragDropSource(); } - for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i) + Tools::ModelDropdown(card.ModelHandle); + for (int8_t y = 0; y < Puzzle::Config::CardSize; ++y) { - ImGui::Separator(); - - Generated::StaticPuzzleCard& card = staticData.Cards[i]; - ImGui::PushID(i); - char cardName[64]{0}; - bx::snprintf(cardName, sizeof(cardName), "%i", i); - ImGui::Selectable(cardName); - if (ImGui::BeginDragDropSource()) + ImGui::PushID(y); + for (int8_t x = 0; x < Puzzle::Config::CardSize; ++x) { - Puzzle::DrawCard(card, debug.DebugCardRotation, ImGui::GetCursorScreenPos()); - ImGui::SetDragDropPayload("cardtype", &i, sizeof(i)); - ImGui::EndDragDropSource(); - } - - Tools::ModelDropdown(card.ModelHandle); - for (int8_t y = 0; y < Puzzle::Config::CardSize; ++y) - { - ImGui::PushID(y); - for (int8_t x = 0; x < Puzzle::Config::CardSize; ++x) + if (x > 0) ImGui::SameLine(); + ImGui::PushID(x); + auto& node = Puzzle::EditCardNodeAt(card, 0, x, y); + if (ImGui::Button(Generated::PuzzleElementType::ShortName[node], {26, 24})) { - if (x > 0) ImGui::SameLine(); - ImGui::PushID(x); - auto& node = Puzzle::EditCardNodeAt(card, 0, x, y); - if (ImGui::Button(Generated::PuzzleElementType::ShortName[node], {26, 24})) + int32_t newVal = int32_t(node) + 1; + if (newVal >= Generated::PuzzleElementType::EntryCount) { - int32_t newVal = int32_t(node) + 1; - if (newVal >= Generated::PuzzleElementType::EntryCount) - { - newVal = 0; - } - node = Generated::PuzzleElementType::Enum(newVal); + newVal = 0; } - ImGui::PopID(); + node = Generated::PuzzleElementType::Enum(newVal); } ImGui::PopID(); } ImGui::PopID(); } + ImGui::PopID(); } - ImGui::End(); + } + ImGui::End(); + } + + void GameRendering::Update() + { + ZoneScopedN("Rendering"); + SharedData& shared = GetShared(); + + HandleEvents(); + + // Start Rendering + { + ZoneScopedN("Imgui Start Frame"); + imguiBeginFrame(20); + ImGui_ImplSDL3_NewFrame(); + ImGui::DockSpaceOverViewport(0, 0, ImGuiDockNodeFlags_PassthruCentralNode); + } + + if (UIVisible == UIVisibilityState::Debug) + { + RenderDebugUI(); } GetInstance().GameLevel.Update(); GetInstance().GameLevel.Render(MainViewID, Models, Materials); // Finish Frame - imguiEndFrame(); + { + ZoneScopedN("Imgui End Frame"); + imguiEndFrame(); + } if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ZoneScopedN("Imgui Platform Update"); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); } - START_PERF(); - bgfx::frame(); - END_PERF(shared.Window.PerfCounters, PerfCounterType::Submit, shared.Window.FrameCounter); + { + ZoneScopedN("BGFX Frame"); + START_PERF(); + bgfx::frame(); + END_PERF(shared.Window.PerfCounters, PerfCounterType::Submit, shared.Window.FrameCounter); + } } void GameRendering::Shutdown() { + ZoneScopedN("Shutdown"); LOG("--- RENDERING_SHUTDOWN ---"); ImGui::SaveIniSettingsToDisk("imgui.ini"); auto& debug = GetInstance().DebugData; diff --git a/src/game/rendering/Rendering.h b/src/game/rendering/Rendering.h index 3158f6c..11d4030 100644 --- a/src/game/rendering/Rendering.h +++ b/src/game/rendering/Rendering.h @@ -105,7 +105,7 @@ namespace Game Model Models[MaxModels]; int32_t LastWidth = 0; int32_t LastHeight = 0; - uint32_t ResetFlags = BGFX_RESET_VSYNC; + uint32_t ResetFlags = 0; // BGFX_RESET_VSYNC; uint16_t MainViewID = 10; float LastShaderLoadTime = 0.0f; int32_t DitherRecursion = 1; @@ -115,6 +115,8 @@ namespace Game public: void Setup(); void Update(); + void HandleEvents(); + void RenderDebugUI(); void Shutdown(); uint16_t GetModelHandleFromPath(const char* path); };