Skip to content

Commit

Permalink
Merge pull request #11192 from unknownbrackets/stencil
Browse files Browse the repository at this point in the history
Correct stencil upload bugs
  • Loading branch information
hrydgard authored Jun 18, 2018
2 parents da5f0f7 + bd13f6b commit fb70dad
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 8 deletions.
7 changes: 5 additions & 2 deletions GPU/Common/FramebufferCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,13 @@ struct VirtualFramebuffer {
// width/height: The detected size of the current framebuffer.
u16 width;
u16 height;
// renderWidth/renderHeight: The actual size we render at. May be scaled to render at higher resolutions.
// renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions.
// The physical buffer may be larger than renderWidth/renderHeight.
u16 renderWidth;
u16 renderHeight;
// bufferWidth/bufferHeight: The actual (but non scaled) size of the buffer we render to. May only be bigger than width/height.
// bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than width/height.
// Actual physical buffer is this size times the render resolution multiplier.
// The buffer may be used to render a width or height from 0 to these values without being recreated.
u16 bufferWidth;
u16 bufferHeight;

Expand Down
16 changes: 10 additions & 6 deletions GPU/GLES/StencilBufferGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,15 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
std::vector<GLRShader *> shaders;
shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code, "stencil"));
shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code, "stencil"));
std::vector<GLRProgram::Semantic> semantics;
semantics.push_back({ 0, "a_position" });
semantics.push_back({ 1, "a_texcoord0" });
std::vector<GLRProgram::UniformLocQuery> queries;
queries.push_back({ &u_stencilUploadTex, "tex" });
queries.push_back({ &u_stencilValue, "u_stencilValue" });
std::vector<GLRProgram::Initializer> inits;
inits.push_back({ &u_stencilUploadTex, 0, 0 });
stencilUploadProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false);
stencilUploadProgram_ = render_->CreateProgram(shaders, semantics, queries, inits, false);
for (auto iter : shaders) {
render_->DeleteShader(iter);
}
Expand All @@ -146,27 +149,28 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe

// Our fragment shader (and discard) is slow. Since the source is 1x, we can stencil to 1x.
// Then after we're done, we'll just blit it across and stretch it there.
if (dstBuffer->bufferWidth == dstBuffer->renderWidth || !dstBuffer->fbo) {
if (dstBuffer->width == dstBuffer->renderWidth || !dstBuffer->fbo) {
useBlit = false;
}
u16 w = useBlit ? dstBuffer->bufferWidth : dstBuffer->renderWidth;
u16 h = useBlit ? dstBuffer->bufferHeight : dstBuffer->renderHeight;
u16 w = useBlit ? dstBuffer->width : dstBuffer->renderWidth;
u16 h = useBlit ? dstBuffer->height : dstBuffer->renderHeight;

Draw::Framebuffer *blitFBO = nullptr;
if (useBlit) {
blitFBO = GetTempFBO(TempFBO::COPY, w, h, Draw::FBO_8888);
draw_->BindFramebufferAsRenderTarget(blitFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
} else if (dstBuffer->fbo) {
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR });
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::DONT_CARE });
}
render_->SetViewport({ 0, 0, (float)w, (float)h, 0.0f, 1.0f });

float u1 = 1.0f;
float v1 = 1.0f;
MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1);
MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstBuffer->height, u1, v1);
textureCacheGL_->ForgetLastTexture();

// We must bind the program after starting the render pass, and set the color mask after clearing.
render_->SetScissor({ 0, 0, w, h });
render_->SetDepth(false, false, GL_ALWAYS);
render_->Clear(0, 0, 0, GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, 0x8, 0, 0, 0, 0);
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF);
Expand Down
4 changes: 4 additions & 0 deletions GPU/Vulkan/StencilBufferVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "GPU/Vulkan/TextureCacheVulkan.h"
#include "GPU/Vulkan/VulkanUtil.h"

// This shader references gl_FragDepth to prevent early fragment tests.
// They shouldn't happen since it uses discard, but Adreno detects that incorrectly - see #10634.
static const char *stencil_fs = R"(#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
Expand All @@ -38,6 +40,8 @@ layout (location = 0) in vec2 v_texcoord0;
layout (location = 0) out vec4 fragColor0;
void main() {
gl_FragDepth = 0.0;
if (u_stencilValue == 0) {
fragColor0 = vec4(0.0);
} else {
Expand Down

0 comments on commit fb70dad

Please sign in to comment.