aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/CodeGen
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/CodeGen
parent52c115a1f8f98dcd0a1f9da3d176f4a100f825b4 (diff)
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>
Diffstat (limited to 'Ryujinx.Graphics.Shader/CodeGen')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs38
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs8
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs11
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs3
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs14
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs126
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs32
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs18
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs141
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/TypeConversion.cs33
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs54
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs19
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Spirv/EnumConversion.cs17
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs147
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs8
15 files changed, 442 insertions, 227 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index c6e3b339..4da21cb7 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -350,19 +350,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
}
- public static string GetVarTypeName(VariableType type)
+ public static string GetVarTypeName(AggregateType type, bool precise = true)
{
- switch (type)
- {
- case VariableType.Bool: return "bool";
- case VariableType.F32: return "precise float";
- case VariableType.F64: return "double";
- case VariableType.None: return "void";
- case VariableType.S32: return "int";
- case VariableType.U32: return "uint";
- }
-
- throw new ArgumentException($"Invalid variable type \"{type}\".");
+ return type switch
+ {
+ AggregateType.Void => "void",
+ AggregateType.Bool => "bool",
+ AggregateType.FP32 => precise ? "precise float" : "float",
+ AggregateType.FP64 => "double",
+ AggregateType.S32 => "int",
+ AggregateType.U32 => "uint",
+ AggregateType.Vector2 | AggregateType.Bool => "bvec2",
+ AggregateType.Vector2 | AggregateType.FP32 => precise ? "precise vec2" : "vec2",
+ AggregateType.Vector2 | AggregateType.FP64 => "dvec2",
+ AggregateType.Vector2 | AggregateType.S32 => "ivec2",
+ AggregateType.Vector2 | AggregateType.U32 => "uvec2",
+ AggregateType.Vector3 | AggregateType.Bool => "bvec3",
+ AggregateType.Vector3 | AggregateType.FP32 => precise ? "precise vec3" : "vec3",
+ AggregateType.Vector3 | AggregateType.FP64 => "dvec3",
+ AggregateType.Vector3 | AggregateType.S32 => "ivec3",
+ AggregateType.Vector3 | AggregateType.U32 => "uvec3",
+ AggregateType.Vector4 | AggregateType.Bool => "bvec4",
+ AggregateType.Vector4 | AggregateType.FP32 => precise ? "precise vec4" : "vec4",
+ AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
+ AggregateType.Vector4 | AggregateType.S32 => "ivec4",
+ AggregateType.Vector4 | AggregateType.U32 => "uvec4",
+ _ => throw new ArgumentException($"Invalid variable type \"{type}\".")
+ };
}
private static void DeclareUniforms(CodeGenContext context, BufferDescriptor[] descriptors)
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
index e1b8eb6e..90826a15 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
@@ -126,8 +126,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
else if (node is AstAssignment assignment)
{
- VariableType srcType = OperandManager.GetNodeDestType(context, assignment.Source);
- VariableType dstType = OperandManager.GetNodeDestType(context, assignment.Destination, isAsgDest: true);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, assignment.Source);
+ AggregateType dstType = OperandManager.GetNodeDestType(context, assignment.Destination, isAsgDest: true);
string dest;
@@ -158,9 +158,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static string GetCondExpr(CodeGenContext context, IAstNode cond)
{
- VariableType srcType = OperandManager.GetNodeDestType(context, cond);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, cond);
- return ReinterpretCast(context, cond, srcType, VariableType.Bool);
+ return ReinterpretCast(context, cond, srcType, AggregateType.Bool);
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
index b890b015..9ca4618d 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
@@ -1,5 +1,6 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
+using Ryujinx.Graphics.Shader.Translation;
using System;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenBallot;
@@ -8,6 +9,7 @@ using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenFSI;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenPacking;
+using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenVector;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
@@ -32,12 +34,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
IAstNode src = operation.GetSource(0);
- VariableType type = GetSrcVarType(operation.Inst, 0);
+ AggregateType type = GetSrcVarType(operation.Inst, 0);
string srcExpr = GetSoureExpr(context, src, type);
string zero;
- if (type == VariableType.F64)
+ if (type == AggregateType.FP64)
{
zero = "0.0";
}
@@ -95,7 +97,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
}
else
{
- VariableType dstType = GetSrcVarType(inst, argIndex);
+ AggregateType dstType = GetSrcVarType(inst, argIndex);
args += GetSoureExpr(context, operation.GetSource(argIndex), dstType);
}
@@ -226,6 +228,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.UnpackHalf2x16:
return UnpackHalf2x16(context, operation);
+
+ case Instruction.VectorExtract:
+ return VectorExtract(context, operation);
}
}
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs
index 51e7bd21..68793c5d 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs
@@ -1,4 +1,5 @@
using Ryujinx.Graphics.Shader.StructuredIr;
+using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@@ -9,7 +10,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
public static string Ballot(CodeGenContext context, AstOperation operation)
{
- VariableType dstType = GetSrcVarType(operation.Inst, 0);
+ AggregateType dstType = GetSrcVarType(operation.Inst, 0);
string arg = GetSoureExpr(context, operation.GetSource(0), dstType);
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index c40f96f1..743b695c 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
@@ -1,5 +1,6 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
+using Ryujinx.Graphics.Shader.Translation;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.TypeConversion;
@@ -7,11 +8,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
static class InstGenHelper
{
- private static readonly InstInfo[] InfoTable;
+ private static readonly InstInfo[] _infoTable;
static InstGenHelper()
{
- InfoTable = new InstInfo[(int)Instruction.Count];
+ _infoTable = new InstInfo[(int)Instruction.Count];
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
@@ -132,6 +133,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.Truncate, InstType.CallUnary, "trunc");
Add(Instruction.UnpackDouble2x32, InstType.Special);
Add(Instruction.UnpackHalf2x16, InstType.Special);
+ Add(Instruction.VectorExtract, InstType.Special);
Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB");
Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB");
Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB");
@@ -139,15 +141,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0)
{
- InfoTable[(int)inst] = new InstInfo(flags, opName, precedence);
+ _infoTable[(int)inst] = new InstInfo(flags, opName, precedence);
}
public static InstInfo GetInstructionInfo(Instruction inst)
{
- return InfoTable[(int)(inst & Instruction.Mask)];
+ return _infoTable[(int)(inst & Instruction.Mask)];
}
- public static string GetSoureExpr(CodeGenContext context, IAstNode node, VariableType dstType)
+ public static string GetSoureExpr(CodeGenContext context, IAstNode node, AggregateType dstType)
{
return ReinterpretCast(context, node, OperandManager.GetNodeDestType(context, node), dstType);
}
@@ -191,7 +193,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return false;
}
- InstInfo info = InfoTable[(int)(operation.Inst & Instruction.Mask)];
+ InstInfo info = _infoTable[(int)(operation.Inst & Instruction.Mask)];
if ((info.Type & (InstType.Call | InstType.Special)) != 0)
{
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
index 022e3a44..f667d080 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
@@ -1,5 +1,6 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
+using Ryujinx.Graphics.Shader.Translation;
using System;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
@@ -23,7 +24,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.ImageStore:
return "// imageStore(bindless)";
case Instruction.ImageLoad:
- NumberFormatter.TryFormat(0, texOp.Format.GetComponentType(), out string imageConst);
+ AggregateType componentType = texOp.Format.GetComponentType();
+
+ NumberFormatter.TryFormat(0, componentType, out string imageConst);
+
+ AggregateType outputType = texOp.GetVectorType(componentType);
+
+ if ((outputType & AggregateType.ElementCountMask) != 0)
+ {
+ return $"{Declarations.GetVarTypeName(outputType, precise: false)}({imageConst})";
+ }
+
return imageConst;
default:
return NumberFormatter.FormatInt(0);
@@ -58,7 +69,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
int srcIndex = isBindless ? 1 : 0;
- string Src(VariableType type)
+ string Src(AggregateType type)
{
return GetSoureExpr(context, texOp.GetSource(srcIndex++), type);
}
@@ -67,7 +78,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (isIndexed)
{
- indexExpr = Src(VariableType.S32);
+ indexExpr = Src(AggregateType.S32);
}
string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);
@@ -113,19 +124,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
for (int index = 0; index < pCount; index++)
{
- elems[index] = Src(VariableType.S32);
+ elems[index] = Src(AggregateType.S32);
}
Append(ApplyScaling("ivec" + pCount + "(" + string.Join(", ", elems) + ")"));
}
else
{
- Append(Src(VariableType.S32));
+ Append(Src(AggregateType.S32));
}
if (texOp.Inst == Instruction.ImageStore)
{
- VariableType type = texOp.Format.GetComponentType();
+ AggregateType type = texOp.Format.GetComponentType();
string[] cElems = new string[4];
@@ -139,8 +150,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
cElems[index] = type switch
{
- VariableType.S32 => NumberFormatter.FormatInt(0),
- VariableType.U32 => NumberFormatter.FormatUint(0),
+ AggregateType.S32 => NumberFormatter.FormatInt(0),
+ AggregateType.U32 => NumberFormatter.FormatUint(0),
_ => NumberFormatter.FormatFloat(0)
};
}
@@ -148,8 +159,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string prefix = type switch
{
- VariableType.S32 => "i",
- VariableType.U32 => "u",
+ AggregateType.S32 => "i",
+ AggregateType.U32 => "u",
_ => string.Empty
};
@@ -158,7 +169,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (texOp.Inst == Instruction.ImageAtomic)
{
- VariableType type = texOp.Format.GetComponentType();
+ AggregateType type = texOp.Format.GetComponentType();
if ((texOp.Flags & TextureFlags.AtomicMask) == TextureFlags.CAS)
{
@@ -176,14 +187,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCall += ")";
- if (type != VariableType.S32)
+ if (type != AggregateType.S32)
{
texCall = "int(" + texCall + ")";
}
}
else
{
- texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMask(texOp.Index) : "");
+ texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMaskMultiDest(texOp.Index) : "");
}
return texCall;
@@ -288,7 +299,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (isIndexed)
{
- indexExpr = GetSoureExpr(context, texOp.GetSource(0), VariableType.S32);
+ indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
}
string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
@@ -303,14 +314,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
for (int index = 0; index < coordsCount; index++)
{
- elems[index] = GetSoureExpr(context, texOp.GetSource(coordsIndex + index), VariableType.F32);
+ elems[index] = GetSoureExpr(context, texOp.GetSource(coordsIndex + index), AggregateType.FP32);
}
coordsExpr = "vec" + coordsCount + "(" + string.Join(", ", elems) + ")";
}
else
{
- coordsExpr = GetSoureExpr(context, texOp.GetSource(coordsIndex), VariableType.F32);
+ coordsExpr = GetSoureExpr(context, texOp.GetSource(coordsIndex), AggregateType.FP32);
}
return $"textureQueryLod({samplerName}, {coordsExpr}){GetMask(texOp.Index)}";
@@ -362,9 +373,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string offsetExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
- VariableType srcType = OperandManager.GetNodeDestType(context, src2);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, src2);
- string src = TypeConversion.ReinterpretCast(context, src2, srcType, VariableType.U32);
+ string src = TypeConversion.ReinterpretCast(context, src2, srcType, AggregateType.U32);
return $"{arrayName}[{offsetExpr}] = {src}";
}
@@ -376,9 +387,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string offsetExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
- VariableType srcType = OperandManager.GetNodeDestType(context, src2);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, src2);
- string src = TypeConversion.ReinterpretCast(context, src2, srcType, VariableType.U32);
+ string src = TypeConversion.ReinterpretCast(context, src2, srcType, AggregateType.U32);
return $"{HelperFunctionNames.StoreShared16}({offsetExpr}, {src})";
}
@@ -390,9 +401,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string offsetExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
- VariableType srcType = OperandManager.GetNodeDestType(context, src2);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, src2);
- string src = TypeConversion.ReinterpretCast(context, src2, srcType, VariableType.U32);
+ string src = TypeConversion.ReinterpretCast(context, src2, srcType, AggregateType.U32);
return $"{HelperFunctionNames.StoreShared8}({offsetExpr}, {src})";
}
@@ -406,9 +417,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
- VariableType srcType = OperandManager.GetNodeDestType(context, src3);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, src3);
- string src = TypeConversion.ReinterpretCast(context, src3, srcType, VariableType.U32);
+ string src = TypeConversion.ReinterpretCast(context, src3, srcType, AggregateType.U32);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
@@ -424,9 +435,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
- VariableType srcType = OperandManager.GetNodeDestType(context, src3);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, src3);
- string src = TypeConversion.ReinterpretCast(context, src3, srcType, VariableType.U32);
+ string src = TypeConversion.ReinterpretCast(context, src3, srcType, AggregateType.U32);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
@@ -442,9 +453,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string indexExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
- VariableType srcType = OperandManager.GetNodeDestType(context, src3);
+ AggregateType srcType = OperandManager.GetNodeDestType(context, src3);
- string src = TypeConversion.ReinterpretCast(context, src3, srcType, VariableType.U32);
+ string src = TypeConversion.ReinterpretCast(context, src3, srcType, AggregateType.U32);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
@@ -469,6 +480,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
+ bool colorIsVector = isGather || !isShadow;
+
SamplerType type = texOp.Type & SamplerType.Mask;
bool is2D = type == SamplerType.Texture2D;
@@ -492,7 +505,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
// TODO: Bindless texture support. For now we just return 0.
if (isBindless)
{
- return NumberFormatter.FormatFloat(0);
+ string scalarValue = NumberFormatter.FormatFloat(0);
+
+ if (colorIsVector)
+ {
+ AggregateType outputType = texOp.GetVectorType(AggregateType.FP32);
+
+ if ((outputType & AggregateType.ElementCountMask) != 0)
+ {
+ return $"{Declarations.GetVarTypeName(outputType, precise: false)}({scalarValue})";
+ }
+ }
+
+ return scalarValue;
}
string texCall = intCoords ? "texelFetch" : "texture";
@@ -521,7 +546,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
int srcIndex = isBindless ? 1 : 0;
- string Src(VariableType type)
+ string Src(AggregateType type)
{
return GetSoureExpr(context, texOp.GetSource(srcIndex++), type);
}
@@ -530,7 +555,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (isIndexed)
{
- indexExpr = Src(VariableType.S32);
+ indexExpr = Src(AggregateType.S32);
}
string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
@@ -578,7 +603,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCall += ", " + str;
}
- VariableType coordType = intCoords ? VariableType.S32 : VariableType.F32;
+ AggregateType coordType = intCoords ? AggregateType.S32 : AggregateType.FP32;
string AssemblePVector(int count)
{
@@ -590,7 +615,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
if (arrayIndexElem == index)
{
- elems[index] = Src(VariableType.S32);
+ elems[index] = Src(AggregateType.S32);
if (!intCoords)
{
@@ -652,20 +677,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
for (int index = 0; index < count; index++)
{
- elems[index] = Src(VariableType.F32);
+ elems[index] = Src(AggregateType.FP32);
}
return "vec" + count + "(" + string.Join(", ", elems) + ")";
}
else
{
- return Src(VariableType.F32);
+ return Src(AggregateType.FP32);
}
}
if (hasExtraCompareArg)
{
- Append(Src(VariableType.F32));
+ Append(Src(AggregateType.FP32));
}
if (hasDerivatives)
@@ -676,7 +701,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (isMultisample)
{
- Append(Src(VariableType.S32));
+ Append(Src(AggregateType.S32));
}
else if (hasLodLevel)
{
@@ -691,14 +716,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
for (int index = 0; index < count; index++)
{
- elems[index] = Src(VariableType.S32);
+ elems[index] = Src(AggregateType.S32);
}
return "ivec" + count + "(" + string.Join(", ", elems) + ")";
}
else
{
- return Src(VariableType.S32);
+ return Src(AggregateType.S32);
}
}
@@ -718,17 +743,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (hasLodBias)
{
- Append(Src(VariableType.F32));
+ Append(Src(AggregateType.FP32));
}
// textureGather* optional extra component index,
// not needed for shadow samplers.
if (isGather && !isShadow)
{
- Append(Src(VariableType.S32));
+ Append(Src(AggregateType.S32));
}
- texCall += ")" + (isGather || !isShadow ? GetMask(texOp.Index) : "");
+ texCall += ")" + (colorIsVector ? GetMaskMultiDest(texOp.Index) : "");
return texCall;
}
@@ -751,7 +776,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (isIndexed)
{
- indexExpr = GetSoureExpr(context, texOp.GetSource(0), VariableType.S32);
+ indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
}
string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);
@@ -804,5 +829,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
return '.' + "rgba".Substring(index, 1);
}
+
+ private static string GetMaskMultiDest(int mask)
+ {
+ string swizzle = ".";
+
+ for (int i = 0; i < 4; i++)
+ {
+ if ((mask & (1 << i)) != 0)
+ {
+ swizzle += "xyzw"[i];
+ }
+ }
+
+ return swizzle;
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs
new file mode 100644
index 00000000..f09ea2e8
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs
@@ -0,0 +1,32 @@
+using Ryujinx.Graphics.Shader.IntermediateRepresentation;
+using Ryujinx.Graphics.Shader.StructuredIr;
+
+using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
+using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
+
+namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
+{
+ static class InstGenVector
+ {
+ public static string VectorExtract(CodeGenContext context, AstOperation operation)
+ {
+ IAstNode vector = operation.GetSource(0);
+ IAstNode index = operation.GetSource(1);
+
+ string vectorExpr = GetSoureExpr(context, vector, OperandManager.GetNodeDestType(context, vector));
+
+ if (index is AstOperand indexOperand && indexOperand.Type == OperandType.Constant)
+ {
+ char elem = "xyzw"[indexOperand.Value];
+
+ return $"{vectorExpr}.{elem}";
+ }
+ else
+ {
+ string indexExpr = GetSoureExpr(context, index, GetSrcVarType(operation.Inst, 1));
+
+ return $"{vectorExpr}[{indexExpr}]";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs
index 2ec44277..eb27e9bf 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/NumberFormatter.cs
@@ -1,4 +1,4 @@
-using Ryujinx.Graphics.Shader.StructuredIr;
+using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Globalization;
@@ -8,21 +8,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
private const int MaxDecimal = 256;
- public static bool TryFormat(int value, VariableType dstType, out string formatted)
+ public static bool TryFormat(int value, AggregateType dstType, out string formatted)
{
- if (dstType == VariableType.F32)
+ if (dstType == AggregateType.FP32)
{
return TryFormatFloat(BitConverter.Int32BitsToSingle(value), out formatted);
}
- else if (dstType == VariableType.S32)
+ else if (dstType == AggregateType.S32)
{
formatted = FormatInt(value);
}
- else if (dstType == VariableType.U32)
+ else if (dstType == AggregateType.U32)
{
formatted = FormatUint((uint)value);
}
- else if (dstType == VariableType.Bool)
+ else if (dstType == AggregateType.Bool)
{
formatted = value != 0 ? "true" : "false";
}
@@ -65,13 +65,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return true;
}
- public static string FormatInt(int value, VariableType dstType)
+ public static string FormatInt(int value, AggregateType dstType)
{
- if (dstType == VariableType.S32)
+ if (dstType == AggregateType.S32)
{
return FormatInt(value);
}
- else if (dstType == VariableType.U32)
+ else if (dstType == AggregateType.U32)
{
return FormatUint((uint)value);
}
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index ccc87a7f..080f1708 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -4,6 +4,7 @@ using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Numerics;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@@ -17,9 +18,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
public string Name { get; }
- public VariableType Type { get; }
+ public AggregateType Type { get; }
- public BuiltInAttribute(string name, VariableType type)
+ public BuiltInAttribute(string name, AggregateType type)
{
Name = name;
Type = type;
@@ -28,64 +29,64 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static Dictionary<int, BuiltInAttribute> _builtInAttributes = new Dictionary<int, BuiltInAttribute>()
{
- { AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", VariableType.S32) },
- { AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", VariableType.F32) },
- { AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", VariableType.F32) },
- { AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", VariableType.F32) },
- { AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", VariableType.F32) },
- { AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", VariableType.F32) },
- { AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", VariableType.F32) },
- { AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", VariableType.F32) },
- { AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", VariableType.F32) },
- { AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", VariableType.F32) },
- { AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", VariableType.F32) },
- { AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", VariableType.F32) },
- { AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", VariableType.F32) },
- { AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", VariableType.F32) },
- { AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", VariableType.F32) },
- { AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", VariableType.F32) },
- { AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", VariableType.F32) },
- { AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", VariableType.F32) },
- { AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", VariableType.S32) },
- { AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", VariableType.S32) },
- { AttributeConsts.BaseInstance, new BuiltInAttribute("gl_BaseInstanceARB", VariableType.S32) },
- { AttributeConsts.BaseVertex, new BuiltInAttribute("gl_BaseVertexARB", VariableType.S32) },
- { AttributeConsts.InstanceIndex, new BuiltInAttribute("gl_InstanceIndex", VariableType.S32) },
- { AttributeConsts.VertexIndex, new BuiltInAttribute("gl_VertexIndex", VariableType.S32) },
- { AttributeConsts.DrawIndex, new BuiltInAttribute("gl_DrawIDARB", VariableType.S32) },
- { AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
+ { AttributeConsts.Layer, new BuiltInAttribute("gl_Layer", AggregateType.S32) },
+ { AttributeConsts.PointSize, new BuiltInAttribute("gl_PointSize", AggregateType.FP32) },
+ { AttributeConsts.PositionX, new BuiltInAttribute("gl_Position.x", AggregateType.FP32) },
+ { AttributeConsts.PositionY, new BuiltInAttribute("gl_Position.y", AggregateType.FP32) },
+ { AttributeConsts.PositionZ, new BuiltInAttribute("gl_Position.z", AggregateType.FP32) },
+ { AttributeConsts.PositionW, new BuiltInAttribute("gl_Position.w", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance0, new BuiltInAttribute("gl_ClipDistance[0]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance1, new BuiltInAttribute("gl_ClipDistance[1]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance2, new BuiltInAttribute("gl_ClipDistance[2]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance3, new BuiltInAttribute("gl_ClipDistance[3]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance4, new BuiltInAttribute("gl_ClipDistance[4]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance5, new BuiltInAttribute("gl_ClipDistance[5]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance6, new BuiltInAttribute("gl_ClipDistance[6]", AggregateType.FP32) },
+ { AttributeConsts.ClipDistance7, new BuiltInAttribute("gl_ClipDistance[7]", AggregateType.FP32) },
+ { AttributeConsts.PointCoordX, new BuiltInAttribute("gl_PointCoord.x", AggregateType.FP32) },
+ { AttributeConsts.PointCoordY, new BuiltInAttribute("gl_PointCoord.y", AggregateType.FP32) },
+ { AttributeConsts.TessCoordX, new BuiltInAttribute("gl_TessCoord.x", AggregateType.FP32) },
+ { AttributeConsts.TessCoordY, new BuiltInAttribute("gl_TessCoord.y", AggregateType.FP32) },
+ { AttributeConsts.InstanceId, new BuiltInAttribute("gl_InstanceID", AggregateType.S32) },
+ { AttributeConsts.VertexId, new BuiltInAttribute("gl_VertexID", AggregateType.S32) },
+ { AttributeConsts.BaseInstance, new BuiltInAttribute("gl_BaseInstanceARB", AggregateType.S32) },
+ { AttributeConsts.BaseVertex, new BuiltInAttribute("gl_BaseVertexARB", AggregateType.S32) },
+ { AttributeConsts.InstanceIndex, new BuiltInAttribute("gl_InstanceIndex", AggregateType.S32) },
+ { AttributeConsts.VertexIndex, new BuiltInAttribute("gl_VertexIndex", AggregateType.S32) },
+ { AttributeConsts.DrawIndex, new BuiltInAttribute("gl_DrawIDARB", AggregateType.S32) },
+ { AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", AggregateType.Bool) },
// Special.
- { AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", VariableType.F32) },
- { AttributeConsts.ThreadKill, new BuiltInAttribute("gl_HelperInvocation", VariableType.Bool) },
- { AttributeConsts.ThreadIdX, new BuiltInAttribute("gl_LocalInvocationID.x", VariableType.U32) },
- { AttributeConsts.ThreadIdY, new BuiltInAttribute("gl_LocalInvocationID.y", VariableType.U32) },
- { AttributeConsts.ThreadIdZ, new BuiltInAttribute("gl_LocalInvocationID.z", VariableType.U32) },
- { AttributeConsts.CtaIdX, new BuiltInAttribute("gl_WorkGroupID.x", VariableType.U32) },
- { AttributeConsts.CtaIdY, new BuiltInAttribute("gl_WorkGroupID.y", VariableType.U32) },
- { AttributeConsts.CtaIdZ, new BuiltInAttribute("gl_WorkGroupID.z", VariableType.U32) },
- { AttributeConsts.LaneId, new BuiltInAttribute(null, VariableType.U32) },
- { AttributeConsts.InvocationId, new BuiltInAttribute("gl_InvocationID", VariableType.S32) },
- { AttributeConsts.PrimitiveId, new BuiltInAttribute("gl_PrimitiveID", VariableType.S32) },
- { AttributeConsts.PatchVerticesIn, new BuiltInAttribute("gl_PatchVerticesIn", VariableType.S32) },
- { AttributeConsts.EqMask, new BuiltInAttribute(null, VariableType.U32) },
- { AttributeConsts.GeMask, new BuiltInAttribute(null, VariableType.U32) },
- { AttributeConsts.GtMask, new BuiltInAttribute(null, VariableType.U32) },
- { AttributeConsts.LeMask, new BuiltInAttribute(null, VariableType.U32) },
- { AttributeConsts.LtMask, new BuiltInAttribute(null, VariableType.U32) },
+ { AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", AggregateType.FP32) },
+ { AttributeConsts.ThreadKill, new BuiltInAttribute("gl_HelperInvocation", AggregateType.Bool) },
+ { AttributeConsts.ThreadIdX, new BuiltInAttribute("gl_LocalInvocationID.x", AggregateType.U32) },
+ { AttributeConsts.ThreadIdY, new BuiltInAttribute("gl_LocalInvocationID.y", AggregateType.U32) },
+ { AttributeConsts.ThreadIdZ, new BuiltInAttribute("gl_LocalInvocationID.z", AggregateType.U32) },
+ { AttributeConsts.CtaIdX, new BuiltInAttribute("gl_WorkGroupID.x", AggregateType.U32) },
+ { AttributeConsts.CtaIdY, new BuiltInAttribute("gl_WorkGroupID.y", AggregateType.U32) },
+ { AttributeConsts.CtaIdZ, new BuiltInAttribute("gl_WorkGroupID.z", AggregateType.U32) },
+ { AttributeConsts.LaneId, new BuiltInAttribute(null, AggregateType.U32) },
+ { AttributeConsts.InvocationId, new BuiltInAttribute("gl_InvocationID", AggregateType.S32) },
+ { AttributeConsts.PrimitiveId, new BuiltInAttribute("gl_PrimitiveID", AggregateType.S32) },
+ { AttributeConsts.PatchVerticesIn, new BuiltInAttribute("gl_PatchVerticesIn", AggregateType.S32) },
+ { AttributeConsts.EqMask, new BuiltInAttribute(null, AggregateType.U32) },
+ { AttributeConsts.GeMask, new BuiltInAttribute(null, AggregateType.U32) },
+ { AttributeConsts.GtMask, new BuiltInAttribute(null, AggregateType.U32) },
+ { AttributeConsts.LeMask, new BuiltInAttribute(null, AggregateType.U32) },
+ { AttributeConsts.LtMask, new BuiltInAttribute(null, AggregateType.U32) },
// Support uniforms.
- { AttributeConsts.FragmentOutputIsBgraBase + 0, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[0]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 4, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[1]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 8, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[2]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 12, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[3]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 16, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[4]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 20, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[5]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 24, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[6]", VariableType.Bool) },
- { AttributeConsts.FragmentOutputIsBgraBase + 28, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[7]", VariableType.Bool) },
-
- { AttributeConsts.SupportBlockViewInverseX, new BuiltInAttribute($"{DefaultNames.SupportBlockViewportInverse}.x", VariableType.F32) },
- { AttributeConsts.SupportBlockViewInverseY, new BuiltInAttribute($"{DefaultNames.SupportBlockViewportInverse}.y", VariableType.F32) }
+ { AttributeConsts.FragmentOutputIsBgraBase + 0, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[0]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 4, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[1]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 8, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[2]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 12, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[3]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 16, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[4]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 20, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[5]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 24, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[6]", AggregateType.Bool) },
+ { AttributeConsts.FragmentOutputIsBgraBase + 28, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[7]", AggregateType.Bool) },
+
+ { AttributeConsts.SupportBlockViewInverseX, new BuiltInAttribute($"{DefaultNames.SupportBlockViewportInverse}.x", AggregateType.FP32) },
+ { AttributeConsts.SupportBlockViewInverseY, new BuiltInAttribute($"{DefaultNames.SupportBlockViewportInverse}.y", AggregateType.FP32) }
};
private Dictionary<AstOperand, string> _locals;
@@ -329,7 +330,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
if (cbIndexable)
{
- return GetUbName(stage, NumberFormatter.FormatInt(slot, VariableType.S32));
+ return GetUbName(stage, NumberFormatter.FormatInt(slot, AggregateType.S32));
}
return $"{GetShaderStagePrefix(stage)}_{DefaultNames.UniformNamePrefix}{slot}_{DefaultNames.UniformNameSuffix}";
@@ -404,7 +405,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
}
- public static VariableType GetNodeDestType(CodeGenContext context, IAstNode node, bool isAsgDest = false)
+ public static AggregateType GetNodeDestType(CodeGenContext context, IAstNode node, bool isAsgDest = false)
{
if (node is AstOperation operation)
{
@@ -431,12 +432,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return context.GetFunction(funcId.Value).ReturnType;
}
- else if (operation is AstTextureOperation texOp &&
- (texOp.Inst == Instruction.ImageLoad ||
- texOp.Inst == Instruction.ImageStore ||
- texOp.Inst == Instruction.ImageAtomic))
+ else if (operation.Inst == Instruction.VectorExtract)
{
- return texOp.Format.GetComponentType();
+ return GetNodeDestType(context, operation.GetSource(0)) & ~AggregateType.ElementCountMask;
+ }
+ else if (operation is AstTextureOperation texOp)
+ {
+ if (texOp.Inst == Instruction.ImageLoad ||
+ texOp.Inst == Instruction.ImageStore ||
+ texOp.Inst == Instruction.ImageAtomic)
+ {
+ return texOp.GetVectorType(texOp.Format.GetComponentType());
+ }
+ else if (texOp.Inst == Instruction.TextureSample)
+ {
+ return texOp.GetVectorType(GetDestVarType(operation.Inst));
+ }
}
return GetDestVarType(operation.Inst);
@@ -458,7 +469,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
}
- private static VariableType GetOperandVarType(CodeGenContext context, AstOperand operand, bool isAsgDest = false)
+ private static AggregateType GetOperandVarType(CodeGenContext context, AstOperand operand, bool isAsgDest = false)
{
if (operand.Type == OperandType.Attribute)
{
@@ -474,7 +485,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
AttributeType type = context.Config.GpuAccessor.QueryAttributeType(location);
- return type.ToVariableType();
+ return type.ToAggregateType();
}
}
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/TypeConversion.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/TypeConversion.cs
index b13a74f4..22c8623c 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/TypeConversion.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/TypeConversion.cs
@@ -1,6 +1,7 @@
using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
+using Ryujinx.Graphics.Shader.Translation;
using System;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
@@ -10,8 +11,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public static string ReinterpretCast(
CodeGenContext context,
IAstNode node,
- VariableType srcType,
- VariableType dstType)
+ AggregateType srcType,
+ AggregateType dstType)
{
if (node is AstOperand operand && operand.Type == OperandType.Constant)
{
@@ -26,46 +27,46 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return ReinterpretCast(expr, node, srcType, dstType);
}
- private static string ReinterpretCast(string expr, IAstNode node, VariableType srcType, VariableType dstType)
+ private static string ReinterpretCast(string expr, IAstNode node, AggregateType srcType, AggregateType dstType)
{
if (srcType == dstType)
{
return expr;
}
- if (srcType == VariableType.F32)
+ if (srcType == AggregateType.FP32)
{
switch (dstType)
{
- case VariableType.Bool: return $"(floatBitsToInt({expr}) != 0)";
- case VariableType.S32: return $"floatBitsToInt({expr})";
- case VariableType.U32: return $"floatBitsToUint({expr})";
+ case AggregateType.Bool: return $"(floatBitsToInt({expr}) != 0)";
+ case AggregateType.S32: return $"floatBitsToInt({expr})";
+ case AggregateType.U32: return $"floatBitsToUint({expr})";
}
}
- else if (dstType == VariableType.F32)
+ else if (dstType == AggregateType.FP32)
{
switch (srcType)
{
- case VariableType.Bool: return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, VariableType.S32)})";
- case VariableType.S32: return $"intBitsToFloat({expr})";
- case VariableType.U32: return $"uintBitsToFloat({expr})";
+ case AggregateType.Bool: return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
+ case AggregateType.S32: return $"intBitsToFloat({expr})";
+ case AggregateType.U32: return $"uintBitsToFloat({expr})";
}
}
- else if (srcType == VariableType.Bool)
+ else if (srcType == AggregateType.Bool)
{
return ReinterpretBoolToInt(expr, node, dstType);
}
- else if (dstType == VariableType.Bool)
+ else if (dstType == AggregateType.Bool)
{
expr = InstGenHelper.Enclose(expr, node, Instruction.CompareNotEqual, isLhs: true);
return $"({expr} != 0)";
}
- else if (dstType == VariableType.S32)
+ else if (dstType == AggregateType.S32)
{
return $"int({expr})";
}
- else if (dstType == VariableType.U32)
+ else if (dstType == AggregateType.U32)
{
return $"uint({expr})";
}
@@ -73,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
throw new ArgumentException($"Invalid reinterpret cast from \"{srcType}\" to \"{dstType}\".");
}
- private static string ReinterpretBoolToInt(string expr, IAstNode node, VariableType dstType)
+ private static string ReinterpretBoolToInt(string expr, IAstNode node, AggregateType dstType)
{
string trueExpr = NumberFormatter.FormatInt(IrConsts.True, dstType);
string falseExpr = NumberFormatter.FormatInt(IrConsts.False, dstType);
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
index dff5474a..41afdf18 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
@@ -241,6 +241,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
throw new NotImplementedException(node.GetType().Name);
}
+ public Instruction GetWithType(IAstNode node, out AggregateType type)
+ {
+ if (node is AstOperation operation)
+ {
+ var opResult = Instructions.Generate(this, operation);
+ type = opResult.Type;
+ return opResult.Value;
+ }
+ else if (node is AstOperand operand)
+ {
+ switch (operand.Type)
+ {
+ case IrOperandType.LocalVariable:
+ type = operand.VarType;
+ return GetLocal(type, operand);
+ default:
+ throw new ArgumentException($"Invalid operand type \"{operand.Type}\".");
+ }
+ }
+
+ throw new NotImplementedException(node.GetType().Name);
+ }
+
private Instruction GetUndefined(AggregateType type)
{
return type switch
@@ -325,7 +348,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (components > 1)
{
attrOffset &= ~0xf;
- type = AggregateType.Vector | AggregateType.FP32;
+ type = components switch
+ {
+ 2 => AggregateType.Vector2 | AggregateType.FP32,
+ 3 => AggregateType.Vector3 | AggregateType.FP32,
+ 4 => AggregateType.Vector4 | AggregateType.FP32,
+ _ => AggregateType.FP32
+ };
+
attrInfo = new AttributeInfo(attrOffset, (attr - attrOffset) / 4, components, type, false);
}
}
@@ -335,7 +365,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
bool isIndexed = AttributeInfo.IsArrayAttributeSpirv(Config.Stage, isOutAttr) && (!attrInfo.IsBuiltin || AttributeInfo.IsArrayBuiltIn(attr));
- if ((type & (AggregateType.Array | AggregateType.Vector)) == 0)
+ if ((type & (AggregateType.Array | AggregateType.ElementCountMask)) == 0)
{
if (invocationId != null)
{
@@ -452,7 +482,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
elemType = attrInfo.Type & AggregateType.ElementTypeMask;
- if ((attrInfo.Type & (AggregateType.Array | AggregateType.Vector)) == 0)
+ if ((attrInfo.Type & (AggregateType.Array | AggregateType.ElementCountMask)) == 0)
{
return ioVariable;
}
@@ -533,13 +563,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public Instruction GetLocal(AggregateType dstType, AstOperand local)
{
- var srcType = local.VarType.Convert();
+ var srcType = local.VarType;
return BitcastIfNeeded(dstType, srcType, Load(GetType(srcType), GetLocalPointer(local)));
}
public Instruction GetArgument(AggregateType dstType, AstOperand funcArg)
{
- var srcType = funcArg.VarType.Convert();
+ var srcType = funcArg.VarType;
return BitcastIfNeeded(dstType, srcType, Load(GetType(srcType), GetArgumentPointer(funcArg)));
}
@@ -550,13 +580,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public Instruction GetType(AggregateType type, int length = 1)
{
- if (type.HasFlag(AggregateType.Array))
+ if ((type & AggregateType.Array) != 0)
{
return TypeArray(GetType(type & ~AggregateType.Array), Constant(TypeU32(), length));
}
- else if (type.HasFlag(AggregateType.Vector))
+ else if ((type & AggregateType.ElementCountMask) != 0)
{
- return TypeVector(GetType(type & ~AggregateType.Vector), length);
+ int vectorLength = (type & AggregateType.ElementCountMask) switch
+ {
+ AggregateType.Vector2 => 2,
+ AggregateType.Vector3 => 3,
+ AggregateType.Vector4 => 4,
+ _ => 1
+ };
+
+ return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength);
}
return type switch
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
index 819ece41..3da72b40 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
@@ -23,11 +23,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
DeclareParameters(context, function.OutArguments, function.InArguments.Length);
}
- private static void DeclareParameters(CodeGenContext context, IEnumerable<VariableType> argTypes, int argIndex)
+ private static void DeclareParameters(CodeGenContext context, IEnumerable<AggregateType> argTypes, int argIndex)
{
foreach (var argType in argTypes)
{
- var argPointerType = context.TypePointer(StorageClass.Function, context.GetType(argType.Convert()));
+ var argPointerType = context.TypePointer(StorageClass.Function, context.GetType(argType));
var spvArg = context.FunctionParameter(argPointerType);
context.DeclareArgument(argIndex++, spvArg);
@@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
foreach (AstOperand local in function.Locals)
{
- var localPointerType = context.TypePointer(StorageClass.Function, context.GetType(local.VarType.Convert()));
+ var localPointerType = context.TypePointer(StorageClass.Function, context.GetType(local.VarType));
var spvLocal = context.Variable(localPointerType, StorageClass.Function);
context.AddLocalVariable(spvLocal);
@@ -62,7 +62,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
for (int i = 0; i < function.InArguments.Length; i++)
{
- var type = function.GetArgumentType(i).Convert();
+ var type = function.GetArgumentType(i);
var localPointerType = context.TypePointer(StorageClass.Function, context.GetType(type));
var spvLocal = context.Variable(localPointerType, StorageClass.Function);
@@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var dim = GetDim(descriptor.Type);
var imageType = context.TypeImage(
- context.GetType(meta.Format.GetComponentType().Convert()),
+ context.GetType(meta.Format.GetComponentType()),
dim,
descriptor.Type.HasFlag(SamplerType.Shadow),
descriptor.Type.HasFlag(SamplerType.Array),
@@ -652,7 +652,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (components > 1)
{
attr &= ~0xf;
- type = AggregateType.Vector | AggregateType.FP32;
+ type = components switch
+ {
+ 2 => AggregateType.Vector2 | AggregateType.FP32,
+ 3 => AggregateType.Vector3 | AggregateType.FP32,
+ 4 => AggregateType.Vector4 | AggregateType.FP32,
+ _ => AggregateType.FP32
+ };
+
hasComponent = false;
}
}
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/EnumConversion.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/EnumConversion.cs
index 0ddb4264..aa3d046a 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/EnumConversion.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/EnumConversion.cs
@@ -1,5 +1,4 @@
-using Ryujinx.Graphics.Shader.StructuredIr;
-using Ryujinx.Graphics.Shader.Translation;
+using Ryujinx.Graphics.Shader.Translation;
using System;
using static Spv.Specification;
@@ -7,20 +6,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
static class EnumConversion
{
- public static AggregateType Convert(this VariableType type)
- {
- return type switch
- {
- VariableType.None => AggregateType.Void,
- VariableType.Bool => AggregateType.Bool,
- VariableType.F32 => AggregateType.FP32,
- VariableType.F64 => AggregateType.FP64,
- VariableType.S32 => AggregateType.S32,
- VariableType.U32 => AggregateType.U32,
- _ => throw new ArgumentException($"Invalid variable type \"{type}\".")
- };
- }
-
public static ExecutionModel Convert(this ShaderStage stage)
{
return stage switch
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
index ae280377..a02c4c22 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
@@ -4,6 +4,7 @@ using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Numerics;
using static Spv.Specification;
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
@@ -146,6 +147,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.Truncate, GenerateTruncate);
Add(Instruction.UnpackDouble2x32, GenerateUnpackDouble2x32);
Add(Instruction.UnpackHalf2x16, GenerateUnpackHalf2x16);
+ Add(Instruction.VectorExtract, GenerateVectorExtract);
Add(Instruction.VoteAll, GenerateVoteAll);
Add(Instruction.VoteAllEqual, GenerateVoteAllEqual);
Add(Instruction.VoteAny, GenerateVoteAny);
@@ -317,7 +319,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
else
{
- var type = function.GetArgumentType(i).Convert();
+ var type = function.GetArgumentType(i);
var value = context.Get(type, operand);
var spvLocal = spvLocals[i];
@@ -327,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
}
- var retType = function.ReturnType.Convert();
+ var retType = function.ReturnType;
var result = context.FunctionCall(context.GetType(retType), spvFunc, args);
return new OperationResult(retType, result);
}
@@ -604,10 +606,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
// TODO: Bindless texture support. For now we just return 0/do nothing.
if (isBindless)
{
- return new OperationResult(componentType.Convert(), componentType switch
+ return new OperationResult(componentType, componentType switch
{
- VariableType.S32 => context.Constant(context.TypeS32(), 0),
- VariableType.U32 => context.Constant(context.TypeU32(), 0u),
+ AggregateType.S32 => context.Constant(context.TypeS32(), 0),
+ AggregateType.U32 => context.Constant(context.TypeU32(), 0u),
_ => context.Constant(context.TypeFP32(), 0f),
});
}
@@ -652,13 +654,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
pCoords = Src(AggregateType.S32);
}
- SpvInstruction value = Src(componentType.Convert());
+ SpvInstruction value = Src(componentType);
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable);
- SpvInstruction resultType = context.GetType(componentType.Convert());
+ SpvInstruction resultType = context.GetType(componentType);
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
var pointer = context.ImageTexelPointer(imagePointerType, imageVariable, pCoords, context.Constant(context.TypeU32(), 0));
@@ -668,10 +670,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var result = (texOp.Flags & TextureFlags.AtomicMask) switch
{
TextureFlags.Add => context.AtomicIAdd(resultType, pointer, one, zero, value),
- TextureFlags.Minimum => componentType == VariableType.S32
+ TextureFlags.Minimum => componentType == AggregateType.S32
? context.AtomicSMin(resultType, pointer, one, zero, value)
: context.AtomicUMin(resultType, pointer, one, zero, value),
- TextureFlags.Maximum => componentType == VariableType.S32
+ TextureFlags.Maximum => componentType == AggregateType.S32
? context.AtomicSMax(resultType, pointer, one, zero, value)
: context.AtomicUMax(resultType, pointer, one, zero, value),
TextureFlags.Increment => context.AtomicIIncrement(resultType, pointer, one, zero),
@@ -680,11 +682,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
TextureFlags.BitwiseOr => context.AtomicOr(resultType, pointer, one, zero, value),
TextureFlags.BitwiseXor => context.AtomicXor(resultType, pointer, one, zero, value),
TextureFlags.Swap => context.AtomicExchange(resultType, pointer, one, zero, value),
- TextureFlags.CAS => context.AtomicCompareExchange(resultType, pointer, one, zero, zero, Src(componentType.Convert()), value),
+ TextureFlags.CAS => context.AtomicCompareExchange(resultType, pointer, one, zero, zero, Src(componentType), value),
_ => context.AtomicIAdd(resultType, pointer, one, zero, value),
};
- return new OperationResult(componentType.Convert(), result);
+ return new OperationResult(componentType, result);
}
private static OperationResult GenerateImageLoad(CodeGenContext context, AstOperation operation)
@@ -698,14 +700,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
// TODO: Bindless texture support. For now we just return 0/do nothing.
if (isBindless)
{
- var zero = componentType switch
- {
- VariableType.S32 => context.Constant(context.TypeS32(), 0),
- VariableType.U32 => context.Constant(context.TypeU32(), 0u),
- _ => context.Constant(context.TypeFP32(), 0f),
- };
-
- return new OperationResult(componentType.Convert(), zero);
+ return GetZeroOperationResult(context, texOp, componentType, isVector: true);
}
bool isArray = (texOp.Type & SamplerType.Array) != 0;
@@ -753,12 +748,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable);
- var imageComponentType = context.GetType(componentType.Convert());
+ var imageComponentType = context.GetType(componentType);
+ var swizzledResultType = texOp.GetVectorType(componentType);
var texel = context.ImageRead(context.TypeVector(imageComponentType, 4), image, pCoords, ImageOperandsMask.MaskNone);
- var result = context.CompositeExtract(imageComponentType, texel, (SpvLiteralInteger)texOp.Index);
+ var result = GetSwizzledResult(context, texel, swizzledResultType, texOp.Index);
- return new OperationResult(componentType.Convert(), result);
+ return new OperationResult(componentType, result);
}
private static OperationResult GenerateImageStore(CodeGenContext context, AstOperation operation)
@@ -823,20 +819,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
if (srcIndex < texOp.SourcesCount)
{
- cElems[i] = Src(componentType.Convert());
+ cElems[i] = Src(componentType);
}
else
{
cElems[i] = componentType switch
{
- VariableType.S32 => context.Constant(context.TypeS32(), 0),
- VariableType.U32 => context.Constant(context.TypeU32(), 0u),
+ AggregateType.S32 => context.Constant(context.TypeS32(), 0),
+ AggregateType.U32 => context.Constant(context.TypeU32(), 0u),
_ => context.Constant(context.TypeFP32(), 0f),
};
}
}
- var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType.Convert()), ComponentsCount), cElems);
+ var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
@@ -1238,7 +1234,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var validLocal = (AstOperand)operation.GetSource(3);
- context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType.Convert(), AggregateType.Bool, valid));
+ context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType, AggregateType.Bool, valid));
return new OperationResult(AggregateType.FP32, result);
}
@@ -1268,7 +1264,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var validLocal = (AstOperand)operation.GetSource(3);
- context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType.Convert(), AggregateType.Bool, valid));
+ context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType, AggregateType.Bool, valid));
return new OperationResult(AggregateType.FP32, result);
}
@@ -1294,7 +1290,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var validLocal = (AstOperand)operation.GetSource(3);
- context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType.Convert(), AggregateType.Bool, valid));
+ context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType, AggregateType.Bool, valid));
return new OperationResult(AggregateType.FP32, result);
}
@@ -1324,7 +1320,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var validLocal = (AstOperand)operation.GetSource(3);
- context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType.Convert(), AggregateType.Bool, valid));
+ context.Store(context.GetLocalPointer(validLocal), context.BitcastIfNeeded(validLocal.VarType, AggregateType.Bool, valid));
return new OperationResult(AggregateType.FP32, result);
}
@@ -1485,10 +1481,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
+ bool colorIsVector = isGather || !isShadow;
+
// TODO: Bindless texture support. For now we just return 0.
if (isBindless)
{
- return new OperationResult(AggregateType.FP32, context.Constant(context.TypeFP32(), 0f));
+ return GetZeroOperationResult(context, texOp, AggregateType.FP32, colorIsVector);
}
// This combination is valid, but not available on GLSL.
@@ -1705,7 +1703,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
operandsList.Add(sample);
}
- bool colorIsVector = isGather || !isShadow;
var resultType = colorIsVector ? context.TypeVector(context.TypeFP32(), 4) : context.TypeFP32();
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
@@ -1758,12 +1755,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
result = context.ImageSampleImplicitLod(resultType, image, pCoords, operandsMask, operands);
}
+ var swizzledResultType = AggregateType.FP32;
+
if (colorIsVector)
{
- result = context.CompositeExtract(context.TypeFP32(), result, (SpvLiteralInteger)texOp.Index);
+ swizzledResultType = texOp.GetVectorType(swizzledResultType);
+
+ result = GetSwizzledResult(context, result, swizzledResultType, texOp.Index);
}
- return new OperationResult(AggregateType.FP32, result);
+ return new OperationResult(swizzledResultType, result);
}
private static OperationResult GenerateTextureSize(CodeGenContext context, AstOperation operation)
@@ -1862,6 +1863,26 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return new OperationResult(AggregateType.FP32, result);
}
+ private static OperationResult GenerateVectorExtract(CodeGenContext context, AstOperation operation)
+ {
+ var vector = context.GetWithType(operation.GetSource(0), out AggregateType vectorType);
+ var scalarType = vectorType & ~AggregateType.ElementCountMask;
+ var resultType = context.GetType(scalarType);
+ SpvInstruction result;
+
+ if (operation.GetSource(1) is AstOperand indexOperand && indexOperand.Type == OperandType.Constant)
+ {
+ result = context.CompositeExtract(resultType, vector, (SpvLiteralInteger)indexOperand.Value);
+ }
+ else
+ {
+ var index = context.Get(AggregateType.S32, operation.GetSource(1));
+ result = context.VectorExtractDynamic(resultType, vector, index);
+ }
+
+ return new OperationResult(scalarType, result);
+ }
+
private static OperationResult GenerateVoteAll(CodeGenContext context, AstOperation operation)
{
var execution = context.Constant(context.TypeU32(), Scope.Subgroup);
@@ -2044,6 +2065,64 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.AddLabel(loopEnd);
}
+ private static OperationResult GetZeroOperationResult(
+ CodeGenContext context,
+ AstTextureOperation texOp,
+ AggregateType scalarType,
+ bool isVector)
+ {
+ var zero = scalarType switch
+ {
+ AggregateType.S32 => context.Constant(context.TypeS32(), 0),
+ AggregateType.U32 => context.Constant(context.TypeU32(), 0u),
+ _ => context.Constant(context.TypeFP32(), 0f),
+ };
+
+ if (isVector)
+ {
+ AggregateType outputType = texOp.GetVectorType(scalarType);
+
+ if ((outputType & AggregateType.ElementCountMask) != 0)
+ {
+ int componentsCount = BitOperations.PopCount((uint)texOp.Index);
+
+ SpvInstruction[] values = new SpvInstruction[componentsCount];
+
+ values.AsSpan().Fill(zero);
+
+ return new OperationResult(outputType, context.ConstantComposite(context.GetType(outputType), values));
+ }
+ }
+
+ return new OperationResult(scalarType, zero);
+ }
+
+ private static SpvInstruction GetSwizzledResult(CodeGenContext context, SpvInstruction vector, AggregateType swizzledResultType, int mask)
+ {
+ if ((swizzledResultType & AggregateType.ElementCountMask) != 0)
+ {
+ SpvLiteralInteger[] components = new SpvLiteralInteger[BitOperations.PopCount((uint)mask)];
+
+ int componentIndex = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ if ((mask & (1 << i)) != 0)
+ {
+ components[componentIndex++] = i;
+ }
+ }
+
+ return context.VectorShuffle(context.GetType(swizzledResultType), vector, vector, components);
+ }
+ else
+ {
+ int componentIndex = (int)BitOperations.TrailingZeroCount(mask);
+
+ return context.CompositeExtract(context.GetType(swizzledResultType), vector, (SpvLiteralInteger)componentIndex);
+ }
+ }
+
private static SpvInstruction GetStorageElemPointer(CodeGenContext context, AstOperation operation)
{
var sbVariable = context.StorageBuffersArray;
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
index 6e1db972..9f08b319 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
@@ -104,13 +104,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
for (int funcIndex = 0; funcIndex < info.Functions.Count; funcIndex++)
{
var function = info.Functions[funcIndex];
- var retType = context.GetType(function.ReturnType.Convert());
+ var retType = context.GetType(function.ReturnType);
var funcArgs = new SpvInstruction[function.InArguments.Length + function.OutArguments.Length];
for (int argIndex = 0; argIndex < funcArgs.Length; argIndex++)
{
- var argType = context.GetType(function.GetArgumentType(argIndex).Convert());
+ var argType = context.GetType(function.GetArgumentType(argIndex));
var argPointerType = context.TypePointer(StorageClass.Function, argType);
funcArgs[argIndex] = argPointerType;
}
@@ -387,7 +387,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (dest.Type == OperandType.LocalVariable)
{
- var source = context.Get(dest.VarType.Convert(), assignment.Source);
+ var source = context.Get(dest.VarType, assignment.Source);
context.Store(context.GetLocalPointer(dest), source);
}
else if (dest.Type == OperandType.Attribute || dest.Type == OperandType.AttributePerPatch)
@@ -407,7 +407,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
else if (dest.Type == OperandType.Argument)
{
- var source = context.Get(dest.VarType.Convert(), assignment.Source);
+ var source = context.Get(dest.VarType, assignment.Source);
context.Store(context.GetArgumentPointer(dest), source);
}
else