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; ```
This commit is contained in:
parent
46177901b8
commit
d8827b07b5
1 changed files with 20 additions and 3 deletions
|
@ -577,9 +577,26 @@ private:
|
||||||
if (std::holds_alternative<OperationNode>(*offset)) {
|
if (std::holds_alternative<OperationNode>(*offset)) {
|
||||||
// Indirect access
|
// Indirect access
|
||||||
const std::string final_offset = code.GenerateTemporary();
|
const std::string final_offset = code.GenerateTemporary();
|
||||||
code.AddLine("uint {} = (ftou({}) / 4);", final_offset, Visit(offset));
|
code.AddLine("uint {} = ftou({}) >> 2;", final_offset, Visit(offset));
|
||||||
return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()),
|
|
||||||
final_offset, final_offset);
|
if (!device.HasComponentIndexingBug()) {
|
||||||
|
return fmt::format("{}[{} >> 2][{} & 3]", GetConstBuffer(cbuf->GetIndex()),
|
||||||
|
final_offset, final_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// AMD's proprietary GLSL compiler emits ill code for variable component access.
|
||||||
|
// To bypass this driver bug generate 4 ifs, one per each component.
|
||||||
|
const std::string pack = code.GenerateTemporary();
|
||||||
|
code.AddLine("vec4 {} = {}[{} >> 2];", pack, GetConstBuffer(cbuf->GetIndex()),
|
||||||
|
final_offset);
|
||||||
|
|
||||||
|
const std::string result = code.GenerateTemporary();
|
||||||
|
code.AddLine("float {};", result);
|
||||||
|
for (u32 swizzle = 0; swizzle < 4; ++swizzle) {
|
||||||
|
code.AddLine("if (({} & 3) == {}) {} = {}{};", final_offset, swizzle, result,
|
||||||
|
pack, GetSwizzle(swizzle));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE_MSG("Unmanaged offset node type");
|
UNREACHABLE_MSG("Unmanaged offset node type");
|
||||||
|
|
Loading…
Reference in a new issue