Add support for large sampler arrays on Vulkan (#6489)
* Add support for large sampler arrays on Vulkan * Shader cache version bump * Format whitespace * Move DescriptorSetManager to PipelineLayoutCacheEntry to allow different pool sizes per layout * Handle array textures with different types on the same buffer * Somewhat better caching system * Avoid useless buffer data modification checks * Move redundant bindings update checking to the backend * Fix an issue where texture arrays would get the same bindings across stages on Vulkan * Backport some fixes from part 2 * Fix typo * PR feedback * Format whitespace * Add some missing XML docs
This commit is contained in:
parent
808803d97a
commit
3e6e0e4afa
83 changed files with 3263 additions and 955 deletions
|
@ -339,24 +339,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
|
||||
private static void DeclareSamplers(CodeGenContext context, IEnumerable<TextureDefinition> definitions)
|
||||
{
|
||||
int arraySize = 0;
|
||||
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
string indexExpr = string.Empty;
|
||||
string arrayDecl = string.Empty;
|
||||
|
||||
if (definition.Type.HasFlag(SamplerType.Indexed))
|
||||
if (definition.ArrayLength > 1)
|
||||
{
|
||||
if (arraySize == 0)
|
||||
{
|
||||
arraySize = ResourceManager.SamplerArraySize;
|
||||
}
|
||||
else if (--arraySize != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
indexExpr = $"[{NumberFormatter.FormatInt(arraySize)}]";
|
||||
arrayDecl = $"[{NumberFormatter.FormatInt(definition.ArrayLength)}]";
|
||||
}
|
||||
else if (definition.ArrayLength == 0)
|
||||
{
|
||||
arrayDecl = "[]";
|
||||
}
|
||||
|
||||
string samplerTypeName = definition.Type.ToGlslSamplerType();
|
||||
|
@ -368,30 +361,23 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
layout = $", set = {definition.Set}";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (binding = {definition.Binding}{layout}) uniform {samplerTypeName} {definition.Name}{indexExpr};");
|
||||
context.AppendLine($"layout (binding = {definition.Binding}{layout}) uniform {samplerTypeName} {definition.Name}{arrayDecl};");
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeclareImages(CodeGenContext context, IEnumerable<TextureDefinition> definitions)
|
||||
{
|
||||
int arraySize = 0;
|
||||
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
string indexExpr = string.Empty;
|
||||
string arrayDecl = string.Empty;
|
||||
|
||||
if (definition.Type.HasFlag(SamplerType.Indexed))
|
||||
if (definition.ArrayLength > 1)
|
||||
{
|
||||
if (arraySize == 0)
|
||||
{
|
||||
arraySize = ResourceManager.SamplerArraySize;
|
||||
}
|
||||
else if (--arraySize != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
indexExpr = $"[{NumberFormatter.FormatInt(arraySize)}]";
|
||||
arrayDecl = $"[{NumberFormatter.FormatInt(definition.ArrayLength)}]";
|
||||
}
|
||||
else if (definition.ArrayLength == 0)
|
||||
{
|
||||
arrayDecl = "[]";
|
||||
}
|
||||
|
||||
string imageTypeName = definition.Type.ToGlslImageType(definition.Format.GetComponentType());
|
||||
|
@ -413,7 +399,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
layout = $", set = {definition.Set}{layout}";
|
||||
}
|
||||
|
||||
context.AppendLine($"layout (binding = {definition.Binding}{layout}) uniform {imageTypeName} {definition.Name}{indexExpr};");
|
||||
context.AppendLine($"layout (binding = {definition.Binding}{layout}) uniform {imageTypeName} {definition.Name}{arrayDecl};");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
AggregateType type = GetSrcVarType(operation.Inst, 0);
|
||||
|
||||
string srcExpr = GetSoureExpr(context, src, type);
|
||||
string srcExpr = GetSourceExpr(context, src, type);
|
||||
string zero;
|
||||
|
||||
if (type == AggregateType.FP64)
|
||||
|
@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
for (int argIndex = operation.SourcesCount - arity + 2; argIndex < operation.SourcesCount; argIndex++)
|
||||
{
|
||||
builder.Append($", {GetSoureExpr(context, operation.GetSource(argIndex), dstType)}");
|
||||
builder.Append($", {GetSourceExpr(context, operation.GetSource(argIndex), dstType)}");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -94,7 +94,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
AggregateType dstType = GetSrcVarType(inst, argIndex);
|
||||
|
||||
builder.Append(GetSoureExpr(context, operation.GetSource(argIndex), dstType));
|
||||
builder.Append(GetSourceExpr(context, operation.GetSource(argIndex), dstType));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
// Return may optionally have a return value (and in this case it is unary).
|
||||
if (inst == Instruction.Return && operation.SourcesCount != 0)
|
||||
{
|
||||
return $"{op} {GetSoureExpr(context, operation.GetSource(0), context.CurrentFunction.ReturnType)}";
|
||||
return $"{op} {GetSourceExpr(context, operation.GetSource(0), context.CurrentFunction.ReturnType)}";
|
||||
}
|
||||
|
||||
int arity = (int)(info.Type & InstType.ArityMask);
|
||||
|
@ -118,7 +118,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
IAstNode src = operation.GetSource(index);
|
||||
|
||||
string srcExpr = GetSoureExpr(context, src, GetSrcVarType(inst, index));
|
||||
string srcExpr = GetSourceExpr(context, src, GetSrcVarType(inst, index));
|
||||
|
||||
bool isLhs = arity == 2 && index == 0;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
AggregateType dstType = GetSrcVarType(operation.Inst, 0);
|
||||
|
||||
string arg = GetSoureExpr(context, operation.GetSource(0), dstType);
|
||||
string arg = GetSourceExpr(context, operation.GetSource(0), dstType);
|
||||
char component = "xyzw"[operation.Index];
|
||||
|
||||
if (context.HostCapabilities.SupportsShaderBallot)
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
args[i] = GetSoureExpr(context, operation.GetSource(i + 1), function.GetArgumentType(i));
|
||||
args[i] = GetSourceExpr(context, operation.GetSource(i + 1), function.GetArgumentType(i));
|
||||
}
|
||||
|
||||
return $"{function.Name}({string.Join(", ", args)})";
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
return _infoTable[(int)(inst & Instruction.Mask)];
|
||||
}
|
||||
|
||||
public static string GetSoureExpr(CodeGenContext context, IAstNode node, AggregateType dstType)
|
||||
public static string GetSourceExpr(CodeGenContext context, IAstNode node, AggregateType dstType)
|
||||
{
|
||||
return ReinterpretCast(context, node, OperandManager.GetNodeDestType(context, node), dstType);
|
||||
}
|
||||
|
|
|
@ -14,35 +14,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0/do nothing.
|
||||
if (isBindless)
|
||||
{
|
||||
switch (texOp.Inst)
|
||||
{
|
||||
case Instruction.ImageStore:
|
||||
return "// imageStore(bindless)";
|
||||
case Instruction.ImageLoad:
|
||||
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(context, outputType, precise: false)}({imageConst})";
|
||||
}
|
||||
|
||||
return imageConst;
|
||||
default:
|
||||
return NumberFormatter.FormatInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
var texCallBuilder = new StringBuilder();
|
||||
|
||||
|
@ -70,21 +42,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
texCallBuilder.Append(texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore");
|
||||
}
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
string Src(AggregateType type)
|
||||
{
|
||||
return GetSoureExpr(context, texOp.GetSource(srcIndex++), type);
|
||||
return GetSourceExpr(context, texOp.GetSource(srcIndex++), type);
|
||||
}
|
||||
|
||||
string indexExpr = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
indexExpr = Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
string imageName = GetImageName(context.Properties, texOp, indexExpr);
|
||||
string imageName = GetImageName(context, texOp, ref srcIndex);
|
||||
|
||||
texCallBuilder.Append('(');
|
||||
texCallBuilder.Append(imageName);
|
||||
|
@ -198,27 +163,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
int coordsIndex = 0;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
{
|
||||
return NumberFormatter.FormatFloat(0);
|
||||
}
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
string indexExpr = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
|
||||
}
|
||||
|
||||
string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
|
||||
|
||||
int coordsIndex = isBindless || isIndexed ? 1 : 0;
|
||||
string samplerName = GetSamplerName(context, texOp, ref coordsIndex);
|
||||
|
||||
string coordsExpr;
|
||||
|
||||
|
@ -228,14 +175,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
for (int index = 0; index < coordsCount; index++)
|
||||
{
|
||||
elems[index] = GetSoureExpr(context, texOp.GetSource(coordsIndex + index), AggregateType.FP32);
|
||||
elems[index] = GetSourceExpr(context, texOp.GetSource(coordsIndex + index), AggregateType.FP32);
|
||||
}
|
||||
|
||||
coordsExpr = "vec" + coordsCount + "(" + string.Join(", ", elems) + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
coordsExpr = GetSoureExpr(context, texOp.GetSource(coordsIndex), AggregateType.FP32);
|
||||
coordsExpr = GetSourceExpr(context, texOp.GetSource(coordsIndex), AggregateType.FP32);
|
||||
}
|
||||
|
||||
return $"textureQueryLod({samplerName}, {coordsExpr}){GetMask(texOp.Index)}";
|
||||
|
@ -250,7 +197,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
|
||||
bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
|
||||
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
|
||||
|
@ -260,12 +206,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
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;
|
||||
|
@ -286,24 +229,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
hasLodLevel = false;
|
||||
}
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
{
|
||||
string scalarValue = NumberFormatter.FormatFloat(0);
|
||||
|
||||
if (colorIsVector)
|
||||
{
|
||||
AggregateType outputType = texOp.GetVectorType(AggregateType.FP32);
|
||||
|
||||
if ((outputType & AggregateType.ElementCountMask) != 0)
|
||||
{
|
||||
return $"{Declarations.GetVarTypeName(context, outputType, precise: false)}({scalarValue})";
|
||||
}
|
||||
}
|
||||
|
||||
return scalarValue;
|
||||
}
|
||||
|
||||
string texCall = intCoords ? "texelFetch" : "texture";
|
||||
|
||||
if (isGather)
|
||||
|
@ -328,21 +253,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
texCall += "Offsets";
|
||||
}
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
string Src(AggregateType type)
|
||||
{
|
||||
return GetSoureExpr(context, texOp.GetSource(srcIndex++), type);
|
||||
return GetSourceExpr(context, texOp.GetSource(srcIndex++), type);
|
||||
}
|
||||
|
||||
string indexExpr = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
indexExpr = Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
|
||||
string samplerName = GetSamplerName(context, texOp, ref srcIndex);
|
||||
|
||||
texCall += "(" + samplerName;
|
||||
|
||||
|
@ -512,6 +430,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
Append(Src(AggregateType.S32));
|
||||
}
|
||||
|
||||
bool colorIsVector = isGather || !isShadow;
|
||||
|
||||
texCall += ")" + (colorIsVector ? GetMaskMultiDest(texOp.Index) : "");
|
||||
|
||||
return texCall;
|
||||
|
@ -521,24 +441,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
{
|
||||
return NumberFormatter.FormatInt(0);
|
||||
}
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
string indexExpr = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
|
||||
}
|
||||
|
||||
string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
|
||||
string samplerName = GetSamplerName(context, texOp, ref srcIndex);
|
||||
|
||||
return $"textureSamples({samplerName})";
|
||||
}
|
||||
|
@ -547,24 +452,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
{
|
||||
return NumberFormatter.FormatInt(0);
|
||||
}
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
string indexExpr = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
|
||||
}
|
||||
|
||||
string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
|
||||
string samplerName = GetSamplerName(context, texOp, ref srcIndex);
|
||||
|
||||
if (texOp.Index == 3)
|
||||
{
|
||||
|
@ -578,9 +468,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
if (hasLod)
|
||||
{
|
||||
int lodSrcIndex = isBindless || isIndexed ? 1 : 0;
|
||||
IAstNode lod = operation.GetSource(lodSrcIndex);
|
||||
string lodExpr = GetSoureExpr(context, lod, GetSrcVarType(operation.Inst, lodSrcIndex));
|
||||
IAstNode lod = operation.GetSource(srcIndex);
|
||||
string lodExpr = GetSourceExpr(context, lod, GetSrcVarType(operation.Inst, srcIndex));
|
||||
|
||||
texCall = $"textureSize({samplerName}, {lodExpr}){GetMask(texOp.Index)}";
|
||||
}
|
||||
|
@ -697,12 +586,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
|
||||
if (storageKind == StorageKind.Input)
|
||||
{
|
||||
string expr = GetSoureExpr(context, operation.GetSource(srcIndex++), AggregateType.S32);
|
||||
string expr = GetSourceExpr(context, operation.GetSource(srcIndex++), AggregateType.S32);
|
||||
varName = $"gl_in[{expr}].{varName}";
|
||||
}
|
||||
else if (storageKind == StorageKind.Output)
|
||||
{
|
||||
string expr = GetSoureExpr(context, operation.GetSource(srcIndex++), AggregateType.S32);
|
||||
string expr = GetSourceExpr(context, operation.GetSource(srcIndex++), AggregateType.S32);
|
||||
varName = $"gl_out[{expr}].{varName}";
|
||||
}
|
||||
}
|
||||
|
@ -735,38 +624,40 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
varName += $"[{GetSoureExpr(context, src, AggregateType.S32)}]";
|
||||
varName += $"[{GetSourceExpr(context, src, AggregateType.S32)}]";
|
||||
}
|
||||
}
|
||||
|
||||
if (isStore)
|
||||
{
|
||||
varType &= AggregateType.ElementTypeMask;
|
||||
varName = $"{varName} = {GetSoureExpr(context, operation.GetSource(srcIndex), varType)}";
|
||||
varName = $"{varName} = {GetSourceExpr(context, operation.GetSource(srcIndex), varType)}";
|
||||
}
|
||||
|
||||
return varName;
|
||||
}
|
||||
|
||||
private static string GetSamplerName(ShaderProperties resourceDefinitions, AstTextureOperation texOp, string indexExpr)
|
||||
private static string GetSamplerName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex)
|
||||
{
|
||||
string name = resourceDefinitions.Textures[texOp.Binding].Name;
|
||||
TextureDefinition definition = context.Properties.Textures[texOp.Binding];
|
||||
string name = definition.Name;
|
||||
|
||||
if (texOp.Type.HasFlag(SamplerType.Indexed))
|
||||
if (definition.ArrayLength != 1)
|
||||
{
|
||||
name = $"{name}[{indexExpr}]";
|
||||
name = $"{name}[{GetSourceExpr(context, texOp.GetSource(srcIndex++), AggregateType.S32)}]";
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private static string GetImageName(ShaderProperties resourceDefinitions, AstTextureOperation texOp, string indexExpr)
|
||||
private static string GetImageName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex)
|
||||
{
|
||||
string name = resourceDefinitions.Images[texOp.Binding].Name;
|
||||
TextureDefinition definition = context.Properties.Images[texOp.Binding];
|
||||
string name = definition.Name;
|
||||
|
||||
if (texOp.Type.HasFlag(SamplerType.Indexed))
|
||||
if (definition.ArrayLength != 1)
|
||||
{
|
||||
name = $"{name}[{indexExpr}]";
|
||||
name = $"{name}[{GetSourceExpr(context, texOp.GetSource(srcIndex++), AggregateType.S32)}]";
|
||||
}
|
||||
|
||||
return name;
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
IAstNode src0 = operation.GetSource(0);
|
||||
IAstNode src1 = operation.GetSource(1);
|
||||
|
||||
string src0Expr = GetSoureExpr(context, src0, GetSrcVarType(operation.Inst, 0));
|
||||
string src1Expr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 1));
|
||||
string src0Expr = GetSourceExpr(context, src0, GetSrcVarType(operation.Inst, 0));
|
||||
string src1Expr = GetSourceExpr(context, src1, GetSrcVarType(operation.Inst, 1));
|
||||
|
||||
return $"packDouble2x32(uvec2({src0Expr}, {src1Expr}))";
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
IAstNode src0 = operation.GetSource(0);
|
||||
IAstNode src1 = operation.GetSource(1);
|
||||
|
||||
string src0Expr = GetSoureExpr(context, src0, GetSrcVarType(operation.Inst, 0));
|
||||
string src1Expr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 1));
|
||||
string src0Expr = GetSourceExpr(context, src0, GetSrcVarType(operation.Inst, 0));
|
||||
string src1Expr = GetSourceExpr(context, src1, GetSrcVarType(operation.Inst, 1));
|
||||
|
||||
return $"packHalf2x16(vec2({src0Expr}, {src1Expr}))";
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
IAstNode src = operation.GetSource(0);
|
||||
|
||||
string srcExpr = GetSoureExpr(context, src, GetSrcVarType(operation.Inst, 0));
|
||||
string srcExpr = GetSourceExpr(context, src, GetSrcVarType(operation.Inst, 0));
|
||||
|
||||
return $"unpackDouble2x32({srcExpr}){GetMask(operation.Index)}";
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
IAstNode src = operation.GetSource(0);
|
||||
|
||||
string srcExpr = GetSoureExpr(context, src, GetSrcVarType(operation.Inst, 0));
|
||||
string srcExpr = GetSourceExpr(context, src, GetSrcVarType(operation.Inst, 0));
|
||||
|
||||
return $"unpackHalf2x16({srcExpr}){GetMask(operation.Index)}";
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
{
|
||||
public static string Shuffle(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
string value = GetSoureExpr(context, operation.GetSource(0), AggregateType.FP32);
|
||||
string index = GetSoureExpr(context, operation.GetSource(1), AggregateType.U32);
|
||||
string value = GetSourceExpr(context, operation.GetSource(0), AggregateType.FP32);
|
||||
string index = GetSourceExpr(context, operation.GetSource(1), AggregateType.U32);
|
||||
|
||||
if (context.HostCapabilities.SupportsShaderBallot)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
IAstNode vector = operation.GetSource(0);
|
||||
IAstNode index = operation.GetSource(1);
|
||||
|
||||
string vectorExpr = GetSoureExpr(context, vector, OperandManager.GetNodeDestType(context, vector));
|
||||
string vectorExpr = GetSourceExpr(context, vector, OperandManager.GetNodeDestType(context, vector));
|
||||
|
||||
if (index is AstOperand indexOperand && indexOperand.Type == OperandType.Constant)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
string indexExpr = GetSoureExpr(context, index, GetSrcVarType(operation.Inst, 1));
|
||||
string indexExpr = GetSourceExpr(context, index, GetSrcVarType(operation.Inst, 1));
|
||||
|
||||
return $"{vectorExpr}[{indexExpr}]";
|
||||
}
|
||||
|
|
|
@ -146,9 +146,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
}
|
||||
else if (operation is AstTextureOperation texOp)
|
||||
{
|
||||
if (texOp.Inst == Instruction.ImageLoad ||
|
||||
texOp.Inst == Instruction.ImageStore ||
|
||||
texOp.Inst == Instruction.ImageAtomic)
|
||||
if (texOp.Inst.IsImage())
|
||||
{
|
||||
return texOp.GetVectorType(texOp.Format.GetComponentType());
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
public Dictionary<int, Instruction> SharedMemories { get; } = new();
|
||||
|
||||
public Dictionary<int, SamplerType> SamplersTypes { get; } = new();
|
||||
public Dictionary<int, (Instruction, Instruction, Instruction)> Samplers { get; } = new();
|
||||
public Dictionary<int, (Instruction, Instruction)> Images { get; } = new();
|
||||
public Dictionary<int, SamplerDeclaration> Samplers { get; } = new();
|
||||
public Dictionary<int, ImageDeclaration> Images { get; } = new();
|
||||
|
||||
public Dictionary<IoDefinition, Instruction> Inputs { get; } = new();
|
||||
public Dictionary<IoDefinition, Instruction> Outputs { get; } = new();
|
||||
|
|
|
@ -181,9 +181,27 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
var sampledImageType = context.TypeSampledImage(imageType);
|
||||
var sampledImagePointerType = context.TypePointer(StorageClass.UniformConstant, sampledImageType);
|
||||
var sampledImageVariable = context.Variable(sampledImagePointerType, StorageClass.UniformConstant);
|
||||
var sampledImageArrayPointerType = sampledImagePointerType;
|
||||
|
||||
context.Samplers.Add(sampler.Binding, (imageType, sampledImageType, sampledImageVariable));
|
||||
if (sampler.ArrayLength == 0)
|
||||
{
|
||||
var sampledImageArrayType = context.TypeRuntimeArray(sampledImageType);
|
||||
sampledImageArrayPointerType = context.TypePointer(StorageClass.UniformConstant, sampledImageArrayType);
|
||||
}
|
||||
else if (sampler.ArrayLength != 1)
|
||||
{
|
||||
var sampledImageArrayType = context.TypeArray(sampledImageType, context.Constant(context.TypeU32(), sampler.ArrayLength));
|
||||
sampledImageArrayPointerType = context.TypePointer(StorageClass.UniformConstant, sampledImageArrayType);
|
||||
}
|
||||
|
||||
var sampledImageVariable = context.Variable(sampledImageArrayPointerType, StorageClass.UniformConstant);
|
||||
|
||||
context.Samplers.Add(sampler.Binding, new SamplerDeclaration(
|
||||
imageType,
|
||||
sampledImageType,
|
||||
sampledImagePointerType,
|
||||
sampledImageVariable,
|
||||
sampler.ArrayLength != 1));
|
||||
context.SamplersTypes.Add(sampler.Binding, sampler.Type);
|
||||
|
||||
context.Name(sampledImageVariable, sampler.Name);
|
||||
|
@ -211,9 +229,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
GetImageFormat(image.Format));
|
||||
|
||||
var imagePointerType = context.TypePointer(StorageClass.UniformConstant, imageType);
|
||||
var imageVariable = context.Variable(imagePointerType, StorageClass.UniformConstant);
|
||||
var imageArrayPointerType = imagePointerType;
|
||||
|
||||
context.Images.Add(image.Binding, (imageType, imageVariable));
|
||||
if (image.ArrayLength == 0)
|
||||
{
|
||||
var imageArrayType = context.TypeRuntimeArray(imageType);
|
||||
imageArrayPointerType = context.TypePointer(StorageClass.UniformConstant, imageArrayType);
|
||||
}
|
||||
else if (image.ArrayLength != 1)
|
||||
{
|
||||
var imageArrayType = context.TypeArray(imageType, context.Constant(context.TypeU32(), image.ArrayLength));
|
||||
imageArrayPointerType = context.TypePointer(StorageClass.UniformConstant, imageArrayType);
|
||||
}
|
||||
|
||||
var imageVariable = context.Variable(imageArrayPointerType, StorageClass.UniformConstant);
|
||||
|
||||
context.Images.Add(image.Binding, new ImageDeclaration(imageType, imagePointerType, imageVariable, image.ArrayLength != 1));
|
||||
|
||||
context.Name(imageVariable, image.Name);
|
||||
context.Decorate(imageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex);
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
using Spv.Generator;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
readonly struct ImageDeclaration
|
||||
{
|
||||
public readonly Instruction ImageType;
|
||||
public readonly Instruction ImagePointerType;
|
||||
public readonly Instruction Image;
|
||||
public readonly bool IsIndexed;
|
||||
|
||||
public ImageDeclaration(Instruction imageType, Instruction imagePointerType, Instruction image, bool isIndexed)
|
||||
{
|
||||
ImageType = imageType;
|
||||
ImagePointerType = imagePointerType;
|
||||
Image = image;
|
||||
IsIndexed = isIndexed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -591,34 +591,28 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
var componentType = texOp.Format.GetComponentType();
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0/do nothing.
|
||||
if (isBindless)
|
||||
{
|
||||
return new OperationResult(componentType, componentType switch
|
||||
{
|
||||
AggregateType.S32 => context.Constant(context.TypeS32(), 0),
|
||||
AggregateType.U32 => context.Constant(context.TypeU32(), 0u),
|
||||
_ => context.Constant(context.TypeFP32(), 0f),
|
||||
});
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
SpvInstruction Src(AggregateType type)
|
||||
{
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
if (isIndexed)
|
||||
ImageDeclaration declaration = context.Images[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
SpvInstruction resultType = context.GetType(componentType);
|
||||
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
|
||||
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
Src(AggregateType.S32);
|
||||
SpvInstruction textureIndex = Src(AggregateType.S32);
|
||||
|
||||
image = context.AccessChain(imagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
|
@ -646,14 +640,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
SpvInstruction value = Src(componentType);
|
||||
|
||||
(var imageType, var imageVariable) = context.Images[texOp.Binding];
|
||||
|
||||
context.Load(imageType, imageVariable);
|
||||
|
||||
SpvInstruction resultType = context.GetType(componentType);
|
||||
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
|
||||
|
||||
var pointer = context.ImageTexelPointer(imagePointerType, imageVariable, pCoords, context.Constant(context.TypeU32(), 0));
|
||||
var pointer = context.ImageTexelPointer(imagePointerType, image, pCoords, context.Constant(context.TypeU32(), 0));
|
||||
var one = context.Constant(context.TypeU32(), 1);
|
||||
var zero = context.Constant(context.TypeU32(), 0);
|
||||
|
||||
|
@ -683,31 +670,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
var componentType = texOp.Format.GetComponentType();
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0/do nothing.
|
||||
if (isBindless)
|
||||
{
|
||||
return GetZeroOperationResult(context, texOp, componentType, isVector: true);
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
SpvInstruction Src(AggregateType type)
|
||||
{
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
if (isIndexed)
|
||||
ImageDeclaration declaration = context.Images[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
Src(AggregateType.S32);
|
||||
SpvInstruction textureIndex = Src(AggregateType.S32);
|
||||
|
||||
image = context.AccessChain(declaration.ImagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
image = context.Load(declaration.ImageType, image);
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
|
||||
int pCount = coordsCount + (isArray ? 1 : 0);
|
||||
|
@ -731,9 +716,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
pCoords = Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
(var imageType, var imageVariable) = context.Images[texOp.Binding];
|
||||
|
||||
var image = context.Load(imageType, imageVariable);
|
||||
var imageComponentType = context.GetType(componentType);
|
||||
var swizzledResultType = texOp.GetVectorType(componentType);
|
||||
|
||||
|
@ -747,29 +729,27 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0/do nothing.
|
||||
if (isBindless)
|
||||
{
|
||||
return OperationResult.Invalid;
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
SpvInstruction Src(AggregateType type)
|
||||
{
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
if (isIndexed)
|
||||
ImageDeclaration declaration = context.Images[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
Src(AggregateType.S32);
|
||||
SpvInstruction textureIndex = Src(AggregateType.S32);
|
||||
|
||||
image = context.AccessChain(declaration.ImagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
image = context.Load(declaration.ImageType, image);
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
|
||||
int pCount = coordsCount + (isArray ? 1 : 0);
|
||||
|
@ -818,10 +798,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
|
||||
|
||||
(var imageType, var imageVariable) = context.Images[texOp.Binding];
|
||||
|
||||
var image = context.Load(imageType, imageVariable);
|
||||
|
||||
context.ImageWrite(image, pCoords, texel, ImageOperandsMask.MaskNone);
|
||||
|
||||
return OperationResult.Invalid;
|
||||
|
@ -854,16 +830,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
{
|
||||
return new OperationResult(AggregateType.S32, context.Constant(context.TypeS32(), 0));
|
||||
}
|
||||
|
||||
int srcIndex = 0;
|
||||
|
||||
SpvInstruction Src(AggregateType type)
|
||||
|
@ -871,11 +837,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
if (isIndexed)
|
||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
Src(AggregateType.S32);
|
||||
SpvInstruction textureIndex = Src(AggregateType.S32);
|
||||
|
||||
image = context.AccessChain(declaration.SampledImagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
image = context.Load(declaration.SampledImageType, image);
|
||||
|
||||
int pCount = texOp.Type.GetDimensions();
|
||||
|
||||
SpvInstruction pCoords;
|
||||
|
@ -897,10 +870,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
pCoords = Src(AggregateType.FP32);
|
||||
}
|
||||
|
||||
(_, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
|
||||
var resultType = context.TypeVector(context.TypeFP32(), 2);
|
||||
var packed = context.ImageQueryLod(resultType, image, pCoords);
|
||||
var result = context.CompositeExtract(context.TypeFP32(), packed, (SpvLiteralInteger)texOp.Index);
|
||||
|
@ -1182,7 +1151,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
|
||||
bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
|
||||
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
|
||||
|
@ -1192,30 +1160,28 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
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 GetZeroOperationResult(context, texOp, AggregateType.FP32, colorIsVector);
|
||||
}
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
int srcIndex = 0;
|
||||
|
||||
SpvInstruction Src(AggregateType type)
|
||||
{
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
if (isIndexed)
|
||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
Src(AggregateType.S32);
|
||||
SpvInstruction textureIndex = Src(AggregateType.S32);
|
||||
|
||||
image = context.AccessChain(declaration.SampledImagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
image = context.Load(declaration.SampledImageType, image);
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
|
||||
int pCount = coordsCount;
|
||||
|
@ -1419,15 +1385,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
operandsList.Add(sample);
|
||||
}
|
||||
|
||||
bool colorIsVector = isGather || !isShadow;
|
||||
|
||||
var resultType = colorIsVector ? context.TypeVector(context.TypeFP32(), 4) : context.TypeFP32();
|
||||
|
||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
|
||||
if (intCoords)
|
||||
{
|
||||
image = context.Image(imageType, image);
|
||||
image = context.Image(declaration.ImageType, image);
|
||||
}
|
||||
|
||||
var operands = operandsList.ToArray();
|
||||
|
@ -1485,25 +1449,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
return new OperationResult(AggregateType.S32, context.Constant(context.TypeS32(), 0));
|
||||
SpvInstruction textureIndex = context.GetS32(texOp.GetSource(0));
|
||||
|
||||
image = context.AccessChain(declaration.SampledImagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
context.GetS32(texOp.GetSource(0));
|
||||
}
|
||||
|
||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
image = context.Image(imageType, image);
|
||||
image = context.Load(declaration.SampledImageType, image);
|
||||
image = context.Image(declaration.ImageType, image);
|
||||
|
||||
SpvInstruction result = context.ImageQuerySamples(context.TypeS32(), image);
|
||||
|
||||
|
@ -1514,25 +1471,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
||||
SpvInstruction image = declaration.Image;
|
||||
|
||||
// TODO: Bindless texture support. For now we just return 0.
|
||||
if (isBindless)
|
||||
if (declaration.IsIndexed)
|
||||
{
|
||||
return new OperationResult(AggregateType.S32, context.Constant(context.TypeS32(), 0));
|
||||
SpvInstruction textureIndex = context.GetS32(texOp.GetSource(0));
|
||||
|
||||
image = context.AccessChain(declaration.SampledImagePointerType, image, textureIndex);
|
||||
}
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
context.GetS32(texOp.GetSource(0));
|
||||
}
|
||||
|
||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
image = context.Image(imageType, image);
|
||||
image = context.Load(declaration.SampledImageType, image);
|
||||
image = context.Image(declaration.ImageType, image);
|
||||
|
||||
if (texOp.Index == 3)
|
||||
{
|
||||
|
@ -1556,7 +1506,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
|
||||
if (hasLod)
|
||||
{
|
||||
int lodSrcIndex = isBindless || isIndexed ? 1 : 0;
|
||||
int lodSrcIndex = declaration.IsIndexed ? 1 : 0;
|
||||
var lod = context.GetS32(operation.GetSource(lodSrcIndex));
|
||||
result = context.ImageQuerySizeLod(resultType, image, lod);
|
||||
}
|
||||
|
@ -1929,38 +1879,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||
return context.Load(context.GetType(varType), context.Inputs[ioDefinition]);
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
using Spv.Generator;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
readonly struct SamplerDeclaration
|
||||
{
|
||||
public readonly Instruction ImageType;
|
||||
public readonly Instruction SampledImageType;
|
||||
public readonly Instruction SampledImagePointerType;
|
||||
public readonly Instruction Image;
|
||||
public readonly bool IsIndexed;
|
||||
|
||||
public SamplerDeclaration(
|
||||
Instruction imageType,
|
||||
Instruction sampledImageType,
|
||||
Instruction sampledImagePointerType,
|
||||
Instruction image,
|
||||
bool isIndexed)
|
||||
{
|
||||
ImageType = imageType;
|
||||
SampledImageType = sampledImageType;
|
||||
SampledImagePointerType = sampledImagePointerType;
|
||||
Image = image;
|
||||
IsIndexed = isIndexed;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue