diff options
Diffstat (limited to 'Ryujinx.Graphics.Shader/StructuredIr')
8 files changed, 97 insertions, 160 deletions
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs b/Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs index 19397256..2393fd8d 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr class AstOperation : AstNode { public Instruction Inst { get; } + public StorageKind StorageKind { get; } public int Index { get; } @@ -16,9 +17,10 @@ namespace Ryujinx.Graphics.Shader.StructuredIr public int SourcesCount => _sources.Length; - public AstOperation(Instruction inst, IAstNode[] sources, int sourcesCount) + public AstOperation(Instruction inst, StorageKind storageKind, IAstNode[] sources, int sourcesCount) { - Inst = inst; + Inst = inst; + StorageKind = storageKind; _sources = sources; for (int index = 0; index < sources.Length; index++) @@ -36,12 +38,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Index = 0; } - public AstOperation(Instruction inst, int index, IAstNode[] sources, int sourcesCount) : this(inst, sources, sourcesCount) + public AstOperation(Instruction inst, StorageKind storageKind, int index, IAstNode[] sources, int sourcesCount) : this(inst, storageKind, sources, sourcesCount) { Index = index; } - public AstOperation(Instruction inst, params IAstNode[] sources) : this(inst, sources, sources.Length) + public AstOperation(Instruction inst, params IAstNode[] sources) : this(inst, StorageKind.None, sources, sources.Length) { } diff --git a/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs b/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs index 957a956f..a44f13cc 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr int cbufSlot, int handle, int index, - params IAstNode[] sources) : base(inst, index, sources, sources.Length) + params IAstNode[] sources) : base(inst, StorageKind.None, index, sources, sources.Length) { Type = type; Format = format; diff --git a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs index 0a9a9e51..8eccef23 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs @@ -89,7 +89,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr 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.Load, AggregateType.FP32); 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); @@ -122,7 +122,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr 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.Store, AggregateType.Void); 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); @@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { return AggregateType.FP32; } - else if (inst == Instruction.Call) + else if (inst == Instruction.Call || inst == Instruction.Load || inst == Instruction.Store) { return AggregateType.S32; } diff --git a/Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs b/Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs new file mode 100644 index 00000000..21a1b3f0 --- /dev/null +++ b/Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs @@ -0,0 +1,44 @@ +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using System; + +namespace Ryujinx.Graphics.Shader.StructuredIr +{ + readonly struct IoDefinition : IEquatable<IoDefinition> + { + public StorageKind StorageKind { get; } + public IoVariable IoVariable { get; } + public int Location { get; } + public int Component { get; } + + public IoDefinition(StorageKind storageKind, IoVariable ioVariable, int location = 0, int component = 0) + { + StorageKind = storageKind; + IoVariable = ioVariable; + Location = location; + Component = component; + } + + public override bool Equals(object other) + { + return other is IoDefinition ioDefinition && Equals(ioDefinition); + } + + public bool Equals(IoDefinition other) + { + return StorageKind == other.StorageKind && + IoVariable == other.IoVariable && + Location == other.Location && + Component == other.Component; + } + + public override int GetHashCode() + { + return (int)StorageKind | ((int)IoVariable << 8) | (Location << 16) | (Component << 24); + } + + public override string ToString() + { + return $"{StorageKind}.{IoVariable}.{Location}.{Component}"; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs index 730468a4..38ed1584 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs @@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr return type switch { OperandType.Argument => AggregateType.S32, - OperandType.Attribute => AggregateType.FP32, - OperandType.AttributePerPatch => AggregateType.FP32, OperandType.Constant => AggregateType.S32, OperandType.ConstantBuffer => AggregateType.FP32, OperandType.Undefined => AggregateType.S32, diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs index b8d38fa6..b4ca8ee5 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs @@ -65,49 +65,35 @@ namespace Ryujinx.Graphics.Shader.StructuredIr context.LeaveFunction(); } - if (config.TransformFeedbackEnabled && (config.LastInVertexPipeline || config.Stage == ShaderStage.Fragment)) - { - for (int tfbIndex = 0; tfbIndex < 4; tfbIndex++) - { - var locations = config.GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex); - var stride = config.GpuAccessor.QueryTransformFeedbackStride(tfbIndex); - - for (int i = 0; i < locations.Length; i++) - { - byte location = locations[i]; - if (location < 0xc0) - { - context.Info.TransformFeedbackOutputs[location] = new TransformFeedbackOutput(tfbIndex, i * 4, stride); - } - } - } - } - return context.Info; } private static void AddOperation(StructuredProgramContext context, Operation operation) { Instruction inst = operation.Inst; + StorageKind storageKind = operation.StorageKind; - if (inst == Instruction.LoadAttribute) + if ((inst == Instruction.Load || inst == Instruction.Store) && storageKind.IsInputOrOutput()) { - Operand src1 = operation.GetSource(0); - Operand src2 = operation.GetSource(1); + IoVariable ioVariable = (IoVariable)operation.GetSource(0).Value; + bool isOutput = storageKind.IsOutput(); + bool perPatch = storageKind.IsPerPatch(); + int location = 0; + int component = 0; - if (src1.Type == OperandType.Constant && src2.Type == OperandType.Constant) + if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) { - int attrOffset = (src1.Value & AttributeConsts.Mask) + (src2.Value << 2); + location = operation.GetSource(1).Value; - if ((src1.Value & AttributeConsts.LoadOutputMask) != 0) + if (operation.SourcesCount > 2 && + operation.GetSource(2).Type == OperandType.Constant && + context.Config.HasPerLocationInputOrOutputComponent(ioVariable, location, operation.GetSource(2).Value, isOutput)) { - context.Info.Outputs.Add(attrOffset); - } - else - { - context.Info.Inputs.Add(attrOffset); + component = operation.GetSource(2).Value; } } + + context.Info.IoDefinitions.Add(new IoDefinition(storageKind, ioVariable, location, component)); } bool vectorDest = IsVectorDestInst(inst); @@ -119,12 +105,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr for (int index = 0; index < operation.SourcesCount; index++) { - sources[index] = context.GetOperandUse(operation.GetSource(index)); + sources[index] = context.GetOperand(operation.GetSource(index)); } for (int index = 0; index < outDestsCount; index++) { - AstOperand oper = context.GetOperandDef(operation.GetDest(1 + index)); + AstOperand oper = context.GetOperand(operation.GetDest(1 + index)); oper.VarType = InstructionInfo.GetSrcVarType(inst, sourcesCount + index); @@ -163,7 +149,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr } else { - source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount); + source = new AstOperation(inst, operation.StorageKind, operation.Index, sources, operation.SourcesCount); } AggregateType destElemType = destType; @@ -181,17 +167,17 @@ namespace Ryujinx.Graphics.Shader.StructuredIr for (int i = 0; i < operation.DestsCount; i++) { - AstOperand dest = context.GetOperandDef(operation.GetDest(i)); + AstOperand dest = context.GetOperand(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))); + context.AddNode(new AstAssignment(dest, new AstOperation(Instruction.VectorExtract, StorageKind.None, new[] { destVec, index }, 2))); } } else if (operation.Dest != null) { - AstOperand dest = context.GetOperandDef(operation.Dest); + AstOperand dest = context.GetOperand(operation.Dest); // If all the sources are bool, it's better to use short-circuiting // logical operations, rather than forcing a cast to int and doing @@ -234,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr } else if (!isCopy) { - source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount); + source = new AstOperation(inst, operation.StorageKind, operation.Index, sources, operation.SourcesCount); } else { @@ -255,7 +241,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr } else { - context.AddNode(new AstOperation(inst, operation.Index, sources, operation.SourcesCount)); + context.AddNode(new AstOperation(inst, operation.StorageKind, operation.Index, sources, operation.SourcesCount)); } // Those instructions needs to be emulated by using helper functions, @@ -263,13 +249,16 @@ namespace Ryujinx.Graphics.Shader.StructuredIr // decide which helper functions are needed on the final generated code. switch (operation.Inst) { - case Instruction.AtomicMaxS32 | Instruction.MrShared: - case Instruction.AtomicMinS32 | Instruction.MrShared: - context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared; - break; - case Instruction.AtomicMaxS32 | Instruction.MrStorage: - case Instruction.AtomicMinS32 | Instruction.MrStorage: - context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage; + case Instruction.AtomicMaxS32: + case Instruction.AtomicMinS32: + if (operation.StorageKind == StorageKind.SharedMemory) + { + context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared; + } + else if (operation.StorageKind == StorageKind.StorageBuffer) + { + context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage; + } break; case Instruction.MultiplyHighS32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32; diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs index ce57a578..68bbdeb1 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs @@ -37,43 +37,26 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Config = config; - if (config.Stage == ShaderStage.TessellationControl) - { - // Required to index outputs. - Info.Inputs.Add(AttributeConsts.InvocationId); - } - else if (config.GpPassthrough) + if (config.GpPassthrough) { int passthroughAttributes = config.PassthroughAttributes; while (passthroughAttributes != 0) { int index = BitOperations.TrailingZeroCount(passthroughAttributes); - int attrBase = AttributeConsts.UserAttributeBase + index * 16; - Info.Inputs.Add(attrBase); - Info.Inputs.Add(attrBase + 4); - Info.Inputs.Add(attrBase + 8); - Info.Inputs.Add(attrBase + 12); + Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.UserDefined, index)); passthroughAttributes &= ~(1 << index); } - Info.Inputs.Add(AttributeConsts.PositionX); - Info.Inputs.Add(AttributeConsts.PositionY); - Info.Inputs.Add(AttributeConsts.PositionZ); - Info.Inputs.Add(AttributeConsts.PositionW); - Info.Inputs.Add(AttributeConsts.PointSize); - - for (int i = 0; i < 8; i++) - { - Info.Inputs.Add(AttributeConsts.ClipDistance0 + i * 4); - } + Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.Position)); + Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.PointSize)); + Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.ClipDistance)); } else if (config.Stage == ShaderStage.Fragment) { // Potentially used for texture coordinate scaling. - Info.Inputs.Add(AttributeConsts.PositionX); - Info.Inputs.Add(AttributeConsts.PositionY); + Info.IoDefinitions.Add(new IoDefinition(StorageKind.Input, IoVariable.FragmentCoord)); } } @@ -281,7 +264,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr } else { - cond = GetOperandUse(branchOp.GetSource(0)); + cond = GetOperand(branchOp.GetSource(0)); Instruction invInst = type == AstBlockType.If ? Instruction.BranchIfTrue @@ -315,41 +298,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr return newTemp; } - public AstOperand GetOperandDef(Operand operand) - { - if (operand.Type == OperandType.Attribute) - { - Info.Outputs.Add(operand.Value & AttributeConsts.Mask); - } - else if (operand.Type == OperandType.AttributePerPatch) - { - Info.OutputsPerPatch.Add(operand.Value & AttributeConsts.Mask); - } - - return GetOperand(operand); - } - - public AstOperand GetOperandUse(Operand operand) - { - // If this flag is set, we're reading from an output attribute instead. - if (operand.Type.IsAttribute() && (operand.Value & AttributeConsts.LoadOutputMask) != 0) - { - return GetOperandDef(operand); - } - - if (operand.Type == OperandType.Attribute) - { - Info.Inputs.Add(operand.Value); - } - else if (operand.Type == OperandType.AttributePerPatch) - { - Info.InputsPerPatch.Add(operand.Value); - } - - return GetOperand(operand); - } - - private AstOperand GetOperand(Operand operand) + public AstOperand GetOperand(Operand operand) { if (operand == null) { diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs index 489a5910..c5104146 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs @@ -22,60 +22,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr { public List<StructuredFunction> Functions { get; } - public HashSet<int> Inputs { get; } - public HashSet<int> Outputs { get; } - public HashSet<int> InputsPerPatch { get; } - public HashSet<int> OutputsPerPatch { get; } + public HashSet<IoDefinition> IoDefinitions { get; } public HelperFunctionsMask HelperFunctionsMask { get; set; } - public TransformFeedbackOutput[] TransformFeedbackOutputs { get; } - public StructuredProgramInfo() { Functions = new List<StructuredFunction>(); - Inputs = new HashSet<int>(); - Outputs = new HashSet<int>(); - InputsPerPatch = new HashSet<int>(); - OutputsPerPatch = new HashSet<int>(); - - TransformFeedbackOutputs = new TransformFeedbackOutput[0xc0]; - } - - public TransformFeedbackOutput GetTransformFeedbackOutput(int attr) - { - int index = attr / 4; - return TransformFeedbackOutputs[index]; - } - - public int GetTransformFeedbackOutputComponents(int attr) - { - int index = attr / 4; - int baseIndex = index & ~3; - - int count = 1; - - for (; count < 4; count++) - { - ref var prev = ref TransformFeedbackOutputs[baseIndex + count - 1]; - ref var curr = ref TransformFeedbackOutputs[baseIndex + count]; - - int prevOffset = prev.Offset; - int currOffset = curr.Offset; - - if (!prev.Valid || !curr.Valid || prevOffset + 4 != currOffset) - { - break; - } - } - - if (baseIndex + count <= index) - { - return 1; - } - - return count; + IoDefinitions = new HashSet<IoDefinition>(); } } }
\ No newline at end of file |