Use vector outputs for texture operations (#3939)
* Change AggregateType to include vector type counts * Replace VariableType uses with AggregateType and delete VariableType * Support new local vector types on SPIR-V and GLSL * Start using vector outputs for texture operations * Use vectors on more texture operations * Use vector output for ImageLoad operations * Replace all uses of single destination texture constructors with multi destination ones * Update textureGatherOffsets replacement to split vector operations * Shader cache version bump Co-authored-by: Ac_K <Acoustik666@gmail.com>
This commit is contained in:
parent
52c115a1f8
commit
9dfe81770a
37 changed files with 1100 additions and 747 deletions
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
{
|
||||
|
@ -46,7 +47,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
return new AstOperand(OperandType.Constant, value);
|
||||
}
|
||||
|
||||
public static AstOperand Local(VariableType type)
|
||||
public static AstOperand Local(AggregateType type)
|
||||
{
|
||||
AstOperand local = new AstOperand(OperandType.LocalVariable);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
|
@ -10,7 +11,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
|
||||
public OperandType Type { get; }
|
||||
|
||||
public VariableType VarType { get; set; }
|
||||
public AggregateType VarType { get; set; }
|
||||
|
||||
public int Value { get; }
|
||||
|
||||
|
@ -22,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
Defs = new HashSet<IAstNode>();
|
||||
Uses = new HashSet<IAstNode>();
|
||||
|
||||
VarType = VariableType.S32;
|
||||
VarType = AggregateType.S32;
|
||||
}
|
||||
|
||||
public AstOperand(Operand operand) : this()
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System.Numerics;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.StructuredIr.AstHelper;
|
||||
|
||||
|
@ -56,5 +58,21 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
|
||||
_sources[index] = source;
|
||||
}
|
||||
|
||||
public AggregateType GetVectorType(AggregateType scalarType)
|
||||
{
|
||||
int componentsCount = BitOperations.PopCount((uint)Index);
|
||||
|
||||
AggregateType type = scalarType;
|
||||
|
||||
switch (componentsCount)
|
||||
{
|
||||
case 2: type |= AggregateType.Vector2; break;
|
||||
case 3: type |= AggregateType.Vector3; break;
|
||||
case 4: type |= AggregateType.Vector4; break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
|
@ -7,11 +8,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
{
|
||||
private readonly struct InstInfo
|
||||
{
|
||||
public VariableType DestType { get; }
|
||||
public AggregateType DestType { get; }
|
||||
|
||||
public VariableType[] SrcTypes { get; }
|
||||
public AggregateType[] SrcTypes { get; }
|
||||
|
||||
public InstInfo(VariableType destType, params VariableType[] srcTypes)
|
||||
public InstInfo(AggregateType destType, params AggregateType[] srcTypes)
|
||||
{
|
||||
DestType = destType;
|
||||
SrcTypes = srcTypes;
|
||||
|
@ -24,176 +25,173 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
{
|
||||
_infoTbl = new InstInfo[(int)Instruction.Count];
|
||||
|
||||
// Inst Destination type Source 1 type Source 2 type Source 3 type Source 4 type
|
||||
Add(Instruction.AtomicAdd, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.AtomicAnd, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.AtomicCompareAndSwap, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.AtomicMaxS32, VariableType.S32, VariableType.S32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.AtomicMaxU32, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.AtomicMinS32, VariableType.S32, VariableType.S32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.AtomicMinU32, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.AtomicOr, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.AtomicSwap, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.AtomicXor, VariableType.U32, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.Absolute, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.Add, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.Ballot, VariableType.U32, VariableType.Bool);
|
||||
Add(Instruction.BitCount, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.BitfieldExtractS32, VariableType.S32, VariableType.S32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.BitfieldExtractU32, VariableType.U32, VariableType.U32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.BitfieldInsert, VariableType.Int, VariableType.Int, VariableType.Int, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.BitfieldReverse, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.BitwiseAnd, VariableType.Int, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.BitwiseExclusiveOr, VariableType.Int, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.BitwiseNot, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.BitwiseOr, VariableType.Int, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.BranchIfTrue, VariableType.None, VariableType.Bool);
|
||||
Add(Instruction.BranchIfFalse, VariableType.None, VariableType.Bool);
|
||||
Add(Instruction.Call, VariableType.Scalar);
|
||||
Add(Instruction.Ceiling, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.Clamp, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.ClampU32, VariableType.U32, VariableType.U32, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.CompareEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.CompareGreater, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.CompareGreaterOrEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.CompareGreaterOrEqualU32, VariableType.Bool, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.CompareGreaterU32, VariableType.Bool, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.CompareLess, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.CompareLessOrEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.CompareLessOrEqualU32, VariableType.Bool, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.CompareLessU32, VariableType.Bool, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.CompareNotEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.ConditionalSelect, VariableType.Scalar, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.ConvertFP32ToFP64, VariableType.F64, VariableType.F32);
|
||||
Add(Instruction.ConvertFP64ToFP32, VariableType.F32, VariableType.F64);
|
||||
Add(Instruction.ConvertFP32ToS32, VariableType.S32, VariableType.F32);
|
||||
Add(Instruction.ConvertFP32ToU32, VariableType.U32, VariableType.F32);
|
||||
Add(Instruction.ConvertFP64ToS32, VariableType.S32, VariableType.F64);
|
||||
Add(Instruction.ConvertFP64ToU32, VariableType.U32, VariableType.F64);
|
||||
Add(Instruction.ConvertS32ToFP32, VariableType.F32, VariableType.S32);
|
||||
Add(Instruction.ConvertS32ToFP64, VariableType.F64, VariableType.S32);
|
||||
Add(Instruction.ConvertU32ToFP32, VariableType.F32, VariableType.U32);
|
||||
Add(Instruction.ConvertU32ToFP64, VariableType.F64, VariableType.U32);
|
||||
Add(Instruction.Cosine, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.Ddx, VariableType.F32, VariableType.F32);
|
||||
Add(Instruction.Ddy, VariableType.F32, VariableType.F32);
|
||||
Add(Instruction.Divide, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.ExponentB2, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.FindLSB, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.FindMSBS32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.FindMSBU32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.Floor, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.FusedMultiplyAdd, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.ImageLoad, VariableType.F32);
|
||||
Add(Instruction.ImageStore, VariableType.None);
|
||||
Add(Instruction.ImageAtomic, VariableType.S32);
|
||||
Add(Instruction.IsNan, VariableType.Bool, VariableType.Scalar);
|
||||
Add(Instruction.LoadAttribute, VariableType.F32, VariableType.S32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.LoadConstant, VariableType.F32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.LoadGlobal, VariableType.U32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.LoadLocal, VariableType.U32, VariableType.S32);
|
||||
Add(Instruction.LoadShared, VariableType.U32, VariableType.S32);
|
||||
Add(Instruction.LoadStorage, VariableType.U32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.Lod, VariableType.F32);
|
||||
Add(Instruction.LogarithmB2, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.LogicalAnd, VariableType.Bool, VariableType.Bool, VariableType.Bool);
|
||||
Add(Instruction.LogicalExclusiveOr, VariableType.Bool, VariableType.Bool, VariableType.Bool);
|
||||
Add(Instruction.LogicalNot, VariableType.Bool, VariableType.Bool);
|
||||
Add(Instruction.LogicalOr, VariableType.Bool, VariableType.Bool, VariableType.Bool);
|
||||
Add(Instruction.Maximum, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.MaximumU32, VariableType.U32, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.Minimum, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.MinimumU32, VariableType.U32, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.Multiply, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.MultiplyHighS32, VariableType.S32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.MultiplyHighU32, VariableType.U32, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.Negate, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.PackDouble2x32, VariableType.F64, VariableType.U32, VariableType.U32);
|
||||
Add(Instruction.PackHalf2x16, VariableType.U32, VariableType.F32, VariableType.F32);
|
||||
Add(Instruction.ReciprocalSquareRoot, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.Round, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.ShiftLeft, VariableType.Int, VariableType.Int, VariableType.Int);
|
||||
Add(Instruction.ShiftRightS32, VariableType.S32, VariableType.S32, VariableType.Int);
|
||||
Add(Instruction.ShiftRightU32, VariableType.U32, VariableType.U32, VariableType.Int);
|
||||
Add(Instruction.Shuffle, VariableType.F32, VariableType.F32, VariableType.U32, VariableType.U32, VariableType.Bool);
|
||||
Add(Instruction.ShuffleDown, VariableType.F32, VariableType.F32, VariableType.U32, VariableType.U32, VariableType.Bool);
|
||||
Add(Instruction.ShuffleUp, VariableType.F32, VariableType.F32, VariableType.U32, VariableType.U32, VariableType.Bool);
|
||||
Add(Instruction.ShuffleXor, VariableType.F32, VariableType.F32, VariableType.U32, VariableType.U32, VariableType.Bool);
|
||||
Add(Instruction.Sine, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.SquareRoot, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.StoreAttribute, VariableType.None, VariableType.S32, VariableType.S32, VariableType.F32);
|
||||
Add(Instruction.StoreGlobal, VariableType.None, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreLocal, VariableType.None, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreShared, VariableType.None, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreShared16, VariableType.None, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreShared8, VariableType.None, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreStorage, VariableType.None, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreStorage16, VariableType.None, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.StoreStorage8, VariableType.None, VariableType.S32, VariableType.S32, VariableType.U32);
|
||||
Add(Instruction.Subtract, VariableType.Scalar, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.SwizzleAdd, VariableType.F32, VariableType.F32, VariableType.F32, VariableType.S32);
|
||||
Add(Instruction.TextureSample, VariableType.F32);
|
||||
Add(Instruction.TextureSize, VariableType.S32, VariableType.S32, VariableType.S32);
|
||||
Add(Instruction.Truncate, VariableType.Scalar, VariableType.Scalar);
|
||||
Add(Instruction.UnpackDouble2x32, VariableType.U32, VariableType.F64);
|
||||
Add(Instruction.UnpackHalf2x16, VariableType.F32, VariableType.U32);
|
||||
Add(Instruction.VoteAll, VariableType.Bool, VariableType.Bool);
|
||||
Add(Instruction.VoteAllEqual, VariableType.Bool, VariableType.Bool);
|
||||
Add(Instruction.VoteAny, VariableType.Bool, VariableType.Bool);
|
||||
// Inst Destination type Source 1 type Source 2 type Source 3 type Source 4 type
|
||||
Add(Instruction.AtomicAdd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.AtomicAnd, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.AtomicCompareAndSwap, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.AtomicMaxS32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.AtomicMaxU32, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.AtomicMinS32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.AtomicMinU32, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.AtomicOr, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.AtomicSwap, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.AtomicXor, AggregateType.U32, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.Absolute, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.Add, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.Ballot, AggregateType.U32, AggregateType.Bool);
|
||||
Add(Instruction.BitCount, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitfieldExtractS32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitfieldExtractU32, AggregateType.U32, AggregateType.U32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitfieldInsert, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitfieldReverse, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitwiseAnd, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitwiseExclusiveOr, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitwiseNot, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BitwiseOr, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.BranchIfTrue, AggregateType.Void, AggregateType.Bool);
|
||||
Add(Instruction.BranchIfFalse, AggregateType.Void, AggregateType.Bool);
|
||||
Add(Instruction.Call, AggregateType.Scalar);
|
||||
Add(Instruction.Ceiling, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.Clamp, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.ClampU32, AggregateType.U32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.CompareEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.CompareGreater, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.CompareGreaterOrEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.CompareGreaterOrEqualU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.CompareGreaterU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.CompareLess, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.CompareLessOrEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.CompareLessOrEqualU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.CompareLessU32, AggregateType.Bool, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.CompareNotEqual, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.ConditionalSelect, AggregateType.Scalar, AggregateType.Bool, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.ConvertFP32ToFP64, AggregateType.FP64, AggregateType.FP32);
|
||||
Add(Instruction.ConvertFP64ToFP32, AggregateType.FP32, AggregateType.FP64);
|
||||
Add(Instruction.ConvertFP32ToS32, AggregateType.S32, AggregateType.FP32);
|
||||
Add(Instruction.ConvertFP32ToU32, AggregateType.U32, AggregateType.FP32);
|
||||
Add(Instruction.ConvertFP64ToS32, AggregateType.S32, AggregateType.FP64);
|
||||
Add(Instruction.ConvertFP64ToU32, AggregateType.U32, AggregateType.FP64);
|
||||
Add(Instruction.ConvertS32ToFP32, AggregateType.FP32, AggregateType.S32);
|
||||
Add(Instruction.ConvertS32ToFP64, AggregateType.FP64, AggregateType.S32);
|
||||
Add(Instruction.ConvertU32ToFP32, AggregateType.FP32, AggregateType.U32);
|
||||
Add(Instruction.ConvertU32ToFP64, AggregateType.FP64, AggregateType.U32);
|
||||
Add(Instruction.Cosine, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.Ddx, AggregateType.FP32, AggregateType.FP32);
|
||||
Add(Instruction.Ddy, AggregateType.FP32, AggregateType.FP32);
|
||||
Add(Instruction.Divide, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.ExponentB2, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.FindLSB, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.FindMSBS32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.FindMSBU32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.Floor, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.FusedMultiplyAdd, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.ImageLoad, AggregateType.FP32);
|
||||
Add(Instruction.ImageStore, AggregateType.Void);
|
||||
Add(Instruction.ImageAtomic, AggregateType.S32);
|
||||
Add(Instruction.IsNan, AggregateType.Bool, AggregateType.Scalar);
|
||||
Add(Instruction.LoadAttribute, AggregateType.FP32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.LoadConstant, AggregateType.FP32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.LoadGlobal, AggregateType.U32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.LoadLocal, AggregateType.U32, AggregateType.S32);
|
||||
Add(Instruction.LoadShared, AggregateType.U32, AggregateType.S32);
|
||||
Add(Instruction.LoadStorage, AggregateType.U32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.Lod, AggregateType.FP32);
|
||||
Add(Instruction.LogarithmB2, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.LogicalAnd, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
|
||||
Add(Instruction.LogicalExclusiveOr, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
|
||||
Add(Instruction.LogicalNot, AggregateType.Bool, AggregateType.Bool);
|
||||
Add(Instruction.LogicalOr, AggregateType.Bool, AggregateType.Bool, AggregateType.Bool);
|
||||
Add(Instruction.Maximum, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.MaximumU32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.Minimum, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.MinimumU32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.Multiply, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.MultiplyHighS32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.MultiplyHighU32, AggregateType.U32, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.Negate, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.PackDouble2x32, AggregateType.FP64, AggregateType.U32, AggregateType.U32);
|
||||
Add(Instruction.PackHalf2x16, AggregateType.U32, AggregateType.FP32, AggregateType.FP32);
|
||||
Add(Instruction.ReciprocalSquareRoot, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.Round, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.ShiftLeft, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.ShiftRightS32, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.ShiftRightU32, AggregateType.U32, AggregateType.U32, AggregateType.S32);
|
||||
Add(Instruction.Shuffle, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
|
||||
Add(Instruction.ShuffleDown, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
|
||||
Add(Instruction.ShuffleUp, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
|
||||
Add(Instruction.ShuffleXor, AggregateType.FP32, AggregateType.FP32, AggregateType.U32, AggregateType.U32, AggregateType.Bool);
|
||||
Add(Instruction.Sine, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.SquareRoot, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.StoreAttribute, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.FP32);
|
||||
Add(Instruction.StoreGlobal, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreLocal, AggregateType.Void, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreShared, AggregateType.Void, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreShared16, AggregateType.Void, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreShared8, AggregateType.Void, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreStorage, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreStorage16, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.StoreStorage8, AggregateType.Void, AggregateType.S32, AggregateType.S32, AggregateType.U32);
|
||||
Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
|
||||
Add(Instruction.TextureSample, AggregateType.FP32);
|
||||
Add(Instruction.TextureSize, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||
Add(Instruction.Truncate, AggregateType.Scalar, AggregateType.Scalar);
|
||||
Add(Instruction.UnpackDouble2x32, AggregateType.U32, AggregateType.FP64);
|
||||
Add(Instruction.UnpackHalf2x16, AggregateType.FP32, AggregateType.U32);
|
||||
Add(Instruction.VectorExtract, AggregateType.Scalar, AggregateType.Vector4, AggregateType.S32);
|
||||
Add(Instruction.VoteAll, AggregateType.Bool, AggregateType.Bool);
|
||||
Add(Instruction.VoteAllEqual, AggregateType.Bool, AggregateType.Bool);
|
||||
Add(Instruction.VoteAny, AggregateType.Bool, AggregateType.Bool);
|
||||
}
|
||||
|
||||
private static void Add(Instruction inst, VariableType destType, params VariableType[] srcTypes)
|
||||
private static void Add(Instruction inst, AggregateType destType, params AggregateType[] srcTypes)
|
||||
{
|
||||
_infoTbl[(int)inst] = new InstInfo(destType, srcTypes);
|
||||
}
|
||||
|
||||
public static VariableType GetDestVarType(Instruction inst)
|
||||
public static AggregateType GetDestVarType(Instruction inst)
|
||||
{
|
||||
return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].DestType, inst);
|
||||
}
|
||||
|
||||
public static VariableType GetSrcVarType(Instruction inst, int index)
|
||||
public static AggregateType GetSrcVarType(Instruction inst, int index)
|
||||
{
|
||||
// TODO: Return correct type depending on source index,
|
||||
// that can improve the decompiler output.
|
||||
if (inst == Instruction.ImageLoad ||
|
||||
inst == Instruction.ImageStore ||
|
||||
if (inst == Instruction.ImageLoad ||
|
||||
inst == Instruction.ImageStore ||
|
||||
inst == Instruction.ImageAtomic ||
|
||||
inst == Instruction.Lod ||
|
||||
inst == Instruction.Lod ||
|
||||
inst == Instruction.TextureSample)
|
||||
{
|
||||
return VariableType.F32;
|
||||
return AggregateType.FP32;
|
||||
}
|
||||
else if (inst == Instruction.Call)
|
||||
{
|
||||
return VariableType.S32;
|
||||
return AggregateType.S32;
|
||||
}
|
||||
|
||||
return GetFinalVarType(_infoTbl[(int)(inst & Instruction.Mask)].SrcTypes[index], inst);
|
||||
}
|
||||
|
||||
private static VariableType GetFinalVarType(VariableType type, Instruction inst)
|
||||
private static AggregateType GetFinalVarType(AggregateType type, Instruction inst)
|
||||
{
|
||||
if (type == VariableType.Scalar)
|
||||
if (type == AggregateType.Scalar)
|
||||
{
|
||||
if ((inst & Instruction.FP32) != 0)
|
||||
{
|
||||
return VariableType.F32;
|
||||
return AggregateType.FP32;
|
||||
}
|
||||
else if ((inst & Instruction.FP64) != 0)
|
||||
{
|
||||
return VariableType.F64;
|
||||
return AggregateType.FP64;
|
||||
}
|
||||
else
|
||||
{
|
||||
return VariableType.S32;
|
||||
return AggregateType.S32;
|
||||
}
|
||||
}
|
||||
else if (type == VariableType.Int)
|
||||
{
|
||||
return VariableType.S32;
|
||||
}
|
||||
else if (type == VariableType.None)
|
||||
else if (type == AggregateType.Void)
|
||||
{
|
||||
throw new ArgumentException($"Invalid operand for instruction \"{inst}\".");
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
{
|
||||
static class OperandInfo
|
||||
{
|
||||
public static VariableType GetVarType(AstOperand operand)
|
||||
public static AggregateType GetVarType(AstOperand operand)
|
||||
{
|
||||
if (operand.Type == OperandType.LocalVariable)
|
||||
{
|
||||
|
@ -17,16 +18,16 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
}
|
||||
}
|
||||
|
||||
public static VariableType GetVarType(OperandType type)
|
||||
public static AggregateType GetVarType(OperandType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
OperandType.Argument => VariableType.S32,
|
||||
OperandType.Attribute => VariableType.F32,
|
||||
OperandType.AttributePerPatch => VariableType.F32,
|
||||
OperandType.Constant => VariableType.S32,
|
||||
OperandType.ConstantBuffer => VariableType.F32,
|
||||
OperandType.Undefined => VariableType.S32,
|
||||
OperandType.Argument => AggregateType.S32,
|
||||
OperandType.Attribute => AggregateType.FP32,
|
||||
OperandType.AttributePerPatch => AggregateType.FP32,
|
||||
OperandType.Constant => AggregateType.S32,
|
||||
OperandType.ConstantBuffer => AggregateType.FP32,
|
||||
OperandType.Undefined => AggregateType.S32,
|
||||
_ => throw new ArgumentException($"Invalid operand type \"{type}\".")
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
|
@ -8,19 +9,19 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
|
||||
public string Name { get; }
|
||||
|
||||
public VariableType ReturnType { get; }
|
||||
public AggregateType ReturnType { get; }
|
||||
|
||||
public VariableType[] InArguments { get; }
|
||||
public VariableType[] OutArguments { get; }
|
||||
public AggregateType[] InArguments { get; }
|
||||
public AggregateType[] OutArguments { get; }
|
||||
|
||||
public HashSet<AstOperand> Locals { get; }
|
||||
|
||||
public StructuredFunction(
|
||||
AstBlock mainBlock,
|
||||
string name,
|
||||
VariableType returnType,
|
||||
VariableType[] inArguments,
|
||||
VariableType[] outArguments)
|
||||
AggregateType returnType,
|
||||
AggregateType[] inArguments,
|
||||
AggregateType[] outArguments)
|
||||
{
|
||||
MainBlock = mainBlock;
|
||||
Name = name;
|
||||
|
@ -31,7 +32,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
Locals = new HashSet<AstOperand>();
|
||||
}
|
||||
|
||||
public VariableType GetArgumentType(int index)
|
||||
public AggregateType GetArgumentType(int index)
|
||||
{
|
||||
return index >= InArguments.Length
|
||||
? OutArguments[index - InArguments.Length]
|
||||
|
|
|
@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
|||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
{
|
||||
|
@ -17,19 +18,19 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
|
||||
BasicBlock[] blocks = function.Blocks;
|
||||
|
||||
VariableType returnType = function.ReturnsValue ? VariableType.S32 : VariableType.None;
|
||||
AggregateType returnType = function.ReturnsValue ? AggregateType.S32 : AggregateType.Void;
|
||||
|
||||
VariableType[] inArguments = new VariableType[function.InArgumentsCount];
|
||||
VariableType[] outArguments = new VariableType[function.OutArgumentsCount];
|
||||
AggregateType[] inArguments = new AggregateType[function.InArgumentsCount];
|
||||
AggregateType[] outArguments = new AggregateType[function.OutArgumentsCount];
|
||||
|
||||
for (int i = 0; i < inArguments.Length; i++)
|
||||
{
|
||||
inArguments[i] = VariableType.S32;
|
||||
inArguments[i] = AggregateType.S32;
|
||||
}
|
||||
|
||||
for (int i = 0; i < outArguments.Length; i++)
|
||||
{
|
||||
outArguments[i] = VariableType.S32;
|
||||
outArguments[i] = AggregateType.S32;
|
||||
}
|
||||
|
||||
context.EnterFunction(blocks.Length, function.Name, returnType, inArguments, outArguments);
|
||||
|
@ -109,8 +110,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
}
|
||||
}
|
||||
|
||||
bool vectorDest = IsVectorDestInst(inst);
|
||||
|
||||
int sourcesCount = operation.SourcesCount;
|
||||
int outDestsCount = operation.DestsCount != 0 ? operation.DestsCount - 1 : 0;
|
||||
int outDestsCount = operation.DestsCount != 0 && !vectorDest ? operation.DestsCount - 1 : 0;
|
||||
|
||||
IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount];
|
||||
|
||||
|
@ -141,7 +144,52 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
sources);
|
||||
}
|
||||
|
||||
if (operation.Dest != null)
|
||||
int componentsCount = BitOperations.PopCount((uint)operation.Index);
|
||||
|
||||
if (vectorDest && componentsCount > 1)
|
||||
{
|
||||
AggregateType destType = InstructionInfo.GetDestVarType(inst);
|
||||
|
||||
IAstNode source;
|
||||
|
||||
if (operation is TextureOperation texOp)
|
||||
{
|
||||
if (texOp.Inst == Instruction.ImageLoad)
|
||||
{
|
||||
destType = texOp.Format.GetComponentType();
|
||||
}
|
||||
|
||||
source = GetAstTextureOperation(texOp);
|
||||
}
|
||||
else
|
||||
{
|
||||
source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount);
|
||||
}
|
||||
|
||||
AggregateType destElemType = destType;
|
||||
|
||||
switch (componentsCount)
|
||||
{
|
||||
case 2: destType |= AggregateType.Vector2; break;
|
||||
case 3: destType |= AggregateType.Vector3; break;
|
||||
case 4: destType |= AggregateType.Vector4; break;
|
||||
}
|
||||
|
||||
AstOperand destVec = context.NewTemp(destType);
|
||||
|
||||
context.AddNode(new AstAssignment(destVec, source));
|
||||
|
||||
for (int i = 0; i < operation.DestsCount; i++)
|
||||
{
|
||||
AstOperand dest = context.GetOperandDef(operation.GetDest(i));
|
||||
AstOperand index = new AstOperand(OperandType.Constant, i);
|
||||
|
||||
dest.VarType = destElemType;
|
||||
|
||||
context.AddNode(new AstAssignment(dest, new AstOperation(Instruction.VectorExtract, new[] { destVec, index }, 2)));
|
||||
}
|
||||
}
|
||||
else if (operation.Dest != null)
|
||||
{
|
||||
AstOperand dest = context.GetOperandDef(operation.Dest);
|
||||
|
||||
|
@ -149,7 +197,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
// logical operations, rather than forcing a cast to int and doing
|
||||
// a bitwise operation with the value, as it is likely to be used as
|
||||
// a bool in the end.
|
||||
if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool))
|
||||
if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, AggregateType.Bool))
|
||||
{
|
||||
inst = GetLogicalFromBitwiseInst(inst);
|
||||
}
|
||||
|
@ -159,9 +207,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
|
||||
if (isCondSel || isCopy)
|
||||
{
|
||||
VariableType type = GetVarTypeFromUses(operation.Dest);
|
||||
AggregateType type = GetVarTypeFromUses(operation.Dest);
|
||||
|
||||
if (isCondSel && type == VariableType.F32)
|
||||
if (isCondSel && type == AggregateType.FP32)
|
||||
{
|
||||
inst |= Instruction.FP32;
|
||||
}
|
||||
|
@ -259,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
}
|
||||
}
|
||||
|
||||
private static VariableType GetVarTypeFromUses(Operand dest)
|
||||
private static AggregateType GetVarTypeFromUses(Operand dest)
|
||||
{
|
||||
HashSet<Operand> visited = new HashSet<Operand>();
|
||||
|
||||
|
@ -315,10 +363,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
}
|
||||
}
|
||||
|
||||
return VariableType.S32;
|
||||
return AggregateType.S32;
|
||||
}
|
||||
|
||||
private static bool AreAllSourceTypesEqual(IAstNode[] sources, VariableType type)
|
||||
private static bool AreAllSourceTypesEqual(IAstNode[] sources, AggregateType type)
|
||||
{
|
||||
foreach (IAstNode node in sources)
|
||||
{
|
||||
|
@ -336,6 +384,16 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool IsVectorDestInst(Instruction inst)
|
||||
{
|
||||
return inst switch
|
||||
{
|
||||
Instruction.ImageLoad or
|
||||
Instruction.TextureSample => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
private static bool IsBranchInst(Instruction inst)
|
||||
{
|
||||
return inst switch
|
||||
|
|
|
@ -80,9 +80,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
public void EnterFunction(
|
||||
int blocksCount,
|
||||
string name,
|
||||
VariableType returnType,
|
||||
VariableType[] inArguments,
|
||||
VariableType[] outArguments)
|
||||
AggregateType returnType,
|
||||
AggregateType[] inArguments,
|
||||
AggregateType[] outArguments)
|
||||
{
|
||||
_loopTails = new HashSet<BasicBlock>();
|
||||
|
||||
|
@ -218,7 +218,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
return gotoTempAsg;
|
||||
}
|
||||
|
||||
AstOperand gotoTemp = NewTemp(VariableType.Bool);
|
||||
AstOperand gotoTemp = NewTemp(AggregateType.Bool);
|
||||
|
||||
gotoTempAsg = Assign(gotoTemp, Const(IrConsts.False));
|
||||
|
||||
|
@ -306,7 +306,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||
return _gotos.ToArray();
|
||||
}
|
||||
|
||||
private AstOperand NewTemp(VariableType type)
|
||||
public AstOperand NewTemp(AggregateType type)
|
||||
{
|
||||
AstOperand newTemp = Local(type);
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||
{
|
||||
enum VariableType
|
||||
{
|
||||
None,
|
||||
Bool,
|
||||
Scalar,
|
||||
Int,
|
||||
F32,
|
||||
F64,
|
||||
S32,
|
||||
U32
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue