mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Merge pull request #23047 from hrydgard/gles-fetch-output-readback
Adreno 5xx: Work around framebuffer fetch (GL) and light ubershader (Vulkan) driver bugs
This commit is contained in:
3 files changed
+28
-9
No files matched your search
@@ -746,7 +746,10 @@ OpenGLContext::OpenGLContext(bool canChangeSwapInterval) : renderManager_(frameT
|
||||
}
|
||||
|
||||
// NOTE: We only support framebuffer fetch on ES3 due to past issues..
|
||||
if (gl_extensions.IsGLES && gl_extensions.GLES3) {
|
||||
// Adreno 5xx (seen on a 506, driver V@145) can fetch black instead of what an earlier draw in the same pass
|
||||
// wrote there, so it gets framebuffer copies instead.
|
||||
bool brokenFramebufferFetch = caps_.vendor == GPUVendor::VENDOR_QUALCOMM && gl_extensions.modelNumber < 600;
|
||||
if (gl_extensions.IsGLES && gl_extensions.GLES3 && !brokenFramebufferFetch) {
|
||||
caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch);
|
||||
|
||||
if (gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
|
||||
@@ -1087,6 +1087,11 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
|
||||
if (!turnip && (deviceProps.driverVersion < 0x801EA000 || deviceProps.deviceID < 0x06000000))
|
||||
bugs_.Infest(Bugs::COLORWRITEMASK_BROKEN_WITH_DEPTHTEST);
|
||||
|
||||
// The light ubershader's loop over the lights gives wrong lighting (LittleBigPlanet's Sackboy and scenery came
|
||||
// out pale). Seen on Adreno 506 with a Vulkan 1.0.20 driver; the per-light shaders are fine.
|
||||
if (!turnip && deviceProps.deviceID >= 0x05000000 && deviceProps.deviceID < 0x06000000)
|
||||
bugs_.Infest(Bugs::UNIFORM_INDEXING_BROKEN);
|
||||
|
||||
// Trying to follow all the rules in https://registry.khronos.org/vulkan/specs/1.3/html/vkspec.html#synchronization-pipeline-barriers-subpass-self-dependencies
|
||||
// and https://registry.khronos.org/vulkan/specs/1.3/html/vkspec.html#renderpass-feedbackloop, but still it doesn't
|
||||
// quite work - artifacts on triangle boundaries on Adreno.
|
||||
|
||||
@@ -1200,18 +1200,26 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
}
|
||||
}
|
||||
|
||||
// With EXT_shader_framebuffer_fetch, fragColor0 is inout. Adreno 506 (driver V@145) reads it back wrong once
|
||||
// the shader has written it (packing it for the write mask came out black), so build the color in a local.
|
||||
const char *fragColor0 = compat.fragColor0;
|
||||
if (fetchFramebuffer && compat.lastFragData && !strcmp(compat.lastFragData, fragColor0)) {
|
||||
WRITE(p, " vec4 outColor0;\n");
|
||||
fragColor0 = "outColor0";
|
||||
}
|
||||
|
||||
switch (stencilToAlpha) {
|
||||
case REPLACE_ALPHA_DUALSOURCE:
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", compat.fragColor0, replacedAlpha);
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", fragColor0, replacedAlpha);
|
||||
WRITE(p, " %s = vec4(0.0, 0.0, 0.0, v.a);\n", compat.fragColor1);
|
||||
break;
|
||||
|
||||
case REPLACE_ALPHA_YES:
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", compat.fragColor0, replacedAlpha);
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", fragColor0, replacedAlpha);
|
||||
break;
|
||||
|
||||
case REPLACE_ALPHA_NO:
|
||||
WRITE(p, " %s = v;\n", compat.fragColor0);
|
||||
WRITE(p, " %s = v;\n", fragColor0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1221,10 +1229,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
|
||||
switch (simulateLogicOpType) {
|
||||
case LOGICOPTYPE_ONE:
|
||||
WRITE(p, " %s.rgb = splat3(1.0);\n", compat.fragColor0);
|
||||
WRITE(p, " %s.rgb = splat3(1.0);\n", fragColor0);
|
||||
break;
|
||||
case LOGICOPTYPE_INVERT:
|
||||
WRITE(p, " %s.rgb = splat3(1.0) - %s.rgb;\n", compat.fragColor0, compat.fragColor0);
|
||||
WRITE(p, " %s.rgb = splat3(1.0) - %s.rgb;\n", fragColor0, fragColor0);
|
||||
break;
|
||||
case LOGICOPTYPE_NORMAL:
|
||||
break;
|
||||
@@ -1236,7 +1244,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
|
||||
// Final color computed - apply logic ops and bitwise color write mask, through shader blending, if specified.
|
||||
if (colorWriteMask || replaceLogicOp) {
|
||||
WRITE(p, " highp uint v32 = packUnorm4x8%s(%s);\n", packSuffix, compat.fragColor0);
|
||||
WRITE(p, " highp uint v32 = packUnorm4x8%s(%s);\n", packSuffix, fragColor0);
|
||||
WRITE(p, " highp uint d32 = packUnorm4x8%s(destColor);\n", packSuffix);
|
||||
|
||||
// v32 is both the "s" to the logical operation, and the value that we'll merge to the destination with masking later.
|
||||
@@ -1268,11 +1276,14 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
else
|
||||
WRITE(p, " v32 = (v32 & u_colorWriteMask & 0x00FFFFFFu) | (d32 & (~u_colorWriteMask | 0xFF000000u));\n");
|
||||
}
|
||||
WRITE(p, " %s = unpackUnorm4x8%s(v32);\n", compat.fragColor0, packSuffix);
|
||||
WRITE(p, " %s = unpackUnorm4x8%s(v32);\n", fragColor0, packSuffix);
|
||||
}
|
||||
|
||||
if (blueToAlpha) {
|
||||
WRITE(p, " %s = vec4(0.0, 0.0, 0.0, %s.z); // blue to alpha\n", compat.fragColor0, compat.fragColor0);
|
||||
WRITE(p, " %s = vec4(0.0, 0.0, 0.0, %s.z); // blue to alpha\n", fragColor0, fragColor0);
|
||||
}
|
||||
if (fragColor0 != compat.fragColor0) {
|
||||
WRITE(p, " %s = %s;\n", compat.fragColor0, fragColor0);
|
||||
}
|
||||
|
||||
if (fsDepthClamp || fsMinmaxDiscard) {
|
||||
|
||||
Reference in new issue
Block a user