From 9015b139c0195a6f1222e08ba83fbb4c9c260972 Mon Sep 17 00:00:00 2001 From: Baldur Karlsson Date: Wed, 18 Jun 2014 16:07:58 +0100 Subject: [PATCH] Add query and sync object handling. * Sync objects need special handling because the identifier is an opaque pointer and so we can't use the existing GLResource stuff. Instead to handle this, we assign a GLuint ourselves and keep a mapping around to map GLuint<->GLsync. Everything else works as usual from the GLuint --- renderdoc/Makefile | 1 + renderdoc/driver/gl/gl_common.h | 8 + renderdoc/driver/gl/gl_driver.cpp | 8 + renderdoc/driver/gl/gl_driver.h | 14 + renderdoc/driver/gl/gl_hookset.h | 10 + renderdoc/driver/gl/gl_hookset_defs.h | 20 ++ renderdoc/driver/gl/gl_manager.h | 27 +- renderdoc/driver/gl/gl_resources.h | 4 + renderdoc/driver/gl/wrappers/gl_get_funcs.cpp | 10 + .../driver/gl/wrappers/gl_query_funcs.cpp | 256 ++++++++++++++++++ renderdoc/renderdoc.vcxproj | 1 + renderdoc/renderdoc.vcxproj.filters | 3 + 12 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 renderdoc/driver/gl/wrappers/gl_query_funcs.cpp diff --git a/renderdoc/Makefile b/renderdoc/Makefile index 2e1ea0d34..80bf1a9d4 100644 --- a/renderdoc/Makefile +++ b/renderdoc/Makefile @@ -48,6 +48,7 @@ driver/gl/wrappers/gl_debug_funcs.o \ driver/gl/wrappers/gl_draw_funcs.o \ driver/gl/wrappers/gl_framebuffer_funcs.o \ driver/gl/wrappers/gl_get_funcs.o \ +driver/gl/wrappers/gl_query_funcs.o \ driver/gl/wrappers/gl_sampler_funcs.o \ driver/gl/wrappers/gl_shader_funcs.o \ driver/gl/wrappers/gl_state_funcs.o \ diff --git a/renderdoc/driver/gl/gl_common.h b/renderdoc/driver/gl/gl_common.h index 01a120ff0..89ebb2da7 100644 --- a/renderdoc/driver/gl/gl_common.h +++ b/renderdoc/driver/gl/gl_common.h @@ -115,6 +115,14 @@ enum GLChunkType USE_PROGRAMSTAGES, BIND_PROGRAMPIPE, + FENCE_SYNC, + CLIENTWAIT_SYNC, + WAIT_SYNC, + + GEN_QUERIES, + BEGIN_QUERY, + END_QUERY, + CLEAR_COLOR, CLEAR_DEPTH, CLEAR, diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index 93000255e..7be529ca8 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -72,6 +72,14 @@ const char *GLChunkNames[] = "glUseProgramStages", "glBindProgramPipeline", + "glFenceSync", + "glClientWaitSync", + "glWaitSync", + + "glGenQueries", + "glBeginQuery", + "glEndQuery", + "glClearColor", "glClearDepth", "glClear", diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index c6f201c0e..fda902617 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -350,6 +350,20 @@ class WrappedOpenGL IMPLEMENT_FUNCTION_SERIALISED(void, glDebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf)); IMPLEMENT_FUNCTION_SERIALISED(void, glPushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message)); IMPLEMENT_FUNCTION_SERIALISED(void, glPopDebugGroup()); + + bool Serialise_glFenceSync(GLsync real, GLenum condition, GLbitfield flags); + GLsync glFenceSync(GLenum condition, GLbitfield flags); + + IMPLEMENT_FUNCTION_SERIALISED(GLenum, glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)); + IMPLEMENT_FUNCTION_SERIALISED(void, glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)); + IMPLEMENT_FUNCTION_SERIALISED(void, glDeleteSync(GLsync sync)); + IMPLEMENT_FUNCTION_SERIALISED(void, glGenQueries(GLsizei n, GLuint *ids)); + IMPLEMENT_FUNCTION_SERIALISED(void, glBeginQuery(GLenum target, GLuint id)); + IMPLEMENT_FUNCTION_SERIALISED(void, glEndQuery(GLenum target)); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)); + IMPLEMENT_FUNCTION_SERIALISED(void, glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)); + IMPLEMENT_FUNCTION_SERIALISED(void, glDeleteQueries(GLsizei n, const GLuint *ids)); + IMPLEMENT_FUNCTION_SERIALISED(void, glActiveTexture(GLenum texture)); IMPLEMENT_FUNCTION_SERIALISED(void, glTexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)); IMPLEMENT_FUNCTION_SERIALISED(void, glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)); diff --git a/renderdoc/driver/gl/gl_hookset.h b/renderdoc/driver/gl/gl_hookset.h index b63ccfc9c..ddbf77509 100644 --- a/renderdoc/driver/gl/gl_hookset.h +++ b/renderdoc/driver/gl/gl_hookset.h @@ -175,6 +175,16 @@ struct GLHookSet PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture; PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; + PFNGLFENCESYNCPROC glFenceSync; + PFNGLCLIENTWAITSYNCPROC glClientWaitSync; + PFNGLWAITSYNCPROC glWaitSync; + PFNGLDELETESYNCPROC glDeleteSync; + PFNGLGENQUERIESPROC glGenQueries; + PFNGLBEGINQUERYPROC glBeginQuery; + PFNGLENDQUERYPROC glEndQuery; + PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v; + PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; + PFNGLDELETEQUERIESPROC glDeleteQueries; PFNGLBUFFERDATAPROC glBufferData; PFNGLBINDBUFFERBASEPROC glBindBufferBase; PFNGLBINDBUFFERRANGEPROC glBindBufferRange; diff --git a/renderdoc/driver/gl/gl_hookset_defs.h b/renderdoc/driver/gl/gl_hookset_defs.h index 1f3ca5265..58cc2a2d7 100644 --- a/renderdoc/driver/gl/gl_hookset_defs.h +++ b/renderdoc/driver/gl/gl_hookset_defs.h @@ -189,6 +189,16 @@ HookExtension(PFNGLFRAMEBUFFERTEXTUREPROC, glFramebufferTexture); \ HookExtension(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers); \ HookExtension(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC, glGetFramebufferAttachmentParameteriv); \ + HookExtension(PFNGLFENCESYNCPROC, glFenceSync); \ + HookExtension(PFNGLCLIENTWAITSYNCPROC, glClientWaitSync); \ + HookExtension(PFNGLWAITSYNCPROC, glWaitSync); \ + HookExtension(PFNGLDELETESYNCPROC, glDeleteSync); \ + HookExtension(PFNGLGENQUERIESPROC, glGenQueries); \ + HookExtension(PFNGLBEGINQUERYPROC, glBeginQuery); \ + HookExtension(PFNGLENDQUERYPROC, glEndQuery); \ + HookExtension(PFNGLGETQUERYOBJECTUI64VPROC, glGetQueryObjectui64v); \ + HookExtension(PFNGLGETQUERYOBJECTUIVPROC, glGetQueryObjectuiv); \ + HookExtension(PFNGLDELETEQUERIESPROC, glDeleteQueries); \ HookExtension(PFNGLBUFFERDATAPROC, glBufferData); \ HookExtension(PFNGLBINDBUFFERBASEPROC, glBindBufferBase); \ HookExtension(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange); \ @@ -467,6 +477,16 @@ HookWrapper4(void, glFramebufferTexture, GLenum, target, GLenum, attachment, GLuint, texture, GLint, level); \ HookWrapper2(void, glDeleteFramebuffers, GLsizei, n, const GLuint *, framebuffers); \ HookWrapper4(void, glGetFramebufferAttachmentParameteriv, GLenum, target, GLenum, attachment, GLenum, pname, GLint *, params); \ + HookWrapper2(GLsync, glFenceSync, GLenum, condition, GLbitfield, flags); \ + HookWrapper3(GLenum, glClientWaitSync, GLsync, sync, GLbitfield, flags, GLuint64, timeout); \ + HookWrapper3(void, glWaitSync, GLsync, sync, GLbitfield, flags, GLuint64, timeout); \ + HookWrapper1(void, glDeleteSync, GLsync, sync); \ + HookWrapper2(void, glGenQueries, GLsizei, n, GLuint *, ids); \ + HookWrapper2(void, glBeginQuery, GLenum, target, GLuint, id); \ + HookWrapper1(void, glEndQuery, GLenum, target); \ + HookWrapper3(void, glGetQueryObjectui64v, GLuint, id, GLenum, pname, GLuint64 *, params); \ + HookWrapper3(void, glGetQueryObjectuiv, GLuint, id, GLenum, pname, GLuint *, params); \ + HookWrapper2(void, glDeleteQueries, GLsizei, n, const GLuint *, ids); \ HookWrapper4(void, glBufferData, GLenum, target, GLsizeiptr, size, const void *, data, GLenum, usage); \ HookWrapper3(void, glBindBufferBase, GLenum, target, GLuint, index, GLuint, buffer); \ HookWrapper5(void, glBindBufferRange, GLenum, target, GLuint, index, GLuint, buffer, GLintptr, offset, GLsizeiptr, size); \ diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index c9bb0e133..4e1f2e6c0 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -34,7 +34,7 @@ class WrappedOpenGL; class GLResourceManager : public ResourceManager { public: - GLResourceManager(WrappedOpenGL *gl) : m_GL(gl) {} + GLResourceManager(WrappedOpenGL *gl) : m_GL(gl), m_SyncName(1) {} ~GLResourceManager() {} void Shutdown() @@ -115,6 +115,25 @@ class GLResourceManager : public ResourceManager return ResourceManager::GetResourceRecord(GetID(res)); } + void RegisterSync(GLsync sync, GLuint &name, ResourceId &id) + { + name = (GLuint)Atomic::Inc64(&m_SyncName); + id = RegisterResource(SyncRes(name)); + + m_SyncIDs[sync] = id; + m_CurrentSyncs[name] = sync; + } + + GLsync GetSync(GLuint name) + { + return m_CurrentSyncs[name]; + } + + ResourceId GetSyncID(GLsync sync) + { + return m_SyncIDs[sync]; + } + private: bool SerialisableResource(ResourceId id, GLResourceRecord *record); @@ -131,6 +150,12 @@ class GLResourceManager : public ResourceManager map m_CurrentResourceIds; + // sync objects must be treated differently as they're not GLuint names, but pointer sized. + // We manually give them GLuint names so they're otherwise namespaced as (eResSync, GLuint) + map m_SyncIDs; + map m_CurrentSyncs; + volatile int64_t m_SyncName; + WrappedOpenGL *m_GL; }; diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index edce6777f..2d5dde447 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -43,6 +43,8 @@ enum GLNamespace eResShader, eResProgram, eResProgramPipe, + eResQuery, + eResSync, }; enum GLSpecialResource @@ -86,6 +88,8 @@ inline GLResource VertexArrayRes(GLuint i) { return GLResource(eResVertexArray, inline GLResource ShaderRes(GLuint i) { return GLResource(eResShader, i); } inline GLResource ProgramRes(GLuint i) { return GLResource(eResProgram, i); } inline GLResource ProgramPipeRes(GLuint i) { return GLResource(eResProgramPipe, i); } +inline GLResource QueryRes(GLuint i) { return GLResource(eResQuery, i); } +inline GLResource SyncRes(GLuint i) { return GLResource(eResSync, i); } struct GLResourceRecord : public ResourceRecord { diff --git a/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp index b05f5fc84..e50518590 100644 --- a/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_get_funcs.cpp @@ -154,6 +154,16 @@ void WrappedOpenGL::glGetBufferSubData(GLenum target, GLintptr offset, GLsizeipt m_Real.glGetBufferSubData(target, offset, size, data); } +void WrappedOpenGL::glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) +{ + m_Real.glGetQueryObjectuiv(id, pname, params); +} + +void WrappedOpenGL::glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params) +{ + m_Real.glGetQueryObjectui64v(id, pname, params); +} + const GLubyte *WrappedOpenGL::glGetString(GLenum name) { if(name == GL_EXTENSIONS) diff --git a/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp new file mode 100644 index 000000000..0f0cdb9a1 --- /dev/null +++ b/renderdoc/driver/gl/wrappers/gl_query_funcs.cpp @@ -0,0 +1,256 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2014 Crytek + * + * 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 "common/common.h" +#include "common/string_utils.h" +#include "../gl_driver.h" + +bool WrappedOpenGL::Serialise_glFenceSync(GLsync real, GLenum condition, GLbitfield flags) +{ + SERIALISE_ELEMENT(GLenum, Condition, condition); + SERIALISE_ELEMENT(uint32_t, Flags, flags); + SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetSyncID(real)); + + if(m_State < WRITING) + { + GLsync real = m_Real.glFenceSync(Condition, Flags); + + GLuint name = 0; + ResourceId liveid = ResourceId(); + GetResourceManager()->RegisterSync(real, name, liveid); + + GLResource res = SyncRes(name); + + ResourceId live = m_ResourceManager->RegisterResource(res); + GetResourceManager()->AddLiveResource(id, res); + } + + return true; +} + +GLsync WrappedOpenGL::glFenceSync(GLenum condition, GLbitfield flags) +{ + GLsync sync = m_Real.glFenceSync(condition, flags); + + GLuint name = 0; + ResourceId id = ResourceId(); + GetResourceManager()->RegisterSync(sync, name, id); + GLResource res = SyncRes(name); + + if(m_State == WRITING_CAPFRAME) + { + Chunk *chunk = NULL; + + { + SCOPED_SERIALISE_CONTEXT(FENCE_SYNC); + Serialise_glFenceSync(sync, condition, flags); + + chunk = scope.Get(); + } + + m_ContextRecord->AddChunk(chunk); + } + else + { + GetResourceManager()->AddLiveResource(id, res); + } + + return sync; +} + +bool WrappedOpenGL::Serialise_glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + SERIALISE_ELEMENT(uint32_t, Flags, flags); + SERIALISE_ELEMENT(uint64_t, Timeout, timeout); + SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetSyncID(sync)); + + if(m_State < WRITING) + { + GLResource res = GetResourceManager()->GetLiveResource(id); + glClientWaitSync(GetResourceManager()->GetSync(res.name), Flags, Timeout); + } + + return true; +} + +GLenum WrappedOpenGL::glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + GLenum ret = m_Real.glClientWaitSync(sync, flags, timeout); + + if(m_State == WRITING_CAPFRAME) + { + SCOPED_SERIALISE_CONTEXT(CLIENTWAIT_SYNC); + Serialise_glClientWaitSync(sync, flags, timeout); + + m_ContextRecord->AddChunk(scope.Get()); + } + + return ret; +} + +bool WrappedOpenGL::Serialise_glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + SERIALISE_ELEMENT(uint32_t, Flags, flags); + SERIALISE_ELEMENT(uint64_t, Timeout, timeout); + SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetSyncID(sync)); + + if(m_State < WRITING) + { + GLResource res = GetResourceManager()->GetLiveResource(id); + glWaitSync(GetResourceManager()->GetSync(res.name), Flags, Timeout); + } + + return true; +} + +void WrappedOpenGL::glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) +{ + m_Real.glWaitSync(sync, flags, timeout); + + if(m_State == WRITING_CAPFRAME) + { + SCOPED_SERIALISE_CONTEXT(WAIT_SYNC); + Serialise_glWaitSync(sync, flags, timeout); + + m_ContextRecord->AddChunk(scope.Get()); + } +} + +void WrappedOpenGL::glDeleteSync(GLsync sync) +{ + m_Real.glDeleteSync(sync); + + ResourceId id = GetResourceManager()->GetSyncID(sync); + + GetResourceManager()->UnregisterResource(GetResourceManager()->GetCurrentResource(id)); +} + +bool WrappedOpenGL::Serialise_glGenQueries(GLsizei n, GLuint* ids) +{ + SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(QueryRes(*ids))); + + if(m_State == READING) + { + GLuint real = 0; + m_Real.glGenSamplers(1, &real); + + GLResource res = QueryRes(real); + + ResourceId live = m_ResourceManager->RegisterResource(res); + GetResourceManager()->AddLiveResource(id, res); + } + + return true; +} + +void WrappedOpenGL::glGenQueries(GLsizei count, GLuint *ids) +{ + m_Real.glGenSamplers(count, ids); + + for(GLsizei i=0; i < count; i++) + { + GLResource res = QueryRes(ids[i]); + ResourceId id = GetResourceManager()->RegisterResource(res); + + if(m_State >= WRITING) + { + Chunk *chunk = NULL; + + { + SCOPED_SERIALISE_CONTEXT(GEN_QUERIES); + Serialise_glGenQueries(1, ids+i); + + chunk = scope.Get(); + } + + GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id); + RDCASSERT(record); + + record->AddChunk(chunk); + } + else + { + GetResourceManager()->AddLiveResource(id, res); + } + } +} + +bool WrappedOpenGL::Serialise_glBeginQuery(GLenum target, GLuint qid) +{ + SERIALISE_ELEMENT(GLenum, Target, target); + SERIALISE_ELEMENT(ResourceId, id, GetResourceManager()->GetID(QueryRes(qid))); + + if(m_State < WRITING) + { + glBeginQuery(Target, GetResourceManager()->GetLiveResource(id).name); + } + + return true; +} + +void WrappedOpenGL::glBeginQuery(GLenum target, GLuint id) +{ + m_Real.glBeginQuery(target, id); + + if(m_State == WRITING_CAPFRAME) + { + SCOPED_SERIALISE_CONTEXT(BEGIN_QUERY); + Serialise_glBeginQuery(target, id); + + m_ContextRecord->AddChunk(scope.Get()); + } +} + +bool WrappedOpenGL::Serialise_glEndQuery(GLenum target) +{ + SERIALISE_ELEMENT(GLenum, Target, target); + + if(m_State < WRITING) + { + glEndQuery(Target); + } + + return true; +} + +void WrappedOpenGL::glEndQuery(GLenum target) +{ + m_Real.glEndQuery(target); + + if(m_State == WRITING_CAPFRAME) + { + SCOPED_SERIALISE_CONTEXT(END_QUERY); + Serialise_glEndQuery(target); + + m_ContextRecord->AddChunk(scope.Get()); + } +} + +void WrappedOpenGL::glDeleteQueries(GLsizei n, const GLuint *ids) +{ + m_Real.glDeleteQueries(n, ids); + + for(GLsizei i=0; i < n; i++) + GetResourceManager()->UnregisterResource(QueryRes(ids[i])); +} diff --git a/renderdoc/renderdoc.vcxproj b/renderdoc/renderdoc.vcxproj index 5e7a668a1..6b22297a8 100644 --- a/renderdoc/renderdoc.vcxproj +++ b/renderdoc/renderdoc.vcxproj @@ -339,6 +339,7 @@ + diff --git a/renderdoc/renderdoc.vcxproj.filters b/renderdoc/renderdoc.vcxproj.filters index e8eb58b5f..f2019b0ae 100644 --- a/renderdoc/renderdoc.vcxproj.filters +++ b/renderdoc/renderdoc.vcxproj.filters @@ -503,6 +503,9 @@ Drivers\OpenGL\Function Wrappers + + Drivers\OpenGL\Function Wrappers +