diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index d6d3efb02..6fe2dba01 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -644,8 +644,6 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform) m_DrawcallStack.push_back(&m_ParentDrawcall); - m_ShareGroupID = UINTPTR_MAX - 2000; - m_CurEventID = 0; m_CurDrawcallID = 0; m_FirstEventID = 0; @@ -1028,7 +1026,9 @@ void WrappedOpenGL::DeleteContext(void *contextHandle) // if this is the last context in the share group, delete the group. if(lastInGroup) - GetResourceManager()->DeleteContext(ctxdata.shareGroup); + { + delete ctxdata.shareGroup; + } if(ctxdata.built && ctxdata.ready) { @@ -1125,16 +1125,13 @@ void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext, if(shareContext == NULL) { - // no sharing, allocate a new group ID - ctxdata.shareGroup = (void *)m_ShareGroupID; - - // we're counting down from UINTPTR_MAX when allocating IDs - m_ShareGroupID--; + // no sharing, allocate a new group + ctxdata.shareGroup = new ContextShareGroup(m_Platform, winData); } else { // use the same shareGroup ID as the share context. - ctxdata.shareGroup = ShareCtx(shareContext); + ctxdata.shareGroup = GetShareGroup(shareContext); } RenderDoc::Inst().AddDeviceFrameCapturer(ctxdata.ctx, this); @@ -1178,16 +1175,13 @@ void WrappedOpenGL::RegisterReplayContext(GLWindowingData winData, void *shareCo if(shareContext == NULL) { - // no sharing, allocate a new group ID - ctxdata.shareGroup = (void *)m_ShareGroupID; - - // we're counting down from UINTPTR_MAX when allocating IDs - m_ShareGroupID--; + // create the sharegroup + ctxdata.shareGroup = new ContextShareGroup(m_Platform, winData); } else { // use the same shareGroup ID as the share context. - ctxdata.shareGroup = ShareCtx(shareContext); + ctxdata.shareGroup = GetShareGroup(shareContext); } ActivateContext(winData); @@ -1260,7 +1254,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) // // First we process any queued fetches from the context itself (i.e. non-shared resources), // then from the context's share group. - for(void *ctx : {(void *)winData.ctx, ShareCtx(winData.ctx)}) + for(void *ctx : {(void *)winData.ctx, (void *)GetShareGroup(winData.ctx)}) { QueuedResource fetch; fetch.res.ContextShareGroup = ctx; @@ -1285,7 +1279,7 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) // also if there are any queued releases, process them now if(!m_QueuedReleases.empty()) { - for(void *ctx : {(void *)winData.ctx, ShareCtx(winData.ctx)}) + for(void *ctx : {(void *)winData.ctx, (void *)GetShareGroup(winData.ctx)}) { QueuedResource fetch; fetch.res.ContextShareGroup = ctx; @@ -1316,12 +1310,12 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData) if(tlsData) { - tlsData->ctxPair = {winData.ctx, ShareCtx(winData.ctx)}; + tlsData->ctxPair = {winData.ctx, GetShareGroup(winData.ctx)}; tlsData->ctxRecord = ctxdata.m_ContextDataRecord; } else { - tlsData = new GLContextTLSData(ContextPair({winData.ctx, ShareCtx(winData.ctx)}), + tlsData = new GLContextTLSData(ContextPair({winData.ctx, GetShareGroup(winData.ctx)}), ctxdata.m_ContextDataRecord); m_CtxDataVector.push_back(tlsData); @@ -2692,24 +2686,11 @@ void WrappedOpenGL::QueuePrepareInitialState(GLResource res) void WrappedOpenGL::QueueResourceRelease(GLResource res) { - if(res.name == 0) - return; + QueuedResource q; + q.res = res; - ContextPair &ctx = GetCtx(); - if(res.ContextShareGroup == ctx.ctx || res.ContextShareGroup == ctx.shareGroup) - { - // if we're already on a context, delete immediately - ReleaseResource(res); - } - else - { - // otherwise, queue for next time this becomes active - QueuedResource q; - q.res = res; - - auto insertPos = std::lower_bound(m_QueuedReleases.begin(), m_QueuedReleases.end(), q); - m_QueuedReleases.insert(insertPos - m_QueuedReleases.begin(), q); - } + auto insertPos = std::lower_bound(m_QueuedReleases.begin(), m_QueuedReleases.end(), q); + m_QueuedReleases.insert(insertPos - m_QueuedReleases.begin(), q); } void WrappedOpenGL::CreateTextureImage(GLuint tex, GLenum internalFormat, GLenum internalFormatHint, diff --git a/renderdoc/driver/gl/gl_driver.h b/renderdoc/driver/gl/gl_driver.h index daa4e434d..2ea307ac6 100644 --- a/renderdoc/driver/gl/gl_driver.h +++ b/renderdoc/driver/gl/gl_driver.h @@ -78,6 +78,24 @@ struct Replacement GLResource res; }; +struct ContextShareGroup +{ + GLPlatform &m_Platform; + GLWindowingData m_BackDoor; // holds the backdoor context for the share group + + explicit ContextShareGroup(GLPlatform &platform, const GLWindowingData &windata) + : m_Platform(platform) + { + // create a backdoor context for the purpose of retrieving resources + m_BackDoor = m_Platform.CloneTemporaryContext(windata); + } + ~ContextShareGroup() + { + // destroy the backdoor context + m_Platform.DeleteClonedContext(m_BackDoor); + } +}; + class WrappedOpenGL : public IFrameCapturer { private: @@ -157,8 +175,6 @@ private: uint64_t m_CurCtxDataTLS; rdcarray m_CtxDataVector; - uintptr_t m_ShareGroupID; - uint32_t m_InternalShader = 0; rdcarray m_LastContexts; @@ -371,7 +387,7 @@ private: void *ctx; - void *shareGroup; + ContextShareGroup *shareGroup; GLDEBUGPROC m_RealDebugFunc; const void *m_RealDebugFuncParam; @@ -585,7 +601,7 @@ public: void PushInternalShader() { m_InternalShader++; } void PopInternalShader() { m_InternalShader--; } bool IsInternalShader() { return m_InternalShader > 0; } - void *ShareCtx(void *ctx) { return ctx ? m_ContextData[ctx].shareGroup : NULL; } + ContextShareGroup *GetShareGroup(void *ctx) { return ctx ? m_ContextData[ctx].shareGroup : NULL; } void SetStructuredExport(uint64_t sectionVersion) { m_SectionVersion = sectionVersion; diff --git a/renderdoc/driver/gl/gl_initstate.cpp b/renderdoc/driver/gl/gl_initstate.cpp index f7df2f251..e188b6dcc 100644 --- a/renderdoc/driver/gl/gl_initstate.cpp +++ b/renderdoc/driver/gl/gl_initstate.cpp @@ -553,14 +553,32 @@ bool GLResourceManager::Prepare_InitialState(GLResource res) // and we just start getting commands there, but that case already isn't supported as we don't // detect it and insert state-change chunks, we assume all commands will come from a single // thread. + RDCASSERT(res.ContextShareGroup); + ContextPair &ctx = m_Driver->GetCtx(); if(res.ContextShareGroup == ctx.ctx || res.ContextShareGroup == ctx.shareGroup) { // call immediately, we are on the right context or share group ContextPrepare_InitialState(res); } + else if(IsResourceTrackedForPersistency(res)) + { + GLWindowingData oldContextData = m_Driver->m_ActiveContexts[Threading::GetCurrentID()]; + + ContextShareGroup *shareGroup = (ContextShareGroup *)res.ContextShareGroup; + + m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = shareGroup->m_BackDoor; + m_Driver->m_Platform.MakeContextCurrent(shareGroup->m_BackDoor); + + ContextPrepare_InitialState(res); + + // restore the context + m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = oldContextData; + m_Driver->m_Platform.MakeContextCurrent(oldContextData); + } else { + // queue if we can't use the backdoor m_Driver->QueuePrepareInitialState(res); } @@ -1783,6 +1801,35 @@ template bool GLResourceManager::Serialise_InitialState<>(WriteSerialiser &ser, GLResourceRecord *record, const GLInitialContents *initial); +bool GLResourceManager::Serialise_InitialState(WriteSerialiser &ser, ResourceId id, + GLResourceRecord *record, + const GLInitialContents *initial) +{ + GLResource res = GetCurrentResource(id); + + if(IsResourceTrackedForPersistency(res)) + { + GLWindowingData oldContextData = m_Driver->m_ActiveContexts[Threading::GetCurrentID()]; + + GLWindowingData backdoor = ((ContextShareGroup *)res.ContextShareGroup)->m_BackDoor; + + m_Driver->m_Platform.MakeContextCurrent(backdoor); + + m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = backdoor; + + bool success = Serialise_InitialState(ser, id, record, initial); + + // restore the context + m_Driver->m_ActiveContexts[Threading::GetCurrentID()] = oldContextData; + + m_Driver->m_Platform.MakeContextCurrent(oldContextData); + + return success; + } + + return Serialise_InitialState(ser, id, record, initial); +} + void GLResourceManager::Create_InitialState(ResourceId id, GLResource live, bool hasData) { if(IsStructuredExporting(m_State)) diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 62a2bf09e..b50bc91a6 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -134,6 +134,29 @@ bool GLResourceManager::ResourceTypeRelease(GLResource res) if(HasCurrentResource(res)) UnregisterResource(res); - m_Driver->QueueResourceRelease(res); + if(res.name) + { + ContextPair &ctx = m_Driver->GetCtx(); + if(res.ContextShareGroup == ctx.ctx || res.ContextShareGroup == ctx.shareGroup) + { + m_Driver->ReleaseResource(res); + } + else if(IsResourceTrackedForPersistency(res)) + { + ContextShareGroup *contextShareGroup = (ContextShareGroup *)res.ContextShareGroup; + + m_Driver->m_Platform.MakeContextCurrent(contextShareGroup->m_BackDoor); + + m_Driver->ReleaseResource(res); + + // restore the context + m_Driver->m_Platform.MakeContextCurrent(m_Driver->m_ActiveContexts[Threading::GetCurrentID()]); + } + else + { + // queue if we can't use the backdoor + m_Driver->QueueResourceRelease(res); + } + } return true; } diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index 3462c8fc7..0ce186e16 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -270,13 +270,10 @@ public: template bool Serialise_InitialState(SerialiserType &ser, ResourceId id, GLResourceRecord *record, const GLInitialContents *initial); + bool Serialise_InitialState(WriteSerialiser &ser, ResourceId id, GLResourceRecord *record, + const GLInitialContents *initial); void ContextPrepare_InitialState(GLResource res); - bool Serialise_InitialState(WriteSerialiser &ser, ResourceId id, GLResourceRecord *record, - const GLInitialContents *initial) - { - return Serialise_InitialState(ser, id, record, initial); - } void SetInternalResource(GLResource res); diff --git a/renderdoc/driver/gl/gl_postvs.cpp b/renderdoc/driver/gl/gl_postvs.cpp index 4028643bc..984610966 100644 --- a/renderdoc/driver/gl/gl_postvs.cpp +++ b/renderdoc/driver/gl/gl_postvs.cpp @@ -1852,7 +1852,7 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, uint32_ // no multiview support (void)viewID; - ContextPair ctx = {m_ReplayCtx.ctx, m_pDriver->ShareCtx(m_ReplayCtx.ctx)}; + ContextPair ctx = {m_ReplayCtx.ctx, m_pDriver->GetShareGroup(m_ReplayCtx.ctx)}; if(m_PostVSData.find(eventId) != m_PostVSData.end()) postvs = m_PostVSData[eventId];