GLES: Accept a color mask for clears.

Otherwise, we end up clearing RGB when we try to only clear alpha, which
is fairly common.

Makes Valkyria Chronicles 3 action mode visible again.
This commit is contained in:
Unknown W. Brackets 2018-01-18 22:17:29 -08:00 committed by Henrik Rydgård
parent e98f265d68
commit acb692677b
7 changed files with 14 additions and 12 deletions

View file

@ -709,11 +709,13 @@ rotateVBO:
}
GLbitfield target = 0;
// Without this, we will clear RGB when clearing stencil, which breaks games.
uint8_t rgbaMask = (colorMask ? 7 : 0) | (alphaMask ? 8 : 0);
if (colorMask || alphaMask) target |= GL_COLOR_BUFFER_BIT;
if (alphaMask) target |= GL_STENCIL_BUFFER_BIT;
if (depthMask) target |= GL_DEPTH_BUFFER_BIT;
render_->Clear(clearColor, clearDepth, clearColor >> 24, target);
render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask);
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
int scissorX1 = gstate.getScissorX1();

View file

@ -113,10 +113,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
if (dstBuffer->fbo) {
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR });
}
// TODO: This incorrectly does not apply to the clear currently.
render_->SetNoBlendAndMask(0x8);
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
render_->SetNoBlendAndMask(0xF);
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT, 0x8);
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
return true;
}
@ -172,7 +169,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
textureCacheGL_->ForgetLastTexture();
// We must bind the program after starting the render pass, and set the color mask after clearing.
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT);
render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8);
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF);
render_->BindProgram(stencilUploadProgram_);
render_->SetNoBlendAndMask(0x8);

View file

@ -498,10 +498,10 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
break;
case GLRRenderCommand::CLEAR:
glDisable(GL_SCISSOR_TEST);
// TODO: We sometimes pass a color mask in that we want to respect (StencilBufferGLES.)
// We want to clear to only clear alpha, in that case.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
colorMask = 0xF;
if (c.clear.colorMask != colorMask) {
glColorMask(c.clear.colorMask & 1, (c.clear.colorMask >> 1) & 1, (c.clear.colorMask >> 2) & 1, (c.clear.colorMask >> 3) & 1);
colorMask = c.clear.colorMask;
}
if (c.clear.clearMask & GL_COLOR_BUFFER_BIT) {
float color[4];
Uint8x4ToFloat4(color, c.clear.clearColor);

View file

@ -117,6 +117,7 @@ struct GLRRenderData {
float clearZ;
int clearStencil;
int clearMask; // VK_IMAGE_ASPECT_COLOR_BIT etc
int colorMask; // Like blend, but for the clear.
} clear;
struct {
int slot;

View file

@ -193,6 +193,7 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende
}
if (clearMask) {
data.clear.clearMask = clearMask;
data.clear.colorMask = 0xF;
step->commands.push_back(data);
}

View file

@ -571,13 +571,14 @@ public:
curRenderStep_->commands.push_back(data);
}
void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask) {
void Clear(uint32_t clearColor, float clearZ, int clearStencil, int clearMask, int colorMask = 0xF) {
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data{ GLRRenderCommand::CLEAR };
data.clear.clearMask = clearMask;
data.clear.clearColor = clearColor;
data.clear.clearZ = clearZ;
data.clear.clearStencil = clearStencil;
data.clear.colorMask = colorMask;
curRenderStep_->commands.push_back(data);
}

View file

@ -186,7 +186,7 @@ public:
bool depthWriteEnabled;
GLuint depthComp;
// TODO: Two-sided
GLboolean stencilEnabled;
bool stencilEnabled;
GLuint stencilFail;
GLuint stencilZFail;
GLuint stencilPass;