Cache FBO attachments to avoid repeated query & lookup

This commit is contained in:
baldurk
2020-08-26 18:44:45 +01:00
parent 3a1b4500ee
commit f63a948392
5 changed files with 156 additions and 97 deletions
+101 -38
View File
@@ -67,55 +67,118 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref)
if(res.name == 0)
return;
MarkResourceFrameReferenced(res, ref);
rdcpair<ResourceId, GLResourceRecord *> &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);
}
}
+19
View File
@@ -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<GLResource, rdcpair<ResourceId, GLResourceRecord *>> m_CurrentResources;
@@ -331,5 +342,13 @@ private:
std::map<ResourceId, rdcstr> m_Names;
volatile int64_t m_SyncName;
struct FBOCache
{
uint32_t age = 0;
rdcarray<ResourceId> attachments;
};
rdcflatmap<ResourceId, FBOCache *> m_FBOAttachmentsCache;
WrappedOpenGL *m_Driver;
};
+1 -58
View File
@@ -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);
}
}
+5 -1
View File
@@ -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
@@ -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));