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>
|
||||
<ClInclude Include="BoundingBox.h" />
|
||||
<ClInclude Include="FramebufferManager.h" />
|
||||
<ClInclude Include="GPUTimer.h" />
|
||||
<ClInclude Include="PerfQuery.h" />
|
||||
<ClInclude Include="PostProcessing.h" />
|
||||
<ClInclude Include="ProgramShaderCache.h" />
|
||||
|
@ -79,4 +80,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -90,8 +90,11 @@
|
|||
</ClInclude>
|
||||
<ClInclude Include="SamplerCache.h" />
|
||||
<ClInclude Include="VideoBackend.h" />
|
||||
<ClInclude Include="GPUTimer.h">
|
||||
<Filter>GLUtil</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -16,6 +16,7 @@
|
|||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "VideoBackends/OGL/FramebufferManager.h"
|
||||
#include "VideoBackends/OGL/GPUTimer.h"
|
||||
#include "VideoBackends/OGL/ProgramShaderCache.h"
|
||||
#include "VideoBackends/OGL/Render.h"
|
||||
#include "VideoBackends/OGL/SamplerCache.h"
|
||||
|
@ -62,6 +63,8 @@ struct TextureDecodingProgramInfo
|
|||
bool valid = false;
|
||||
};
|
||||
|
||||
//#define TIME_TEXTURE_DECODING 1
|
||||
|
||||
static std::map<std::pair<u32, u32>, TextureDecodingProgramInfo> s_texture_decoding_program_info;
|
||||
static std::array<GLuint, TextureConversionShader::BUFFER_FORMAT_COUNT>
|
||||
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())
|
||||
return;
|
||||
|
||||
#ifdef TIME_TEXTURE_DECODING
|
||||
GPUTimer timer;
|
||||
#endif
|
||||
|
||||
// Copy to GPU-visible buffer, aligned to the data type.
|
||||
auto info = iter->second;
|
||||
u32 bytes_per_buffer_elem =
|
||||
|
@ -775,5 +782,10 @@ void TextureCache::DecodeTextureOnGPU(TCacheEntryBase* entry, u32 dst_level, con
|
|||
glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
|
||||
|
||||
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