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>
This commit is contained in:
parent
52c115a1f8
commit
9dfe81770a
37 changed files with 1100 additions and 747 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue