Implement GPU duration counters on OpenGL

This commit is contained in:
baldurk committed 2015-01-29 10:17:51 +00:00
1 parent 96d0f472e0
commit c5fafbed5d
9 files changed
+267 -23

No files matched your search

+1
View File
@@ -38,6 +38,7 @@ driver/gl/gl_common.o \
driver/gl/gl_driver.o \
driver/gl/gl_manager.o \
driver/gl/gl_debug.o \
driver/gl/gl_counters.o \
driver/gl/gl_replay.o \
driver/gl/gl_replay_linux.o \
driver/gl/gl_shader_refl.o \
+202
View File
@@ -0,0 +1,202 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "gl_replay.h"
#include "gl_driver.h"
#include "gl_resources.h"
void GLReplay::PreContextInitCounters()
{
}
void GLReplay::PostContextInitCounters()
{
}
void GLReplay::PreContextShutdownCounters()
{
}
void GLReplay::PostContextShutdownCounters()
{
}
vector<uint32_t> GLReplay::EnumerateCounters()
{
vector<uint32_t> ret;
ret.push_back(eCounter_EventGPUDuration);
return ret;
}
void GLReplay::DescribeCounter(uint32_t counterID, CounterDescription &desc)
{
desc.counterID = counterID;
if(counterID == eCounter_EventGPUDuration)
{
desc.name = "GPU Duration";
desc.description = "Time taken for this event on the GPU, as measured by delta between two GPU timestamps.";
desc.resultByteWidth = 8;
desc.resultCompType = eCompType_Double;
desc.units = eUnits_Seconds;
}
else
{
desc.name = "Unknown";
desc.description = "Unknown counter ID";
desc.resultByteWidth = 0;
desc.resultCompType = eCompType_None;
desc.units = eUnits_Absolute;
}
}
struct GPUTimer
{
GLuint obj;
uint32_t eventID;
};
struct CounterContext
{
uint32_t frameID;
uint32_t minEID;
uint32_t maxEID;
uint32_t eventStart;
vector<GPUTimer> timers;
int reuseIdx;
};
void GLReplay::FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode)
{
if(drawnode.children.empty()) return;
for(size_t i=0; i < drawnode.children.size(); i++)
{
const FetchDrawcall &d = drawnode.children[i].draw;
FillTimers(ctx, drawnode.children[i]);
if(d.events.count == 0) continue;
GPUTimer *timer = NULL;
bool includeEvent = (d.eventID >= ctx.minEID && d.eventID <= ctx.maxEID);
if(includeEvent)
{
if(ctx.reuseIdx == -1)
{
ctx.timers.push_back(GPUTimer());
timer = &ctx.timers.back();
timer->eventID = d.eventID;
timer->obj = 0;
m_pDriver->glGenQueries(1, &timer->obj);
}
else
{
timer = &ctx.timers[ctx.reuseIdx++];
}
}
m_pDriver->ReplayLog(ctx.frameID, ctx.eventStart, d.eventID, eReplay_WithoutDraw);
if(includeEvent && timer->obj)
{
m_pDriver->glBeginQuery(eGL_TIME_ELAPSED, timer->obj);
m_pDriver->ReplayLog(ctx.frameID, ctx.eventStart, d.eventID, eReplay_OnlyDraw);
m_pDriver->glEndQuery(eGL_TIME_ELAPSED);
}
else
{
m_pDriver->ReplayLog(ctx.frameID, ctx.eventStart, d.eventID, eReplay_OnlyDraw);
}
ctx.eventStart = d.eventID+1;
}
}
vector<CounterResult> GLReplay::FetchCounters(uint32_t frameID, uint32_t minEventID, uint32_t maxEventID, const vector<uint32_t> &counters)
{
vector<CounterResult> ret;
if(counters.empty())
{
RDCERR("No counters specified to FetchCounters");
return ret;
}
MakeCurrentReplayContext(&m_ReplayCtx);
uint32_t counterID = counters[0];
RDCASSERT(counters.size() == 1);
RDCASSERT(counterID == eCounter_EventGPUDuration);
SCOPED_TIMER("Fetch Counters over %u-%u for %u", minEventID, maxEventID, counterID);
CounterContext ctx;
ctx.frameID = frameID;
ctx.minEID = minEventID;
ctx.maxEID = maxEventID;
for(int loop=0; loop < 1; loop++)
{
ctx.eventStart = 0;
ctx.reuseIdx = loop == 0 ? -1 : 0;
FillTimers(ctx, m_pDriver->GetRootDraw());
double nanosToSecs = 1.0/1000000000.0;
GLuint prevbind = 0;
m_pDriver->glGetIntegerv(eGL_QUERY_BUFFER_BINDING, (GLint *)&prevbind);
m_pDriver->glBindBuffer(eGL_QUERY_BUFFER, 0);
for(size_t i=0; i < ctx.timers.size(); i++)
{
if(ctx.timers[i].obj)
{
GLuint elapsed = 0;
m_pDriver->glGetQueryObjectuiv(ctx.timers[i].obj, eGL_QUERY_RESULT, &elapsed);
double duration = double(elapsed)*nanosToSecs;
ret.push_back(CounterResult(ctx.timers[i].eventID, counterID, duration));
}
else
{
ret.push_back(CounterResult(ctx.timers[i].eventID, counterID, 0.0));
}
}
m_pDriver->glBindBuffer(eGL_QUERY_BUFFER, prevbind);
}
for(size_t i=0; i < ctx.timers.size(); i++)
m_pDriver->glDeleteQueries(1, &ctx.timers[i].obj);
return ret;
}
+2
View File
@@ -373,6 +373,8 @@ class WrappedOpenGL
vector<FetchFrameRecord> &GetFrameRecord() { return m_FrameRecord; }
FetchAPIEvent GetEvent(uint32_t eventID);
const DrawcallTreeNode &GetRootDraw() { return m_ParentDrawcall; }
const FetchDrawcall *GetDrawcall(uint32_t frameID, uint32_t eventID);
void CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams, bool core);
+6 -22
View File
@@ -44,6 +44,8 @@ GLReplay::GLReplay()
void GLReplay::Shutdown()
{
PreContextShutdownCounters();
DeleteDebugData();
DestroyOutputWindow(m_DebugID);
@@ -51,6 +53,8 @@ void GLReplay::Shutdown()
CloseReplayContext();
delete m_pDriver;
GLReplay::PostContextShutdownCounters();
}
#pragma region Implemented
@@ -122,6 +126,8 @@ void GLReplay::SetReplayData(GLWindowingData data)
m_ReplayCtx = data;
InitDebugData();
PostContextInitCounters();
}
void GLReplay::InitCallstackResolver()
@@ -2199,28 +2205,6 @@ void GLReplay::RemoveReplacement(ResourceId id)
RDCUNIMPLEMENTED("RemoveReplacement");
}
vector<uint32_t> GLReplay::EnumerateCounters()
{
GLNOTIMP("EnumerateCounters");
return vector<uint32_t>();
}
void GLReplay::DescribeCounter(uint32_t counterID, CounterDescription &desc)
{
desc.counterID = counterID;
desc.name = "Unsupported";
desc.description = "Counters are not implemented on OpenGL yet";
desc.resultByteWidth = 0;
desc.resultCompType = eCompType_None;
desc.units = eUnits_Absolute;
}
vector<CounterResult> GLReplay::FetchCounters(uint32_t frameID, uint32_t minEventID, uint32_t maxEventID, const vector<uint32_t> &counters)
{
RDCUNIMPLEMENTED("FetchCounters");
return vector<CounterResult>();
}
void GLReplay::BuildTargetShader(string source, string entry, const uint32_t compileFlags, ShaderStageType type, ResourceId *id, string *errors)
{
RDCUNIMPLEMENTED("BuildTargetShader");
+15 -1
View File
@@ -34,6 +34,8 @@ using std::pair;
using std::map;
class WrappedOpenGL;
struct CounterContext;
struct DrawcallTreeNode;
struct GLPostVSData
{
@@ -177,7 +179,12 @@ class GLReplay : public IReplayDriver
void InitCallstackResolver();
bool HasCallstacks();
Callstack::StackResolver *GetCallstackResolver();
// called before any context is created, to init any counters
static void PreContextInitCounters();
// called after any context is destroyed, to do corresponding shutdown of counters
static void PostContextShutdownCounters();
void SetReplayData(GLWindowingData data);
private:
void FillCBufferValue(WrappedOpenGL &gl, GLuint prog, bool bufferBacked, bool rowMajor, uint32_t offs, uint32_t matStride,
@@ -305,6 +312,13 @@ class GLReplay : public IReplayDriver
void InitDebugData();
void DeleteDebugData();
// called after the context is created, to init any counters
void PostContextInitCounters();
// called before the context is destroyed, to shutdown any counters
void PreContextShutdownCounters();
void FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode);
GLuint CreateShaderProgram(const char *vs, const char *ps, const char *gs = NULL);
GLuint CreateCShaderProgram(const char *cs);
+17
View File
@@ -248,6 +248,8 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
int attribs[64] = {0};
int i=0;
GLReplay::PreContextInitCounters();
attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
attribs[i++] = 4;
attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB;
@@ -273,6 +275,7 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(fbcfg == NULL)
{
XCloseDisplay(dpy);
GLReplay::PostContextShutdownCounters();
RDCERR("Couldn't choose default framebuffer config");
return eReplayCreate_APIInitFailed;
}
@@ -281,7 +284,9 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(ctx == NULL)
{
XFree(fbcfg);
XCloseDisplay(dpy);
GLReplay::PostContextShutdownCounters();
RDCERR("Couldn't create 4.3 context - RenderDoc requires OpenGL 4.3 availability");
return eReplayCreate_APIHardwareUnsupported;
}
@@ -299,7 +304,9 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
{
glXDestroyPbufferProc(dpy, pbuffer);
glXDestroyCtxProc(dpy, ctx);
XFree(fbcfg);
XCloseDisplay(dpy);
GLReplay::PostContextShutdownCounters();
RDCERR("Couldn't make pbuffer & context current");
return eReplayCreate_APIInitFailed;
}
@@ -310,6 +317,11 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(getInt == NULL || getStr == NULL)
{
RDCERR("Couldn't get glGetIntegerv (%p) or glGetStringi (%p) entry points", getInt, getStr);
glXDestroyPbufferProc(dpy, pbuffer);
glXDestroyCtxProc(dpy, ctx);
XFree(fbcfg);
XCloseDisplay(dpy);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIInitFailed;
}
else
@@ -334,6 +346,11 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(!found)
{
RDCERR("RenderDoc requires EXT_direct_state_access availability, and it is not reported. Try updating your drivers.");
glXDestroyPbufferProc(dpy, pbuffer);
glXDestroyCtxProc(dpy, ctx);
XFree(fbcfg);
XCloseDisplay(dpy);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIHardwareUnsupported;
}
}
+20
View File
@@ -343,6 +343,8 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
wglDeleteRC(rc);
ReleaseDC(w, dc);
DestroyWindow(w);
GLReplay::PreContextInitCounters();
// we don't use the default framebuffer (backbuffer) for anything, so we make it
// tiny and with no depth/stencil bits
@@ -361,6 +363,8 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(pf == 0)
{
RDCERR("Couldn't choose pixel format");
ReleaseDC(w, dc);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIInitFailed;
}
@@ -368,6 +372,8 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(res == FALSE)
{
RDCERR("Couldn't set pixel format");
ReleaseDC(w, dc);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIInitFailed;
}
@@ -387,6 +393,8 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(rc == NULL)
{
RDCERR("Couldn't create 4.3 RC - RenderDoc requires OpenGL 4.3 availability");
ReleaseDC(w, dc);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIHardwareUnsupported;
}
@@ -394,6 +402,10 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(res == FALSE)
{
RDCERR("Couldn't make 4.3 RC current");
wglMakeCurrentProc(NULL, NULL);
wglDeleteRC(rc);
ReleaseDC(w, dc);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIInitFailed;
}
@@ -403,6 +415,10 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(getInt == NULL || getStr == NULL)
{
RDCERR("Couldn't get glGetIntegerv (%p) or glGetStringi (%p) entry points", getInt, getStr);
wglMakeCurrentProc(NULL, NULL);
wglDeleteRC(rc);
ReleaseDC(w, dc);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIInitFailed;
}
else
@@ -427,6 +443,10 @@ ReplayCreateStatus GL_CreateReplayDevice(const char *logfile, IReplayDriver **dr
if(!found)
{
RDCERR("RenderDoc requires EXT_direct_state_access availability, and it is not reported. Try updating your drivers.");
wglMakeCurrentProc(NULL, NULL);
wglDeleteRC(rc);
ReleaseDC(w, dc);
GLReplay::PostContextShutdownCounters();
return eReplayCreate_APIHardwareUnsupported;
}
}
+1
View File
@@ -316,6 +316,7 @@
<ClCompile Include="driver\d3d11\shaders\dxbc_inspect.cpp" />
<ClCompile Include="driver\dxgi\dxgi_wrapped.cpp" />
<ClCompile Include="driver\gl\gl_common.cpp" />
<ClCompile Include="driver\gl\gl_counters.cpp" />
<ClCompile Include="driver\gl\gl_debug.cpp" />
<ClCompile Include="driver\gl\gl_driver.cpp" />
<ClCompile Include="driver\gl\gl_manager.cpp" />
+3
View File
@@ -548,6 +548,9 @@
<ClCompile Include="driver\d3d11\d3d11_counters.cpp">
<Filter>Drivers\D3D11</Filter>
</ClCompile>
<ClCompile Include="driver\gl\gl_counters.cpp">
<Filter>Drivers\OpenGL</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="os\win32\comexport.def">