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
					
				@ -577,9 +577,26 @@ private:
 | 
			
		||||
            if (std::holds_alternative<OperationNode>(*offset)) {
 | 
			
		||||
                // Indirect access
 | 
			
		||||
                const std::string final_offset = code.GenerateTemporary();
 | 
			
		||||
                code.AddLine("uint {} = (ftou({}) / 4);", final_offset, Visit(offset));
 | 
			
		||||
                return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()),
 | 
			
		||||
                                   final_offset, final_offset);
 | 
			
		||||
                code.AddLine("uint {} = ftou({}) >> 2;", final_offset, Visit(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");
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user