summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-05-23 20:27:54 -0300
committerGravatar ReinUsesLisp2019-05-24 02:47:56 -0300
commitd8827b07b5c823903609e00b8f0e1c27fa34fb91 (patch)
treeb170468a3bd2e56f367a999561ea0e6b705a2f81 /src
parentgl_device: Add test to detect broken component indexing (diff)
downloadyuzu-d8827b07b5c823903609e00b8f0e1c27fa34fb91.tar.gz
yuzu-d8827b07b5c823903609e00b8f0e1c27fa34fb91.tar.xz
yuzu-d8827b07b5c823903609e00b8f0e1c27fa34fb91.zip
gl_shader_decompiler: Use an if based cbuf indexing for broken drivers
The following code is broken on AMD's proprietary GLSL compiler: ```glsl uint idx = ...; vec4 values = ...; float some_value = values[idx & 3]; ``` It index the wrong components, to fix this the following pessimized code is emitted when that bug is present: ```glsl uint idx = ...; vec4 values = ...; float some_value; if ((idx & 3) == 0) some_value = values.x; if ((idx & 3) == 1) some_value = values.y; if ((idx & 3) == 2) some_value = values.z; if ((idx & 3) == 3) some_value = values.w; ```
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 6d4658c8b..4a40e4843 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -577,9 +577,26 @@ private:
577 if (std::holds_alternative<OperationNode>(*offset)) { 577 if (std::holds_alternative<OperationNode>(*offset)) {
578 // Indirect access 578 // Indirect access
579 const std::string final_offset = code.GenerateTemporary(); 579 const std::string final_offset = code.GenerateTemporary();
580 code.AddLine("uint {} = (ftou({}) / 4);", final_offset, Visit(offset)); 580 code.AddLine("uint {} = ftou({}) >> 2;", final_offset, Visit(offset));
581 return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()), 581
582 final_offset, final_offset); 582 if (!device.HasComponentIndexingBug()) {
583 return fmt::format("{}[{} >> 2][{} & 3]", GetConstBuffer(cbuf->GetIndex()),
584 final_offset, final_offset);
585 }
586
587 // AMD's proprietary GLSL compiler emits ill code for variable component access.
588 // To bypass this driver bug generate 4 ifs, one per each component.
589 const std::string pack = code.GenerateTemporary();
590 code.AddLine("vec4 {} = {}[{} >> 2];", pack, GetConstBuffer(cbuf->GetIndex()),
591 final_offset);
592
593 const std::string result = code.GenerateTemporary();
594 code.AddLine("float {};", result);
595 for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
596 code.AddLine("if (({} & 3) == {}) {} = {}{};", final_offset, swizzle, result,
597 pack, GetSwizzle(swizzle));
598 }
599 return result;
583 } 600 }
584 601
585 UNREACHABLE_MSG("Unmanaged offset node type"); 602 UNREACHABLE_MSG("Unmanaged offset node type");