aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2022-12-29 12:09:34 -0300
committerGitHub <noreply@github.com>2022-12-29 16:09:34 +0100
commit9dfe81770a8337a7a469eb3bac0ae9599cc0f61c (patch)
treee0c470a0ae67984394037f72fb7e16250674ba7e /Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
parent52c115a1f8f98dcd0a1f9da3d176f4a100f825b4 (diff)
Use vector outputs for texture operations (#3939)1.1.499
* 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>
Diffstat (limited to 'Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs')
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs84
1 files changed, 71 insertions, 13 deletions
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
index 7678a4bf..ec989cca 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgram.cs
@@ -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