diff options
| author | 2019-05-23 20:27:54 -0300 | |
|---|---|---|
| committer | 2019-05-24 02:47:56 -0300 | |
| commit | d8827b07b5c823903609e00b8f0e1c27fa34fb91 (patch) | |
| tree | b170468a3bd2e56f367a999561ea0e6b705a2f81 /src | |
| parent | gl_device: Add test to detect broken component indexing (diff) | |
| download | yuzu-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.cpp | 23 |
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"); |