DrawParametersReplace.cs
1 using Ryujinx.Graphics.Shader.IntermediateRepresentation; 2 using System.Collections.Generic; 3 4 using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; 5 6 namespace Ryujinx.Graphics.Shader.Translation.Transforms 7 { 8 class DrawParametersReplace : ITransformPass 9 { 10 public static bool IsEnabled(IGpuAccessor gpuAccessor, ShaderStage stage, TargetLanguage targetLanguage, FeatureFlags usedFeatures) 11 { 12 return stage == ShaderStage.Vertex; 13 } 14 15 public static LinkedListNode<INode> RunPass(TransformContext context, LinkedListNode<INode> node) 16 { 17 Operation operation = (Operation)node.Value; 18 19 if (context.GpuAccessor.QueryHasConstantBufferDrawParameters()) 20 { 21 if (ReplaceConstantBufferWithDrawParameters(node, operation)) 22 { 23 context.UsedFeatures |= FeatureFlags.DrawParameters; 24 } 25 } 26 else if (HasConstantBufferDrawParameters(operation)) 27 { 28 context.UsedFeatures |= FeatureFlags.DrawParameters; 29 } 30 31 return node; 32 } 33 34 private static bool ReplaceConstantBufferWithDrawParameters(LinkedListNode<INode> node, Operation operation) 35 { 36 Operand GenerateLoad(IoVariable ioVariable) 37 { 38 Operand value = Local(); 39 node.List.AddBefore(node, new Operation(Instruction.Load, StorageKind.Input, value, Const((int)ioVariable))); 40 return value; 41 } 42 43 bool modified = false; 44 45 for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) 46 { 47 Operand src = operation.GetSource(srcIndex); 48 49 if (src.Type == OperandType.ConstantBuffer && src.GetCbufSlot() == 0) 50 { 51 switch (src.GetCbufOffset()) 52 { 53 case Constants.NvnBaseVertexByteOffset / 4: 54 operation.SetSource(srcIndex, GenerateLoad(IoVariable.BaseVertex)); 55 modified = true; 56 break; 57 case Constants.NvnBaseInstanceByteOffset / 4: 58 operation.SetSource(srcIndex, GenerateLoad(IoVariable.BaseInstance)); 59 modified = true; 60 break; 61 case Constants.NvnDrawIndexByteOffset / 4: 62 operation.SetSource(srcIndex, GenerateLoad(IoVariable.DrawIndex)); 63 modified = true; 64 break; 65 } 66 } 67 } 68 69 return modified; 70 } 71 72 private static bool HasConstantBufferDrawParameters(Operation operation) 73 { 74 for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++) 75 { 76 Operand src = operation.GetSource(srcIndex); 77 78 if (src.Type == OperandType.ConstantBuffer && src.GetCbufSlot() == 0) 79 { 80 switch (src.GetCbufOffset()) 81 { 82 case Constants.NvnBaseVertexByteOffset / 4: 83 case Constants.NvnBaseInstanceByteOffset / 4: 84 case Constants.NvnDrawIndexByteOffset / 4: 85 return true; 86 } 87 } 88 } 89 90 return false; 91 } 92 } 93 }