GpuChannelGraphicsState.cs
1 using Ryujinx.Common.Memory; 2 using Ryujinx.Graphics.GAL; 3 using Ryujinx.Graphics.Gpu.Engine.Threed; 4 using Ryujinx.Graphics.Shader; 5 6 namespace Ryujinx.Graphics.Gpu.Shader 7 { 8 /// <summary> 9 /// State used by the <see cref="GpuAccessor"/>. 10 /// </summary> 11 struct GpuChannelGraphicsState 12 { 13 // New fields should be added to the end of the struct to keep disk shader cache compatibility. 14 15 /// <summary> 16 /// Early Z force enable. 17 /// </summary> 18 public bool EarlyZForce; 19 20 /// <summary> 21 /// Primitive topology of current draw. 22 /// </summary> 23 public PrimitiveTopology Topology; 24 25 /// <summary> 26 /// Tessellation mode. 27 /// </summary> 28 public TessMode TessellationMode; 29 30 /// <summary> 31 /// Indicates whether alpha-to-coverage is enabled. 32 /// </summary> 33 public bool AlphaToCoverageEnable; 34 35 /// <summary> 36 /// Indicates whether alpha-to-coverage dithering is enabled. 37 /// </summary> 38 public bool AlphaToCoverageDitherEnable; 39 40 /// <summary> 41 /// Indicates whether the viewport transform is disabled. 42 /// </summary> 43 public bool ViewportTransformDisable; 44 45 /// <summary> 46 /// Depth mode zero to one or minus one to one. 47 /// </summary> 48 public bool DepthMode; 49 50 /// <summary> 51 /// Indicates if the point size is set on the shader or is fixed. 52 /// </summary> 53 public bool ProgramPointSizeEnable; 54 55 /// <summary> 56 /// Point size used if <see cref="ProgramPointSizeEnable" /> is false. 57 /// </summary> 58 public float PointSize; 59 60 /// <summary> 61 /// Indicates whether alpha test is enabled. 62 /// </summary> 63 public bool AlphaTestEnable; 64 65 /// <summary> 66 /// When alpha test is enabled, indicates the comparison that decides if the fragment should be discarded. 67 /// </summary> 68 public CompareOp AlphaTestCompare; 69 70 /// <summary> 71 /// When alpha test is enabled, indicates the value to compare with the fragment output alpha. 72 /// </summary> 73 public float AlphaTestReference; 74 75 /// <summary> 76 /// Type of the vertex attributes consumed by the shader. 77 /// </summary> 78 public Array32<AttributeType> AttributeTypes; 79 80 /// <summary> 81 /// Indicates that the draw is writing the base vertex, base instance and draw index to Constant Buffer 0. 82 /// </summary> 83 public bool HasConstantBufferDrawParameters; 84 85 /// <summary> 86 /// Indicates that any storage buffer use is unaligned. 87 /// </summary> 88 public bool HasUnalignedStorageBuffer; 89 90 /// <summary> 91 /// Type of the fragment shader outputs. 92 /// </summary> 93 public Array8<AttributeType> FragmentOutputTypes; 94 95 /// <summary> 96 /// Indicates whether dual source blend is enabled. 97 /// </summary> 98 public bool DualSourceBlendEnable; 99 100 /// <summary> 101 /// Indicates whether Y negate of the fragment coordinates is enabled. 102 /// </summary> 103 public bool YNegateEnabled; 104 105 /// <summary> 106 /// Creates a new graphics state from this state that can be used for shader generation. 107 /// </summary> 108 /// <param name="hostSupportsAlphaTest">Indicates if the host API supports alpha test operations</param> 109 /// <param name="hostSupportsQuads">Indicates if the host API supports quad primitives</param> 110 /// <param name="hasGeometryShader">Indicates if a geometry shader is used</param> 111 /// <param name="originUpperLeft">If true, indicates that the fragment origin is the upper left corner of the viewport, otherwise it is the lower left corner</param> 112 /// <returns>GPU graphics state that can be used for shader translation</returns> 113 public readonly GpuGraphicsState CreateShaderGraphicsState(bool hostSupportsAlphaTest, bool hostSupportsQuads, bool hasGeometryShader, bool originUpperLeft) 114 { 115 AlphaTestOp alphaTestOp; 116 117 if (hostSupportsAlphaTest || !AlphaTestEnable) 118 { 119 alphaTestOp = AlphaTestOp.Always; 120 } 121 else 122 { 123 alphaTestOp = AlphaTestCompare switch 124 { 125 CompareOp.Never or CompareOp.NeverGl => AlphaTestOp.Never, 126 CompareOp.Less or CompareOp.LessGl => AlphaTestOp.Less, 127 CompareOp.Equal or CompareOp.EqualGl => AlphaTestOp.Equal, 128 CompareOp.LessOrEqual or CompareOp.LessOrEqualGl => AlphaTestOp.LessOrEqual, 129 CompareOp.Greater or CompareOp.GreaterGl => AlphaTestOp.Greater, 130 CompareOp.NotEqual or CompareOp.NotEqualGl => AlphaTestOp.NotEqual, 131 CompareOp.GreaterOrEqual or CompareOp.GreaterOrEqualGl => AlphaTestOp.GreaterOrEqual, 132 _ => AlphaTestOp.Always, 133 }; 134 } 135 136 bool isQuad = Topology == PrimitiveTopology.Quads || Topology == PrimitiveTopology.QuadStrip; 137 bool halvePrimitiveId = !hostSupportsQuads && !hasGeometryShader && isQuad; 138 139 return new GpuGraphicsState( 140 EarlyZForce, 141 ConvertToInputTopology(Topology, TessellationMode), 142 TessellationMode.UnpackCw(), 143 TessellationMode.UnpackPatchType(), 144 TessellationMode.UnpackSpacing(), 145 AlphaToCoverageEnable, 146 AlphaToCoverageDitherEnable, 147 ViewportTransformDisable, 148 DepthMode, 149 ProgramPointSizeEnable, 150 PointSize, 151 alphaTestOp, 152 AlphaTestReference, 153 in AttributeTypes, 154 HasConstantBufferDrawParameters, 155 in FragmentOutputTypes, 156 DualSourceBlendEnable, 157 YNegateEnabled, 158 originUpperLeft, 159 halvePrimitiveId); 160 } 161 162 /// <summary> 163 /// Converts the Maxwell primitive topology to the shader translator topology. 164 /// </summary> 165 /// <param name="topology">Maxwell primitive topology</param> 166 /// <param name="tessellationMode">Maxwell tessellation mode</param> 167 /// <returns>Shader translator topology</returns> 168 private static InputTopology ConvertToInputTopology(PrimitiveTopology topology, TessMode tessellationMode) 169 { 170 return topology switch 171 { 172 PrimitiveTopology.Points => InputTopology.Points, 173 PrimitiveTopology.Lines or 174 PrimitiveTopology.LineLoop or 175 PrimitiveTopology.LineStrip => InputTopology.Lines, 176 PrimitiveTopology.LinesAdjacency or 177 PrimitiveTopology.LineStripAdjacency => InputTopology.LinesAdjacency, 178 PrimitiveTopology.Triangles or 179 PrimitiveTopology.TriangleStrip or 180 PrimitiveTopology.TriangleFan => InputTopology.Triangles, 181 PrimitiveTopology.TrianglesAdjacency or 182 PrimitiveTopology.TriangleStripAdjacency => InputTopology.TrianglesAdjacency, 183 PrimitiveTopology.Patches => tessellationMode.UnpackPatchType() == TessPatchType.Isolines 184 ? InputTopology.Lines 185 : InputTopology.Triangles, 186 _ => InputTopology.Points, 187 }; 188 } 189 } 190 }