OGL: Add GPUTimer class for measuring execution time of a draw/dispatch
This commit is contained in:
parent
b01bcb80f4
commit
02f887ede0
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/GL/GLExtensions/GLExtensions.h"
|
||||||
|
|
||||||
|
#ifndef GL_TIME_ELAPSED
|
||||||
|
#define GL_TIME_ELAPSED 0x88BF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OGL
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This class can be used to measure the time it takes for the GPU to perform a draw call
|
||||||
|
* or compute dispatch. To use:
|
||||||
|
*
|
||||||
|
* - Create an instance of GPUTimer before issuing the draw call.
|
||||||
|
* (this can be before or after any binding that needs to be done)
|
||||||
|
*
|
||||||
|
* - (optionally) call Begin(). This is not needed for a single draw call.
|
||||||
|
*
|
||||||
|
* - Issue the draw call or compute dispatch as normal.
|
||||||
|
*
|
||||||
|
* - (optionally) call End(). This is not necessary for a single draw call.
|
||||||
|
*
|
||||||
|
* - Call GetTime{Seconds,Milliseconds,Nanoseconds} to determine how long the operation
|
||||||
|
* took to execute on the GPU.
|
||||||
|
*
|
||||||
|
* NOTE: When the timer is read back, this will force a GL flush, so the more often a timer is used,
|
||||||
|
* the larger of a performance impact it will have. Only one timer can be active at any time, due to
|
||||||
|
* using GL_TIME_ELAPSED. This is not enforced by the class, however.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class GPUTimer final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GPUTimer()
|
||||||
|
{
|
||||||
|
glGenQueries(1, &m_query_id);
|
||||||
|
Begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
~GPUTimer()
|
||||||
|
{
|
||||||
|
End();
|
||||||
|
glDeleteQueries(1, &m_query_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Begin()
|
||||||
|
{
|
||||||
|
if (m_started)
|
||||||
|
glEndQuery(GL_TIME_ELAPSED);
|
||||||
|
|
||||||
|
glBeginQuery(GL_TIME_ELAPSED, m_query_id);
|
||||||
|
m_started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void End()
|
||||||
|
{
|
||||||
|
if (!m_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
glEndQuery(GL_TIME_ELAPSED);
|
||||||
|
m_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetTimeSeconds()
|
||||||
|
{
|
||||||
|
GetResult();
|
||||||
|
return static_cast<double>(m_result) / 1000000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetTimeMilliseconds()
|
||||||
|
{
|
||||||
|
GetResult();
|
||||||
|
return static_cast<double>(m_result) / 1000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetTimeNanoseconds()
|
||||||
|
{
|
||||||
|
GetResult();
|
||||||
|
return m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GetResult()
|
||||||
|
{
|
||||||
|
if (m_has_result)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_started)
|
||||||
|
End();
|
||||||
|
|
||||||
|
glGetQueryObjectuiv(m_query_id, GL_QUERY_RESULT, &m_result);
|
||||||
|
m_has_result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint m_query_id;
|
||||||
|
GLuint m_result = 0;
|
||||||
|
bool m_started = false;
|
||||||
|
bool m_has_result = false;
|
||||||
|
};
|
||||||
|
} // namespace OGL
|
|
@ -53,6 +53,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="BoundingBox.h" />
|
<ClInclude Include="BoundingBox.h" />
|
||||||
<ClInclude Include="FramebufferManager.h" />
|
<ClInclude Include="FramebufferManager.h" />
|
||||||
|
<ClInclude Include="GPUTimer.h" />
|
||||||
<ClInclude Include="PerfQuery.h" />
|
<ClInclude Include="PerfQuery.h" />
|
||||||
<ClInclude Include="PostProcessing.h" />
|
<ClInclude Include="PostProcessing.h" />
|
||||||
<ClInclude Include="ProgramShaderCache.h" />
|
<ClInclude Include="ProgramShaderCache.h" />
|
||||||
|
@ -79,4 +80,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -90,8 +90,11 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="SamplerCache.h" />
|
<ClInclude Include="SamplerCache.h" />
|
||||||
<ClInclude Include="VideoBackend.h" />
|
<ClInclude Include="VideoBackend.h" />
|
||||||
|
<ClInclude Include="GPUTimer.h">
|
||||||
|
<Filter>GLUtil</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="CMakeLists.txt" />
|
<Text Include="CMakeLists.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -16,6 +16,7 @@
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
|
|
||||||
#include "VideoBackends/OGL/FramebufferManager.h"
|
#include "VideoBackends/OGL/FramebufferManager.h"
|
||||||
|
#include "VideoBackends/OGL/GPUTimer.h"
|
||||||
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
||||||
#include "VideoBackends/OGL/Render.h"
|
#include "VideoBackends/OGL/Render.h"
|
||||||
#include "VideoBackends/OGL/SamplerCache.h"
|
#include "VideoBackends/OGL/SamplerCache.h"
|
||||||
|
@ -62,6 +63,8 @@ struct TextureDecodingProgramInfo
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//#define TIME_TEXTURE_DECODING 1
|
||||||
|
|
||||||
static std::map<std::pair<u32, u32>, TextureDecodingProgramInfo> s_texture_decoding_program_info;
|
static std::map<std::pair<u32, u32>, TextureDecodingProgramInfo> s_texture_decoding_program_info;
|
||||||
static std::array<GLuint, TextureConversionShader::BUFFER_FORMAT_COUNT>
|
static std::array<GLuint, TextureConversionShader::BUFFER_FORMAT_COUNT>
|
||||||
s_texture_decoding_buffer_views;
|
s_texture_decoding_buffer_views;
|
||||||
|
@ -713,6 +716,10 @@ void TextureCache::DecodeTextureOnGPU(TCacheEntryBase* entry, u32 dst_level, con
|
||||||
if (iter == s_texture_decoding_program_info.end())
|
if (iter == s_texture_decoding_program_info.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef TIME_TEXTURE_DECODING
|
||||||
|
GPUTimer timer;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy to GPU-visible buffer, aligned to the data type.
|
// Copy to GPU-visible buffer, aligned to the data type.
|
||||||
auto info = iter->second;
|
auto info = iter->second;
|
||||||
u32 bytes_per_buffer_elem =
|
u32 bytes_per_buffer_elem =
|
||||||
|
@ -775,5 +782,10 @@ void TextureCache::DecodeTextureOnGPU(TCacheEntryBase* entry, u32 dst_level, con
|
||||||
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
|
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
|
||||||
|
|
||||||
TextureCache::SetStage();
|
TextureCache::SetStage();
|
||||||
|
|
||||||
|
#ifdef TIME_TEXTURE_DECODING
|
||||||
|
WARN_LOG(VIDEO, "Decode texture format %u size %ux%u took %.4fms", static_cast<u32>(format),
|
||||||
|
width, height, timer.GetTimeMilliseconds());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue