diff --git a/src/core/gpu.cpp b/src/core/gpu.cpp index c23cd8c2c..54196d37b 100644 --- a/src/core/gpu.cpp +++ b/src/core/gpu.cpp @@ -757,12 +757,66 @@ bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride void GPU::DrawDebugStateWindow() { ImGui::SetNextWindowSize(ImVec2(450, 550), ImGuiCond_FirstUseEver); - if (!ImGui::Begin("GPU State", &m_system->GetSettings().debugging.show_gpu_state)) + if (!ImGui::Begin("GPU", &m_system->GetSettings().debugging.show_gpu_state)) { ImGui::End(); return; } + const bool is_idle_frame = m_stats.num_polygons == 0; + if (!is_idle_frame) + { + m_last_stats = m_stats; + m_stats = {}; + } + + if (ImGui::CollapsingHeader("Statistics", ImGuiTreeNodeFlags_DefaultOpen)) + { + const Stats& stats = m_last_stats; + + ImGui::Columns(2); + ImGui::SetColumnWidth(0, 200.0f); + + ImGui::TextUnformatted("Idle Frame: "); + ImGui::NextColumn(); + ImGui::Text("%s", is_idle_frame ? "Yes" : "No"); + ImGui::NextColumn(); + + ImGui::TextUnformatted("VRAM Reads: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_vram_reads); + ImGui::NextColumn(); + + ImGui::TextUnformatted("VRAM Fills: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_vram_fills); + ImGui::NextColumn(); + + ImGui::TextUnformatted("VRAM Writes: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_vram_writes); + ImGui::NextColumn(); + + ImGui::TextUnformatted("VRAM Copies: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_vram_copies); + ImGui::NextColumn(); + + ImGui::TextUnformatted("Vertices Processed: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_vertices); + ImGui::NextColumn(); + + ImGui::TextUnformatted("Polygons Drawn: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_polygons); + ImGui::NextColumn(); + + ImGui::Columns(1); + } + + DrawRendererStats(is_idle_frame); + if (ImGui::CollapsingHeader("CRTC", ImGuiTreeNodeFlags_DefaultOpen)) { const auto& cs = m_crtc_state; @@ -803,4 +857,4 @@ void GPU::DrawDebugStateWindow() ImGui::End(); } -void GPU::DrawRendererStatsWindow() {} +void GPU::DrawRendererStats(bool is_idle_frame) {} diff --git a/src/core/gpu.h b/src/core/gpu.h index 2b090cfb0..78d4bd2f7 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -104,7 +104,6 @@ public: // Render statistics debug window. void DrawDebugStateWindow(); - virtual void DrawRendererStatsWindow(); // MMIO access u32 ReadRegister(u32 offset); @@ -289,13 +288,14 @@ protected: void HandleGetGPUInfoCommand(u32 value); // Rendering in the backend - virtual void UpdateDisplay(); virtual void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer); virtual void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color); virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data); virtual void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height); virtual void DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32* command_ptr); virtual void FlushRender(); + virtual void UpdateDisplay(); + virtual void DrawRendererStats(bool is_idle_frame); HostDisplay* m_host_display = nullptr; System* m_system = nullptr; @@ -461,6 +461,18 @@ protected: std::vector m_GP0_buffer; std::deque m_GPUREAD_buffer; + struct Stats + { + u32 num_vram_reads; + u32 num_vram_fills; + u32 num_vram_writes; + u32 num_vram_copies; + u32 num_vertices; + u32 num_polygons; + }; + Stats m_stats = {}; + Stats m_last_stats = {}; + private: using GP0CommandHandler = bool (GPU::*)(const u32*&, u32); using GP0CommandHandlerTable = std::array; diff --git a/src/core/gpu_commands.cpp b/src/core/gpu_commands.cpp index 849b6a305..f71b74ba5 100644 --- a/src/core/gpu_commands.cpp +++ b/src/core/gpu_commands.cpp @@ -236,6 +236,8 @@ bool GPU::HandleRenderCommand(const u32*& command_ptr, u32 command_size) DispatchRenderCommand(rc, num_vertices, command_ptr); command_ptr += total_words; + m_stats.num_vertices += num_vertices; + m_stats.num_polygons++; return true; } @@ -256,6 +258,7 @@ bool GPU::HandleFillRectangleCommand(const u32*& command_ptr, u32 command_size) Log_DebugPrintf("Fill VRAM rectangle offset=(%u,%u), size=(%u,%u)", dst_x, dst_y, width, height); FillVRAM(dst_x, dst_y, width, height, color); + m_stats.num_vram_fills++; return true; } @@ -293,6 +296,7 @@ bool GPU::HandleCopyRectangleCPUToVRAMCommand(const u32*& command_ptr, u32 comma FlushRender(); UpdateVRAM(dst_x, dst_y, copy_width, copy_height, &command_ptr[3]); command_ptr += num_words; + m_stats.num_vram_writes++; return true; } @@ -332,7 +336,7 @@ bool GPU::HandleCopyRectangleVRAMToCPUCommand(const u32*& command_ptr, u32 comma sizeof(u16) * width, temp.data(), true); } - // Is this correct? + m_stats.num_vram_reads++; return true; } @@ -361,5 +365,6 @@ bool GPU::HandleCopyRectangleVRAMToVRAMCommand(const u32*& command_ptr, u32 comm FlushRender(); CopyVRAM(src_x, src_y, dst_x, dst_y, width, height); + m_stats.num_vram_copies++; return true; } diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 0a04de0d6..2737ac140 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -3,6 +3,7 @@ #include "YBaseLib/Log.h" #include "settings.h" #include "system.h" +#include #include Log_SetChannel(GPU_HW); @@ -291,3 +292,37 @@ void GPU_HW::DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32 LoadVertices(rc, num_vertices, command_ptr); } + +void GPU_HW::DrawRendererStats(bool is_idle_frame) +{ + if (!is_idle_frame) + { + m_last_renderer_stats = m_renderer_stats; + m_renderer_stats = {}; + } + + if (ImGui::CollapsingHeader("Renderer Statistics", ImGuiTreeNodeFlags_DefaultOpen)) + { + const auto& stats = m_last_renderer_stats; + + ImGui::Columns(2); + ImGui::SetColumnWidth(0, 200.0f); + + ImGui::TextUnformatted("Batches Drawn:"); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_batches); + ImGui::NextColumn(); + + ImGui::TextUnformatted("VRAM Read Texture Updates:"); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_vram_read_texture_updates); + ImGui::NextColumn(); + + ImGui::TextUnformatted("Uniform Buffer Updates: "); + ImGui::NextColumn(); + ImGui::Text("%u", stats.num_uniform_buffer_updates); + ImGui::NextColumn(); + + ImGui::Columns(1); + } +} \ No newline at end of file diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index 2768868db..f538fd192 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -33,6 +33,13 @@ public: virtual void UpdateSettings() override; protected: + enum : u32 + { + VRAM_UPDATE_TEXTURE_BUFFER_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u32), + VERTEX_BUFFER_SIZE = 1 * 1024 * 1024, + UNIFORM_BUFFER_SIZE = 512 * 1024 + }; + struct BatchVertex { s32 x; @@ -88,11 +95,12 @@ protected: float u_dst_alpha_factor; }; - static constexpr u32 VRAM_UPDATE_TEXTURE_BUFFER_SIZE = VRAM_WIDTH * VRAM_HEIGHT * sizeof(u32); - static constexpr u32 VERTEX_BUFFER_SIZE = 1 * 1024 * 1024; - static constexpr u32 MIN_BATCH_VERTEX_COUNT = 6; - static constexpr u32 MAX_BATCH_VERTEX_COUNT = VERTEX_BUFFER_SIZE / sizeof(BatchVertex); - static constexpr u32 UNIFORM_BUFFER_SIZE = 512 * 1024; + struct RendererStats + { + u32 num_batches; + u32 num_vram_read_texture_updates; + u32 num_uniform_buffer_updates; + }; static constexpr std::tuple RGBA8ToFloat(u32 rgba) { @@ -112,6 +120,7 @@ protected: bool IsFlushed() const { return m_batch_current_vertex_ptr == m_batch_start_vertex_ptr; } void DispatchRenderCommand(RenderCommand rc, u32 num_vertices, const u32* command_ptr) override; + void DrawRendererStats(bool is_idle_frame) override; void CalcScissorRect(int* left, int* top, int* right, int* bottom); @@ -131,13 +140,25 @@ protected: BatchConfig m_batch = {}; BatchUBOData m_batch_ubo_data = {}; - bool m_batch_ubo_dirty = true; // Bounding box of VRAM area that the GPU has drawn into. Common::Rectangle m_vram_dirty_rect; + + // Statistics + RendererStats m_renderer_stats = {}; + RendererStats m_last_renderer_stats = {}; + + // Changed state + bool m_batch_ubo_dirty = true; bool m_vram_read_texture_dirty = false; private: + enum : u32 + { + MIN_BATCH_VERTEX_COUNT = 6, + MAX_BATCH_VERTEX_COUNT = VERTEX_BUFFER_SIZE / sizeof(BatchVertex) + }; + static BatchPrimitive GetPrimitiveForCommand(RenderCommand rc); void LoadVertices(RenderCommand rc, u32 num_vertices, const u32* command_ptr); diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index 509d25e5d..5d978553f 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -6,7 +6,6 @@ #include "gpu_hw_shadergen.h" #include "host_display.h" #include "host_interface.h" -#include "imgui.h" #include "system.h" Log_SetChannel(GPU_HW_D3D11); @@ -120,58 +119,6 @@ void GPU_HW_D3D11::UpdateSettings() UpdateDisplay(); } -void GPU_HW_D3D11::DrawRendererStatsWindow() -{ - GPU_HW::DrawRendererStatsWindow(); - - ImGui::SetNextWindowSize(ImVec2(300.0f, 150.0f), ImGuiCond_FirstUseEver); - - const bool is_null_frame = m_stats.num_batches == 0; - if (!is_null_frame) - { - m_last_stats = m_stats; - m_stats = {}; - } - - if (ImGui::Begin("GPU Renderer Statistics", &m_show_renderer_statistics)) - { - ImGui::Columns(2); - ImGui::SetColumnWidth(0, 200.0f); - - ImGui::TextUnformatted("GPU Active In This Frame: "); - ImGui::NextColumn(); - ImGui::Text("%s", is_null_frame ? "Yes" : "No"); - ImGui::NextColumn(); - - ImGui::TextUnformatted("VRAM Reads: "); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vram_reads); - ImGui::NextColumn(); - - ImGui::TextUnformatted("VRAM Writes: "); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vram_writes); - ImGui::NextColumn(); - - ImGui::TextUnformatted("VRAM Read Texture Updates:"); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vram_read_texture_updates); - ImGui::NextColumn(); - - ImGui::TextUnformatted("Batches Drawn:"); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_batches); - ImGui::NextColumn(); - - ImGui::TextUnformatted("Vertices Drawn: "); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vertices); - ImGui::NextColumn(); - } - - ImGui::End(); -} - void GPU_HW_D3D11::MapBatchVertexPointer(u32 required_vertices) { Assert(!m_batch_start_vertex_ptr); @@ -449,7 +396,7 @@ void GPU_HW_D3D11::UploadUniformBlock(const void* data, u32 data_size) m_context->VSSetConstantBuffers(0, 1, m_uniform_stream_buffer.GetD3DBufferArray()); m_context->PSSetConstantBuffers(0, 1, m_uniform_stream_buffer.GetD3DBufferArray()); - m_stats.num_uniform_buffer_updates++; + m_renderer_stats.num_uniform_buffer_updates++; } void GPU_HW_D3D11::SetViewport(u32 x, u32 y, u32 width, u32 height) @@ -640,7 +587,6 @@ void GPU_HW_D3D11::UpdateDisplay() void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) { Log_WarningPrintf("VRAM readback not implemented"); - m_stats.num_vram_reads++; } void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) @@ -677,7 +623,6 @@ void GPU_HW_D3D11::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* d RestoreGraphicsAPIState(); InvalidateVRAMReadTexture(); - m_stats.num_vram_writes++; } void GPU_HW_D3D11::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) @@ -696,7 +641,7 @@ void GPU_HW_D3D11::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 widt void GPU_HW_D3D11::UpdateVRAMReadTexture() { - m_stats.num_vram_read_texture_updates++; + m_renderer_stats.num_vram_read_texture_updates++; m_vram_read_texture_dirty = false; m_vram_dirty_rect.SetInvalid(); @@ -710,8 +655,7 @@ void GPU_HW_D3D11::FlushRender() if (vertex_count == 0) return; - m_stats.num_batches++; - m_stats.num_vertices += vertex_count; + m_renderer_stats.num_batches++; m_vertex_stream_buffer.Unmap(m_context.Get(), vertex_count * sizeof(BatchVertex)); m_batch_start_vertex_ptr = nullptr; diff --git a/src/core/gpu_hw_d3d11.h b/src/core/gpu_hw_d3d11.h index d13dcee32..6a560f623 100644 --- a/src/core/gpu_hw_d3d11.h +++ b/src/core/gpu_hw_d3d11.h @@ -26,8 +26,6 @@ public: void RestoreGraphicsAPIState() override; void UpdateSettings() override; - void DrawRendererStatsWindow() override; - protected: void UpdateDisplay() override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override; @@ -38,16 +36,6 @@ protected: void MapBatchVertexPointer(u32 required_vertices) override; private: - struct GLStats - { - u32 num_batches; - u32 num_vertices; - u32 num_vram_reads; - u32 num_vram_writes; - u32 num_vram_read_texture_updates; - u32 num_uniform_buffer_updates; - }; - void SetCapabilities(); bool CreateFramebuffer(); void ClearFramebuffer(); @@ -112,9 +100,4 @@ private: ComPtr m_fill_pixel_shader; ComPtr m_vram_write_pixel_shader; std::array, 2>, 2> m_display_pixel_shaders; // [depth_24][interlaced] - - GLStats m_stats = {}; - GLStats m_last_stats = {}; - - bool m_show_renderer_statistics = false; }; diff --git a/src/core/gpu_hw_opengl.cpp b/src/core/gpu_hw_opengl.cpp index 49a2edf51..204ad5415 100644 --- a/src/core/gpu_hw_opengl.cpp +++ b/src/core/gpu_hw_opengl.cpp @@ -4,7 +4,6 @@ #include "YBaseLib/String.h" #include "gpu_hw_shadergen.h" #include "host_display.h" -#include "imgui.h" #include "system.h" Log_SetChannel(GPU_HW_OpenGL); @@ -88,58 +87,6 @@ void GPU_HW_OpenGL::UpdateSettings() UpdateDisplay(); } -void GPU_HW_OpenGL::DrawRendererStatsWindow() -{ - GPU_HW::DrawRendererStatsWindow(); - - ImGui::SetNextWindowSize(ImVec2(300.0f, 150.0f), ImGuiCond_FirstUseEver); - - const bool is_null_frame = m_stats.num_batches == 0; - if (!is_null_frame) - { - m_last_stats = m_stats; - m_stats = {}; - } - - if (ImGui::Begin("GPU Renderer Statistics", &m_show_renderer_statistics)) - { - ImGui::Columns(2); - ImGui::SetColumnWidth(0, 200.0f); - - ImGui::TextUnformatted("GPU Active In This Frame: "); - ImGui::NextColumn(); - ImGui::Text("%s", is_null_frame ? "Yes" : "No"); - ImGui::NextColumn(); - - ImGui::TextUnformatted("VRAM Reads: "); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vram_reads); - ImGui::NextColumn(); - - ImGui::TextUnformatted("VRAM Writes: "); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vram_writes); - ImGui::NextColumn(); - - ImGui::TextUnformatted("VRAM Read Texture Updates:"); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vram_read_texture_updates); - ImGui::NextColumn(); - - ImGui::TextUnformatted("Batches Drawn:"); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_batches); - ImGui::NextColumn(); - - ImGui::TextUnformatted("Vertices Drawn: "); - ImGui::NextColumn(); - ImGui::Text("%u", m_last_stats.num_vertices); - ImGui::NextColumn(); - } - - ImGui::End(); -} - void GPU_HW_OpenGL::MapBatchVertexPointer(u32 required_vertices) { Assert(!m_batch_start_vertex_ptr); @@ -429,7 +376,7 @@ void GPU_HW_OpenGL::UploadUniformBlock(const void* data, u32 data_size) glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_uniform_stream_buffer->GetGLBufferId(), res.buffer_offset, data_size); - m_stats.num_uniform_buffer_updates++; + m_renderer_stats.num_uniform_buffer_updates++; } void GPU_HW_OpenGL::UpdateDisplay() @@ -593,8 +540,6 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) source_ptr -= source_stride; dst_ptr += dst_stride; } - - m_stats.num_vram_reads++; } void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) @@ -703,7 +648,6 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* #endif InvalidateVRAMReadTexture(); - m_stats.num_vram_writes++; } void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) @@ -730,7 +674,7 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid void GPU_HW_OpenGL::UpdateVRAMReadTexture() { - m_stats.num_vram_read_texture_updates++; + m_renderer_stats.num_vram_read_texture_updates++; m_vram_read_texture_dirty = false; m_vram_dirty_rect.SetInvalid(); @@ -745,8 +689,7 @@ void GPU_HW_OpenGL::FlushRender() if (vertex_count == 0) return; - m_stats.num_batches++; - m_stats.num_vertices += vertex_count; + m_renderer_stats.num_batches++; m_vertex_stream_buffer->Unmap(vertex_count * sizeof(BatchVertex)); m_vertex_stream_buffer->Bind(); diff --git a/src/core/gpu_hw_opengl.h b/src/core/gpu_hw_opengl.h index 2297f2b93..e4adaccd2 100644 --- a/src/core/gpu_hw_opengl.h +++ b/src/core/gpu_hw_opengl.h @@ -22,8 +22,6 @@ public: void RestoreGraphicsAPIState() override; void UpdateSettings() override; - void DrawRendererStatsWindow() override; - protected: void UpdateDisplay() override; void ReadVRAM(u32 x, u32 y, u32 width, u32 height, void* buffer) override; @@ -81,9 +79,4 @@ private: std::array, 9>, 4> m_render_programs; // [render_mode][texture_mode][dithering] std::array, 2> m_display_programs; // [depth_24][interlaced] GL::Program m_vram_write_program; - - GLStats m_stats = {}; - GLStats m_last_stats = {}; - - bool m_show_renderer_statistics = false; }; diff --git a/src/core/settings.h b/src/core/settings.h index 8b0db77de..fbee45171 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -24,7 +24,6 @@ struct Settings struct DebugSettings { bool show_gpu_state = false; - bool show_gpu_renderer_stats = false; bool show_vram = false; bool dump_cpu_to_vram_copies = false; bool dump_vram_to_cpu_copies = false; diff --git a/src/duckstation/sdl_host_interface.cpp b/src/duckstation/sdl_host_interface.cpp index dcd968ee9..0cb53d2bf 100644 --- a/src/duckstation/sdl_host_interface.cpp +++ b/src/duckstation/sdl_host_interface.cpp @@ -866,7 +866,6 @@ void SDLHostInterface::DrawDebugMenu() ImGui::Separator(); ImGui::MenuItem("Show GPU State", nullptr, &debug_settings.show_gpu_state); - ImGui::MenuItem("Show GPU Renderer Stats", nullptr, &debug_settings.show_gpu_renderer_stats); ImGui::MenuItem("Show VRAM", nullptr, &debug_settings.show_vram); ImGui::MenuItem("Dump CPU to VRAM Copies", nullptr, &debug_settings.dump_cpu_to_vram_copies); ImGui::MenuItem("Dump VRAM to CPU Copies", nullptr, &debug_settings.dump_vram_to_cpu_copies); @@ -893,8 +892,6 @@ void SDLHostInterface::DrawDebugWindows() if (debug_settings.show_gpu_state) m_system->GetGPU()->DrawDebugStateWindow(); - if (debug_settings.show_gpu_renderer_stats) - m_system->GetGPU()->DrawRendererStatsWindow(); if (debug_settings.show_cdrom_state) m_system->GetCDROM()->DrawDebugWindow(); if (debug_settings.show_timers_state)