GL non-sharing context support

This commit is contained in:
baldurk
2018-05-08 11:10:32 +01:00
parent 0f3f822597
commit a461df2b58
21 changed files with 372 additions and 290 deletions
+2 -3
View File
@@ -12,7 +12,7 @@ RenderDoc only supports the core profile of OpenGL - from 3.2 up to 4.5 inclusiv
.. note::
that to be more compatible with applications, RenderDoc will still attempt to capture on a compatibility context, but it will not replay successfully unless the given subset of functionality is used.
To be more compatible with applications, RenderDoc will still attempt to capture on a compatibility context, but it will not replay successfully unless the given subset of functionality is used.
On OpenGL ES, any context version 2.0 and above is supported.
@@ -35,7 +35,7 @@ On OpenGL ES, you must be able to create a GLES 3 context to replay.
Multiple contexts & multithreading
----------------------------------
RenderDoc assumes that all GL commands (with the exception of perhaps a SwapBuffers call) for frames will come from a single thread, and that all contexts are set up to share objects with each other. This means that e.g. if commands come from a second thread during loading, or some time during initialisation, this will be supported only if the second context shares with the primary context. During frame capture all commands are serialised as if they come from a single thread.
RenderDoc assumes that all GL commands (with the exception of perhaps a SwapBuffers call) for frames will come from a single thread. This means that e.g. if commands come from a second thread during loading, or some time during initialisation, this will be supported. However during frame capture all commands are serialised as if they come from a single thread, so interleaved rendering commands from multiple threads will not work.
Extension support
-----------------
@@ -47,7 +47,6 @@ OpenGL remaining work
There are a couple of places where OpenGL is not yet at feature parity with other APIs.
* Full & complete support for multiple threads feeding GL simultaneously, or multiple contexts that don't share with each other (or only share within defined groups).
* Shader debugging is not supported on any shader stage.
* Pixel history is not implemented.
+2
View File
@@ -1758,6 +1758,8 @@ enum class GLChunk : uint32_t
glIndirectSubCommand,
glContextInit,
Max,
};
+192 -58
View File
@@ -519,6 +519,8 @@ WrappedOpenGL::WrappedOpenGL(const GLHookSet &funcs, GLPlatform &platform)
m_DrawcallStack.push_back(&m_ParentDrawcall);
m_ShareGroupID = UINTPTR_MAX - 2000;
m_CurEventID = 0;
m_CurDrawcallID = 0;
m_FirstEventID = 0;
@@ -566,15 +568,9 @@ WrappedOpenGL::WrappedOpenGL(const GLHookSet &funcs, GLPlatform &platform)
m_ContextRecord->Length = 0;
m_ContextRecord->SpecialResource = true;
// register VAO 0 as a special VAO, so that it can be tracked if the app uses it
// we immediately mark it dirty since the vertex array tracking functions expect a proper VAO
m_FakeVAOID = GetResourceManager()->RegisterResource(VertexArrayRes(NULL, 0));
GetResourceManager()->AddResourceRecord(m_FakeVAOID);
GetResourceManager()->MarkDirtyResource(m_FakeVAOID);
// also register an ID for the backbuffer, so we can identify it properly.
m_FBO0_ID = GetResourceManager()->RegisterResource(FramebufferRes(NULL, 0));
GetResourceManager()->AddResourceRecord(m_FBO0_ID);
// we register an ID for the backbuffer, this will be tied to the fake-created backbuffer on
// replay, and every context's FBO 0 will be pointed to it with ReplaceResource
m_FBO0_ID = ResourceIDGen::GetNewUniqueID();
}
else
{
@@ -589,11 +585,11 @@ WrappedOpenGL::WrappedOpenGL(const GLHookSet &funcs, GLPlatform &platform)
m_FakeBB_FBO = 0;
m_FakeBB_Color = 0;
m_FakeBB_DepthStencil = 0;
m_FakeVAO = 0;
m_FakeIdxSize = 0;
m_CurChunkOffset = 0;
m_AddedDrawcall = false;
m_CurCtxPairTLS = Threading::AllocateTLSSlot();
}
void WrappedOpenGL::Initialise(GLInitParams &params, uint64_t sectionVersion)
@@ -604,12 +600,6 @@ void WrappedOpenGL::Initialise(GLInitParams &params, uint64_t sectionVersion)
m_InitParams = params;
m_SectionVersion = sectionVersion;
// as a concession to compatibility, generate a 'fake' VBO to act as VBO 0.
// consider making it an error/warning for programs to use this?
gl.glGenVertexArrays(1, &m_FakeVAO);
gl.glBindVertexArray(m_FakeVAO);
gl.glBindVertexArray(0);
gl.glGenFramebuffers(1, &m_FakeBB_FBO);
gl.glBindFramebuffer(eGL_FRAMEBUFFER, m_FakeBB_FBO);
@@ -749,8 +739,6 @@ std::string WrappedOpenGL::GetChunkName(uint32_t idx)
WrappedOpenGL::~WrappedOpenGL()
{
if(m_FakeVAO)
m_Real.glDeleteVertexArrays(1, &m_FakeVAO);
if(m_FakeBB_FBO)
m_Real.glDeleteFramebuffers(1, &m_FakeBB_FBO);
if(m_FakeBB_Color)
@@ -785,14 +773,17 @@ WrappedOpenGL::~WrappedOpenGL()
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
}
void *WrappedOpenGL::GetCtx()
ContextPair &WrappedOpenGL::GetCtx()
{
return (void *)m_ActiveContexts[Threading::GetCurrentID()].ctx;
ContextPair *ret = (ContextPair *)Threading::GetTLSValue(m_CurCtxPairTLS);
if(ret)
return *ret;
return m_EmptyPair;
}
WrappedOpenGL::ContextData &WrappedOpenGL::GetCtxData()
{
return m_ContextData[GetCtx()];
return m_ContextData[GetCtx().ctx];
}
// defined in gl_<platform>_hooks.cpp
@@ -808,8 +799,26 @@ void WrappedOpenGL::DeleteContext(void *contextHandle)
RenderDoc::Inst().RemoveDeviceFrameCapturer(ctxdata.ctx);
// delete the context
GetResourceManager()->DeleteContext(contextHandle);
bool lastInGroup = true;
for(auto it = m_ContextData.begin(); it != m_ContextData.end(); ++it)
{
// if we find another context that's not this one, but is in the same share group, we're note
// the last
if(it->second.shareGroup == ctxdata.shareGroup && it->second.ctx &&
it->second.ctx != contextHandle)
{
lastInGroup = false;
break;
}
}
// if this is the last context in the share group, delete the group.
if(lastInGroup)
GetResourceManager()->DeleteContext(ctxdata.shareGroup);
if(ctxdata.built && ctxdata.ready)
{
if(ctxdata.Program)
@@ -879,16 +888,46 @@ void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext,
ctxdata.isCore = core;
ctxdata.attribsCreate = attribsCreate;
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--;
}
else
{
// use the same shareGroup ID as the share context.
ctxdata.shareGroup = ShareCtx(shareContext);
}
RenderDoc::Inst().AddDeviceFrameCapturer(ctxdata.ctx, this);
}
void WrappedOpenGL::RegisterContext(GLWindowingData winData, void *shareContext, bool core,
bool attribsCreate)
void WrappedOpenGL::RegisterReplayContext(GLWindowingData winData, void *shareContext, bool core,
bool attribsCreate)
{
ContextData &ctxdata = m_ContextData[winData.ctx];
ctxdata.ctx = winData.ctx;
ctxdata.isCore = core;
ctxdata.attribsCreate = attribsCreate;
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--;
}
else
{
// use the same shareGroup ID as the share context.
ctxdata.shareGroup = ShareCtx(shareContext);
}
ActivateContext(winData);
}
void WrappedOpenGL::ActivateContext(GLWindowingData winData)
@@ -911,6 +950,23 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
m_LastContexts.erase(m_LastContexts.begin());
}
// update thread-local context pair
{
ContextPair *ctx = (ContextPair *)Threading::GetTLSValue(m_CurCtxPairTLS);
if(ctx)
{
*ctx = {winData.ctx, ShareCtx(winData.ctx)};
}
else
{
ctx = new ContextPair({winData.ctx, ShareCtx(winData.ctx)});
m_CtxPairs.push_back(ctx);
Threading::SetTLSValue(m_CurCtxPairTLS, ctx);
}
}
// TODO: support multiple GL contexts more explicitly
Keyboard::AddInputWindow((void *)winData.wnd);
@@ -920,24 +976,30 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
if(IsActiveCapturing(m_State))
{
// fetch any initial states needed. Note this is insufficient, and doesn't handle the case
// where
// we might just suddenly start getting commands on a thread that already has a context
// active.
// For now we assume we'll only get GL commands from a single thread
QueuedInitialStateFetch fetch;
fetch.res.Context = winData.ctx;
size_t before = m_QueuedInitialFetches.size();
auto it = std::lower_bound(m_QueuedInitialFetches.begin(), m_QueuedInitialFetches.end(), fetch);
for(; it != m_QueuedInitialFetches.end() && it->res.Context == winData.ctx;)
// where we might just suddenly start getting commands on a thread that already has a context
// active. For now we assume we'll only get GL commands from a single thread
//
// 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)})
{
GetResourceManager()->ContextPrepare_InitialState(it->res);
it = m_QueuedInitialFetches.erase(it);
}
size_t after = m_QueuedInitialFetches.size();
QueuedInitialStateFetch fetch;
fetch.res.ContextShareGroup = ctx;
size_t before = m_QueuedInitialFetches.size();
auto it =
std::lower_bound(m_QueuedInitialFetches.begin(), m_QueuedInitialFetches.end(), fetch);
for(; it != m_QueuedInitialFetches.end() && it->res.ContextShareGroup == ctx;)
{
GetResourceManager()->ContextPrepare_InitialState(it->res);
it = m_QueuedInitialFetches.erase(it);
}
size_t after = m_QueuedInitialFetches.size();
(void)before;
(void)after;
RDCDEBUG("Prepared %zu resources on context %p, %zu left", before - after, winData.ctx, after);
(void)before;
(void)after;
RDCDEBUG("Prepared %zu resources on context/sharegroup %p, %zu left", before - after, ctx,
after);
}
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::MakeContextCurrent);
@@ -1057,6 +1119,59 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
gl_CurChunk = GLChunk::glGenBuffers;
glGenBuffers(1, &ctxdata.m_ClientMemoryIBO);
}
if(IsCaptureMode(m_State))
{
// check if we already have VAO 0 registered for this context. This could be possible if
// VAOs are shared and a previous context in the share group created it.
GLResource vao0 = VertexArrayRes(GetCtx(), 0);
if(!GetResourceManager()->HasCurrentResource(vao0))
{
ResourceId id = GetResourceManager()->RegisterResource(vao0);
GLResourceRecord *record = GetResourceManager()->AddResourceRecord(id);
RDCASSERT(record);
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::glGenVertexArrays);
GLuint zero = 0;
Serialise_glGenVertexArrays(ser, 1, &zero);
record->AddChunk(scope.Get());
}
// give it a name
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::glObjectLabel);
Serialise_glObjectLabel(ser, eGL_VERTEX_ARRAY, 0, -1, "Default VAO");
record->AddChunk(scope.Get());
}
// we immediately mark it dirty since the vertex array tracking functions expect a proper
// VAO
GetResourceManager()->MarkDirtyResource(id);
}
// we also do the same for FBO 0, but this is treated 'specially' as we actually only create
// one backbuffer and re-point all FBOs at it, however there may be several IDs
// corresponding to the default backbuffer. We rename them all.
GLResource fbo0 = FramebufferRes(GetCtx(), 0);
if(!GetResourceManager()->HasCurrentResource(fbo0))
{
ResourceId id = GetResourceManager()->RegisterResource(fbo0);
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::glContextInit);
Serialise_ContextInit(ser);
m_DeviceRecord->AddChunk(scope.Get());
}
}
}
// this is hack but GL context creation is an *utter mess*. For first-frame captures, only
@@ -1312,7 +1427,7 @@ void WrappedOpenGL::SwapBuffers(void *windowHandle)
RenderDoc::Inst().Tick();
// don't do anything if no context is active.
if(GetCtx() == NULL)
if(m_ActiveContexts[Threading::GetCurrentID()].ctx == NULL)
{
m_NoCtxFrames++;
if(m_NoCtxFrames == 100)
@@ -1581,15 +1696,6 @@ void WrappedOpenGL::StartFrameCapture(void *dev, void *wnd)
GetResourceManager()->MarkResourceFrameReferenced(m_DeviceResourceID, eFrameRef_Write);
GLuint prevVAO = 0;
m_Real.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&prevVAO);
m_Real.glBindVertexArray(m_FakeVAO);
GetResourceManager()->MarkVAOReferenced(VertexArrayRes(NULL, m_FakeVAO), eFrameRef_Write, true);
m_Real.glBindVertexArray(prevVAO);
GetResourceManager()->PrepareInitialContents();
FreeCaptureData();
@@ -1695,7 +1801,10 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
// remember to update this estimated chunk length if you add more parameters
SCOPED_SERIALISE_CHUNK(GLChunk::DeviceInitialisation, 32);
SERIALISE_ELEMENT(m_FakeVAOID);
// legacy behaviour where we had a single global VAO 0. Ignore, but preserve for easier
// compatibility with old captures
ResourceId vao;
SERIALISE_ELEMENT(vao);
SERIALISE_ELEMENT(m_FBO0_ID);
}
@@ -2014,6 +2123,21 @@ bool WrappedOpenGL::Serialise_CaptureScope(SerialiserType &ser)
return true;
}
template <typename SerialiserType>
bool WrappedOpenGL::Serialise_ContextInit(SerialiserType &ser)
{
SERIALISE_ELEMENT_LOCAL(FBO0_ID, GetResourceManager()->GetID(FramebufferRes(GetCtx(), 0)));
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
GetResourceManager()->ReplaceResource(FBO0_ID, m_FBO0_ID);
}
return true;
}
void WrappedOpenGL::ContextEndFrame()
{
USE_SCRATCH_SERIALISER();
@@ -2118,6 +2242,18 @@ void WrappedOpenGL::BeginCaptureFrame()
Serialise_BeginCaptureFrame(ser);
m_ContextRecord->AddChunk(scope.Get(), 1);
// mark VAO 0 on this context as referenced
{
GLuint prevVAO = 0;
m_Real.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&prevVAO);
m_Real.glBindVertexArray(0);
GetResourceManager()->MarkVAOReferenced(VertexArrayRes(GetCtx(), 0), eFrameRef_Write, true);
m_Real.glBindVertexArray(prevVAO);
}
}
void WrappedOpenGL::FinishCapture()
@@ -2524,16 +2660,13 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
{
case GLChunk::DeviceInitialisation:
{
SERIALISE_ELEMENT(m_FakeVAOID).Named("VAO 0 ID");
// legacy behaviour where we had a single global VAO 0. Ignore
ResourceId vao;
SERIALISE_ELEMENT(vao).Hidden();
SERIALISE_ELEMENT(m_FBO0_ID).Named("FBO 0 ID");
SERIALISE_CHECK_READ_ERRORS();
GetResourceManager()->AddLiveResource(m_FakeVAOID, VertexArrayRes(NULL, 0));
AddResource(m_FakeVAOID, ResourceType::StateObject, "");
GetReplay()->GetResourceDesc(m_FakeVAOID).SetCustomName("Special VAO 0");
GetResourceManager()->AddLiveResource(m_FBO0_ID, FramebufferRes(GetCtx(), m_FakeBB_FBO));
AddResource(m_FBO0_ID, ResourceType::SwapchainImage, "");
@@ -2557,6 +2690,7 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
return true;
}
case GLChunk::glContextInit: return Serialise_ContextInit(ser);
case GLChunk::glGenBuffersARB:
case GLChunk::glGenBuffers: return Serialise_glGenBuffers(ser, 0, 0);
@@ -4139,7 +4273,7 @@ void WrappedOpenGL::AddUsage(const DrawcallDescription &d)
GLResourceManager *rm = GetResourceManager();
void *ctx = GetCtx();
ContextPair &ctx = GetCtx();
uint32_t e = d.eventId;
+20 -8
View File
@@ -130,6 +130,12 @@ private:
static std::map<uint64_t, GLWindowingData> m_ActiveContexts;
ContextPair m_EmptyPair;
uint64_t m_CurCtxPairTLS;
std::vector<ContextPair *> m_CtxPairs;
uintptr_t m_ShareGroupID;
std::vector<GLWindowingData> m_LastContexts;
public:
@@ -346,10 +352,6 @@ private:
GLuint m_FakeBB_FBO;
GLuint m_FakeBB_Color;
GLuint m_FakeBB_DepthStencil;
GLuint m_FakeVAO;
GLsizeiptr m_FakeIdxSize;
ResourceId m_FakeVAOID;
ResourceId m_FBO0_ID;
uint32_t m_InitChunkIndex = 0;
@@ -365,6 +367,9 @@ private:
template <typename SerialiserType>
bool Serialise_CaptureScope(SerialiserType &ser);
template <typename SerialiserType>
bool Serialise_ContextInit(SerialiserType &ser);
bool HasSuccessfulCapture(CaptureFailReason &reason)
{
reason = m_FailureReason;
@@ -385,6 +390,7 @@ private:
ContextData()
{
ctx = NULL;
shareGroup = NULL;
built = ready = false;
attribsCreate = false;
@@ -406,6 +412,8 @@ private:
void *ctx;
void *shareGroup;
bool built;
bool ready;
@@ -496,7 +504,10 @@ private:
{
GLResource res;
bool operator<(const QueuedInitialStateFetch &o) const { return res.Context < o.res.Context; }
bool operator<(const QueuedInitialStateFetch &o) const
{
return res.ContextShareGroup < o.res.ContextShareGroup;
}
};
vector<QueuedInitialStateFetch> m_QueuedInitialFetches;
@@ -555,7 +566,8 @@ public:
bool isGLESMode() { return m_DriverType == RDCDriver::OpenGLES; }
RDCDriver GetDriverType() { return m_DriverType; }
GLInitParams &GetInitParams() { return m_InitParams; }
static void *GetCtx();
ContextPair &GetCtx();
void *ShareCtx(void *ctx) { return ctx ? m_ContextData[ctx].shareGroup : NULL; }
void SetStructuredExport(uint64_t sectionVersion)
{
m_SectionVersion = sectionVersion;
@@ -581,7 +593,6 @@ public:
ReplayStatus ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
GLuint GetFakeBBFBO() { return m_FakeBB_FBO; }
GLuint GetFakeVAO() { return m_FakeVAO; }
FrameRecord &GetFrameRecord() { return m_FrameRecord; }
const APIEvent &GetEvent(uint32_t eventId);
@@ -592,7 +603,8 @@ public:
vector<EventUsage> GetUsage(ResourceId id) { return m_ResourceUses[id]; }
void CreateContext(GLWindowingData winData, void *shareContext, GLInitParams initParams,
bool core, bool attribsCreate);
void RegisterContext(GLWindowingData winData, void *shareContext, bool core, bool attribsCreate);
void RegisterReplayContext(GLWindowingData winData, void *shareContext, bool core,
bool attribsCreate);
void DeleteContext(void *contextHandle);
void ActivateContext(GLWindowingData winData);
void WindowSize(void *windowHandle, uint32_t w, uint32_t h);
+34 -27
View File
@@ -160,6 +160,8 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
{
FramebufferInitialData &data = initContents.fbo;
ContextPair &ctx = m_GL->GetCtx();
RDCASSERT(!data.valid);
data.valid = true;
@@ -201,8 +203,7 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
}
a.layered = (layered != 0);
a.obj = (type == eGL_RENDERBUFFER) ? RenderbufferRes(res.Context, object)
: TextureRes(res.Context, object);
a.obj = (type == eGL_RENDERBUFFER) ? RenderbufferRes(ctx, object) : TextureRes(ctx, object);
if(type != eGL_RENDERBUFFER)
{
@@ -234,13 +235,14 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
RDCASSERT(!data.valid);
data.valid = true;
#if ENABLED(RDOC_DEVEL)
if(ProgramRes(m_GL->GetCtx(), 0).Context != NULL)
RDCFATAL("Program resources are context-specific - we assume they aren't");
#endif
// programs are shared
void *shareGroup = m_GL->GetCtx().shareGroup;
for(GLuint i = 0; i < (GLuint)ARRAY_COUNT(data.programs); i++)
{
data.programs[i].Namespace = eResProgram;
data.programs[i].ContextShareGroup = shareGroup;
}
gl.glGetProgramPipelineiv(res.name, eGL_VERTEX_SHADER, (GLint *)&data.programs[0].name);
gl.glGetProgramPipelineiv(res.name, eGL_FRAGMENT_SHADER, (GLint *)&data.programs[4].name);
@@ -256,6 +258,8 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
RDCASSERT(!data.valid);
data.valid = true;
ContextPair &ctx = m_GL->GetCtx();
GLuint prevfeedback = 0;
gl.glGetIntegerv(eGL_TRANSFORM_FEEDBACK_BINDING, (GLint *)&prevfeedback);
@@ -268,7 +272,7 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
{
GLuint buffer = 0;
gl.glGetIntegeri_v(eGL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i, (GLint *)&buffer);
data.Buffer[i] = BufferRes(res.Context, buffer);
data.Buffer[i] = BufferRes(ctx, buffer);
gl.glGetInteger64i_v(eGL_TRANSFORM_FEEDBACK_BUFFER_START, i, (GLint64 *)&data.Offset[i]);
gl.glGetInteger64i_v(eGL_TRANSFORM_FEEDBACK_BUFFER_SIZE, i, (GLint64 *)&data.Size[i]);
}
@@ -282,13 +286,12 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
RDCASSERT(!data.valid);
data.valid = true;
ContextPair &ctx = m_GL->GetCtx();
GLuint prevVAO = 0;
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&prevVAO);
if(res.name == 0)
gl.glBindVertexArray(m_GL->GetFakeVAO());
else
gl.glBindVertexArray(res.name);
gl.glBindVertexArray(res.name);
for(GLuint i = 0; i < 16; i++)
{
@@ -306,7 +309,7 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
GLuint buffer = GetBoundVertexBuffer(gl, i);
data.VertexBuffers[i].Buffer = BufferRes(res.Context, buffer);
data.VertexBuffers[i].Buffer = BufferRes(ctx, buffer);
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_STRIDE, i, (GLint *)&data.VertexBuffers[i].Stride);
gl.glGetIntegeri_v(eGL_VERTEX_BINDING_OFFSET, i, (GLint *)&data.VertexBuffers[i].Offset);
@@ -315,7 +318,7 @@ void GLResourceManager::ContextPrepare_InitialState(GLResource res)
GLuint buffer = 0;
gl.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint *)&buffer);
data.ElementArrayBuffer = BufferRes(res.Context, buffer);
data.ElementArrayBuffer = BufferRes(ctx, buffer);
gl.glBindVertexArray(prevVAO);
}
@@ -359,7 +362,8 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
gl.glBindBuffer(eGL_COPY_READ_BUFFER, oldbuf1);
gl.glBindBuffer(eGL_COPY_WRITE_BUFFER, oldbuf2);
SetInitialContents(Id, GLInitialContents(BufferRes(res.Context, buf), length));
SetInitialContents(
Id, GLInitialContents(GLResource(res.ContextShareGroup, eResBuffer, buf), length));
}
else if(res.Namespace == eResProgram)
{
@@ -383,9 +387,11 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
}
else if(res.Namespace == eResFramebuffer)
{
// if FBOs aren't shared we need to fetch the data for this FBO on the right context. It's
// not safe for us to go changing contexts ourselves (the context could be active on another
// thread), so instead we'll queue this up to fetch when we are on the correct context.
// We need to fetch the data for this FBO on the right context.
// It's not safe for us to go changing contexts ourselves (the context could be active on
// another thread), so instead we'll queue this up to fetch when we are on a correct context.
// The correct context depends on whether the object is shared or not - if it's shared, any
// context in the same share group will do, otherwise it must be precisely the right context
//
// Because we've already allocated and set the blob above, it can be filled in any time
// before serialising (end of the frame, and if the context is never used before the end of
@@ -395,7 +401,8 @@ 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.
if(!VendorCheck[VendorCheck_EXT_fbo_shared] && res.Context && m_GL->GetCtx() != res.Context)
ContextPair &ctx = m_GL->GetCtx();
if(res.ContextShareGroup != ctx.ctx && res.ContextShareGroup != ctx.shareGroup)
{
m_GL->QueuePrepareInitialState(res);
}
@@ -411,7 +418,8 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
{
// queue initial state fetching if we're not on the right context, see above in FBOs for more
// explanation of this.
if(res.Context && m_GL->GetCtx() != res.Context)
ContextPair &ctx = m_GL->GetCtx();
if(res.ContextShareGroup != ctx.ctx && res.ContextShareGroup != ctx.shareGroup)
{
m_GL->QueuePrepareInitialState(res);
}
@@ -424,7 +432,8 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
{
// queue initial state fetching if we're not on the right context, see above in FBOs for more
// explanation of this.
if(res.Context && m_GL->GetCtx() != res.Context)
ContextPair &ctx = m_GL->GetCtx();
if(res.ContextShareGroup != ctx.ctx && res.ContextShareGroup != ctx.shareGroup)
{
m_GL->QueuePrepareInitialState(res);
}
@@ -437,7 +446,8 @@ bool GLResourceManager::Prepare_InitialState(GLResource res)
{
// queue initial state fetching if we're not on the right context, see above in FBOs for more
// explanation of this.
if(res.Context && m_GL->GetCtx() != res.Context)
ContextPair &ctx = m_GL->GetCtx();
if(res.ContextShareGroup != ctx.ctx && res.ContextShareGroup != ctx.shareGroup)
{
m_GL->QueuePrepareInitialState(res);
}
@@ -826,7 +836,7 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc
(GLint *)&state.maxLevel);
}
initContents.resource = TextureRes(res.Context, tex);
initContents.resource = GLResource(res.ContextShareGroup, eResTexture, tex);
}
else
{
@@ -835,7 +845,7 @@ void GLResourceManager::PrepareTextureInitialContents(ResourceId liveid, Resourc
GLuint bufName = 0;
gl.glGetTextureLevelParameterivEXT(res.name, details.curType, 0,
eGL_TEXTURE_BUFFER_DATA_STORE_BINDING, (GLint *)&bufName);
state.texBuffer = BufferRes(res.Context, bufName);
state.texBuffer = GLResource(res.ContextShareGroup, eResBuffer, bufName);
gl.glGetTextureLevelParameterivEXT(res.name, details.curType, 0, eGL_TEXTURE_BUFFER_OFFSET,
(GLint *)&state.texBufOffs);
@@ -2079,10 +2089,7 @@ void GLResourceManager::Apply_InitialState(GLResource live, GLInitialContents in
GLuint VAO = 0;
gl.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, (GLint *)&VAO);
if(live.name == 0)
gl.glBindVertexArray(m_GL->GetFakeVAO());
else
gl.glBindVertexArray(live.name);
gl.glBindVertexArray(live.name);
for(GLuint i = 0; i < 16; i++)
{
+12 -8
View File
@@ -38,6 +38,8 @@ void GLResourceManager::MarkVAOReferenced(GLResource res, FrameRefType ref, bool
if(res.name || allowFake0)
{
ContextPair &ctx = m_GL->GetCtx();
MarkResourceFrameReferenced(res, ref == eFrameRef_Unknown ? eFrameRef_Unknown : eFrameRef_Read);
GLint numVBufferBindings = 16;
@@ -47,12 +49,12 @@ void GLResourceManager::MarkVAOReferenced(GLResource res, FrameRefType ref, bool
{
GLuint buffer = GetBoundVertexBuffer(gl, i);
MarkResourceFrameReferenced(BufferRes(res.Context, buffer), ref);
MarkResourceFrameReferenced(BufferRes(ctx, buffer), ref);
}
GLuint ibuffer = 0;
gl.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint *)&ibuffer);
MarkResourceFrameReferenced(BufferRes(res.Context, ibuffer), ref);
MarkResourceFrameReferenced(BufferRes(ctx, ibuffer), ref);
}
}
@@ -65,6 +67,8 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref)
const GLHookSet &gl = m_GL->GetHookset();
ContextPair &ctx = m_GL->GetCtx();
GLint numCols = 8;
gl.glGetIntegerv(eGL_MAX_COLOR_ATTACHMENTS, &numCols);
@@ -81,9 +85,9 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref)
(GLint *)&type);
if(type == eGL_RENDERBUFFER)
MarkResourceFrameReferenced(RenderbufferRes(res.Context, name), ref);
MarkResourceFrameReferenced(RenderbufferRes(ctx, name), ref);
else
MarkResourceFrameReferenced(TextureRes(res.Context, name), ref);
MarkResourceFrameReferenced(TextureRes(ctx, name), ref);
}
gl.glGetNamedFramebufferAttachmentParameterivEXT(
@@ -94,9 +98,9 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref)
if(name)
{
if(type == eGL_RENDERBUFFER)
MarkResourceFrameReferenced(RenderbufferRes(res.Context, name), ref);
MarkResourceFrameReferenced(RenderbufferRes(ctx, name), ref);
else
MarkResourceFrameReferenced(TextureRes(res.Context, name), ref);
MarkResourceFrameReferenced(TextureRes(ctx, name), ref);
}
gl.glGetNamedFramebufferAttachmentParameterivEXT(
@@ -107,9 +111,9 @@ void GLResourceManager::MarkFBOReferenced(GLResource res, FrameRefType ref)
if(name)
{
if(type == eGL_RENDERBUFFER)
MarkResourceFrameReferenced(RenderbufferRes(res.Context, name), ref);
MarkResourceFrameReferenced(RenderbufferRes(ctx, name), ref);
else
MarkResourceFrameReferenced(TextureRes(res.Context, name), ref);
MarkResourceFrameReferenced(TextureRes(ctx, name), ref);
}
}
+3 -3
View File
@@ -106,7 +106,7 @@ public:
size_t count = 0;
for(auto it = m_CurrentResourceIds.begin(); it != m_CurrentResourceIds.end(); it++)
{
if(it->first.Context == context)
if(it->first.ContextShareGroup == context)
{
++count;
ResourceId res = it->second;
@@ -117,7 +117,7 @@ public:
it = m_CurrentResourceIds.erase(it);
}
}
RDCDEBUG("Removed %zu/%zu resources belonging to context %p", count,
RDCDEBUG("Removed %zu/%zu resources belonging to context/sharegroup %p", count,
m_CurrentResourceIds.size(), context);
}
@@ -213,7 +213,7 @@ public:
using ResourceManager::MarkCleanResource;
void MarkCleanResource(GLResource res) { return ResourceManager::MarkCleanResource(GetID(res)); }
void RegisterSync(void *ctx, GLsync sync, GLuint &name, ResourceId &id)
void RegisterSync(ContextPair &ctx, GLsync sync, GLuint &name, ResourceId &id)
{
name = (GLuint)Atomic::Inc64(&m_SyncName);
id = RegisterResource(SyncRes(ctx, name));
+3
View File
@@ -210,6 +210,9 @@ uint64_t GLReplay::MakeOutputWindow(WindowingData window, bool depth)
m_pDriver->m_Platform.GetOutputWindowDimensions(win, win.width, win.height);
MakeCurrentReplayContext(&win);
m_pDriver->RegisterReplayContext(win, m_ReplayCtx.ctx, true, true);
InitOutputWindow(win);
CreateOutputWindowBackbuffer(win, depth);
+2 -2
View File
@@ -41,7 +41,7 @@ void GLReplay::CreateOverlayProgram(GLuint Program, GLuint Pipeline, GLuint frag
{
WrappedOpenGL &gl = *m_pDriver;
void *ctx = m_ReplayCtx.ctx;
ContextPair &ctx = gl.GetCtx();
// delete the old program if it exists
if(DebugData.overlayProg != 0)
@@ -151,7 +151,7 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeHint, DebugOve
GLMarkerRegion renderoverlay(StringFormat::Fmt("RenderOverlay %d", overlay));
void *ctx = m_ReplayCtx.ctx;
ContextPair &ctx = gl.GetCtx();
GLRenderState rs(&gl.GetHookset());
rs.FetchState(&gl);
+5 -3
View File
@@ -414,7 +414,7 @@ void GLReplay::InitPostVSBuffers(uint32_t eventId)
}
else // drawcall is indexed
{
ResourceId idxId = rm->GetID(BufferRes(NULL, elArrayBuffer));
ResourceId idxId = rm->GetID(BufferRes(gl.GetCtx(), elArrayBuffer));
bytebuf idxdata;
GetBufferData(idxId, drawcall->indexOffset * drawcall->indexByteWidth,
@@ -1422,6 +1422,8 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDat
GLPostVSData postvs;
RDCEraseEl(postvs);
ContextPair ctx = {m_ReplayCtx.ctx, m_pDriver->ShareCtx(m_ReplayCtx.ctx)};
if(m_PostVSData.find(eventId) != m_PostVSData.end())
postvs = m_PostVSData[eventId];
@@ -1430,7 +1432,7 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDat
MeshFormat ret;
if(s.useIndices && s.idxBuf)
ret.indexResourceId = m_pDriver->GetResourceManager()->GetID(BufferRes(NULL, s.idxBuf));
ret.indexResourceId = m_pDriver->GetResourceManager()->GetID(BufferRes(ctx, s.idxBuf));
else
ret.indexResourceId = ResourceId();
ret.indexByteOffset = 0;
@@ -1438,7 +1440,7 @@ MeshFormat GLReplay::GetPostVSBuffers(uint32_t eventId, uint32_t instID, MeshDat
ret.baseVertex = 0;
if(s.buf)
ret.vertexResourceId = m_pDriver->GetResourceManager()->GetID(BufferRes(NULL, s.buf));
ret.vertexResourceId = m_pDriver->GetResourceManager()->GetID(BufferRes(ctx, s.buf));
else
ret.vertexResourceId = ResourceId();
+31 -19
View File
@@ -525,7 +525,7 @@ void GLRenderState::MarkDirty(WrappedOpenGL *gl)
{
GLResourceManager *manager = gl->GetResourceManager();
void *ctx = gl->GetCtx();
ContextPair &ctx = gl->GetCtx();
GLint maxCount = 0;
GLuint name = 0;
@@ -711,9 +711,9 @@ bool GLRenderState::CheckEnableDisableParam(GLenum pname)
void GLRenderState::FetchState(WrappedOpenGL *gl)
{
void *ctx = WrappedOpenGL::GetCtx();
ContextPair &ctx = gl->GetCtx();
if(ctx == NULL)
if(ctx.ctx == NULL)
{
ContextPresent = false;
return;
@@ -744,19 +744,24 @@ void GLRenderState::FetchState(WrappedOpenGL *gl)
sizeof(Tex2DMSArray) == sizeof(Samplers),
"All texture arrays should be identically sized");
#if ENABLED(RDOC_DEVEL)
if(TextureRes(ctx, 0).Context != NULL)
RDCFATAL("Texture resources are context-specific - we assume they aren't");
if(BufferRes(ctx, 0).Context != NULL)
RDCFATAL("Buffer resources are context-specific - we assume they aren't");
if(SamplerRes(ctx, 0).Context != NULL)
RDCFATAL("Sampler resources are context-specific - we assume they aren't");
#endif
for(GLuint i = 0; i < RDCMIN(maxTextures, (GLuint)ARRAY_COUNT(Tex2D)); i++)
{
m_Real->glActiveTexture(GLenum(eGL_TEXTURE0 + i));
// textures are always shared
Tex1D[i].ContextShareGroup = ctx.shareGroup;
Tex2D[i].ContextShareGroup = ctx.shareGroup;
Tex3D[i].ContextShareGroup = ctx.shareGroup;
Tex1DArray[i].ContextShareGroup = ctx.shareGroup;
Tex2DArray[i].ContextShareGroup = ctx.shareGroup;
TexCube[i].ContextShareGroup = ctx.shareGroup;
TexRect[i].ContextShareGroup = ctx.shareGroup;
TexBuffer[i].ContextShareGroup = ctx.shareGroup;
Tex2DMS[i].ContextShareGroup = ctx.shareGroup;
Tex2DMSArray[i].ContextShareGroup = ctx.shareGroup;
TexCubeArray[i].ContextShareGroup = ctx.shareGroup;
Samplers[i].ContextShareGroup = ctx.shareGroup;
if(!IsGLES)
m_Real->glGetIntegerv(eGL_TEXTURE_BINDING_1D, (GLint *)&Tex1D[i].name);
else
@@ -806,6 +811,9 @@ void GLRenderState::FetchState(WrappedOpenGL *gl)
{
GLboolean layered = GL_FALSE;
// textures are always shared
Images[i].res.ContextShareGroup = ctx.shareGroup;
m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_NAME, i, (GLint *)&Images[i].res.name);
m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_LEVEL, i, (GLint *)&Images[i].level);
m_Real->glGetIntegeri_v(eGL_IMAGE_BINDING_ACCESS, i, (GLint *)&Images[i].access);
@@ -930,6 +938,10 @@ void GLRenderState::FetchState(WrappedOpenGL *gl)
RDCEraseEl(Subroutines);
}
// buffers are always shared
for(size_t i = 0; i < ARRAY_COUNT(BufferBindings); i++)
BufferBindings[i].ContextShareGroup = ctx.shareGroup;
m_Real->glGetIntegerv(eGL_ARRAY_BUFFER_BINDING, (GLint *)&BufferBindings[eBufIdx_Array].name);
m_Real->glGetIntegerv(eGL_COPY_READ_BUFFER_BINDING,
(GLint *)&BufferBindings[eBufIdx_Copy_Read].name);
@@ -1000,6 +1012,9 @@ void GLRenderState::FetchState(WrappedOpenGL *gl)
m_Real->glGetIntegerv(idxBufs[b].maxcount, &maxCount);
for(int i = 0; i < idxBufs[b].count && i < maxCount; i++)
{
// buffers are always shared
idxBufs[b].bufs[i].res.ContextShareGroup = ctx.shareGroup;
m_Real->glGetIntegeri_v(idxBufs[b].binding, i, (GLint *)&idxBufs[b].bufs[i].res.name);
m_Real->glGetInteger64i_v(idxBufs[b].start, i, (GLint64 *)&idxBufs[b].bufs[i].start);
m_Real->glGetInteger64i_v(idxBufs[b].size, i, (GLint64 *)&idxBufs[b].bufs[i].size);
@@ -1260,9 +1275,9 @@ void GLRenderState::FetchState(WrappedOpenGL *gl)
void GLRenderState::ApplyState(WrappedOpenGL *gl)
{
void *ctx = WrappedOpenGL::GetCtx();
ContextPair &ctx = gl->GetCtx();
if(!ContextPresent || ctx == NULL)
if(!ContextPresent || ctx.ctx == NULL)
return;
for(GLuint i = 0; i < eEnabled_Count; i++)
@@ -1322,10 +1337,7 @@ void GLRenderState::ApplyState(WrappedOpenGL *gl)
m_Real->glActiveTexture(ActiveTexture);
if(VAO.name)
m_Real->glBindVertexArray(VAO.name);
else
m_Real->glBindVertexArray(gl->GetFakeVAO());
m_Real->glBindVertexArray(VAO.name);
if(HasExt[ARB_transform_feedback2])
m_Real->glBindTransformFeedback(eGL_TRANSFORM_FEEDBACK, FeedbackObj.name);
@@ -1548,7 +1560,7 @@ void GLRenderState::ApplyState(WrappedOpenGL *gl)
// this will always return true during capture, but on replay we only do
// this work if we're on the replay context
if(gl->GetReplay()->IsReplayContext(ctx))
if(gl->GetReplay()->IsReplayContext(ctx.ctx))
{
// apply drawbuffers/readbuffer to default framebuffer
m_Real->glBindFramebuffer(eGL_READ_FRAMEBUFFER, gl->GetFakeBBFBO());
+1 -1
View File
@@ -540,7 +540,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
RDCASSERT(strlen(text) < (size_t)FONT_MAX_CHARS);
ContextData &ctxdata = m_ContextData[GetCtx()];
ContextData &ctxdata = GetCtxData();
if(!ctxdata.built || !ctxdata.ready)
return;
+3 -3
View File
@@ -210,7 +210,7 @@ void GLReplay::SetReplayData(GLWindowingData data)
{
m_ReplayCtx = data;
if(m_pDriver != NULL)
m_pDriver->RegisterContext(m_ReplayCtx, NULL, true, true);
m_pDriver->RegisterReplayContext(m_ReplayCtx, NULL, true, true);
InitDebugData();
@@ -662,7 +662,7 @@ void GLReplay::SavePipelineState()
// Index buffer
void *ctx = m_ReplayCtx.ctx;
ContextPair &ctx = gl.GetCtx();
GLuint ibuffer = 0;
gl.glGetIntegerv(eGL_ELEMENT_ARRAY_BUFFER_BINDING, (GLint *)&ibuffer);
@@ -1976,7 +1976,7 @@ void GLReplay::FillCBufferVariables(ResourceId shader, string entryPoint, uint32
else
{
ResourceId id =
m_pDriver->GetResourceManager()->GetID(ProgramPipeRes(m_ReplayCtx.ctx, curProg));
m_pDriver->GetResourceManager()->GetID(ProgramPipeRes(m_pDriver->GetCtx(), curProg));
auto &pipeDetails = m_pDriver->m_Pipelines[id];
size_t s = ShaderIdx(shaderDetails.type);
+2 -1
View File
@@ -156,13 +156,14 @@ ReplayStatus GLES_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
WrappedOpenGL *gl = new WrappedOpenGL(real, GetGLPlatformEGL());
gl->SetDriverType(RDCDriver::OpenGLES);
gl->Initialise(initParams, ver);
RDCLOG("Created OPEN GL ES replay device.");
GLReplay *replay = gl->GetReplay();
replay->SetProxy(rdc == NULL);
replay->SetReplayData(data);
gl->Initialise(initParams, ver);
*driver = (IReplayDriver *)replay;
return ReplayStatus::Succeeded;
}
+3 -2
View File
@@ -290,9 +290,8 @@ ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
}
WrappedOpenGL *gl = new WrappedOpenGL(real, GetGLPlatform());
gl->Initialise(initParams, ver);
RDCLOG("Created device.");
GLReplay *replay = gl->GetReplay();
replay->SetProxy(rdc == NULL);
GLWindowingData data;
@@ -301,6 +300,8 @@ ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
data.wnd = pbuffer;
replay->SetReplayData(data);
gl->Initialise(initParams, ver);
*driver = (IReplayDriver *)replay;
return ReplayStatus::Succeeded;
}
+3 -2
View File
@@ -318,9 +318,8 @@ ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
}
WrappedOpenGL *gl = new WrappedOpenGL(real, GetGLPlatform());
gl->Initialise(initParams, ver);
RDCLOG("Created device.");
GLReplay *replay = gl->GetReplay();
replay->SetProxy(rdc == NULL);
GLWindowingData data;
@@ -329,6 +328,8 @@ ReplayStatus GL_CreateReplayDevice(RDCFile *rdc, IReplayDriver **driver)
data.wnd = w;
replay->SetReplayData(data);
gl->Initialise(initParams, ver);
*driver = (IReplayDriver *)replay;
return ReplayStatus::Succeeded;
}
+39 -38
View File
@@ -102,37 +102,37 @@ struct GLResource
{
GLResource()
{
ContextShareGroup = NULL;
Namespace = eResUnknown;
Context = NULL;
name = 0;
}
GLResource(NullInitialiser)
{
ContextShareGroup = NULL;
Namespace = eResUnknown;
Context = NULL;
name = 0;
}
GLResource(void *ctx, GLNamespace n, GLuint i)
{
Context = ctx;
ContextShareGroup = ctx;
Namespace = n;
name = i;
}
void *Context;
void *ContextShareGroup;
GLNamespace Namespace;
GLuint name;
bool operator==(const GLResource &o) const
{
return Context == o.Context && Namespace == o.Namespace && name == o.name;
return ContextShareGroup == o.ContextShareGroup && Namespace == o.Namespace && name == o.name;
}
bool operator!=(const GLResource &o) const { return !(*this == o); }
bool operator<(const GLResource &o) const
{
if(Context != o.Context)
return Context < o.Context;
if(ContextShareGroup != o.ContextShareGroup)
return ContextShareGroup < o.ContextShareGroup;
if(Namespace != o.Namespace)
return Namespace < o.Namespace;
return name < o.name;
@@ -141,64 +141,65 @@ struct GLResource
DECLARE_REFLECTION_STRUCT(GLResource);
struct ContextPair
{
void *ctx;
void *shareGroup;
};
// Shared objects currently ignore the context parameter.
// For correctness we'd need to check if the context is shared and if so move up to a 'parent'
// so the context value ends up being identical for objects being shared, but can be different
// for objects in non-shared contexts
inline GLResource TextureRes(void *ctx, GLuint i)
inline GLResource TextureRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResTexture, i);
return GLResource(c.shareGroup, eResTexture, i);
}
inline GLResource SamplerRes(void *ctx, GLuint i)
inline GLResource SamplerRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResSampler, i);
return GLResource(c.shareGroup, eResSampler, i);
}
inline GLResource FramebufferRes(void *ctx, GLuint i)
inline GLResource FramebufferRes(const ContextPair &c, GLuint i)
{
return GLResource(VendorCheck[VendorCheck_EXT_fbo_shared] ? NULL : ctx, eResFramebuffer, i);
return GLResource(VendorCheck[VendorCheck_EXT_fbo_shared] ? c.shareGroup : c.ctx, eResFramebuffer,
i);
}
inline GLResource RenderbufferRes(void *ctx, GLuint i)
inline GLResource RenderbufferRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResRenderbuffer, i);
return GLResource(c.shareGroup, eResRenderbuffer, i);
}
inline GLResource BufferRes(void *ctx, GLuint i)
inline GLResource BufferRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResBuffer, i);
return GLResource(c.shareGroup, eResBuffer, i);
}
inline GLResource VertexArrayRes(void *ctx, GLuint i)
inline GLResource VertexArrayRes(const ContextPair &c, GLuint i)
{
return GLResource(VendorCheck[VendorCheck_EXT_vao_shared] ? NULL : ctx, eResVertexArray, i);
return GLResource(VendorCheck[VendorCheck_EXT_vao_shared] ? c.shareGroup : c.ctx, eResVertexArray,
i);
}
inline GLResource ShaderRes(void *ctx, GLuint i)
inline GLResource ShaderRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResShader, i);
return GLResource(c.shareGroup, eResShader, i);
}
inline GLResource ProgramRes(void *ctx, GLuint i)
inline GLResource ProgramRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResProgram, i);
return GLResource(c.shareGroup, eResProgram, i);
}
inline GLResource ProgramPipeRes(void *ctx, GLuint i)
inline GLResource ProgramPipeRes(const ContextPair &c, GLuint i)
{
return GLResource(ctx, eResProgramPipe, i);
return GLResource(c.ctx, eResProgramPipe, i);
}
inline GLResource FeedbackRes(void *ctx, GLuint i)
inline GLResource FeedbackRes(const ContextPair &c, GLuint i)
{
return GLResource(ctx, eResFeedback, i);
return GLResource(c.ctx, eResFeedback, i);
}
inline GLResource QueryRes(void *ctx, GLuint i)
inline GLResource QueryRes(const ContextPair &c, GLuint i)
{
return GLResource(ctx, eResQuery, i);
return GLResource(c.ctx, eResQuery, i);
}
inline GLResource SyncRes(void *ctx, GLuint i)
inline GLResource SyncRes(const ContextPair &c, GLuint i)
{
(void)ctx;
return GLResource(NULL, eResSync, i);
return GLResource(c.shareGroup, eResSync, i);
}
struct GLResourceRecord : public ResourceRecord
+1
View File
@@ -36,6 +36,7 @@ std::string DoStringise(const GLChunk &el)
STRINGISE_ENUM_CLASS_NAMED(MakeContextCurrent, "MakeContextCurrent");
STRINGISE_ENUM_CLASS_NAMED(glIndirectSubCommand, "Indirect sub-command");
STRINGISE_ENUM_CLASS_NAMED(glContextInit, "Context Initialisation");
STRINGISE_ENUM_CLASS(vrapi_CreateTextureSwapChain);
STRINGISE_ENUM_CLASS(vrapi_CreateTextureSwapChain2);
@@ -3042,9 +3042,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribOffsetEXT(
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
// some intel drivers don't properly update query states (like GL_VERTEX_ATTRIB_ARRAY_SIZE)
// unless the VAO is also bound when performing EXT_dsa functions :(
GLuint prevVAO = 0;
@@ -3168,9 +3165,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribIOffsetEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
// some intel drivers don't properly update query states (like GL_VERTEX_ATTRIB_ARRAY_SIZE)
// unless the VAO is also bound when performing EXT_dsa functions :(
GLuint prevVAO = 0;
@@ -3294,9 +3288,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribLOffsetEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
// some intel drivers don't properly update query states (like GL_VERTEX_ATTRIB_ARRAY_SIZE)
// unless the VAO is also bound when performing EXT_dsa functions :(
GLuint prevVAO = 0;
@@ -3415,9 +3406,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribBindingEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
m_Real.glVertexArrayVertexAttribBindingEXT(vaobj.name, attribindex, bindingindex);
}
return true;
@@ -3500,9 +3488,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribFormatEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
m_Real.glVertexArrayVertexAttribFormatEXT(vaobj.name, attribindex, size, type, normalized,
relativeoffset);
}
@@ -3591,9 +3576,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribIFormatEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
m_Real.glVertexArrayVertexAttribIFormatEXT(vaobj.name, attribindex, size, type, relativeoffset);
}
@@ -3678,9 +3660,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribLFormatEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
m_Real.glVertexArrayVertexAttribLFormatEXT(vaobj.name, attribindex, size, type, relativeoffset);
}
@@ -3762,9 +3741,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribDivisorEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
// at the time of writing, AMD driver seems to not have this entry point
if(m_Real.glVertexArrayVertexAttribDivisorEXT)
{
@@ -3852,9 +3828,6 @@ bool WrappedOpenGL::Serialise_glEnableVertexArrayAttribEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
GLint prevVAO = 0;
m_Real.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, &prevVAO);
@@ -3935,9 +3908,6 @@ bool WrappedOpenGL::Serialise_glDisableVertexArrayAttribEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
GLint prevVAO = 0;
m_Real.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, &prevVAO);
@@ -4134,9 +4104,6 @@ bool WrappedOpenGL::Serialise_glBindVertexArray(SerialiserType &ser, GLuint vaob
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
m_Real.glBindVertexArray(vaobj.name);
}
@@ -4185,9 +4152,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayElementBuffer(SerialiserType &ser, GL
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
// might not have the live resource if this is a pre-capture chunk, and the buffer was never
// referenced at all in the actual frame
if(buffer.name)
@@ -4256,9 +4220,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayBindVertexBufferEXT(SerialiserType &s
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
if(buffer.name)
{
m_Buffers[GetResourceManager()->GetID(buffer)].curType = eGL_ARRAY_BUFFER;
@@ -4393,9 +4354,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexBuffers(SerialiserType &ser, GL
offs.push_back((GLintptr)offsets[i]);
}
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This
// is necessary since these functions can be serialised even if ARB_dsa was not used originally,
@@ -4522,9 +4480,6 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexBindingDivisorEXT(SerialiserTyp
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_FakeVAO;
m_Real.glVertexArrayVertexBindingDivisorEXT(vaobj.name, bindingindex, divisor);
}
@@ -3139,9 +3139,6 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferfv(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This
// is necessary since these functions can be serialised even if ARB_dsa was not used originally,
@@ -3265,9 +3262,6 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferiv(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This
// is necessary since these functions can be serialised even if ARB_dsa was not used originally,
@@ -3382,9 +3376,6 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferuiv(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This
// is necessary since these functions can be serialised even if ARB_dsa was not used originally,
@@ -3488,9 +3479,6 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferfi(SerialiserType &ser, GLu
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This
// is necessary since these functions can be serialised even if ARB_dsa was not used originally,
@@ -163,9 +163,6 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTextureEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
m_Real.glNamedFramebufferTextureEXT(framebuffer.name, attachment, texture.name, level);
if(IsLoading(m_State) && texture.name)
@@ -304,9 +301,6 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTexture1DEXT(SerialiserType &ser
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
m_Real.glNamedFramebufferTexture1DEXT(framebuffer.name, attachment, textarget, texture.name,
level);
@@ -449,9 +443,6 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTexture2DEXT(SerialiserType &ser
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
m_Real.glNamedFramebufferTexture2DEXT(framebuffer.name, attachment, textarget, texture.name,
level);
@@ -700,9 +691,6 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTexture3DEXT(SerialiserType &ser
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
m_Real.glNamedFramebufferTexture3DEXT(framebuffer.name, attachment, textarget, texture.name,
level, zoffset);
@@ -848,9 +836,6 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferRenderbufferEXT(SerialiserType &
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
m_Real.glNamedFramebufferRenderbufferEXT(framebuffer.name, attachment, renderbuffertarget,
renderbuffer.name);
@@ -977,9 +962,6 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTextureLayerEXT(SerialiserType &
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
m_Real.glNamedFramebufferTextureLayerEXT(framebuffer.name, attachment, texture.name, level,
layer);
@@ -1383,20 +1365,13 @@ bool WrappedOpenGL::Serialise_glFramebufferReadBufferEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
{
// since we are faking the default framebuffer with our own
// to see the results, replace back/front/left/right with color attachment 0
if(mode == eGL_BACK_LEFT || mode == eGL_BACK_RIGHT || mode == eGL_BACK ||
mode == eGL_FRONT_LEFT || mode == eGL_FRONT_RIGHT || mode == eGL_FRONT)
mode = eGL_COLOR_ATTACHMENT0;
// since we are faking the default framebuffer with our own
// to see the results, replace back/front/left/right with color attachment 0
if(mode == eGL_BACK_LEFT || mode == eGL_BACK_RIGHT || mode == eGL_BACK ||
mode == eGL_FRONT_LEFT || mode == eGL_FRONT_RIGHT || mode == eGL_FRONT)
mode = eGL_COLOR_ATTACHMENT0;
m_Real.glFramebufferReadBufferEXT(m_FakeBB_FBO, mode);
}
else
{
m_Real.glFramebufferReadBufferEXT(framebuffer.name, mode);
}
m_Real.glFramebufferReadBufferEXT(framebuffer.name, mode);
}
return true;
@@ -1464,7 +1439,7 @@ bool WrappedOpenGL::Serialise_glBindFramebuffer(SerialiserType &ser, GLenum targ
if(IsReplayingAndReading())
{
m_Real.glBindFramebuffer(target, framebuffer.name ? framebuffer.name : m_FakeBB_FBO);
m_Real.glBindFramebuffer(target, framebuffer.name);
}
return true;
@@ -1472,9 +1447,6 @@ bool WrappedOpenGL::Serialise_glBindFramebuffer(SerialiserType &ser, GLenum targ
void WrappedOpenGL::glBindFramebuffer(GLenum target, GLuint framebuffer)
{
if(framebuffer == 0 && IsReplayMode(m_State))
framebuffer = m_FakeBB_FBO;
SERIALISE_TIME_CALL(m_Real.glBindFramebuffer(target, framebuffer));
if(IsActiveCapturing(m_State))
@@ -1508,20 +1480,13 @@ bool WrappedOpenGL::Serialise_glFramebufferDrawBufferEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
{
// since we are faking the default framebuffer with our own
// to see the results, replace back/front/left/right with color attachment 0
if(buf == eGL_BACK_LEFT || buf == eGL_BACK_RIGHT || buf == eGL_BACK ||
buf == eGL_FRONT_LEFT || buf == eGL_FRONT_RIGHT || buf == eGL_FRONT)
buf = eGL_COLOR_ATTACHMENT0;
// since we are faking the default framebuffer with our own
// to see the results, replace back/front/left/right with color attachment 0
if(buf == eGL_BACK_LEFT || buf == eGL_BACK_RIGHT || buf == eGL_BACK || buf == eGL_FRONT_LEFT ||
buf == eGL_FRONT_RIGHT || buf == eGL_FRONT)
buf = eGL_COLOR_ATTACHMENT0;
m_Real.glFramebufferDrawBufferEXT(m_FakeBB_FBO, buf);
}
else
{
m_Real.glFramebufferDrawBufferEXT(framebuffer.name, buf);
}
m_Real.glFramebufferDrawBufferEXT(framebuffer.name, buf);
}
return true;
@@ -1602,7 +1567,7 @@ bool WrappedOpenGL::Serialise_glFramebufferDrawBuffersEXT(SerialiserType &ser,
buffers[i] = eGL_COLOR_ATTACHMENT0;
}
m_Real.glFramebufferDrawBuffersEXT(framebuffer.name ? framebuffer.name : m_FakeBB_FBO, n, bufs);
m_Real.glFramebufferDrawBuffersEXT(framebuffer.name, n, bufs);
}
return true;
@@ -1803,12 +1768,6 @@ bool WrappedOpenGL::Serialise_glBlitNamedFramebuffer(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(readFramebuffer.name == 0)
readFramebuffer.name = m_FakeBB_FBO;
if(drawFramebuffer.name == 0)
drawFramebuffer.name = m_FakeBB_FBO;
// use ARB_direct_state_access functions here as we use EXT_direct_state_access elsewhere. If
// we are running without ARB_dsa support, these functions are emulated in the obvious way. This
// is necessary since these functions can be serialised even if ARB_dsa was not used originally,