Эх сурвалжийг харах

Fix SpirV parse failure (#3597)

* Added .ToString overrides, to help diagnose and debug SpirV generated code.

* Added Spirv to team shared dictionary, so the word will not show up as a warning.

* Fixed bug where we were creating invalid constants (bool 0i and float 0i)

* Update Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Spv.Generator/Instruction.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Adjusted spacing to match style of the rest of the code.

* Added handler for FP64(double) as well, for undefined aggregate types.

* Made the operand labels a static dictionary, to avoid re-allocation on each call.
Replaced Contains/Get with a TryGetValue, to reduce the number of dictionary lookups.

* Added newline between AllOperands and ToString().

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
Nicholas Rodine 3 жил өмнө
parent
commit
80a879cb44

+ 12 - 1
Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs

@@ -234,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
                     IrOperandType.Constant => GetConstant(type, operand),
                     IrOperandType.ConstantBuffer => GetConstantBuffer(type, operand),
                     IrOperandType.LocalVariable => GetLocal(type, operand),
-                    IrOperandType.Undefined => Constant(GetType(type), 0),
+                    IrOperandType.Undefined => GetUndefined(type),
                     _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
                 };
             }
@@ -242,6 +242,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
             throw new NotImplementedException(node.GetType().Name);
         }
 
+        private Instruction GetUndefined(AggregateType type)
+        {
+            return type switch
+            {
+                AggregateType.Bool => ConstantFalse(TypeBool()),
+                AggregateType.FP32 => Constant(TypeFP32(), 0f),
+                AggregateType.FP64 => Constant(TypeFP64(), 0d),
+                _ => Constant(GetType(type), 0)
+            };
+        }
+
         public Instruction GetAttributeElemPointer(int attr, bool isOutAttr, Instruction index, out AggregateType elemType)
         {
             var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;

+ 1 - 0
Ryujinx.sln.DotSettings

@@ -15,6 +15,7 @@
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Ryujinx/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Sint/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Snorm/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/UserDictionary/Words/=Spirv/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Srgb/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/UserDictionary/Words/=Unorm/@EntryIndexedValue">True</s:Boolean>
 </wpf:ResourceDictionary>

+ 15 - 0
Spv.Generator/Instruction.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 
@@ -228,5 +229,19 @@ namespace Spv.Generator
         {
             return obj is Instruction instruction && Equals(instruction);
         }
+        
+        private static readonly Dictionary<Specification.Op, string[]> _operandLabels = new()
+        {
+            { Specification.Op.OpConstant, new [] { "Value" } },
+            { Specification.Op.OpTypeInt, new [] { "Width", "Signed" } },
+            { Specification.Op.OpTypeFloat, new [] { "Width" } }
+        };
+
+        public override string ToString()
+        {
+            var labels = _operandLabels.TryGetValue(Opcode, out var opLabels) ? opLabels : Array.Empty<string>();
+            var result = _resultType == null ? string.Empty : $"{_resultType} ";
+            return $"{result}{Opcode}{_operands.ToString(labels)}";
+        }
     }
 }

+ 19 - 0
Spv.Generator/InstructionOperands.cs

@@ -1,4 +1,6 @@
 using System;
+using System.Collections.Generic;
+using System.Linq;
 using System.Runtime.InteropServices;
 
 namespace Spv.Generator
@@ -49,5 +51,22 @@ namespace Spv.Generator
                 Overflow[Count++] = operand;
             }
         }
+
+        private IEnumerable<Operand> AllOperands => new[] { Operand1, Operand2, Operand3, Operand4, Operand5 }
+            .Concat(Overflow ?? Array.Empty<Operand>())
+            .Take(Count);
+
+        public override string ToString()
+        {
+            return $"({string.Join(", ", AllOperands)})";
+        }
+
+        public string ToString(string[] labels)
+        {
+            var labeledParams = AllOperands.Zip(labels, (op, label) => $"{label}: {op}");
+            var unlabeledParams = AllOperands.Skip(labels.Length).Select(op => op.ToString());
+            var paramsToPrint = labeledParams.Concat(unlabeledParams);
+            return $"({string.Join(", ", paramsToPrint)})";
+        }
     }
 }

+ 2 - 0
Spv.Generator/LiteralInteger.cs

@@ -99,5 +99,7 @@ namespace Spv.Generator
         {
             return obj is LiteralInteger literalInteger && Equals(literalInteger);
         }
+
+        public override string ToString() => $"{_integerType} {_data}";
     }
 }

+ 2 - 0
Spv.Generator/LiteralString.cs

@@ -48,5 +48,7 @@ namespace Spv.Generator
         {
             return obj is LiteralString literalString && Equals(literalString);
         }
+
+        public override string ToString() => _value;
     }
 }