From f63a948392dda16ea6163e93ebd418bdbae0fc23 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 26 Aug 2020 18:44:45 +0100 Subject: [PATCH] Cache FBO attachments to avoid repeated query & lookup --- renderdoc/driver/gl/gl_manager.cpp | 139 +++++++++++++----- renderdoc/driver/gl/gl_manager.h | 19 +++ renderdoc/driver/gl/gl_renderstate.cpp | 59 +------- renderdoc/driver/gl/gl_resources.h | 6 +- .../gl/wrappers/gl_framebuffer_funcs.cpp | 30 ++++ 5 files changed, 156 insertions(+), 97 deletions(-) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index ee95ab6bd..d1c6d36c9 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -67,55 +67,118 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref) if(res.name == 0) return; - MarkResourceFrameReferenced(res, ref); + rdcpair &it = m_CurrentResources[res]; - ContextPair &ctx = m_Driver->GetCtx(); + MarkResourceFrameReferenced(it.first, ref); - GLint numCols = 8; - GL.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &numCols); + MarkFBOAttachmentsReferenced(it.first, it.second, ref, false); +} - GLenum type = eGL_TEXTURE; - GLuint name = 0; +void GLResourceManager::MarkFBODirtyWithWriteReference(GLResourceRecord *record) +{ + MarkFBOAttachmentsReferenced(record->GetResourceID(), record, eFrameRef_ReadBeforeWrite, true); +} - for(int c = 0; c < numCols; c++) +void GLResourceManager::MarkFBOAttachmentsReferenced(ResourceId fboid, GLResourceRecord *record, + FrameRefType ref, bool markDirty) +{ + FBOCache *cache = m_FBOAttachmentsCache[fboid]; + + if(!cache) { - GL.glGetNamedFramebufferAttachmentParameterivEXT(res.name, GLenum(eGL_COLOR_ATTACHMENT0 + c), - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - (GLint *)&name); - GL.glGetNamedFramebufferAttachmentParameterivEXT(res.name, GLenum(eGL_COLOR_ATTACHMENT0 + c), - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, - (GLint *)&type); - - if(type == eGL_RENDERBUFFER) - MarkResourceFrameReferenced(RenderbufferRes(ctx, name), ref); - else - MarkResourceFrameReferenced(TextureRes(ctx, name), ref); + cache = m_FBOAttachmentsCache[fboid] = new FBOCache; + // ensure the starting age is wrong, for whatever age we have + cache->age = (record->age ^ 1); } - GL.glGetNamedFramebufferAttachmentParameterivEXT( - res.name, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&name); - GL.glGetNamedFramebufferAttachmentParameterivEXT( - res.name, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint *)&type); - - if(name) + if(cache->age != record->age) { - if(type == eGL_RENDERBUFFER) - MarkResourceFrameReferenced(RenderbufferRes(ctx, name), ref); - else - MarkResourceFrameReferenced(TextureRes(ctx, name), ref); + cache->age = record->age; + cache->attachments.clear(); + + GLuint fbo = record->Resource.name; + + ContextPair &ctx = m_Driver->GetCtx(); + + GLint numCols = 8; + GL.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &numCols); + + GLenum type = eGL_TEXTURE; + GLuint name = 0; + + ResourceId id; + + for(int c = 0; c < numCols; c++) + { + GL.glGetNamedFramebufferAttachmentParameterivEXT(fbo, GLenum(eGL_COLOR_ATTACHMENT0 + c), + eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + (GLint *)&name); + + if(name) + { + GL.glGetNamedFramebufferAttachmentParameterivEXT(fbo, GLenum(eGL_COLOR_ATTACHMENT0 + c), + eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, + (GLint *)&type); + + if(type == eGL_RENDERBUFFER) + id = GetResID(RenderbufferRes(ctx, name)); + else + id = GetResID(TextureRes(ctx, name)); + + cache->attachments.push_back(id); + GLResourceRecord *r = GetResourceRecord(id); + if(r && r->viewSource != ResourceId()) + cache->attachments.push_back(r->viewSource); + } + } + + GL.glGetNamedFramebufferAttachmentParameterivEXT( + fbo, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&name); + + if(name) + { + GL.glGetNamedFramebufferAttachmentParameterivEXT( + fbo, eGL_DEPTH_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint *)&type); + + if(type == eGL_RENDERBUFFER) + id = GetResID(RenderbufferRes(ctx, name)); + else + id = GetResID(TextureRes(ctx, name)); + + cache->attachments.push_back(id); + GLResourceRecord *r = GetResourceRecord(id); + if(r && r->viewSource != ResourceId()) + cache->attachments.push_back(r->viewSource); + } + + GLuint stencilName = 0; + + GL.glGetNamedFramebufferAttachmentParameterivEXT( + fbo, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&stencilName); + + if(stencilName && stencilName != name) + { + GL.glGetNamedFramebufferAttachmentParameterivEXT( + fbo, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint *)&type); + + if(type == eGL_RENDERBUFFER) + id = GetResID(RenderbufferRes(ctx, stencilName)); + else + id = GetResID(TextureRes(ctx, stencilName)); + + cache->attachments.push_back(id); + GLResourceRecord *r = GetResourceRecord(id); + if(r && r->viewSource != ResourceId()) + cache->attachments.push_back(r->viewSource); + } } - GL.glGetNamedFramebufferAttachmentParameterivEXT( - res.name, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&name); - GL.glGetNamedFramebufferAttachmentParameterivEXT( - res.name, eGL_STENCIL_ATTACHMENT, eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint *)&type); - - if(name) + // we took care of viewSource above so we can directly call the real thing + for(ResourceId id : cache->attachments) { - if(type == eGL_RENDERBUFFER) - MarkResourceFrameReferenced(RenderbufferRes(ctx, name), ref); - else - MarkResourceFrameReferenced(TextureRes(ctx, name), ref); + ResourceManager::MarkResourceFrameReferenced(id, ref); + if(markDirty) + ResourceManager::MarkDirtyResource(id); } } diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index e99388d98..5d998c820 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -170,6 +170,13 @@ public: EraseLiveResource(it->second.first); ReleaseCurrentResource(it->second.first); m_CurrentResources.erase(res); + + auto fboit = m_FBOAttachmentsCache.find(it->second.first); + if(fboit != m_FBOAttachmentsCache.end()) + { + delete fboit->second; + m_FBOAttachmentsCache.erase(fboit); + } } } @@ -295,6 +302,7 @@ public: // this would be handled by record parenting, but that would be a nightmare to track. void MarkVAOReferenced(GLResource res, FrameRefType ref, bool allowFake0 = false); void MarkFBOReferenced(GLResource res, FrameRefType ref); + void MarkFBODirtyWithWriteReference(GLResourceRecord *record); bool IsResourceTrackedForPersistency(const GLResource &res); @@ -320,6 +328,9 @@ private: void Create_InitialState(ResourceId id, GLResource live, bool hasData); void Apply_InitialState(GLResource live, const GLInitialContents &initial); + void MarkFBOAttachmentsReferenced(ResourceId id, GLResourceRecord *record, FrameRefType ref, + bool markDirty); + // unfortunately not all resources have a record even at capture time (certain special resources // do not) so we store a pair to ensure we can always lookup the resource ID rdcflatmap> m_CurrentResources; @@ -331,5 +342,13 @@ private: std::map m_Names; volatile int64_t m_SyncName; + struct FBOCache + { + uint32_t age = 0; + rdcarray attachments; + }; + + rdcflatmap m_FBOAttachmentsCache; + WrappedOpenGL *m_Driver; }; diff --git a/renderdoc/driver/gl/gl_renderstate.cpp b/renderdoc/driver/gl/gl_renderstate.cpp index a6364e68a..6612e68d7 100644 --- a/renderdoc/driver/gl/gl_renderstate.cpp +++ b/renderdoc/driver/gl/gl_renderstate.cpp @@ -611,64 +611,7 @@ void GLRenderState::MarkDirty(WrappedOpenGL *driver) if(ctxData.m_DrawFramebufferRecord) { - name = ctxData.m_DrawFramebufferRecord->Resource.name; - - static GLint fboCount = 0; - if(fboCount == 0) - GL.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &fboCount); - - GLenum type = eGL_TEXTURE; - for(GLint i = 0; i < fboCount; i++) - { - GL.glGetFramebufferAttachmentParameteriv( - eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0 + i), - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&name); - - if(name) - { - GL.glGetFramebufferAttachmentParameteriv( - eGL_DRAW_FRAMEBUFFER, GLenum(eGL_COLOR_ATTACHMENT0 + i), - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, (GLint *)&type); - - if(type == eGL_RENDERBUFFER) - manager->MarkDirtyResource(RenderbufferRes(ctx, name)); - else - manager->MarkDirtyWithWriteReference(TextureRes(ctx, name)); - } - } - - GL.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, (GLint *)&name); - - if(name) - { - GL.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, - (GLint *)&type); - - if(type == eGL_RENDERBUFFER) - manager->MarkDirtyResource(RenderbufferRes(ctx, name)); - else - manager->MarkDirtyWithWriteReference(TextureRes(ctx, name)); - } - - GLuint stencilName = 0; - GL.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT, - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - (GLint *)&stencilName); - - // almost always this will be the same as the depth, so we can skip it if so - if(stencilName && stencilName != name) - { - GL.glGetFramebufferAttachmentParameteriv(eGL_DRAW_FRAMEBUFFER, eGL_STENCIL_ATTACHMENT, - eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, - (GLint *)&type); - - if(type == eGL_RENDERBUFFER) - manager->MarkDirtyResource(RenderbufferRes(ctx, stencilName)); - else - manager->MarkDirtyWithWriteReference(TextureRes(ctx, stencilName)); - } + manager->MarkFBODirtyWithWriteReference(ctxData.m_DrawFramebufferRecord); } } diff --git a/renderdoc/driver/gl/gl_resources.h b/renderdoc/driver/gl/gl_resources.h index 9803f2d1b..00689fd0a 100644 --- a/renderdoc/driver/gl/gl_resources.h +++ b/renderdoc/driver/gl/gl_resources.h @@ -258,7 +258,11 @@ struct GLResourceRecord : public ResourceRecord } bool AlreadyDataType(GLenum target) { return datatype == TextureBinding(target); } - GLenum datatype; + union + { + GLenum datatype; + uint32_t age; + }; GLenum usage; // for texture buffers, this points from the texture to the real buffer, for texture views this diff --git a/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp b/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp index 8ba9ee34a..03ad71d7b 100644 --- a/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp +++ b/renderdoc/driver/gl/wrappers/gl_framebuffer_funcs.cpp @@ -215,6 +215,8 @@ void WrappedOpenGL::glNamedFramebufferTextureEXT(GLuint framebuffer, GLenum atta GLResourceRecord *record = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -269,6 +271,8 @@ void WrappedOpenGL::glFramebufferTexture(GLenum target, GLenum attachment, GLuin record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -353,6 +357,8 @@ void WrappedOpenGL::glNamedFramebufferTexture1DEXT(GLuint framebuffer, GLenum at GLResourceRecord *record = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -409,6 +415,8 @@ void WrappedOpenGL::glFramebufferTexture1D(GLenum target, GLenum attachment, GLe record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -494,6 +502,8 @@ void WrappedOpenGL::glNamedFramebufferTexture2DEXT(GLuint framebuffer, GLenum at GLResourceRecord *record = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -550,6 +560,8 @@ void WrappedOpenGL::glFramebufferTexture2D(GLenum target, GLenum attachment, GLe record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -659,6 +671,8 @@ void WrappedOpenGL::glFramebufferTexture2DMultisampleEXT(GLenum target, GLenum a record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -748,6 +762,8 @@ void WrappedOpenGL::glNamedFramebufferTexture3DEXT(GLuint framebuffer, GLenum at GLResourceRecord *record = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -806,6 +822,8 @@ void WrappedOpenGL::glFramebufferTexture3D(GLenum target, GLenum attachment, GLe record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -892,6 +910,8 @@ void WrappedOpenGL::glNamedFramebufferRenderbufferEXT(GLuint framebuffer, GLenum GLResourceRecord *record = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); + record->age++; + if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() && IsBackgroundCapturing(m_State)) return; @@ -945,6 +965,8 @@ void WrappedOpenGL::glFramebufferRenderbuffer(GLenum target, GLenum attachment, record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(m_HighTrafficResources.find(record->GetResourceID()) != m_HighTrafficResources.end() && IsBackgroundCapturing(m_State)) return; @@ -1026,6 +1048,8 @@ void WrappedOpenGL::glNamedFramebufferTextureLayerEXT(GLuint framebuffer, GLenum GLResourceRecord *record = GetResourceManager()->GetResourceRecord(FramebufferRes(GetCtx(), framebuffer)); + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -1082,6 +1106,8 @@ void WrappedOpenGL::glFramebufferTextureLayer(GLenum target, GLenum attachment, record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -1187,6 +1213,8 @@ void WrappedOpenGL::glFramebufferTextureMultiviewOVR(GLenum target, GLenum attac record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture)); @@ -1303,6 +1331,8 @@ void WrappedOpenGL::glFramebufferTextureMultisampleMultiviewOVR(GLenum target, G record = GetCtxData().m_ReadFramebufferRecord; } + record->age++; + if(texture != 0 && GetResourceManager()->HasResourceRecord(TextureRes(GetCtx(), texture))) { GetResourceManager()->MarkDirtyResource(TextureRes(GetCtx(), texture));