GL backend: Fix an issue with discardEnd flags
In OpenGL with use glInvalidateFramebuffer() for hinting controlling the load/store of tiles. However, glInvalidateFramebuffer() conceptually destroys the content of the framebuffer attachment. This causes a problem when we want for instance to use a buffer for reading only (e.g. a depth buffer) in multiple passes. In such scenario, the attachment will be marked as "discard" (which is a misnomer for storeOp==DONT_CARE in vulkan parlance), without the intention of making the buffer invalid. We fix this by ignoring the discardEnd flags entirely if a buffer has not been written. In this case, we relying on the driver to not write the tiles out -- but we don't have any other way to express this in GL. This issue cannot be encountered currently because the framegraph is not aggressive enough setting the discardEnd flags.
This commit is contained in:
committed by
Mathias Agopian
parent
8c7fbb2e01
commit
b514b2e996
@@ -2092,6 +2092,10 @@ void OpenGLDriver::beginRenderPass(Handle<HwRenderTarget> rth,
|
||||
params.clearColor, params.clearDepth, params.clearStencil);
|
||||
}
|
||||
|
||||
// we need to reset those after we call clearWithRasterPipe()
|
||||
mRenderPassColorWrite = any(clearFlags & TargetBufferFlags::COLOR_ALL);
|
||||
mRenderPassDepthWrite = any(clearFlags & TargetBufferFlags::DEPTH);
|
||||
|
||||
gl.viewport(params.viewport.left, params.viewport.bottom,
|
||||
params.viewport.width, params.viewport.height);
|
||||
|
||||
@@ -2112,11 +2116,18 @@ void OpenGLDriver::endRenderPass(int) {
|
||||
|
||||
GLRenderTarget const* const rt = handle_cast<GLRenderTarget*>(mRenderPassTarget);
|
||||
|
||||
const TargetBufferFlags discardFlags = mRenderPassParams.flags.discardEnd & rt->targets;
|
||||
TargetBufferFlags discardFlags = mRenderPassParams.flags.discardEnd & rt->targets;
|
||||
if (rt->gl.fbo_read) {
|
||||
resolvePass(ResolveAction::STORE, rt, discardFlags);
|
||||
}
|
||||
|
||||
if (!mRenderPassColorWrite) {
|
||||
discardFlags &= ~TargetBufferFlags::COLOR_ALL;
|
||||
}
|
||||
if (!mRenderPassDepthWrite) {
|
||||
discardFlags &= ~TargetBufferFlags::DEPTH;
|
||||
}
|
||||
|
||||
// glInvalidateFramebuffer appeared on GLES 3.0 and GL4.3, for simplicity we just
|
||||
// ignore it on GL (rather than having to do a runtime check).
|
||||
if (GLES30_HEADERS) {
|
||||
|
||||
@@ -316,6 +316,8 @@ private:
|
||||
|
||||
void setRasterStateSlow(backend::RasterState rs) noexcept;
|
||||
void setRasterState(backend::RasterState rs) noexcept {
|
||||
mRenderPassColorWrite |= rs.colorWrite;
|
||||
mRenderPassDepthWrite |= rs.depthWrite;
|
||||
if (UTILS_UNLIKELY(rs != mRasterState)) {
|
||||
setRasterStateSlow(rs);
|
||||
}
|
||||
@@ -374,6 +376,8 @@ private:
|
||||
// state required to represent the current render pass
|
||||
backend::Handle<backend::HwRenderTarget> mRenderPassTarget;
|
||||
backend::RenderPassParams mRenderPassParams;
|
||||
GLboolean mRenderPassColorWrite{};
|
||||
GLboolean mRenderPassDepthWrite{};
|
||||
|
||||
void clearWithRasterPipe(backend::TargetBufferFlags clearFlags,
|
||||
math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user