aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/StructuredIr
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Shader/StructuredIr')
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstOperation.cs10
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstTextureOperation.cs2
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs6
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/IoDefinition.cs44
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/OperandInfo.cs2
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs77
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs67
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs49
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