From f6036195d822a9963f33d7a4a091b74aea5aa661 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jun 2018 17:40:37 -0700 Subject: [PATCH 1/3] GLES: Cleanup stencil upload w/h handling. In case a buffer has been resized recently, we want to upload just the detected drawable area, probably. Before this was inconsistent depending on the render resolution. --- GPU/Common/FramebufferCommon.h | 7 +++++-- GPU/GLES/StencilBufferGLES.cpp | 11 ++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 468701663a..4f19debd01 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -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; diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index fcbba39970..a97fc593d5 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -146,27 +146,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); From 9f4cd3fcdb3ff2a2705239af9824d7f050e99909 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jun 2018 17:42:02 -0700 Subject: [PATCH 2/3] GLES: Add missing semantics for stencil upload. Makes #10634 work for GLES properly. --- GPU/GLES/StencilBufferGLES.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index a97fc593d5..9dac4c9a3f 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -126,12 +126,15 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe std::vector 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 semantics; + semantics.push_back({ 0, "a_position" }); + semantics.push_back({ 1, "a_texcoord0" }); std::vector queries; queries.push_back({ &u_stencilUploadTex, "tex" }); queries.push_back({ &u_stencilValue, "u_stencilValue" }); std::vector 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); } From bd13f6b9066c0f3ee0cd4dbaa9940f7c6787a5c0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Jun 2018 17:45:20 -0700 Subject: [PATCH 3/3] Vulkan: Workaround stencil upload bug on Adreno. We write a static depth value, which will be ignored, to force the driver to support discard. --- GPU/Vulkan/StencilBufferVulkan.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/Vulkan/StencilBufferVulkan.cpp b/GPU/Vulkan/StencilBufferVulkan.cpp index 35661711d5..7ce1e00fe5 100644 --- a/GPU/Vulkan/StencilBufferVulkan.cpp +++ b/GPU/Vulkan/StencilBufferVulkan.cpp @@ -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 @@ -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 {