Store/create backbuffers on a per-context basis. Closes #1083

* This means we can have different context backbuffers with different formats.
This commit is contained in:
baldurk
2018-09-06 17:54:53 +01:00
parent 8a927f847c
commit 0a07902980
15 changed files with 343 additions and 251 deletions
+5 -3
View File
@@ -74,7 +74,7 @@ CGLError GL_EXPORT_NAME(CGLCreateContext)(CGLPixelFormatObj pix, CGLContextObj s
init.isSRGB = value;
value = 1;
// GLX.glXGetConfig(dpy, vis, GLX_SAMPLES_ARB, &value);
init.isSRGB = RDCMAX(1, value);
init.multiSamples = RDCMAX(1, value);
GLWindowingData data;
data.wnd = NULL;
@@ -125,6 +125,10 @@ CGLError GL_EXPORT_NAME(CGLSetCurrentContext)(CGLContextObj ctx)
// data.cfg = NULL;
cglhook.driver.ActivateContext(data);
GLInitParams &params = cglhook.driver.GetInitParams(data);
params.width = 400;
params.height = 200;
}
return ret;
@@ -142,8 +146,6 @@ CGLError GL_EXPORT_NAME(CGLFlushDrawable)(CGLContextObj ctx)
SCOPED_LOCK(glLock);
cglhook.driver.WindowSize((void *)0x4, 800, 200);
cglhook.driver.SwapBuffers((void *)0x4);
return CGL.CGLFlushDrawable(ctx);
+18 -26
View File
@@ -294,6 +294,24 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display, EGLSurface
eglhook.driver.SetDriverType(RDCDriver::OpenGLES);
eglhook.driver.ActivateContext(data);
GLInitParams &params = eglhook.driver.GetInitParams(data);
int height, width;
EGL.QuerySurface(display, draw, EGL_HEIGHT, &height);
EGL.QuerySurface(display, draw, EGL_WIDTH, &width);
int colorspace = 0;
EGL.QuerySurface(display, draw, EGL_GL_COLORSPACE, &colorspace);
// GL_SRGB8_ALPHA8 is specified as color-renderable, unlike GL_SRGB8.
bool isSRGB = params.colorBits == 32 && colorspace == EGL_GL_COLORSPACE_SRGB;
bool isYFlipped = eglhook.IsYFlipped(display, draw);
params.width = width;
params.height = height;
params.isSRGB = isSRGB;
params.isYFlipped = isYFlipped;
}
return ret;
@@ -311,20 +329,7 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sur
SCOPED_LOCK(glLock);
int height, width;
EGL.QuerySurface(dpy, surface, EGL_HEIGHT, &height);
EGL.QuerySurface(dpy, surface, EGL_WIDTH, &width);
GLInitParams &init = eglhook.driver.GetInitParams();
int colorspace = 0;
EGL.QuerySurface(dpy, surface, EGL_GL_COLORSPACE, &colorspace);
// GL_SRGB8_ALPHA8 is specified as color-renderable, unlike GL_SRGB8.
init.isSRGB = init.colorBits == 32 && colorspace == EGL_GL_COLORSPACE_SRGB;
init.isYFlipped = eglhook.IsYFlipped(dpy, surface);
eglhook.driver.SetDriverType(RDCDriver::OpenGLES);
eglhook.driver.WindowSize(surface, width, height);
if(!eglhook.driver.UsesVRFrameMarkers())
eglhook.driver.SwapBuffers(surface);
@@ -344,20 +349,7 @@ HOOK_EXPORT EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface
SCOPED_LOCK(glLock);
int winheight, winwidth;
EGL.QuerySurface(dpy, surface, EGL_HEIGHT, &winheight);
EGL.QuerySurface(dpy, surface, EGL_WIDTH, &winwidth);
GLInitParams &init = eglhook.driver.GetInitParams();
int colorspace = 0;
EGL.QuerySurface(dpy, surface, EGL_GL_COLORSPACE, &colorspace);
// GL_SRGB8_ALPHA8 is specified as color-renderable, unlike GL_SRGB8.
init.isSRGB = init.colorBits == 32 && colorspace == EGL_GL_COLORSPACE_SRGB;
init.isYFlipped = eglhook.IsYFlipped(dpy, surface);
eglhook.driver.SetDriverType(RDCDriver::OpenGLES);
eglhook.driver.WindowSize((void *)eglhook.windows[surface], winwidth, winheight);
if(!eglhook.driver.UsesVRFrameMarkers())
eglhook.driver.SwapBuffers((void *)eglhook.windows[surface]);
+4
View File
@@ -1125,6 +1125,10 @@ bool GLInitParams::IsSupportedVersion(uint64_t ver)
if(ver == 0x1C)
return true;
// 0x1D -> 0x1E - added new chunk for context parameters and per-context tracking of backbuffers
if(ver == 0x1D)
return true;
return false;
}
+2
View File
@@ -2054,6 +2054,8 @@ enum class GLChunk : uint32_t
glAcquireKeyedMutexWin32EXT,
glReleaseKeyedMutexWin32EXT,
ContextConfiguration,
Max,
};
+191 -133
View File
@@ -580,10 +580,6 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform)
m_ContextRecord->DataInSerialiser = false;
m_ContextRecord->Length = 0;
m_ContextRecord->InternalResource = true;
// 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
{
@@ -595,9 +591,7 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform)
InitSPIRVCompiler();
RenderDoc::Inst().RegisterShutdownFunction(&ShutdownSPIRVCompiler);
m_FakeBB_FBO = 0;
m_FakeBB_Color = 0;
m_FakeBB_DepthStencil = 0;
m_CurrentDefaultFBO = 0;
m_CurChunkOffset = 0;
m_AddedDrawcall = false;
@@ -607,14 +601,21 @@ WrappedOpenGL::WrappedOpenGL(GLPlatform &platform)
void WrappedOpenGL::Initialise(GLInitParams &params, uint64_t sectionVersion)
{
// deliberately want to go through our own wrappers to set up e.g. m_Textures members
m_SectionVersion = sectionVersion;
m_GlobalInitParams = params;
}
void WrappedOpenGL::CreateReplayBackbuffer(const GLInitParams &params, ResourceId fboOrigId,
GLuint &fbo, std::string bbname)
{
GLuint col = 0, depth = 0;
WrappedOpenGL &drv = *this;
m_InitParams = params;
m_SectionVersion = sectionVersion;
drv.glGenFramebuffers(1, &fbo);
drv.glBindFramebuffer(eGL_FRAMEBUFFER, fbo);
drv.glGenFramebuffers(1, &m_FakeBB_FBO);
drv.glBindFramebuffer(eGL_FRAMEBUFFER, m_FakeBB_FBO);
m_CurrentDefaultFBO = fbo;
GLenum colfmt = eGL_RGBA8;
@@ -629,27 +630,20 @@ void WrappedOpenGL::Initialise(GLInitParams &params, uint64_t sectionVersion)
if(params.multiSamples > 1)
target = eGL_TEXTURE_2D_MULTISAMPLE;
drv.glGenTextures(1, &m_FakeBB_Color);
drv.glBindTexture(target, m_FakeBB_Color);
drv.glGenTextures(1, &col);
drv.glBindTexture(target, col);
ResourceId colorId = GetResourceManager()->GetID(TextureRes(GetCtx(), m_FakeBB_Color));
const char *name = "Backbuffer Color";
GetResourceManager()->SetName(colorId, name);
// we'll add the chunk later when we re-process it.
AddResource(colorId, ResourceType::SwapchainImage, name);
GetReplay()->GetResourceDesc(colorId).initialisationChunks.clear();
GetReplay()->GetResourceDesc(colorId).SetCustomName(name);
m_Textures[GetResourceManager()->GetID(TextureRes(GetCtx(), col))].creationFlags |=
TextureCategory::SwapBuffer;
if(params.multiSamples > 1)
{
drv.glTextureStorage2DMultisampleEXT(m_FakeBB_Color, target, params.multiSamples, colfmt,
params.width, params.height, true);
drv.glTextureStorage2DMultisampleEXT(col, target, params.multiSamples, colfmt, params.width,
params.height, true);
}
else
{
drv.glTextureImage2DEXT(m_FakeBB_Color, target, 0, colfmt, params.width, params.height, 0,
drv.glTextureImage2DEXT(col, target, 0, colfmt, params.width, params.height, 0,
GetBaseFormat(colfmt), GetDataType(colfmt), NULL);
drv.glTexParameteri(target, eGL_TEXTURE_MAX_LEVEL, 0);
drv.glTexParameteri(target, eGL_TEXTURE_MIN_FILTER, eGL_NEAREST);
@@ -657,15 +651,14 @@ void WrappedOpenGL::Initialise(GLInitParams &params, uint64_t sectionVersion)
drv.glTexParameteri(target, eGL_TEXTURE_WRAP_S, eGL_CLAMP_TO_EDGE);
drv.glTexParameteri(target, eGL_TEXTURE_WRAP_T, eGL_CLAMP_TO_EDGE);
}
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, target, m_FakeBB_Color, 0);
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_COLOR_ATTACHMENT0, target, col, 0);
drv.glViewport(0, 0, params.width, params.height);
m_FakeBB_DepthStencil = 0;
if(params.depthBits > 0 || params.stencilBits > 0)
{
drv.glGenTextures(1, &m_FakeBB_DepthStencil);
drv.glBindTexture(target, m_FakeBB_DepthStencil);
drv.glGenTextures(1, &depth);
drv.glBindTexture(target, depth);
GLenum depthfmt = eGL_DEPTH32F_STENCIL8;
bool stencil = false;
@@ -696,50 +689,80 @@ void WrappedOpenGL::Initialise(GLInitParams &params, uint64_t sectionVersion)
else
RDCERR("Unexpected # stencil bits: %d", params.stencilBits);
ResourceId depthId = GetResourceManager()->GetID(TextureRes(GetCtx(), m_FakeBB_DepthStencil));
name = stencil ? "Backbuffer Depth-stencil" : "Backbuffer Depth";
GetResourceManager()->SetName(depthId, name);
// we'll add the chunk later when we re-process it.
AddResource(depthId, ResourceType::SwapchainImage, name);
GetReplay()->GetResourceDesc(depthId).initialisationChunks.clear();
GetReplay()->GetResourceDesc(depthId).SetCustomName(name);
m_Textures[GetResourceManager()->GetID(TextureRes(GetCtx(), depth))].creationFlags |=
TextureCategory::SwapBuffer;
if(params.multiSamples > 1)
{
drv.glTextureStorage2DMultisampleEXT(m_FakeBB_DepthStencil, target, params.multiSamples,
depthfmt, params.width, params.height, true);
drv.glTextureStorage2DMultisampleEXT(depth, target, params.multiSamples, depthfmt,
params.width, params.height, true);
}
else
{
drv.glTexParameteri(target, eGL_TEXTURE_MAX_LEVEL, 0);
drv.glTextureImage2DEXT(m_FakeBB_DepthStencil, target, 0, depthfmt, params.width,
params.height, 0, GetBaseFormat(depthfmt), GetDataType(depthfmt), NULL);
drv.glTextureImage2DEXT(depth, target, 0, depthfmt, params.width, params.height, 0,
GetBaseFormat(depthfmt), GetDataType(depthfmt), NULL);
}
if(stencil)
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT, target,
m_FakeBB_DepthStencil, 0);
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_DEPTH_STENCIL_ATTACHMENT, target, depth, 0);
else
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, target,
m_FakeBB_DepthStencil, 0);
drv.glFramebufferTexture2D(eGL_FRAMEBUFFER, eGL_DEPTH_ATTACHMENT, target, depth, 0);
}
// give the backbuffer a default clear color
drv.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
drv.glClear(GL_COLOR_BUFFER_BIT);
float clearcol[] = {0.0f, 0.0f, 0.0f, 1.0f};
drv.glClearBufferfv(eGL_COLOR, 0, clearcol);
if(params.depthBits > 0)
if(params.depthBits > 0 || params.stencilBits > 0)
drv.glClearBufferfi(eGL_DEPTH_STENCIL, 0, 1.0f, 0);
GetResourceManager()->AddLiveResource(fboOrigId, FramebufferRes(GetCtx(), fbo));
AddResource(fboOrigId, ResourceType::SwapchainImage, "");
GetReplay()->GetResourceDesc(fboOrigId).SetCustomName(bbname + " FBO");
ResourceId colorId = GetResourceManager()->GetID(TextureRes(GetCtx(), col));
std::string name = bbname + " Color";
GetResourceManager()->SetName(colorId, name);
// we'll add the chunk later when we re-process it.
AddResource(colorId, ResourceType::SwapchainImage, name.c_str());
GetReplay()->GetResourceDesc(colorId).SetCustomName(name);
GetReplay()->GetResourceDesc(fboOrigId).derivedResources.push_back(colorId);
GetReplay()->GetResourceDesc(colorId).parentResources.push_back(fboOrigId);
if(depth)
{
drv.glClearDepthf(1.0f);
drv.glClear(GL_DEPTH_BUFFER_BIT);
ResourceId depthId = GetResourceManager()->GetID(TextureRes(GetCtx(), depth));
name = bbname + (params.stencilBits > 0 ? " Depth-stencil" : " Depth");
GetResourceManager()->SetName(depthId, name);
// we'll add the chunk later when we re-process it.
AddResource(depthId, ResourceType::SwapchainImage, name.c_str());
GetReplay()->GetResourceDesc(depthId).SetCustomName(name);
GetReplay()->GetResourceDesc(fboOrigId).derivedResources.push_back(depthId);
GetReplay()->GetResourceDesc(depthId).parentResources.push_back(fboOrigId);
}
if(params.stencilBits > 0)
if(fbo == m_Global_FBO0)
{
drv.glClearStencil(0);
drv.glClear(GL_STENCIL_BUFFER_BIT);
GetReplay()->GetResourceDesc(fboOrigId).initialisationChunks.clear();
GetReplay()->GetResourceDesc(fboOrigId).initialisationChunks.push_back(m_InitChunkIndex);
GetReplay()->GetResourceDesc(colorId).initialisationChunks.clear();
GetReplay()->GetResourceDesc(colorId).initialisationChunks.push_back(m_InitChunkIndex);
if(depth)
{
ResourceId depthId = GetResourceManager()->GetID(TextureRes(GetCtx(), depth));
GetReplay()->GetResourceDesc(depthId).initialisationChunks.clear();
GetReplay()->GetResourceDesc(depthId).initialisationChunks.push_back(m_InitChunkIndex);
}
}
}
@@ -753,13 +776,6 @@ std::string WrappedOpenGL::GetChunkName(uint32_t idx)
WrappedOpenGL::~WrappedOpenGL()
{
if(m_FakeBB_FBO)
GL.glDeleteFramebuffers(1, &m_FakeBB_FBO);
if(m_FakeBB_Color)
GL.glDeleteTextures(1, &m_FakeBB_Color);
if(m_FakeBB_DepthStencil)
GL.glDeleteTextures(1, &m_FakeBB_DepthStencil);
if(m_IndirectBuffer)
GL.glDeleteBuffers(1, &m_IndirectBuffer);
@@ -938,9 +954,6 @@ void WrappedOpenGL::ContextData::CreateResourceRecord(WrappedOpenGL *driver, voi
void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext,
GLInitParams initParams, bool core, bool attribsCreate)
{
// TODO: support multiple GL contexts more explicitly
m_InitParams = initParams;
RDCLOG("%s context %p created %s, sharing with context %p", core ? "Core" : "Compatibility",
winData.ctx, attribsCreate ? "with attribs" : "without attribs", shareContext);
@@ -948,6 +961,7 @@ void WrappedOpenGL::CreateContext(GLWindowingData winData, void *shareContext,
ctxdata.ctx = winData.ctx;
ctxdata.isCore = core;
ctxdata.attribsCreate = attribsCreate;
ctxdata.initParams = initParams;
if(shareContext == NULL)
{
@@ -1001,6 +1015,48 @@ void WrappedOpenGL::RegisterReplayContext(GLWindowingData winData, void *shareCo
ActivateContext(winData);
}
template <typename SerialiserType>
bool WrappedOpenGL::Serialise_ContextConfiguration(SerialiserType &ser, void *ctx)
{
SERIALISE_ELEMENT_LOCAL(Context, m_ContextData[ctx].m_ContextDataResourceID);
SERIALISE_ELEMENT_LOCAL(FBO, m_ContextData[ctx].m_ContextFBOID);
SERIALISE_ELEMENT_LOCAL(InitParams, m_ContextData[ctx].initParams);
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
// we might encounter multiple instances of this chunk per frame, so only do work on the first
// one
if(!GetResourceManager()->HasLiveResource(FBO))
{
std::string name;
if(m_CurrentDefaultFBO == 0)
{
// if we haven't created a default FBO yet this is the first. Give it a nice friendly name
name = "Backbuffer";
}
else
{
// if not, we have multiple FBOs and we want to distinguish them. Give the subsequent
// backbuffers unique names
name = StringFormat::Fmt("Context %llu Backbuffer", Context);
}
GLuint fbo = 0;
CreateReplayBackbuffer(InitParams, FBO, fbo, name);
// also add a simple resource descriptor for the context
AddResource(Context, ResourceType::Device, "Context");
}
m_CurrentDefaultFBO = GetResourceManager()->GetLiveResource(FBO).name;
}
return true;
}
void WrappedOpenGL::ActivateContext(GLWindowingData winData)
{
m_ActiveContexts[Threading::GetCurrentID()] = winData;
@@ -1281,31 +1337,32 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
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);
// we also do the same for FBO 0, but we must force it not to be shared as even if FBOs are
// shared the FBO0 may not be :(.
GLResource fbo0 = FramebufferRes({GetCtx().ctx, GetCtx().ctx}, 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());
}
ctxdata.m_ContextFBOID = GetResourceManager()->RegisterResource(fbo0);
}
}
// if we're capturing, we need to serialise out the changed state vector
if(IsActiveCapturing(m_State))
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::MakeContextCurrent);
Serialise_BeginCaptureFrame(ser);
GetContextRecord()->AddChunk(scope.Get());
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::MakeContextCurrent);
Serialise_BeginCaptureFrame(ser);
GetContextRecord()->AddChunk(scope.Get());
}
// also serialise out this context's backbuffer params
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::ContextConfiguration);
Serialise_ContextConfiguration(ser, winData.ctx);
GetContextRecord()->AddChunk(scope.Get());
}
}
// this is hack but GL context creation is an *utter mess*. For first-frame captures, only
@@ -1316,13 +1373,6 @@ void WrappedOpenGL::ActivateContext(GLWindowingData winData)
}
}
void WrappedOpenGL::WindowSize(void *windowHandle, uint32_t w, uint32_t h)
{
// TODO: support multiple window handles
m_InitParams.width = w;
m_InitParams.height = h;
}
struct ReplacementSearch
{
bool operator()(const pair<ResourceId, Replacement> &a, ResourceId b) { return a.first < b; }
@@ -1667,7 +1717,7 @@ void WrappedOpenGL::SwapBuffers(void *windowHandle)
}
if(!overlayText.empty())
RenderOverlayText(0.0f, 0.0f, m_InitParams.isYFlipped, overlayText.c_str());
RenderOverlayText(0.0f, 0.0f, overlayText.c_str());
// swallow all errors we might have inadvertantly caused. This is
// better than letting an error propagate and maybe screw up the
@@ -1778,6 +1828,14 @@ void WrappedOpenGL::StartFrameCapture(void *dev, void *wnd)
AttemptCapture();
BeginCaptureFrame();
// serialise out the context configuration for this current context first
{
USE_SCRATCH_SERIALISER();
SCOPED_SERIALISE_CHUNK(GLChunk::ContextConfiguration);
Serialise_ContextConfiguration(ser, GetCtx().ctx);
GetContextRecord()->AddChunk(scope.Get());
}
if(switchctx.ctx != prevctx.ctx)
{
m_Platform.MakeContextCurrent(prevctx);
@@ -1869,18 +1927,23 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
{
SCOPED_SERIALISE_CHUNK(SystemChunk::DriverInit, sizeof(GLInitParams) + 16);
SERIALISE_ELEMENT(m_InitParams);
// we no longer use this one, but for ease of compatibility we still serialise it here. This
// will be immediately overridden by the actual parameters by a
// GLChunk::ContextConfiguration chunk
GLInitParams dummy;
SERIALISE_ELEMENT(dummy);
}
{
// remember to update this estimated chunk length if you add more parameters
SCOPED_SERIALISE_CHUNK(GLChunk::DeviceInitialisation, 32);
// legacy behaviour where we had a single global VAO 0. Ignore, but preserve for easier
// legacy behaviour where we had a single global VAO/FBO 0. Ignore, but preserve for easier
// compatibility with old captures
ResourceId vao;
ResourceId vao, fbo;
SERIALISE_ELEMENT(vao);
SERIALISE_ELEMENT(m_FBO0_ID);
SERIALISE_ELEMENT(fbo);
}
RDCDEBUG("Inserting Resource Serialisers");
@@ -1970,8 +2033,7 @@ bool WrappedOpenGL::EndFrameCapture(void *dev, void *wnd)
{
ContextData &ctxdata = GetCtxData();
RenderOverlayText(0.0f, 0.0f, m_InitParams.isYFlipped, "Failed to capture frame %u: %s",
m_FrameCounter, reasonString);
RenderOverlayText(0.0f, 0.0f, "Failed to capture frame %u: %s", m_FrameCounter, reasonString);
// swallow all errors we might have inadvertantly caused. This is
// better than letting an error propagate and maybe screw up the
@@ -2071,8 +2133,10 @@ WrappedOpenGL::BackbufferImage *WrappedOpenGL::SaveBackbufferImage()
GL.glPixelStorei(eGL_PACK_SKIP_PIXELS, 0);
GL.glPixelStorei(eGL_PACK_ALIGNMENT, 1);
thwidth = (uint16_t)m_InitParams.width;
thheight = (uint16_t)m_InitParams.height;
ContextData &dat = GetCtxData();
thwidth = (uint16_t)dat.initParams.width;
thheight = (uint16_t)dat.initParams.height;
thpixels = new byte[thwidth * thheight * 4];
@@ -2091,7 +2155,7 @@ WrappedOpenGL::BackbufferImage *WrappedOpenGL::SaveBackbufferImage()
}
// flip the image in-place
if(!m_InitParams.isYFlipped)
if(!dat.initParams.isYFlipped)
{
for(uint16_t y = 0; y <= thheight / 2; y++)
{
@@ -2148,7 +2212,7 @@ WrappedOpenGL::BackbufferImage *WrappedOpenGL::SaveBackbufferImage()
float yf = float(y) / float(thheight);
byte *pixelsrc =
&src[3 * uint32_t(xf * widthf) + m_InitParams.width * 3 * uint32_t(yf * heightf)];
&src[3 * uint32_t(xf * widthf) + dat.initParams.width * 3 * uint32_t(yf * heightf)];
memcpy(dst, pixelsrc, 3);
@@ -2213,24 +2277,29 @@ bool WrappedOpenGL::Serialise_CaptureScope(SerialiserType &ser)
return true;
}
template <typename SerialiserType>
bool WrappedOpenGL::Serialise_ContextInit(SerialiserType &ser)
bool WrappedOpenGL::Serialise_ContextInit(ReadSerialiser &ser)
{
SERIALISE_ELEMENT_LOCAL(FBO0_ID, GetResourceManager()->GetID(FramebufferRes(GetCtx(), 0)));
SERIALISE_ELEMENT_LOCAL(FBO0_ID, ResourceId());
SERIALISE_CHECK_READ_ERRORS();
if(IsReplayingAndReading())
{
GetResourceManager()->ReplaceResource(FBO0_ID, m_FBO0_ID);
// this chunk has been replaced by the ContextConfiguration chunk. Previously this was used to
// register the ID of a framebuffer on another context, so it can be redirected to a single
// global FBO0. But now each context's FBO0 is unique. So if this is present, we also have the
// global FBO0 to redirect to.
ResourceId global_fbo0 = GetResourceManager()->GetID(FramebufferRes(GetCtx(), m_Global_FBO0));
GetResourceManager()->ReplaceResource(FBO0_ID, global_fbo0);
AddResource(FBO0_ID, ResourceType::SwapchainImage, "");
GetReplay()->GetResourceDesc(FBO0_ID).SetCustomName("Window FBO");
// this is a hack, but we only support a single 'default' framebuffer so we set these
// replacements up as derived resources
GetReplay()->GetResourceDesc(m_FBO0_ID).derivedResources.push_back(FBO0_ID);
GetReplay()->GetResourceDesc(FBO0_ID).parentResources.push_back(m_FBO0_ID);
GetReplay()->GetResourceDesc(global_fbo0).derivedResources.push_back(FBO0_ID);
GetReplay()->GetResourceDesc(FBO0_ID).parentResources.push_back(global_fbo0);
}
return true;
@@ -2789,8 +2858,13 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
draw.name = "SwapBuffers()";
draw.flags |= DrawFlags::Present;
GLuint col = 0;
GL.glGetNamedFramebufferAttachmentParameterivEXT(m_CurrentDefaultFBO, eGL_COLOR_ATTACHMENT0,
eGL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
(GLint *)&col);
draw.copyDestination = GetResourceManager()->GetOriginalID(
GetResourceManager()->GetID(TextureRes(GetCtx(), m_FakeBB_Color)));
GetResourceManager()->GetID(TextureRes(GetCtx(), col)));
AddDrawcall(draw, true);
}
@@ -2811,9 +2885,9 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
{
case GLChunk::DeviceInitialisation:
{
ResourceId vao;
ResourceId vao, fbo;
SERIALISE_ELEMENT(vao).Hidden();
SERIALISE_ELEMENT(m_FBO0_ID).Named("FBO 0 ID");
SERIALISE_ELEMENT(fbo).Named("FBO 0 ID");
SERIALISE_CHECK_READ_ERRORS();
@@ -2823,36 +2897,18 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
// it can be bound and have initial contents applied to it
if(vao != ResourceId())
{
glGenVertexArrays(1, &m_Fake_VAO0);
glBindVertexArray(m_Fake_VAO0);
GetResourceManager()->AddLiveResource(vao, VertexArrayRes(GetCtx(), m_Fake_VAO0));
glGenVertexArrays(1, &m_Global_VAO0);
glBindVertexArray(m_Global_VAO0);
GetResourceManager()->AddLiveResource(vao, VertexArrayRes(GetCtx(), m_Global_VAO0));
AddResource(vao, ResourceType::StateObject, "Vertex Array");
GetReplay()->GetResourceDesc(vao).SetCustomName("Default VAO");
GetReplay()->GetResourceDesc(vao).initialisationChunks.push_back(m_InitChunkIndex);
}
GetResourceManager()->AddLiveResource(m_FBO0_ID, FramebufferRes(GetCtx(), m_FakeBB_FBO));
AddResource(m_FBO0_ID, ResourceType::SwapchainImage, "");
GetReplay()->GetResourceDesc(m_FBO0_ID).SetCustomName("Default FBO");
GetReplay()->GetResourceDesc(m_FBO0_ID).initialisationChunks.push_back(m_InitChunkIndex);
ResourceId colorId = GetResourceManager()->GetID(TextureRes(GetCtx(), m_FakeBB_Color));
GetReplay()->GetResourceDesc(colorId).initialisationChunks.push_back(m_InitChunkIndex);
GetReplay()->GetResourceDesc(m_FBO0_ID).derivedResources.push_back(colorId);
GetReplay()->GetResourceDesc(colorId).parentResources.push_back(m_FBO0_ID);
if(m_FakeBB_DepthStencil)
{
ResourceId depthId =
GetResourceManager()->GetID(TextureRes(GetCtx(), m_FakeBB_DepthStencil));
GetReplay()->GetResourceDesc(depthId).initialisationChunks.push_back(m_InitChunkIndex);
GetReplay()->GetResourceDesc(m_FBO0_ID).derivedResources.push_back(depthId);
GetReplay()->GetResourceDesc(depthId).parentResources.push_back(m_FBO0_ID);
}
// similar behaviour for a single global FBO 0.
if(fbo != ResourceId())
CreateReplayBackbuffer(m_GlobalInitParams, fbo, m_Global_FBO0, "Backbuffer");
}
return true;
@@ -3919,6 +3975,8 @@ bool WrappedOpenGL::ProcessChunk(ReadSerialiser &ser, GLChunk chunk)
// re-use the serialisation for beginning of the frame
return Serialise_BeginCaptureFrame(ser);
case GLChunk::ContextConfiguration: return Serialise_ContextConfiguration(ser, NULL);
case GLChunk::glIndirectSubCommand:
// this is a fake chunk generated at runtime as part of indirect draws.
// Just in case it gets exported and imported, completely ignore it.
+29 -15
View File
@@ -54,7 +54,7 @@ struct GLInitParams
bool isYFlipped;
// check if a frame capture section version is supported
static const uint64_t CurrentVersion = 0x1D;
static const uint64_t CurrentVersion = 0x1E;
static bool IsSupportedVersion(uint64_t ver);
};
@@ -122,8 +122,8 @@ private:
GLReplay m_Replay;
RDCDriver m_DriverType;
GLInitParams m_InitParams;
uint64_t m_SectionVersion;
GLInitParams m_GlobalInitParams;
WriteSerialiser m_ScratchSerialiser;
std::set<std::string> m_StringDB;
@@ -257,12 +257,15 @@ private:
vector<pair<ResourceId, Replacement>> m_DependentReplacements;
GLuint m_FakeBB_FBO;
GLuint m_FakeBB_Color;
GLuint m_FakeBB_DepthStencil;
ResourceId m_FBO0_ID;
// this object is only created on old captures where VAO0 was a single global object. In new
// captures each context has its own VAO0.
GLuint m_Global_VAO0 = 0;
GLuint m_Fake_VAO0;
// Same principle here, but for FBOs.
GLuint m_Global_FBO0 = 0;
// This tracks whatever is the FBO for the last bound context
GLuint m_CurrentDefaultFBO;
GLuint m_IndirectBuffer = 0;
GLsizeiptr m_IndirectBufferSize = 0;
@@ -281,8 +284,7 @@ private:
template <typename SerialiserType>
bool Serialise_CaptureScope(SerialiserType &ser);
template <typename SerialiserType>
bool Serialise_ContextInit(SerialiserType &ser);
bool Serialise_ContextInit(ReadSerialiser &ser);
bool HasSuccessfulCapture(CaptureFailReason &reason)
{
@@ -296,6 +298,9 @@ private:
void FinishCapture();
void ContextEndFrame();
template <typename SerialiserType>
bool Serialise_ContextConfiguration(SerialiserType &ser, void *ctx);
void CleanupResourceRecord(GLResourceRecord *record, bool freeParents);
void CleanupCapture();
void FreeCaptureData();
@@ -337,6 +342,8 @@ private:
bool attribsCreate;
bool isCore;
GLInitParams initParams;
// map from window handle void* to uint64_t unix timestamp with
// the last time a window was seen/associated with this context.
// Decays after a few seconds since there's no good explicit
@@ -390,6 +397,8 @@ private:
ResourceId m_ContextDataResourceID;
GLResourceRecord *m_ContextDataRecord;
ResourceId m_ContextFBOID;
};
struct ClientMemoryData
@@ -443,8 +452,8 @@ private:
static const int FONT_TEX_HEIGHT = 128;
static const int FONT_MAX_CHARS = 256;
void RenderOverlayText(float x, float y, bool yflipped, const char *fmt, ...);
void RenderOverlayStr(float x, float y, bool yflipped, const char *str);
void RenderOverlayText(float x, float y, const char *fmt, ...);
void RenderOverlayStr(float x, float y, const char *str);
struct BackbufferImage
{
@@ -456,6 +465,9 @@ private:
uint16_t thheight;
};
void CreateReplayBackbuffer(const GLInitParams &params, ResourceId fboOrigId, GLuint &fbo,
std::string bbname);
BackbufferImage *SaveBackbufferImage();
map<void *, BackbufferImage *> m_BackbufferImages;
@@ -488,7 +500,6 @@ public:
void SetDriverType(RDCDriver type) { m_DriverType = type; }
bool isGLESMode() { return m_DriverType == RDCDriver::OpenGLES; }
RDCDriver GetDriverType() { return m_DriverType; }
GLInitParams &GetInitParams() { return m_InitParams; }
ContextPair &GetCtx();
GLResourceRecord *GetContextRecord();
@@ -516,8 +527,8 @@ public:
void ReplayLog(uint32_t startEventID, uint32_t endEventID, ReplayLogType replayType);
ReplayStatus ReadLogInitialisation(RDCFile *rdc, bool storeStructuredBuffers);
GLuint GetFakeVAO0() { return m_Fake_VAO0; }
GLuint GetFakeBBFBO() { return m_FakeBB_FBO; }
GLuint GetFakeVAO0() { return m_Global_VAO0; }
GLuint GetCurrentDefaultFBO() { return m_CurrentDefaultFBO; }
FrameRecord &GetFrameRecord() { return m_FrameRecord; }
const APIEvent &GetEvent(uint32_t eventId);
@@ -531,8 +542,11 @@ public:
void RegisterReplayContext(GLWindowingData winData, void *shareContext, bool core,
bool attribsCreate);
void DeleteContext(void *contextHandle);
GLInitParams &GetInitParams(GLWindowingData winData)
{
return m_ContextData[winData.ctx].initParams;
}
void ActivateContext(GLWindowingData winData);
void WindowSize(void *windowHandle, uint32_t w, uint32_t h);
void SwapBuffers(void *windowHandle);
void HandleVRFrameMarkers(const GLchar *buf, GLsizei length);
bool UsesVRFrameMarkers() { return m_UsesVRMarkers; }
+11 -4
View File
@@ -1130,6 +1130,13 @@ void GLRenderState::FetchState(WrappedOpenGL *driver)
GL.glGetIntegerv(eGL_READ_FRAMEBUFFER_BINDING, (GLint *)&read);
DrawFBO = FramebufferRes(ctx, draw);
ReadFBO = FramebufferRes(ctx, read);
// if the default FBO is bound, we must force the use of the context itself, rather than the
// sharegroup (if FBOs are normally shared).
if(draw == 0)
DrawFBO = FramebufferRes({ctx.ctx, ctx.ctx}, draw);
if(read == 0)
ReadFBO = FramebufferRes({ctx.ctx, ctx.ctx}, read);
}
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, 0);
@@ -1606,8 +1613,8 @@ void GLRenderState::ApplyState(WrappedOpenGL *driver)
if(driver->GetReplay()->IsReplayContext(ctx.ctx))
{
// apply drawbuffers/readbuffer to default framebuffer
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, driver->GetFakeBBFBO());
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, driver->GetFakeBBFBO());
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, driver->GetCurrentDefaultFBO());
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, driver->GetCurrentDefaultFBO());
GL.glDrawBuffers(numDBs, DBs);
// see above for reasoning for this
@@ -1616,12 +1623,12 @@ void GLRenderState::ApplyState(WrappedOpenGL *driver)
if(ReadFBO.name)
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, ReadFBO.name);
else
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, driver->GetFakeBBFBO());
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, driver->GetCurrentDefaultFBO());
if(DrawFBO.name)
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, DrawFBO.name);
else
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, driver->GetFakeBBFBO());
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, driver->GetCurrentDefaultFBO());
}
GL.glHint(eGL_FRAGMENT_SHADER_DERIVATIVE_HINT, Hints.Derivatives);
+14 -13
View File
@@ -270,7 +270,7 @@ void WrappedOpenGL::ContextData::CreateDebugData()
}
}
void WrappedOpenGL::RenderOverlayText(float x, float y, bool yflipped, const char *fmt, ...)
void WrappedOpenGL::RenderOverlayText(float x, float y, const char *fmt, ...)
{
static char tmpBuf[4096];
@@ -286,18 +286,18 @@ void WrappedOpenGL::RenderOverlayText(float x, float y, bool yflipped, const cha
textState.Push(ctxdata.Modern());
RenderOverlayStr(x, y, yflipped, tmpBuf);
RenderOverlayStr(x, y, tmpBuf);
textState.Pop(ctxdata.Modern());
}
void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char *text)
void WrappedOpenGL::RenderOverlayStr(float x, float y, const char *text)
{
if(char *t = strchr((char *)text, '\n'))
{
*t = 0;
RenderOverlayStr(x, y, yflipped, text);
RenderOverlayStr(x, y + 1.0f, yflipped, t + 1);
RenderOverlayStr(x, y, text);
RenderOverlayStr(x, y + 1.0f, t + 1);
*t = '\n';
return;
}
@@ -338,8 +338,8 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char
Vec2f(1.0, 0.0), Vec2f(0.0, 1.0), Vec2f(1.0, 1.0),
};
const Vec2f FontScreenAspect(ctxdata.CharAspect / RDCMAX(1.0f, float(m_InitParams.width)),
1.0f / RDCMAX(1.0f, float(m_InitParams.height)));
const Vec2f FontScreenAspect(ctxdata.CharAspect / RDCMAX(1.0f, float(ctxdata.initParams.width)),
1.0f / RDCMAX(1.0f, float(ctxdata.initParams.height)));
float *vertexData = new float[5 * len * 6];
@@ -360,7 +360,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char
pos.y -= 1.0f;
vertexData[(i * 6 + ch) * 5 + 0] = pos.x;
vertexData[(i * 6 + ch) * 5 + 1] = yflipped ? pos.y : -pos.y;
vertexData[(i * 6 + ch) * 5 + 1] = ctxdata.initParams.isYFlipped ? pos.y : -pos.y;
vertexData[(i * 6 + ch) * 5 + 2] = uv.x;
vertexData[(i * 6 + ch) * 5 + 3] = uv.y;
vertexData[(i * 6 + ch) * 5 + 4] = float(text[i] - FONT_FIRST_CHAR);
@@ -411,12 +411,13 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char
// set viewport & scissor
if(HasExt[ARB_viewport_array])
{
GL.glViewportIndexedf(0, 0.0f, 0.0f, (float)m_InitParams.width, (float)m_InitParams.height);
GL.glViewportIndexedf(0, 0.0f, 0.0f, (float)ctxdata.initParams.width,
(float)ctxdata.initParams.height);
GL.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
GL.glViewport(0, 0, m_InitParams.width, m_InitParams.height);
GL.glViewport(0, 0, ctxdata.initParams.width, ctxdata.initParams.height);
GL.glDisable(eGL_SCISSOR_TEST);
}
@@ -473,7 +474,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char
GL.glDisable(eGL_CULL_FACE);
// set viewport & scissor
GL.glViewport(0, 0, (GLsizei)m_InitParams.width, (GLsizei)m_InitParams.height);
GL.glViewport(0, 0, (GLsizei)ctxdata.initParams.width, (GLsizei)ctxdata.initParams.height);
GL.glDisable(eGL_SCISSOR_TEST);
if(!IsGLES)
GL.glPolygonMode(eGL_FRONT_AND_BACK, eGL_FILL);
@@ -542,7 +543,7 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char
vertices.push_back(Vec4f(maxx, miny, 0.0f, 0.0f));
vertices.push_back(Vec4f(minx, miny, 0.0f, 0.0f));
float mul = yflipped ? -1.0f : 1.0f;
float mul = ctxdata.initParams.isYFlipped ? -1.0f : 1.0f;
while(*text)
{
@@ -567,6 +568,6 @@ void WrappedOpenGL::RenderOverlayStr(float x, float y, bool yflipped, const char
++text;
}
}
m_Platform.DrawQuads((float)m_InitParams.width, (float)m_InitParams.height, vertices);
m_Platform.DrawQuads((float)ctxdata.initParams.width, (float)ctxdata.initParams.height, vertices);
}
}
+1 -4
View File
@@ -202,8 +202,7 @@ std::vector<ResourceId> GLReplay::GetTextures()
auto &res = m_pDriver->m_Textures[it->first];
// skip textures that aren't from the log (except the 'default backbuffer' textures)
if(res.resource.name != m_pDriver->m_FakeBB_Color &&
res.resource.name != m_pDriver->m_FakeBB_DepthStencil &&
if(!(res.creationFlags & TextureCategory::SwapBuffer) &&
m_pDriver->GetResourceManager()->GetOriginalID(it->first) == it->first)
continue;
@@ -489,8 +488,6 @@ void GLReplay::CacheTexture(ResourceId id)
}
tex.creationFlags = res.creationFlags;
if(res.resource.name == drv.m_FakeBB_Color || res.resource.name == drv.m_FakeBB_DepthStencil)
tex.creationFlags |= TextureCategory::SwapBuffer;
// surely this will be the same for each level... right? that would be insane if it wasn't
GLint fmt = 0;
+2
View File
@@ -41,6 +41,8 @@ std::string DoStringise(const GLChunk &el)
STRINGISE_ENUM_CLASS(vrapi_CreateTextureSwapChain);
STRINGISE_ENUM_CLASS(vrapi_CreateTextureSwapChain2);
STRINGISE_ENUM_CLASS_NAMED(ContextConfiguration, "Context Configuration");
// re-use list of GL functions as chunks. Many of these will be aliased. This may not appear in the
// same order as the definition, but that's OK.
#define StringiseFunction(function, alias) STRINGISE_ENUM_CLASS_NAMED(alias, STRINGIZE(alias));
+24 -15
View File
@@ -62,6 +62,26 @@ public:
m_GLXWindowMap.erase(it);
}
void UpdateWindowSize(GLWindowingData data, Display *dpy, GLXDrawable drawable)
{
// if we use the GLXDrawable in XGetGeometry and it's a GLXWindow, then we get
// a BadDrawable error and things go south. Instead we track GLXWindows created
// in glXCreateWindow/glXDestroyWindow and look up the source window it was
// created from to use that.
// If the drawable didn't come through there, it just passes through unscathed
// through this function
Drawable d = UnwrapGLXWindow(drawable);
Window root;
int x, y;
unsigned int width, height, border_width, depth;
XGetGeometry(dpy, d, &root, &x, &y, &width, &height, &border_width, &depth);
GLInitParams &params = driver.GetInitParams(data);
params.width = width;
params.height = height;
}
// default to RTLD_NEXT for GLX lookups if we haven't gotten a more specific library handle
void *handle = RTLD_NEXT;
WrappedOpenGL driver;
@@ -322,6 +342,8 @@ HOOK_EXPORT Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext c
glxhook.driver.ActivateContext(data);
glxhook.UpdateWindowSize(data, dpy, drawable);
if(config)
XFree(config);
if(data.cfg)
@@ -387,6 +409,8 @@ HOOK_EXPORT Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawab
glxhook.driver.ActivateContext(data);
glxhook.UpdateWindowSize(data, dpy, draw);
if(config)
XFree(config);
if(data.cfg)
@@ -408,21 +432,6 @@ HOOK_EXPORT void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
SCOPED_LOCK(glLock);
// if we use the GLXDrawable in XGetGeometry and it's a GLXWindow, then we get
// a BadDrawable error and things go south. Instead we track GLXWindows created
// in glXCreateWindow/glXDestroyWindow and look up the source window it was
// created from to use that.
// If the drawable didn't come through there, it just passes through unscathed
// through this function
Drawable d = glxhook.UnwrapGLXWindow(drawable);
Window root;
int x, y;
unsigned int width, height, border_width, depth;
XGetGeometry(dpy, d, &root, &x, &y, &width, &height, &border_width, &depth);
glxhook.driver.WindowSize((void *)drawable, width, height);
glxhook.driver.SwapBuffers((void *)drawable);
GLX.glXSwapBuffers(dpy, drawable);
+9 -5
View File
@@ -145,11 +145,6 @@ void WGLHook::ProcessSwapBuffers(HDC dc)
if(w != NULL && haveContextCreation && !swapRecurse)
{
RECT r;
GetClientRect(w, &r);
driver.WindowSize(w, r.right - r.left, r.bottom - r.top);
{
SCOPED_LOCK(glLock);
driver.SwapBuffers(w);
@@ -375,7 +370,16 @@ static BOOL WINAPI wglMakeCurrent_hooked(HDC dc, HGLRC rc)
data.ctx = rc;
if(wglhook.haveContextCreation)
{
RECT r;
GetClientRect(data.wnd, &r);
wglhook.driver.ActivateContext(data);
GLInitParams &params = wglhook.driver.GetInitParams(data);
params.width = r.right - r.left;
params.height = r.bottom - r.top;
}
}
SetLastError(err);
@@ -3040,7 +3040,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribOffsetEXT(
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
// 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 :(
@@ -3166,7 +3166,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribIOffsetEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
// 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 :(
@@ -3292,7 +3292,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribLOffsetEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
// 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 :(
@@ -3413,7 +3413,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribBindingEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GL.glVertexArrayVertexAttribBindingEXT(vaobj.name, attribindex, bindingindex);
}
@@ -3498,7 +3498,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribFormatEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GL.glVertexArrayVertexAttribFormatEXT(vaobj.name, attribindex, size, type, normalized,
relativeoffset);
@@ -3588,7 +3588,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribIFormatEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GL.glVertexArrayVertexAttribIFormatEXT(vaobj.name, attribindex, size, type, relativeoffset);
}
@@ -3675,7 +3675,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribLFormatEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GL.glVertexArrayVertexAttribLFormatEXT(vaobj.name, attribindex, size, type, relativeoffset);
}
@@ -3759,7 +3759,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexAttribDivisorEXT(SerialiserType
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
// at the time of writing, AMD driver seems to not have this entry point
if(GL.glVertexArrayVertexAttribDivisorEXT)
@@ -3849,7 +3849,7 @@ bool WrappedOpenGL::Serialise_glEnableVertexArrayAttribEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GLint prevVAO = 0;
GL.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, &prevVAO);
@@ -3932,7 +3932,7 @@ bool WrappedOpenGL::Serialise_glDisableVertexArrayAttribEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GLint prevVAO = 0;
GL.glGetIntegerv(eGL_VERTEX_ARRAY_BINDING, &prevVAO);
@@ -4131,7 +4131,7 @@ bool WrappedOpenGL::Serialise_glBindVertexArray(SerialiserType &ser, GLuint vaob
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GL.glBindVertexArray(vaobj.name);
}
@@ -4182,7 +4182,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayElementBuffer(SerialiserType &ser, GL
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
// 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
@@ -4253,7 +4253,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayBindVertexBufferEXT(SerialiserType &s
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
if(buffer.name)
{
@@ -4390,7 +4390,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexBuffers(SerialiserType &ser, GL
}
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
// 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
@@ -4518,7 +4518,7 @@ bool WrappedOpenGL::Serialise_glVertexArrayVertexBindingDivisorEXT(SerialiserTyp
if(IsReplayingAndReading())
{
if(vaobj.name == 0)
vaobj.name = m_Fake_VAO0;
vaobj.name = m_Global_VAO0;
GL.glVertexArrayVertexBindingDivisorEXT(vaobj.name, bindingindex, divisor);
}
@@ -3321,7 +3321,7 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferfv(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
// 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
@@ -3447,7 +3447,7 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferiv(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
// 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
@@ -3564,7 +3564,7 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferuiv(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
// 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
@@ -3670,7 +3670,7 @@ bool WrappedOpenGL::Serialise_glClearNamedFramebufferfi(SerialiserType &ser, GLu
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
// 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
@@ -164,7 +164,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTextureEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glNamedFramebufferTextureEXT(framebuffer.name, attachment, texture.name, level);
@@ -305,7 +305,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTexture1DEXT(SerialiserType &ser
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glNamedFramebufferTexture1DEXT(framebuffer.name, attachment, textarget, texture.name, level);
@@ -449,7 +449,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTexture2DEXT(SerialiserType &ser
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glNamedFramebufferTexture2DEXT(framebuffer.name, attachment, textarget, texture.name, level);
@@ -594,7 +594,7 @@ bool WrappedOpenGL::Serialise_glFramebufferTexture2DMultisampleEXT(
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GLuint prevread = 0, prevdraw = 0;
GL.glGetIntegerv(eGL_DRAW_FRAMEBUFFER_BINDING, (GLint *)&prevdraw);
@@ -702,7 +702,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTexture3DEXT(SerialiserType &ser
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glNamedFramebufferTexture3DEXT(framebuffer.name, attachment, textarget, texture.name, level,
zoffset);
@@ -850,7 +850,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferRenderbufferEXT(SerialiserType &
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glNamedFramebufferRenderbufferEXT(framebuffer.name, attachment, renderbuffertarget,
renderbuffer.name);
@@ -979,7 +979,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferTextureLayerEXT(SerialiserType &
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glNamedFramebufferTextureLayerEXT(framebuffer.name, attachment, texture.name, level, layer);
@@ -1343,7 +1343,7 @@ bool WrappedOpenGL::Serialise_glNamedFramebufferParameteriEXT(SerialiserType &se
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
if(framebuffer.name)
GL.glNamedFramebufferParameteriEXT(framebuffer.name, pname, param);
@@ -1411,7 +1411,7 @@ bool WrappedOpenGL::Serialise_glFramebufferReadBufferEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
// since we are faking the default framebuffer with our own
// to see the results, replace back/front/left/right with color attachment 0
@@ -1488,7 +1488,7 @@ bool WrappedOpenGL::Serialise_glBindFramebuffer(SerialiserType &ser, GLenum targ
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GL.glBindFramebuffer(target, framebuffer.name);
}
@@ -1532,7 +1532,7 @@ bool WrappedOpenGL::Serialise_glFramebufferDrawBufferEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
// since we are faking the default framebuffer with our own
// to see the results, replace back/front/left/right with color attachment 0
@@ -1611,7 +1611,7 @@ bool WrappedOpenGL::Serialise_glFramebufferDrawBuffersEXT(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(framebuffer.name == 0)
framebuffer.name = m_FakeBB_FBO;
framebuffer.name = m_CurrentDefaultFBO;
GLenum *buffers = (GLenum *)bufs;
@@ -1826,9 +1826,9 @@ bool WrappedOpenGL::Serialise_glBlitNamedFramebuffer(SerialiserType &ser,
if(IsReplayingAndReading())
{
if(readFramebuffer.name == 0)
readFramebuffer.name = m_FakeBB_FBO;
readFramebuffer.name = m_CurrentDefaultFBO;
if(drawFramebuffer.name == 0)
drawFramebuffer.name = m_FakeBB_FBO;
drawFramebuffer.name = m_CurrentDefaultFBO;
// 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,