VectorComponentSelect.cs
1 using Ryujinx.Graphics.Shader.IntermediateRepresentation; 2 using Ryujinx.Graphics.Shader.StructuredIr; 3 using System.Collections.Generic; 4 5 using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; 6 7 namespace Ryujinx.Graphics.Shader.Translation.Transforms 8 { 9 class VectorComponentSelect : ITransformPass 10 { 11 public static bool IsEnabled(IGpuAccessor gpuAccessor, ShaderStage stage, TargetLanguage targetLanguage, FeatureFlags usedFeatures) 12 { 13 return gpuAccessor.QueryHostHasVectorIndexingBug(); 14 } 15 16 public static LinkedListNode<INode> RunPass(TransformContext context, LinkedListNode<INode> node) 17 { 18 Operation operation = (Operation)node.Value; 19 20 if (operation.Inst != Instruction.Load || 21 operation.StorageKind != StorageKind.ConstantBuffer || 22 operation.SourcesCount < 3) 23 { 24 return node; 25 } 26 27 Operand bindingIndex = operation.GetSource(0); 28 Operand fieldIndex = operation.GetSource(1); 29 Operand elemIndex = operation.GetSource(operation.SourcesCount - 1); 30 31 if (bindingIndex.Type != OperandType.Constant || 32 fieldIndex.Type != OperandType.Constant || 33 elemIndex.Type == OperandType.Constant) 34 { 35 return node; 36 } 37 38 BufferDefinition buffer = context.ResourceManager.Properties.ConstantBuffers[bindingIndex.Value]; 39 StructureField field = buffer.Type.Fields[fieldIndex.Value]; 40 41 int elemCount = (field.Type & AggregateType.ElementCountMask) switch 42 { 43 AggregateType.Vector2 => 2, 44 AggregateType.Vector3 => 3, 45 AggregateType.Vector4 => 4, 46 _ => 1 47 }; 48 49 if (elemCount == 1) 50 { 51 return node; 52 } 53 54 Operand result = null; 55 56 for (int i = 0; i < elemCount; i++) 57 { 58 Operand value = Local(); 59 Operand[] inputs = new Operand[operation.SourcesCount]; 60 61 for (int srcIndex = 0; srcIndex < inputs.Length - 1; srcIndex++) 62 { 63 inputs[srcIndex] = operation.GetSource(srcIndex); 64 } 65 66 inputs[^1] = Const(i); 67 68 Operation loadOp = new(Instruction.Load, StorageKind.ConstantBuffer, value, inputs); 69 70 node.List.AddBefore(node, loadOp); 71 72 if (i == 0) 73 { 74 result = value; 75 } 76 else 77 { 78 Operand isCurrentIndex = Local(); 79 Operand selection = Local(); 80 81 Operation compareOp = new(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) }); 82 Operation selectOp = new(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result }); 83 84 node.List.AddBefore(node, compareOp); 85 node.List.AddBefore(node, selectOp); 86 87 result = selection; 88 } 89 } 90 91 operation.TurnIntoCopy(result); 92 93 return node; 94 } 95 } 96 }