mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-23 15:06:32 +00:00
Implemented OpenGL counters using pipeline stats and occlusion queries
Implemented OpenGL counters based on ARB_pipeline_statistics extension and occlusion queries. Because OpenGL doesn't seem to allow concurrent queries of the same type occlusion queries in the log are ignored when executing FetchCounters. Renamed GPUTimer to GPUQueries because D3D11 GPUTimer structure seems to be visible and creates conflicts on VS.
This commit is contained in:
committed by
Baldur Karlsson
parent
460f785a5b
commit
cba4e8aed2
@@ -508,11 +508,13 @@ enum GPUCounters
|
||||
eCounter_SamplesWritten,
|
||||
eCounter_VSInvocations,
|
||||
eCounter_HSInvocations,
|
||||
eCounter_TCSInvocations = eCounter_HSInvocations,
|
||||
eCounter_DSInvocations,
|
||||
eCounter_TESInvocations = eCounter_DSInvocations,
|
||||
eCounter_GSInvocations,
|
||||
eCounter_PSInvocations,
|
||||
eCounter_CSInvocations,
|
||||
eCounter_GLMaxCounters,
|
||||
|
||||
// IHV specific counters can be set above this point
|
||||
// with ranges reserved for each IHV
|
||||
|
||||
@@ -429,30 +429,56 @@ GLenum BufferEnum(size_t idx)
|
||||
|
||||
size_t QueryIdx(GLenum query)
|
||||
{
|
||||
size_t idx = 0;
|
||||
|
||||
switch(query)
|
||||
{
|
||||
case eGL_SAMPLES_PASSED: return 0;
|
||||
case eGL_ANY_SAMPLES_PASSED: return 1;
|
||||
case eGL_ANY_SAMPLES_PASSED_CONSERVATIVE: return 2;
|
||||
case eGL_PRIMITIVES_GENERATED: return 3;
|
||||
case eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return 4;
|
||||
case eGL_TIME_ELAPSED: return 5;
|
||||
case eGL_SAMPLES_PASSED: idx = 0; break;
|
||||
case eGL_ANY_SAMPLES_PASSED: idx = 1; break;
|
||||
case eGL_ANY_SAMPLES_PASSED_CONSERVATIVE: idx = 2; break;
|
||||
case eGL_PRIMITIVES_GENERATED: idx = 3; break;
|
||||
case eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: idx = 4; break;
|
||||
case eGL_TIME_ELAPSED: idx = 5; break;
|
||||
case eGL_VERTICES_SUBMITTED_ARB: idx = 6; break;
|
||||
case eGL_PRIMITIVES_SUBMITTED_ARB: idx = 7; break;
|
||||
case eGL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB: idx = 8; break;
|
||||
case eGL_CLIPPING_INPUT_PRIMITIVES_ARB: idx = 9; break;
|
||||
case eGL_CLIPPING_OUTPUT_PRIMITIVES_ARB: idx = 10; break;
|
||||
case eGL_VERTEX_SHADER_INVOCATIONS_ARB: idx = 11; break;
|
||||
case eGL_TESS_CONTROL_SHADER_PATCHES_ARB: idx = 12; break;
|
||||
case eGL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB: idx = 13; break;
|
||||
case eGL_GEOMETRY_SHADER_INVOCATIONS: idx = 14; break;
|
||||
case eGL_FRAGMENT_SHADER_INVOCATIONS_ARB: idx = 15; break;
|
||||
case eGL_COMPUTE_SHADER_INVOCATIONS_ARB: idx = 16; break;
|
||||
|
||||
default: RDCERR("Unexpected enum as query target: %s", ToStr::Get(query).c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
if(idx >= WrappedOpenGL::MAX_QUERIES)
|
||||
RDCERR("Query index for enum %s out of range %d", ToStr::Get(query).c_str(), idx);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
GLenum QueryEnum(size_t idx)
|
||||
{
|
||||
GLenum enums[] = {
|
||||
eGL_SAMPLES_PASSED,
|
||||
eGL_ANY_SAMPLES_PASSED,
|
||||
eGL_ANY_SAMPLES_PASSED_CONSERVATIVE,
|
||||
eGL_PRIMITIVES_GENERATED,
|
||||
eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
|
||||
eGL_TIME_ELAPSED,
|
||||
};
|
||||
GLenum enums[] = {eGL_SAMPLES_PASSED,
|
||||
eGL_ANY_SAMPLES_PASSED,
|
||||
eGL_ANY_SAMPLES_PASSED_CONSERVATIVE,
|
||||
eGL_PRIMITIVES_GENERATED,
|
||||
eGL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
|
||||
eGL_TIME_ELAPSED,
|
||||
eGL_VERTICES_SUBMITTED_ARB,
|
||||
eGL_PRIMITIVES_SUBMITTED_ARB,
|
||||
eGL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB,
|
||||
eGL_CLIPPING_INPUT_PRIMITIVES_ARB,
|
||||
eGL_CLIPPING_OUTPUT_PRIMITIVES_ARB,
|
||||
eGL_VERTEX_SHADER_INVOCATIONS_ARB,
|
||||
eGL_TESS_CONTROL_SHADER_PATCHES_ARB,
|
||||
eGL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB,
|
||||
eGL_GEOMETRY_SHADER_INVOCATIONS,
|
||||
eGL_FRAGMENT_SHADER_INVOCATIONS_ARB,
|
||||
eGL_COMPUTE_SHADER_INVOCATIONS_ARB};
|
||||
|
||||
if(idx < ARRAY_COUNT(enums))
|
||||
return enums[idx];
|
||||
|
||||
@@ -47,6 +47,18 @@ vector<uint32_t> GLReplay::EnumerateCounters()
|
||||
vector<uint32_t> ret;
|
||||
|
||||
ret.push_back(eCounter_EventGPUDuration);
|
||||
ret.push_back(eCounter_InputVerticesRead);
|
||||
ret.push_back(eCounter_IAPrimitives);
|
||||
ret.push_back(eCounter_GSPrimitives);
|
||||
ret.push_back(eCounter_RasterizerInvocations);
|
||||
ret.push_back(eCounter_RasterizedPrimitives);
|
||||
ret.push_back(eCounter_SamplesWritten);
|
||||
ret.push_back(eCounter_VSInvocations);
|
||||
ret.push_back(eCounter_TCSInvocations);
|
||||
ret.push_back(eCounter_TESInvocations);
|
||||
ret.push_back(eCounter_GSInvocations);
|
||||
ret.push_back(eCounter_PSInvocations);
|
||||
ret.push_back(eCounter_CSInvocations);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -55,39 +67,142 @@ void GLReplay::DescribeCounter(uint32_t counterID, CounterDescription &desc)
|
||||
{
|
||||
desc.counterID = counterID;
|
||||
|
||||
if(counterID == eCounter_EventGPUDuration)
|
||||
switch(counterID)
|
||||
{
|
||||
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;
|
||||
case 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;
|
||||
break;
|
||||
case eCounter_InputVerticesRead:
|
||||
desc.name = "Input Vertices Read";
|
||||
desc.description = "Number of vertices read by input assembler.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_IAPrimitives:
|
||||
desc.name = "Input Primitives";
|
||||
desc.description = "Number of primitives read by the input assembler.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_GSPrimitives:
|
||||
desc.name = "GS Primitives";
|
||||
desc.description = "Number of primitives output by a geometry shader.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_RasterizerInvocations:
|
||||
desc.name = "Rasterizer Invocations";
|
||||
desc.description = "Number of primitives that were sent to the rasterizer.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_RasterizedPrimitives:
|
||||
desc.name = "Rasterized Primitives";
|
||||
desc.description = "Number of primitives that were rendered.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_SamplesWritten:
|
||||
desc.name = "Samples Written";
|
||||
desc.description = "Number of samples that passed depth/stencil test.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_VSInvocations:
|
||||
desc.name = "VS Invocations";
|
||||
desc.description = "Number of times a vertex shader was invoked.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_GSInvocations:
|
||||
desc.name = "GS Invocations";
|
||||
desc.description = "Number of times a geometry shader was invoked.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_TCSInvocations:
|
||||
desc.name = "TCS Invocations";
|
||||
desc.description = "Number of times a tesselation control shader was invoked.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_TESInvocations:
|
||||
desc.name = "TES Invocations";
|
||||
desc.description = "Number of times a tesselation evaluation shader was invoked.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_PSInvocations:
|
||||
desc.name = "PS Invocations";
|
||||
desc.description = "Number of times a pixel shader was invoked.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
case eCounter_CSInvocations:
|
||||
desc.name = "CS Invocations";
|
||||
desc.description = "Number of times a compute shader was invoked.";
|
||||
desc.resultByteWidth = 8;
|
||||
desc.resultCompType = eCompType_UInt;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
default:
|
||||
desc.name = "Unknown";
|
||||
desc.description = "Unknown counter ID";
|
||||
desc.resultByteWidth = 0;
|
||||
desc.resultCompType = eCompType_None;
|
||||
desc.units = eUnits_Absolute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct GPUTimer
|
||||
struct GPUQueries
|
||||
{
|
||||
GLuint obj;
|
||||
GLuint obj[eCounter_GLMaxCounters];
|
||||
uint32_t eventID;
|
||||
};
|
||||
|
||||
struct CounterContext
|
||||
{
|
||||
uint32_t eventStart;
|
||||
vector<GPUTimer> timers;
|
||||
vector<GPUQueries> queries;
|
||||
int reuseIdx;
|
||||
};
|
||||
|
||||
void GLReplay::FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode)
|
||||
GLenum glCounters[] = {
|
||||
eGL_NONE, // Undefined!!
|
||||
eGL_TIME_ELAPSED, // eCounter_EventGPUDuration
|
||||
eGL_VERTICES_SUBMITTED_ARB, // eCounter_InputVerticesRead
|
||||
eGL_PRIMITIVES_SUBMITTED_ARB, // eCounter_IAPrimitives
|
||||
eGL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB, // eCounter_GSPrimitives
|
||||
eGL_CLIPPING_INPUT_PRIMITIVES_ARB, // eCounter_RasterizerInvocations
|
||||
eGL_CLIPPING_OUTPUT_PRIMITIVES_ARB, // eCounter_RasterizedPrimitives
|
||||
eGL_SAMPLES_PASSED, // eCounter_SamplesWritten
|
||||
eGL_VERTEX_SHADER_INVOCATIONS_ARB, // eCounter_VSInvocations
|
||||
eGL_TESS_CONTROL_SHADER_PATCHES_ARB, // eCounter_TCSInvocations
|
||||
eGL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB, // eCounter_TESInvocations
|
||||
eGL_GEOMETRY_SHADER_INVOCATIONS, // eCounter_GSInvocations
|
||||
eGL_FRAGMENT_SHADER_INVOCATIONS_ARB, // eCounter_PSInvocations
|
||||
eGL_COMPUTE_SHADER_INVOCATIONS_ARB // eCounter_CSInvocations
|
||||
};
|
||||
|
||||
void GLReplay::FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode,
|
||||
const vector<uint32_t> &counters)
|
||||
{
|
||||
if(drawnode.children.empty())
|
||||
return;
|
||||
@@ -95,42 +210,55 @@ void GLReplay::FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode)
|
||||
for(size_t i = 0; i < drawnode.children.size(); i++)
|
||||
{
|
||||
const FetchDrawcall &d = drawnode.children[i].draw;
|
||||
FillTimers(ctx, drawnode.children[i]);
|
||||
FillTimers(ctx, drawnode.children[i], counters);
|
||||
|
||||
if(d.events.count == 0)
|
||||
continue;
|
||||
|
||||
GPUTimer *timer = NULL;
|
||||
GPUQueries *queries = NULL;
|
||||
|
||||
{
|
||||
if(ctx.reuseIdx == -1)
|
||||
{
|
||||
ctx.timers.push_back(GPUTimer());
|
||||
ctx.queries.push_back(GPUQueries());
|
||||
|
||||
timer = &ctx.timers.back();
|
||||
timer->eventID = d.eventID;
|
||||
timer->obj = 0;
|
||||
queries = &ctx.queries.back();
|
||||
queries->eventID = d.eventID;
|
||||
for(uint32_t q = 0; q < eCounter_GLMaxCounters; q++)
|
||||
queries->obj[q] = 0;
|
||||
|
||||
m_pDriver->glGenQueries(1, &timer->obj);
|
||||
for(uint32_t c = 0; c < counters.size(); c++)
|
||||
{
|
||||
m_pDriver->glGenQueries(1, &queries->obj[counters[c]]);
|
||||
if(m_pDriver->glGetError())
|
||||
queries->obj[counters[c]] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
timer = &ctx.timers[ctx.reuseIdx++];
|
||||
queries = &ctx.queries[ctx.reuseIdx++];
|
||||
}
|
||||
}
|
||||
|
||||
m_pDriver->ReplayLog(ctx.eventStart, d.eventID, eReplay_WithoutDraw);
|
||||
|
||||
if(timer->obj)
|
||||
{
|
||||
m_pDriver->glBeginQuery(eGL_TIME_ELAPSED, timer->obj);
|
||||
m_pDriver->ReplayLog(ctx.eventStart, d.eventID, eReplay_OnlyDraw);
|
||||
m_pDriver->glEndQuery(eGL_TIME_ELAPSED);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pDriver->ReplayLog(ctx.eventStart, d.eventID, eReplay_OnlyDraw);
|
||||
}
|
||||
// Reverse order so that Timer counter is queried the last.
|
||||
for(int32_t q = (eCounter_GLMaxCounters - 1); q >= 0; q--)
|
||||
if(queries->obj[q])
|
||||
{
|
||||
m_pDriver->glBeginQuery(glCounters[q], queries->obj[q]);
|
||||
if(m_pDriver->glGetError())
|
||||
{
|
||||
m_pDriver->glDeleteQueries(1, &queries->obj[q]);
|
||||
queries->obj[q] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_pDriver->ReplayLog(ctx.eventStart, d.eventID, eReplay_OnlyDraw);
|
||||
|
||||
for(uint32_t q = 0; q < eCounter_GLMaxCounters; q++)
|
||||
if(queries->obj[q])
|
||||
m_pDriver->glEndQuery(glCounters[q]);
|
||||
|
||||
ctx.eventStart = d.eventID + 1;
|
||||
}
|
||||
@@ -148,19 +276,15 @@ vector<CounterResult> GLReplay::FetchCounters(const vector<uint32_t> &counters)
|
||||
|
||||
MakeCurrentReplayContext(&m_ReplayCtx);
|
||||
|
||||
uint32_t counterID = counters[0];
|
||||
RDCASSERT(counters.size() == 1);
|
||||
RDCASSERT(counterID == eCounter_EventGPUDuration);
|
||||
|
||||
SCOPED_TIMER("Fetch Counters for %u", counterID);
|
||||
|
||||
CounterContext ctx;
|
||||
|
||||
for(int loop = 0; loop < 1; loop++)
|
||||
{
|
||||
ctx.eventStart = 0;
|
||||
ctx.reuseIdx = loop == 0 ? -1 : 0;
|
||||
FillTimers(ctx, m_pDriver->GetRootDraw());
|
||||
m_pDriver->SetFetchCounters(true);
|
||||
FillTimers(ctx, m_pDriver->GetRootDraw(), counters);
|
||||
m_pDriver->SetFetchCounters(false);
|
||||
|
||||
double nanosToSecs = 1.0 / 1000000000.0;
|
||||
|
||||
@@ -168,28 +292,42 @@ vector<CounterResult> GLReplay::FetchCounters(const vector<uint32_t> &counters)
|
||||
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++)
|
||||
for(size_t i = 0; i < ctx.queries.size(); i++)
|
||||
{
|
||||
if(ctx.timers[i].obj)
|
||||
for(uint32_t c = 0; c < counters.size(); c++)
|
||||
{
|
||||
GLuint elapsed = 0;
|
||||
m_pDriver->glGetQueryObjectuiv(ctx.timers[i].obj, eGL_QUERY_RESULT, &elapsed);
|
||||
if(ctx.queries[i].obj[counters[c]])
|
||||
{
|
||||
GLuint64 data = 0;
|
||||
m_pDriver->glGetQueryObjectui64v(ctx.queries[i].obj[counters[c]], eGL_QUERY_RESULT, &data);
|
||||
|
||||
double duration = double(elapsed) * nanosToSecs;
|
||||
double duration = double(data) * nanosToSecs;
|
||||
|
||||
ret.push_back(CounterResult(ctx.timers[i].eventID, counterID, duration));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.push_back(CounterResult(ctx.timers[i].eventID, counterID, 0.0));
|
||||
if(m_pDriver->glGetError())
|
||||
{
|
||||
data = (uint64_t)-1;
|
||||
duration = -1;
|
||||
}
|
||||
|
||||
if(counters[c] == eCounter_EventGPUDuration)
|
||||
{
|
||||
ret.push_back(CounterResult(ctx.queries[i].eventID, eCounter_EventGPUDuration, duration));
|
||||
}
|
||||
else
|
||||
ret.push_back(CounterResult(ctx.queries[i].eventID, counters[c], data));
|
||||
}
|
||||
else
|
||||
ret.push_back(CounterResult(ctx.queries[i].eventID, counters[c], (uint64_t)-1));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
for(size_t i = 0; i < ctx.queries.size(); i++)
|
||||
for(uint32_t c = 0; c < counters.size(); c++)
|
||||
if(ctx.queries[i].obj[counters[c]])
|
||||
m_pDriver->glDeleteQueries(1, &ctx.queries[i].obj[counters[c]]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -739,6 +739,8 @@ WrappedOpenGL::WrappedOpenGL(const char *logfile, const GLHookSet &funcs) : m_Re
|
||||
m_FirstEventID = 0;
|
||||
m_LastEventID = ~0U;
|
||||
|
||||
m_FetchCounters = false;
|
||||
|
||||
RDCEraseEl(m_ActiveQueries);
|
||||
m_ActiveConditional = false;
|
||||
m_ActiveFeedback = false;
|
||||
|
||||
@@ -156,7 +156,16 @@ private:
|
||||
|
||||
vector<GLWindowingData> m_LastContexts;
|
||||
|
||||
bool m_ActiveQueries[8][8]; // first index type, second index (for some, always 0)
|
||||
public:
|
||||
enum
|
||||
{
|
||||
MAX_QUERIES = 17,
|
||||
MAX_QUERY_INDICES = 8
|
||||
};
|
||||
|
||||
private:
|
||||
bool m_ActiveQueries[MAX_QUERIES]
|
||||
[MAX_QUERY_INDICES]; // first index type, second index (for some, always 0)
|
||||
bool m_ActiveConditional;
|
||||
bool m_ActiveFeedback;
|
||||
|
||||
@@ -221,6 +230,8 @@ private:
|
||||
|
||||
map<ResourceId, vector<EventUsage> > m_ResourceUses;
|
||||
|
||||
bool m_FetchCounters;
|
||||
|
||||
// buffer used
|
||||
vector<byte> m_ScratchBuf;
|
||||
|
||||
@@ -484,6 +495,7 @@ public:
|
||||
GLReplay *GetReplay() { return &m_Replay; }
|
||||
void *GetCtx();
|
||||
|
||||
void SetFetchCounters(bool in) { m_FetchCounters = in; };
|
||||
const GLHookSet &GetHookset() { return m_Real; }
|
||||
void SetDebugMsgContext(const char *context) { m_DebugMsgContext = context; }
|
||||
void AddDebugMessage(DebugMessage msg)
|
||||
|
||||
@@ -382,7 +382,8 @@ private:
|
||||
// called before the context is destroyed, to shutdown any counters
|
||||
void PreContextShutdownCounters();
|
||||
|
||||
void FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode);
|
||||
void FillTimers(CounterContext &ctx, const DrawcallTreeNode &drawnode,
|
||||
const vector<uint32_t> &counters);
|
||||
|
||||
GLuint CreateShaderProgram(const vector<string> &vs, const vector<string> &fs,
|
||||
const vector<string> &gs);
|
||||
|
||||
@@ -262,8 +262,12 @@ bool WrappedOpenGL::Serialise_glBeginQuery(GLenum target, GLuint qid)
|
||||
|
||||
if(m_State < WRITING)
|
||||
{
|
||||
m_Real.glBeginQuery(Target, GetResourceManager()->GetLiveResource(id).name);
|
||||
m_ActiveQueries[QueryIdx(Target)][0] = true;
|
||||
// Queries in the log interfere with the queries from FetchCounters.
|
||||
if(!m_FetchCounters)
|
||||
{
|
||||
m_Real.glBeginQuery(Target, GetResourceManager()->GetLiveResource(id).name);
|
||||
m_ActiveQueries[QueryIdx(Target)][0] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -272,6 +276,8 @@ bool WrappedOpenGL::Serialise_glBeginQuery(GLenum target, GLuint qid)
|
||||
void WrappedOpenGL::glBeginQuery(GLenum target, GLuint id)
|
||||
{
|
||||
m_Real.glBeginQuery(target, id);
|
||||
if(m_ActiveQueries[QueryIdx(target)][0])
|
||||
RDCLOG("Query already active %s", ToStr::Get(target).c_str());
|
||||
m_ActiveQueries[QueryIdx(target)][0] = true;
|
||||
|
||||
if(m_State == WRITING_CAPFRAME)
|
||||
@@ -320,8 +326,12 @@ bool WrappedOpenGL::Serialise_glEndQuery(GLenum target)
|
||||
|
||||
if(m_State < WRITING)
|
||||
{
|
||||
m_ActiveQueries[QueryIdx(Target)][0] = false;
|
||||
m_Real.glEndQuery(Target);
|
||||
// Queries in the log interfere with the queries from FetchCounters.
|
||||
if(!m_FetchCounters)
|
||||
{
|
||||
m_ActiveQueries[QueryIdx(Target)][0] = false;
|
||||
m_Real.glEndQuery(Target);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user