GPUDevice: End timer on command flush

Fixes incorrect GPU usage readings in OpenGL, D3D11 is still
problematic, at least on AMD.
This commit is contained in:
Stenzek 2024-12-28 13:00:34 +10:00
parent 7bb0c7d1fb
commit 8c807118c0
No known key found for this signature in database
4 changed files with 47 additions and 28 deletions

View File

@ -509,12 +509,14 @@ std::string D3D11Device::GetDriverInfo() const
void D3D11Device::FlushCommands() void D3D11Device::FlushCommands()
{ {
m_context->Flush(); m_context->Flush();
EndTimestampQuery();
TrimTexturePool(); TrimTexturePool();
} }
void D3D11Device::WaitForGPUIdle() void D3D11Device::WaitForGPUIdle()
{ {
m_context->Flush(); m_context->Flush();
EndTimestampQuery();
TrimTexturePool(); TrimTexturePool();
} }
@ -671,7 +673,10 @@ GPUDevice::PresentResult D3D11Device::BeginPresent(GPUSwapChain* swap_chain, u32
// in this configuration. It does reduce accuracy a little, but better than seeing 100% all of // in this configuration. It does reduce accuracy a little, but better than seeing 100% all of
// the time, when it's more like a couple of percent. // the time, when it's more like a couple of percent.
if (SC == m_main_swap_chain.get() && SC->GetVSyncMode() == GPUVSyncMode::FIFO && m_gpu_timing_enabled) if (SC == m_main_swap_chain.get() && SC->GetVSyncMode() == GPUVSyncMode::FIFO && m_gpu_timing_enabled)
{
PopTimestampQuery(); PopTimestampQuery();
EndTimestampQuery();
}
m_context->ClearRenderTargetView(SC->GetRTV(), GSVector4::rgba32(clear_color).F32); m_context->ClearRenderTargetView(SC->GetRTV(), GSVector4::rgba32(clear_color).F32);
m_context->OMSetRenderTargets(1, SC->GetRTVArray(), nullptr); m_context->OMSetRenderTargets(1, SC->GetRTVArray(), nullptr);
@ -690,7 +695,10 @@ void D3D11Device::EndPresent(GPUSwapChain* swap_chain, bool explicit_present, u6
DebugAssert(m_num_current_render_targets == 0 && !m_current_depth_target); DebugAssert(m_num_current_render_targets == 0 && !m_current_depth_target);
if (SC == m_main_swap_chain.get() && SC->GetVSyncMode() != GPUVSyncMode::FIFO && m_gpu_timing_enabled) if (SC == m_main_swap_chain.get() && SC->GetVSyncMode() != GPUVSyncMode::FIFO && m_gpu_timing_enabled)
{
PopTimestampQuery(); PopTimestampQuery();
EndTimestampQuery();
}
const UINT sync_interval = static_cast<UINT>(SC->GetVSyncMode() == GPUVSyncMode::FIFO); const UINT sync_interval = static_cast<UINT>(SC->GetVSyncMode() == GPUVSyncMode::FIFO);
const UINT flags = const UINT flags =
@ -698,7 +706,7 @@ void D3D11Device::EndPresent(GPUSwapChain* swap_chain, bool explicit_present, u6
SC->GetSwapChain()->Present(sync_interval, flags); SC->GetSwapChain()->Present(sync_interval, flags);
if (m_gpu_timing_enabled) if (m_gpu_timing_enabled)
KickTimestampQuery(); StartTimestampQuery();
TrimTexturePool(); TrimTexturePool();
} }
@ -724,7 +732,7 @@ bool D3D11Device::CreateTimestampQueries()
} }
} }
KickTimestampQuery(); StartTimestampQuery();
return true; return true;
} }
@ -783,7 +791,10 @@ void D3D11Device::PopTimestampQuery()
} }
} }
} }
}
void D3D11Device::EndTimestampQuery()
{
if (m_timestamp_query_started) if (m_timestamp_query_started)
{ {
m_context->End(m_timestamp_queries[m_write_timestamp_query][2].Get()); m_context->End(m_timestamp_queries[m_write_timestamp_query][2].Get());
@ -794,7 +805,7 @@ void D3D11Device::PopTimestampQuery()
} }
} }
void D3D11Device::KickTimestampQuery() void D3D11Device::StartTimestampQuery()
{ {
if (m_timestamp_query_started || !m_timestamp_queries[0][0] || m_waiting_timestamp_queries == NUM_TIMESTAMP_QUERIES) if (m_timestamp_query_started || !m_timestamp_queries[0][0] || m_waiting_timestamp_queries == NUM_TIMESTAMP_QUERIES)
return; return;
@ -815,7 +826,7 @@ bool D3D11Device::SetGPUTimingEnabled(bool enabled)
if (!CreateTimestampQueries()) if (!CreateTimestampQueries())
return false; return false;
KickTimestampQuery(); StartTimestampQuery();
return true; return true;
} }
else else

View File

@ -161,7 +161,8 @@ private:
bool CreateTimestampQueries(); bool CreateTimestampQueries();
void DestroyTimestampQueries(); void DestroyTimestampQueries();
void PopTimestampQuery(); void PopTimestampQuery();
void KickTimestampQuery(); void EndTimestampQuery();
void StartTimestampQuery();
ComPtr<ID3D11Device1> m_device; ComPtr<ID3D11Device1> m_device;
ComPtr<ID3D11DeviceContext1> m_context; ComPtr<ID3D11DeviceContext1> m_context;

View File

@ -656,13 +656,15 @@ std::string OpenGLDevice::GetDriverInfo() const
void OpenGLDevice::FlushCommands() void OpenGLDevice::FlushCommands()
{ {
glFlush(); glFlush();
EndTimestampQuery();
TrimTexturePool(); TrimTexturePool();
} }
void OpenGLDevice::WaitForGPUIdle() void OpenGLDevice::WaitForGPUIdle()
{ {
// Could be glFinish(), but I'm afraid for mobile drivers... glFinish();
glFlush(); EndTimestampQuery();
TrimTexturePool();
} }
void OpenGLDevice::RenderBlankFrame() void OpenGLDevice::RenderBlankFrame()
@ -818,12 +820,15 @@ void OpenGLDevice::EndPresent(GPUSwapChain* swap_chain, bool explicit_present, u
DebugAssert(m_current_fbo == 0); DebugAssert(m_current_fbo == 0);
if (swap_chain == m_main_swap_chain.get() && m_gpu_timing_enabled) if (swap_chain == m_main_swap_chain.get() && m_gpu_timing_enabled)
{
PopTimestampQuery(); PopTimestampQuery();
EndTimestampQuery();
}
m_gl_context->SwapBuffers(); m_gl_context->SwapBuffers();
if (swap_chain == m_main_swap_chain.get() && m_gpu_timing_enabled) if (swap_chain == m_main_swap_chain.get() && m_gpu_timing_enabled)
KickTimestampQuery(); StartTimestampQuery();
TrimTexturePool(); TrimTexturePool();
} }
@ -839,7 +844,7 @@ void OpenGLDevice::CreateTimestampQueries()
const auto GenQueries = gles ? glGenQueriesEXT : glGenQueries; const auto GenQueries = gles ? glGenQueriesEXT : glGenQueries;
GenQueries(static_cast<u32>(m_timestamp_queries.size()), m_timestamp_queries.data()); GenQueries(static_cast<u32>(m_timestamp_queries.size()), m_timestamp_queries.data());
KickTimestampQuery(); StartTimestampQuery();
} }
void OpenGLDevice::DestroyTimestampQueries() void OpenGLDevice::DestroyTimestampQueries()
@ -866,8 +871,7 @@ void OpenGLDevice::DestroyTimestampQueries()
void OpenGLDevice::PopTimestampQuery() void OpenGLDevice::PopTimestampQuery()
{ {
const bool gles = m_gl_context->IsGLES(); const bool gles = IsGLES();
if (gles) if (gles)
{ {
GLint disjoint = 0; GLint disjoint = 0;
@ -885,11 +889,10 @@ void OpenGLDevice::PopTimestampQuery()
} }
} }
while (m_waiting_timestamp_queries > 0)
{
const auto GetQueryObjectiv = gles ? glGetQueryObjectivEXT : glGetQueryObjectiv; const auto GetQueryObjectiv = gles ? glGetQueryObjectivEXT : glGetQueryObjectiv;
const auto GetQueryObjectui64v = gles ? glGetQueryObjectui64vEXT : glGetQueryObjectui64v; const auto GetQueryObjectui64v = gles ? glGetQueryObjectui64vEXT : glGetQueryObjectui64v;
while (m_waiting_timestamp_queries > 0)
{
GLint available = 0; GLint available = 0;
GetQueryObjectiv(m_timestamp_queries[m_read_timestamp_query], GL_QUERY_RESULT_AVAILABLE, &available); GetQueryObjectiv(m_timestamp_queries[m_read_timestamp_query], GL_QUERY_RESULT_AVAILABLE, &available);
if (!available) if (!available)
@ -901,10 +904,25 @@ void OpenGLDevice::PopTimestampQuery()
m_read_timestamp_query = (m_read_timestamp_query + 1) % NUM_TIMESTAMP_QUERIES; m_read_timestamp_query = (m_read_timestamp_query + 1) % NUM_TIMESTAMP_QUERIES;
m_waiting_timestamp_queries--; m_waiting_timestamp_queries--;
} }
}
void OpenGLDevice::StartTimestampQuery()
{
if (m_timestamp_query_started || m_waiting_timestamp_queries == NUM_TIMESTAMP_QUERIES)
return;
const bool gles = IsGLES();
const auto BeginQuery = gles ? glBeginQueryEXT : glBeginQuery;
BeginQuery(GL_TIME_ELAPSED, m_timestamp_queries[m_write_timestamp_query]);
m_timestamp_query_started = true;
}
void OpenGLDevice::EndTimestampQuery()
{
if (m_timestamp_query_started) if (m_timestamp_query_started)
{ {
const auto EndQuery = gles ? glEndQueryEXT : glEndQuery; const auto EndQuery = IsGLES() ? glEndQueryEXT : glEndQuery;
EndQuery(GL_TIME_ELAPSED); EndQuery(GL_TIME_ELAPSED);
m_write_timestamp_query = (m_write_timestamp_query + 1) % NUM_TIMESTAMP_QUERIES; m_write_timestamp_query = (m_write_timestamp_query + 1) % NUM_TIMESTAMP_QUERIES;
@ -913,18 +931,6 @@ void OpenGLDevice::PopTimestampQuery()
} }
} }
void OpenGLDevice::KickTimestampQuery()
{
if (m_timestamp_query_started || m_waiting_timestamp_queries == NUM_TIMESTAMP_QUERIES)
return;
const bool gles = m_gl_context->IsGLES();
const auto BeginQuery = gles ? glBeginQueryEXT : glBeginQuery;
BeginQuery(GL_TIME_ELAPSED, m_timestamp_queries[m_write_timestamp_query]);
m_timestamp_query_started = true;
}
bool OpenGLDevice::SetGPUTimingEnabled(bool enabled) bool OpenGLDevice::SetGPUTimingEnabled(bool enabled)
{ {
if (m_gpu_timing_enabled == enabled) if (m_gpu_timing_enabled == enabled)

View File

@ -177,7 +177,8 @@ private:
void CreateTimestampQueries(); void CreateTimestampQueries();
void DestroyTimestampQueries(); void DestroyTimestampQueries();
void PopTimestampQuery(); void PopTimestampQuery();
void KickTimestampQuery(); void StartTimestampQuery();
void EndTimestampQuery();
GLuint CreateProgramFromPipelineCache(const OpenGLPipeline::ProgramCacheItem& it, GLuint CreateProgramFromPipelineCache(const OpenGLPipeline::ProgramCacheItem& it,
const GPUPipeline::GraphicsConfig& plconfig); const GPUPipeline::GraphicsConfig& plconfig);