mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-24 23:46:41 +00:00
Backdoor context for opengl resource retrieval
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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<GLContextTLSData *> m_CtxDataVector;
|
||||
|
||||
uintptr_t m_ShareGroupID;
|
||||
|
||||
uint32_t m_InternalShader = 0;
|
||||
|
||||
rdcarray<GLWindowingData> 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;
|
||||
|
||||
@@ -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<WriteSerialiser>(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<WriteSerialiser>(ser, id, record, initial);
|
||||
}
|
||||
|
||||
void GLResourceManager::Create_InitialState(ResourceId id, GLResource live, bool hasData)
|
||||
{
|
||||
if(IsStructuredExporting(m_State))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -270,13 +270,10 @@ public:
|
||||
template <typename SerialiserType>
|
||||
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<WriteSerialiser>(ser, id, record, initial);
|
||||
}
|
||||
|
||||
void SetInternalResource(GLResource res);
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user