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>
This commit is contained in:
Nicholas Rodine 2022-08-17 18:49:43 -05:00 committed by GitHub
parent 2197f41506
commit 80a879cb44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 1 deletions

View file

@ -234,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IrOperandType.Constant => GetConstant(type, operand), IrOperandType.Constant => GetConstant(type, operand),
IrOperandType.ConstantBuffer => GetConstantBuffer(type, operand), IrOperandType.ConstantBuffer => GetConstantBuffer(type, operand),
IrOperandType.LocalVariable => GetLocal(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}\".") _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
}; };
} }
@ -242,6 +242,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
throw new NotImplementedException(node.GetType().Name); 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) public Instruction GetAttributeElemPointer(int attr, bool isOutAttr, Instruction index, out AggregateType elemType)
{ {
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input; var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;

View file

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

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -228,5 +229,19 @@ namespace Spv.Generator
{ {
return obj is Instruction instruction && Equals(instruction); 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)}";
}
} }
} }

View file

@ -1,4 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Spv.Generator namespace Spv.Generator
@ -49,5 +51,22 @@ namespace Spv.Generator
Overflow[Count++] = operand; 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)})";
}
} }
} }

View file

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

View file

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