From c4bc20b4d9c2af3894689c6ba54499f2e2316ec4 Mon Sep 17 00:00:00 2001 From: Rodolfo Bogado Date: Wed, 3 Apr 2013 19:53:48 -0300 Subject: [PATCH] Adds support for PE performance metrics in the D3D9 backend --- .../Plugin_VideoDX9/Plugin_VideoDX9.vcxproj | 2 + .../Plugin_VideoDX9.vcxproj.filters | 6 + .../Plugins/Plugin_VideoDX9/Src/PerfQuery.cpp | 146 ++++++++++++++++++ .../Plugins/Plugin_VideoDX9/Src/PerfQuery.h | 46 ++++++ Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 4 +- .../Plugin_VideoDX9/Src/VertexManager.cpp | 5 +- 6 files changed, 206 insertions(+), 3 deletions(-) create mode 100644 Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.cpp create mode 100644 Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.h diff --git a/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj b/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj index c152fcb630..02d39e314f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj +++ b/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj @@ -199,6 +199,7 @@ + @@ -222,6 +223,7 @@ + diff --git a/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj.filters b/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj.filters index 720e1983b0..c1d091c239 100644 --- a/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj.filters +++ b/Source/Plugins/Plugin_VideoDX9/Plugin_VideoDX9.vcxproj.filters @@ -39,6 +39,9 @@ D3D + + Render + @@ -78,6 +81,9 @@ D3D + + Render + diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.cpp new file mode 100644 index 0000000000..cea140031f --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.cpp @@ -0,0 +1,146 @@ +#include "RenderBase.h" + +#include "D3DBase.h" +#include "PerfQuery.h" + +namespace DX9 { + +PerfQuery::PerfQuery() + : m_query_read_pos() + , m_query_count() +{ + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + { + D3D::dev->CreateQuery(D3DQUERYTYPE_OCCLUSION, &m_query_buffer[i].query); + } + ResetQuery(); +} + +PerfQuery::~PerfQuery() +{ + for (int i = 0; i != ARRAYSIZE(m_query_buffer); ++i) + { + m_query_buffer[i].query->Release(); + } +} + +void PerfQuery::EnableQuery(PerfQueryGroup type) +{ + // Is this sane? + if (m_query_count > ARRAYSIZE(m_query_buffer) / 2) + WeakFlush(); + + if (ARRAYSIZE(m_query_buffer) == m_query_count) + { + // TODO + FlushOne(); + ERROR_LOG(VIDEO, "Flushed query buffer early!"); + } + + // start query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count) % ARRAYSIZE(m_query_buffer)]; + entry.query->Issue(D3DISSUE_BEGIN); + entry.query_type = type; + ++m_query_count; + } +} + +void PerfQuery::DisableQuery(PerfQueryGroup type) +{ + // stop query + if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP) + { + auto& entry = m_query_buffer[(m_query_read_pos + m_query_count + ARRAYSIZE(m_query_buffer)-1) % ARRAYSIZE(m_query_buffer)]; + entry.query->Issue(D3DISSUE_END); + } +} + +void PerfQuery::ResetQuery() +{ + m_query_count = 0; + std::fill_n(m_results, ARRAYSIZE(m_results), 0); +} + +u32 PerfQuery::GetQueryResult(PerfQueryType type) +{ + u32 result = 0; + + if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC) + { + result = m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT) + { + result = m_results[PQG_ZCOMP]; + } + else if (type == PQ_BLEND_INPUT) + { + result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC]; + } + else if (type == PQ_EFB_COPY_CLOCKS) + { + result = m_results[PQG_EFB_COPY_CLOCKS]; + } + + return result / 4; +} + +void PerfQuery::FlushOne() +{ + auto& entry = m_query_buffer[m_query_read_pos]; + + UINT64 result = 0; + HRESULT hr = S_FALSE; + while (hr != S_OK && hr != D3DERR_DEVICELOST) + { + // TODO: Might cause us to be stuck in an infinite loop! + hr = entry.query->GetData(&result, sizeof(result), D3DGETDATA_FLUSH); + } + + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; +} + +// TODO: could selectively flush things, but I don't think that will do much +void PerfQuery::FlushResults() +{ + while (!IsFlushed()) + FlushOne(); +} + +void PerfQuery::WeakFlush() +{ + while (!IsFlushed()) + { + auto& entry = m_query_buffer[m_query_read_pos]; + + UINT64 result = 0; + HRESULT hr = entry.query->GetData(&result, sizeof(result), 0); + + if (hr == S_OK) + { + // NOTE: Reported pixel metrics should be referenced to native resolution + m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + + m_query_read_pos = (m_query_read_pos + 1) % ARRAYSIZE(m_query_buffer); + --m_query_count; + } + else + { + break; + } + } +} + +bool PerfQuery::IsFlushed() const +{ + return 0 == m_query_count; +} + + +} // namespace diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.h b/Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.h new file mode 100644 index 0000000000..56f964f7ed --- /dev/null +++ b/Source/Plugins/Plugin_VideoDX9/Src/PerfQuery.h @@ -0,0 +1,46 @@ +#ifndef _PERFQUERY_H_ +#define _PERFQUERY_H_ + +#include "PerfQueryBase.h" + +namespace DX9 { + +class PerfQuery : public PerfQueryBase +{ +public: + PerfQuery(); + ~PerfQuery(); + + void EnableQuery(PerfQueryGroup type); + void DisableQuery(PerfQueryGroup type); + void ResetQuery(); + u32 GetQueryResult(PerfQueryType type); + void FlushResults(); + bool IsFlushed() const; + +private: + struct ActiveQuery + { + IDirect3DQuery9* query; + PerfQueryGroup query_type; + }; + + void WeakFlush(); + + // Only use when non-empty + void FlushOne(); + + // when testing in SMS: 64 was too small, 128 was ok + static const int PERF_QUERY_BUFFER_SIZE = 512; + + ActiveQuery m_query_buffer[PERF_QUERY_BUFFER_SIZE]; + int m_query_read_pos; + + // TODO: sloppy + volatile int m_query_count; + volatile u32 m_results[PQG_NUM_MEMBERS]; +}; + +} // namespace + +#endif // _PERFQUERY_H_ diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 38f2cbed48..2838895d4c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -55,7 +55,7 @@ #include "BPFunctions.h" #include "FPSCounter.h" #include "ConfigManager.h" - +#include "PerfQuery.h" #include @@ -88,6 +88,7 @@ void SetupDeviceObjects() VertexShaderCache::Init(); PixelShaderCache::Init(); g_vertex_manager->CreateDeviceObjects(); + g_perf_query = new PerfQuery; // Texture cache will recreate themselves over time. } @@ -100,6 +101,7 @@ void TeardownDeviceObjects() D3D::dev->SetRenderTarget(0, D3D::GetBackBufferSurface()); D3D::dev->SetDepthStencilSurface(D3D::GetBackBufferDepthSurface()); delete g_framebuffer_manager; + delete g_perf_query; D3D::font.Shutdown(); TextureCache::Invalidate(); VertexLoaderManager::Shutdown(); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index 7ee286d7b5..2908f99a4a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -378,7 +378,8 @@ void VertexManager::vFlush() } PrepareDrawBuffers(stride); - g_nativeVertexFmt->SetupVertexPointers(); + g_nativeVertexFmt->SetupVertexPointers(); + g_perf_query->EnableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); if(m_buffers_count) { DrawVertexBuffer(stride); @@ -387,7 +388,7 @@ void VertexManager::vFlush() { DrawVertexArray(stride); } - + g_perf_query->DisableQuery(bpmem.zcontrol.early_ztest ? PQG_ZCOMP_ZCOMPLOC : PQG_ZCOMP); if (useDstAlpha && !useDualSource) { if (!PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS, g_nativeVertexFmt->m_components))