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()
{
m_context->Flush();
EndTimestampQuery();
TrimTexturePool();
}
void D3D11Device::WaitForGPUIdle()
{
m_context->Flush();
EndTimestampQuery();
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
// 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)
{
PopTimestampQuery();
EndTimestampQuery();
}
m_context->ClearRenderTargetView(SC->GetRTV(), GSVector4::rgba32(clear_color).F32);
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);
if (SC == m_main_swap_chain.get() && SC->GetVSyncMode() != GPUVSyncMode::FIFO && m_gpu_timing_enabled)
{
PopTimestampQuery();
EndTimestampQuery();
}
const UINT sync_interval = static_cast<UINT>(SC->GetVSyncMode() == GPUVSyncMode::FIFO);
const UINT flags =
@ -698,7 +706,7 @@ void D3D11Device::EndPresent(GPUSwapChain* swap_chain, bool explicit_present, u6
SC->GetSwapChain()->Present(sync_interval, flags);
if (m_gpu_timing_enabled)
KickTimestampQuery();
StartTimestampQuery();
TrimTexturePool();
}
@ -724,7 +732,7 @@ bool D3D11Device::CreateTimestampQueries()
}
}
KickTimestampQuery();
StartTimestampQuery();
return true;
}
@ -783,7 +791,10 @@ void D3D11Device::PopTimestampQuery()
}
}
}
}
void D3D11Device::EndTimestampQuery()
{
if (m_timestamp_query_started)
{
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)
return;
@ -815,7 +826,7 @@ bool D3D11Device::SetGPUTimingEnabled(bool enabled)
if (!CreateTimestampQueries())
return false;
KickTimestampQuery();
StartTimestampQuery();
return true;
}
else

View File

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

View File

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

View File

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