/ src / Ryujinx.Graphics.Shader / Translation / Transforms / DrawParametersReplace.cs
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  }