diff --git a/src/Menu.cpp b/src/Menu.cpp index ce1241384f..3b8f70ccc1 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -179,6 +179,7 @@ void Menu::SetupImGuiStyle() const } bool IsEnabled = false; +bool ShowPerfOverlay = false; Menu::~Menu() { @@ -581,6 +582,11 @@ void Menu::DrawGeneralSettings() if (auto _tt = Util::HoverTooltipWrapper()) { ImGui::Text("Skips a shader being replaced if it hasn't been compiled yet. Also makes compilation blazingly fast!"); } + ImGui::TableNextColumn(); + ImGui::Checkbox("Perf Overlay", &ShowPerfOverlay); + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::Text("Shows an overlay with performance statistics."); + } ImGui::EndTable(); } @@ -998,20 +1004,7 @@ void Menu::DrawFooter() ImGui::SameLine(); ImGui::BulletText(std::format("D3D12 Interop: {}", globals::upscaling->d3d12Interop ? "Active" : "Inactive").c_str()); ImGui::SameLine(); - ImGui::BulletText(std::format("GPU: {}", globals::state->adapterDescription.c_str()).c_str()); - - if (dxgiAdapter3) { - ImGui::SameLine(); - DXGI_QUERY_VIDEO_MEMORY_INFO videoMemoryInfo; - dxgiAdapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &videoMemoryInfo); - - float currentGpuUsage = videoMemoryInfo.CurrentUsage / (1024.f * 1024.f * 1024.f); - float totalGpuMemory = videoMemoryInfo.Budget / (1024.f * 1024.f * 1024.f); - float percent = currentGpuUsage / totalGpuMemory; - - auto progressOverlay = std::format("GPU Usage: {:.02f}GB/{:.02f}GB ({:2.1f}%) ", currentGpuUsage, totalGpuMemory, 100 * percent); - ImGui::ProgressBar(percent, ImVec2(500.f, ImGui::GetTextLineHeight()), progressOverlay.c_str()); - } + ImGui::Text(std::format("GPU: {}", globals::state->adapterDescription.c_str()).c_str()); } void Menu::DrawOverlay() @@ -1022,7 +1015,7 @@ void Menu::DrawOverlay() auto failed = shaderCache->GetFailedTasks(); auto hide = shaderCache->IsHideErrors(); - if (!(shaderCache->IsCompiling() || IsEnabled || inTestMode || (failed && !hide))) { + if (!(shaderCache->IsCompiling() || IsEnabled || inTestMode || (failed && !hide) || ShowPerfOverlay)) { auto& io = ImGui::GetIO(); io.ClearInputKeys(); io.ClearEventsQueue(); @@ -1088,6 +1081,9 @@ void Menu::DrawOverlay() ImGui::GetIO().MouseDrawCursor = false; } + if (ShowPerfOverlay) + DrawPerfOverlay(); + if (inTestMode) { // In test mode float seconds = (float)duration_cast(high_resolution_clock::now() - lastTestSwitch).count() / 1000; auto remaining = (float)testInterval - seconds; @@ -1114,6 +1110,41 @@ void Menu::DrawOverlay() ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); } +void Menu::DrawPerfOverlay() +{ + ImGui::SetNextWindowPos(ImVec2(Util::GetNativeViewportSizeScaled(1.f).x, Util::GetNativeViewportSizeScaled(0.f).y + 20.f), ImGuiCond_Always, ImVec2(1.f, 0.f)); + ImGui::SetNextWindowSize(Util::GetNativeViewportSizeScaled(0.2f), ImGuiCond_Appearing); + ImGui::Begin("PerformanceOverlay", NULL, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize); + { + ImGui::Text("Draw Calls:"); + //ImGui::Text(std::format("None: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::None])).c_str()); + ImGui::Text(std::format("Grass: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Grass])).c_str()); + ImGui::Text(std::format("Sky: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Sky])).c_str()); + ImGui::Text(std::format("Water: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Water])).c_str()); + ImGui::Text(std::format("BloodSplatter: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::BloodSplatter])).c_str()); + ImGui::Text(std::format("ImageSpace: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::ImageSpace])).c_str()); + ImGui::Text(std::format("Lighting: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Lighting])).c_str()); + ImGui::Text(std::format("Effect: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Effect])).c_str()); + ImGui::Text(std::format("Utility: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Utility])).c_str()); + ImGui::Text(std::format("DistantTree: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::DistantTree])).c_str()); + ImGui::Text(std::format("Particle: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Particle])).c_str()); + ImGui::Text(std::format("Total: {}", int(globals::state->smoothDrawCalls[RE::BSShader::Type::Total])).c_str()); + + if (dxgiAdapter3) { + DXGI_QUERY_VIDEO_MEMORY_INFO videoMemoryInfo; + dxgiAdapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &videoMemoryInfo); + + float currentGpuUsage = videoMemoryInfo.CurrentUsage / (1024.f * 1024.f * 1024.f); + float totalGpuMemory = videoMemoryInfo.Budget / (1024.f * 1024.f * 1024.f); + float percent = currentGpuUsage / totalGpuMemory; + + auto progressOverlay = std::format("GPU: {:.02f}GB/{:.02f}GB ({:2.1f}%) ", currentGpuUsage, totalGpuMemory, 100 * percent); + ImGui::ProgressBar(percent, ImVec2(200.f, ImGui::GetTextLineHeight()), progressOverlay.c_str()); + } + ImGui::End(); + } +} + const ImGuiKey Menu::VirtualKeyToImGuiKey(WPARAM vkKey) { switch (vkKey) { diff --git a/src/Menu.h b/src/Menu.h index 8941f67741..e191e97024 100644 --- a/src/Menu.h +++ b/src/Menu.h @@ -39,6 +39,7 @@ class Menu void Init(); void DrawSettings(); void DrawOverlay(); + void DrawPerfOverlay(); void ProcessInputEvents(RE::InputEvent* const* a_events); bool ShouldSwallowInput(); diff --git a/src/State.cpp b/src/State.cpp index d855cc2569..71a10661be 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -69,10 +69,17 @@ void State::Draw() currentExtraDescriptor = 0; if (frameChecker.IsNewFrame()) { + for (int i = 0; i < RE::BSShader::Type::Total + 1; ++i) + smoothDrawCalls[i] = smoothDrawCalls[i] * 0.95 + drawCalls[i] * 0.05; + for (auto& c : drawCalls) + c = 0; ID3D11Buffer* buffers[3] = { permutationCB->CB(), sharedDataCB->CB(), featureDataCB->CB() }; context->PSSetConstantBuffers(4, 3, buffers); context->CSSetConstantBuffers(5, 2, buffers + 1); } + drawCalls[RE::BSShader::Type::Total]++; + if (currentShader) + drawCalls[currentShader->shaderType.get()]++; if (currentShader && updateShader) { auto type = currentShader->shaderType.get(); @@ -488,6 +495,10 @@ void State::ModifyRenderTarget(RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::B void State::SetupResources() { + for (auto& c : drawCalls) + c = 0; + for (auto& c : smoothDrawCalls) + c = 0; auto renderer = globals::game::renderer; permutationCB = new ConstantBuffer(ConstantBufferDesc()); diff --git a/src/State.h b/src/State.h index c74419e6e8..cbae3b852b 100644 --- a/src/State.h +++ b/src/State.h @@ -44,6 +44,8 @@ class State bool upscalerLoaded = false; float timer = 0; + double smoothDrawCalls[RE::BSShader::Type::Total + 1]; + int drawCalls[RE::BSShader::Type::Total + 1]; enum ConfigMode {