Ensure that glBlitFramebuffer for internal copies has correct state

* In particular we need to disable scissor (which can affect the blit) and any
  color/write masks.
This commit is contained in:
baldurk
2018-07-06 22:44:24 +01:00
parent 3327b1f3e1
commit 20273c3854
7 changed files with 98 additions and 18 deletions
+75
View File
@@ -1335,6 +1335,81 @@ GLuint GetBoundVertexBuffer(GLuint i)
return buffer;
}
void SafeBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0,
GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
bool scissorEnabled = false;
GLboolean ColorMask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
GLboolean DepthMask = GL_TRUE;
GLint StencilMask = 0xff, StencilBackMask = 0xff;
// fetch current state
{
if(HasExt[ARB_viewport_array])
scissorEnabled = GL.glIsEnabledi(eGL_SCISSOR_TEST, 0) != 0;
else
scissorEnabled = GL.glIsEnabled(eGL_SCISSOR_TEST) != 0;
if(HasExt[EXT_draw_buffers2] || HasExt[ARB_draw_buffers_blend])
GL.glGetBooleani_v(eGL_COLOR_WRITEMASK, 0, ColorMask);
else
GL.glGetBooleanv(eGL_COLOR_WRITEMASK, ColorMask);
GL.glGetBooleanv(eGL_DEPTH_WRITEMASK, &DepthMask);
GL.glGetIntegerv(eGL_STENCIL_WRITEMASK, &StencilMask);
GL.glGetIntegerv(eGL_STENCIL_BACK_WRITEMASK, &StencilBackMask);
}
// apply safe state
{
if(HasExt[ARB_viewport_array])
GL.glDisablei(eGL_SCISSOR_TEST, 0);
else
GL.glDisable(eGL_SCISSOR_TEST);
if(HasExt[EXT_draw_buffers2] || HasExt[ARB_draw_buffers_blend])
GL.glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
else
GL.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
GL.glDepthMask(GL_TRUE);
GL.glStencilMaskSeparate(eGL_FRONT, 0xff);
GL.glStencilMaskSeparate(eGL_BACK, 0xff);
}
GL.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
// restore original state
{
if(HasExt[ARB_viewport_array])
{
if(scissorEnabled)
GL.glEnablei(eGL_SCISSOR_TEST, 0);
else
GL.glDisablei(eGL_SCISSOR_TEST, 0);
}
else
{
if(scissorEnabled)
GL.glEnable(eGL_SCISSOR_TEST);
else
GL.glDisable(eGL_SCISSOR_TEST);
}
if(HasExt[EXT_draw_buffers2] || HasExt[ARB_draw_buffers_blend])
GL.glColorMaski(0, ColorMask[0], ColorMask[1], ColorMask[2], ColorMask[3]);
else
GL.glColorMask(ColorMask[0], ColorMask[1], ColorMask[2], ColorMask[3]);
GL.glDepthMask(DepthMask);
GL.glStencilMaskSeparate(eGL_FRONT, StencilMask);
GL.glStencilMaskSeparate(eGL_BACK, StencilBackMask);
}
}
BufferCategory MakeBufferCategory(GLenum bufferTarget)
{
switch(bufferTarget)
+5
View File
@@ -499,6 +499,11 @@ void GetBindpointMapping(GLuint curProg, int shadIdx, ShaderReflection *refl,
void ResortBindings(ShaderReflection *refl, ShaderBindpointMapping *mapping);
// calls glBlitFramebuffer but ensures no state can interfere like scissor or color mask
// pops state for only a single drawbuffer!
void SafeBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0,
GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
enum UniformType
{
UNIFORM_UNKNOWN,
+2 -2
View File
@@ -877,7 +877,7 @@ bool GLReplay::GetMinMax(ResourceId texid, uint32_t sliceFace, uint32_t mip, uin
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, texDetails.renderbufferFBOs[1]);
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, texDetails.renderbufferFBOs[0]);
GL.glBlitFramebuffer(
SafeBlitFramebuffer(
0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width, texDetails.height,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, eGL_NEAREST);
@@ -1049,7 +1049,7 @@ bool GLReplay::GetHistogram(ResourceId texid, uint32_t sliceFace, uint32_t mip,
GL.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, texDetails.renderbufferFBOs[1]);
GL.glBindFramebuffer(eGL_READ_FRAMEBUFFER, texDetails.renderbufferFBOs[0]);
GL.glBlitFramebuffer(
SafeBlitFramebuffer(
0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width, texDetails.height,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, eGL_NEAREST);
+6 -6
View File
@@ -699,9 +699,9 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeHint, DebugOve
}
// get latest depth/stencil from read FBO (existing FBO) into draw FBO (overlay FBO)
drv.glBlitFramebuffer(0, 0, DebugData.overlayTexWidth, DebugData.overlayTexHeight, 0, 0,
DebugData.overlayTexWidth, DebugData.overlayTexHeight,
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, eGL_NEAREST);
SafeBlitFramebuffer(0, 0, DebugData.overlayTexWidth, DebugData.overlayTexHeight, 0, 0,
DebugData.overlayTexWidth, DebugData.overlayTexHeight,
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, eGL_NEAREST);
ReplayLog(eventId, eReplay_OnlyDraw);
@@ -1317,9 +1317,9 @@ ResourceId GLReplay::RenderOverlay(ResourceId texid, CompType typeHint, DebugOve
drv.glBindProgramPipeline(0);
drv.glBindFramebuffer(eGL_READ_FRAMEBUFFER, curdrawfbo);
drv.glBlitFramebuffer(0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width,
texDetails.height, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
eGL_NEAREST);
SafeBlitFramebuffer(0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width,
texDetails.height, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
eGL_NEAREST);
m_pDriver->ReplayLog(0, events[i], eReplay_OnlyDraw);
+1 -1
View File
@@ -94,7 +94,7 @@ bool GLReplay::RenderTextureInternal(TextureDisplay cfg, int flags)
drv.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, texDetails.renderbufferFBOs[1]);
drv.glBindFramebuffer(eGL_READ_FRAMEBUFFER, texDetails.renderbufferFBOs[0]);
drv.glBlitFramebuffer(
SafeBlitFramebuffer(
0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width, texDetails.height,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, eGL_NEAREST);
+3 -3
View File
@@ -2317,7 +2317,7 @@ void GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
float col[] = {0.3f, 0.4f, 0.5f, 1.0f};
drv.glClearBufferfv(eGL_COLOR, 0, col);
drv.glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, eGL_NEAREST);
SafeBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, eGL_NEAREST);
// rewrite the variables to temporary texture
texType = eGL_TEXTURE_2D;
@@ -2380,8 +2380,8 @@ void GLReplay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip,
else if(b == eGL_DEPTH_STENCIL)
mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
drv.glBlitFramebuffer(0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width,
texDetails.height, mask, eGL_NEAREST);
SafeBlitFramebuffer(0, 0, texDetails.width, texDetails.height, 0, 0, texDetails.width,
texDetails.height, mask, eGL_NEAREST);
drv.glBindFramebuffer(eGL_DRAW_FRAMEBUFFER, curDrawFBO);
drv.glBindFramebuffer(eGL_READ_FRAMEBUFFER, curReadFBO);
+6 -6
View File
@@ -1198,8 +1198,8 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev
}
else if(!layered)
{
GL.glBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY,
dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST);
SafeBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY,
dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST);
}
else if(srcTarget == eGL_TEXTURE_CUBE_MAP)
{
@@ -1218,8 +1218,8 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev
GL.glFramebufferTexture2D(eGL_DRAW_FRAMEBUFFER, attach, textargets[dstZ + slice], dstName,
dstLevel);
GL.glBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY,
dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST);
SafeBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY,
dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST);
}
}
else
@@ -1229,8 +1229,8 @@ void APIENTRY _glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLev
GL.glFramebufferTextureLayer(eGL_READ_FRAMEBUFFER, attach, srcName, srcLevel, srcZ + slice);
GL.glFramebufferTextureLayer(eGL_DRAW_FRAMEBUFFER, attach, dstName, dstLevel, dstZ + slice);
GL.glBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY,
dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST);
SafeBlitFramebuffer(srcX, srcY, srcX + srcWidth, srcY + srcHeight, dstX, dstY,
dstX + srcWidth, dstY + srcHeight, mask, eGL_NEAREST);
}
}
}