aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/Optimizations
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/Optimizations')
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs32
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs19
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs22
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs8
4 files changed, 60 insertions, 21 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs
index ca46a1f5..9a3ae1b8 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs
@@ -32,25 +32,49 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
continue;
}
- if (handleAsgOp.Inst != Instruction.LoadConstant)
+ if (handleAsgOp.Inst != Instruction.Load ||
+ handleAsgOp.StorageKind != StorageKind.ConstantBuffer ||
+ handleAsgOp.SourcesCount != 4)
{
continue;
}
Operand ldcSrc0 = handleAsgOp.GetSource(0);
+
+ if (ldcSrc0.Type != OperandType.Constant ||
+ !config.ResourceManager.TryGetConstantBufferSlot(ldcSrc0.Value, out int src0CbufSlot) ||
+ src0CbufSlot != 2)
+ {
+ continue;
+ }
+
Operand ldcSrc1 = handleAsgOp.GetSource(1);
- if (ldcSrc0.Type != OperandType.Constant || ldcSrc0.Value != 2)
+ // We expect field index 0 to be accessed.
+ if (ldcSrc1.Type != OperandType.Constant || ldcSrc1.Value != 0)
+ {
+ continue;
+ }
+
+ Operand ldcSrc2 = handleAsgOp.GetSource(2);
+
+ // FIXME: This is missing some checks, for example, a check to ensure that the shift value is 2.
+ // Might be not worth fixing since if that doesn't kick in, the result will be no texture
+ // to access anyway which is also wrong.
+ // Plus this whole transform is fundamentally flawed as-is since we have no way to know the array size.
+ // Eventually, this should be entirely removed in favor of a implementation that supports true bindless
+ // texture access.
+ if (!(ldcSrc2.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32)
{
continue;
}
- if (!(ldcSrc1.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32)
+ if (!(shrOp.GetSource(0).AsgOp is Operation shrOp2) || shrOp2.Inst != Instruction.ShiftRightU32)
{
continue;
}
- if (!(shrOp.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add)
+ if (!(shrOp2.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add)
{
continue;
}
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs
index 6729f077..4caadb73 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{
static class ConstantFolding
{
- public static void RunPass(Operation operation)
+ public static void RunPass(ShaderConfig config, Operation operation)
{
if (!AreAllSourcesConstant(operation))
{
@@ -153,8 +153,21 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
EvaluateFPUnary(operation, (x) => float.IsNaN(x));
break;
- case Instruction.LoadConstant:
- operation.TurnIntoCopy(Cbuf(operation.GetSource(0).Value, operation.GetSource(1).Value));
+ case Instruction.Load:
+ if (operation.StorageKind == StorageKind.ConstantBuffer && operation.SourcesCount == 4)
+ {
+ int binding = operation.GetSource(0).Value;
+ int fieldIndex = operation.GetSource(1).Value;
+
+ if (config.ResourceManager.TryGetConstantBufferSlot(binding, out int cbufSlot) && fieldIndex == 0)
+ {
+ int vecIndex = operation.GetSource(2).Value;
+ int elemIndex = operation.GetSource(3).Value;
+ int cbufOffset = vecIndex * 4 + elemIndex;
+
+ operation.TurnIntoCopy(Cbuf(cbufSlot, cbufOffset));
+ }
+ }
break;
case Instruction.Maximum:
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs
index 774d3e36..7758b4c6 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs
@@ -347,21 +347,23 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
return wordOffset;
}
- Operand[] sources = new Operand[operation.SourcesCount];
+ Operand cbufOffset = GetCbufOffset();
+ Operand vecIndex = Local();
+ Operand elemIndex = Local();
- int cbSlot = UbeFirstCbuf + storageIndex;
+ node.List.AddBefore(node, new Operation(Instruction.ShiftRightU32, 0, vecIndex, cbufOffset, Const(2)));
+ node.List.AddBefore(node, new Operation(Instruction.BitwiseAnd, 0, elemIndex, cbufOffset, Const(3)));
- sources[0] = Const(cbSlot);
- sources[1] = GetCbufOffset();
+ Operand[] sources = new Operand[4];
- config.SetUsedConstantBuffer(cbSlot);
+ int cbSlot = UbeFirstCbuf + storageIndex;
- for (int index = 2; index < operation.SourcesCount; index++)
- {
- sources[index] = operation.GetSource(index);
- }
+ sources[0] = Const(config.ResourceManager.GetConstantBufferBinding(cbSlot));
+ sources[1] = Const(0);
+ sources[2] = vecIndex;
+ sources[3] = elemIndex;
- Operation ldcOp = new Operation(Instruction.LoadConstant, operation.Dest, sources);
+ Operation ldcOp = new Operation(Instruction.Load, StorageKind.ConstantBuffer, operation.Dest, sources);
for (int index = 0; index < operation.SourcesCount; index++)
{
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs
index b41e47e4..b126e2c4 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs
@@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
{
public static void RunPass(BasicBlock[] blocks, ShaderConfig config)
{
- RunOptimizationPasses(blocks);
+ RunOptimizationPasses(blocks, config);
int sbUseMask = 0;
int ubeUseMask = 0;
@@ -31,10 +31,10 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask);
// Run optimizations one last time to remove any code that is now optimizable after above passes.
- RunOptimizationPasses(blocks);
+ RunOptimizationPasses(blocks, config);
}
- private static void RunOptimizationPasses(BasicBlock[] blocks)
+ private static void RunOptimizationPasses(BasicBlock[] blocks, ShaderConfig config)
{
bool modified;
@@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
continue;
}
- ConstantFolding.RunPass(operation);
+ ConstantFolding.RunPass(config, operation);
Simplification.RunPass(operation);
if (DestIsLocalVar(operation))