diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2024-04-07 18:25:55 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-07 18:25:55 -0300 |
| commit | 3e6e0e4afaa3c3ffb118cb17b61feb16966a7eeb (patch) | |
| tree | a4652499c089b0853e39c382cad82a9db4d6ad08 /src/Ryujinx.Graphics.Shader/CodeGen | |
| parent | 808803d97a0c06809bf000687c252f960048fcf0 (diff) | |
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
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/CodeGen')
15 files changed, 220 insertions, 349 deletions
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index 500de71f..763487da 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -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};"); } } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs index eb0cb92d..9e7f64b0 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs @@ -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; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs index 6cc7048b..000d7f79 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs @@ -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) diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenCall.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenCall.cs index 0618ba8a..d5448856 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenCall.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenCall.cs @@ -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)})"; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs index 5c2d16f4..4b28f387 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs @@ -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); } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 2e90bd16..b4773b81 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -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); - } - - string indexExpr = null; - - if (isIndexed) - { - indexExpr = Src(AggregateType.S32); + return GetSourceExpr(context, texOp.GetSource(srcIndex++), type); } - 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; - - // 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); - } + int srcIndex = 0; - 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; - - // 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); - } + int srcIndex = 0; - 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; diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs index ad84c485..4469785d 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenPacking.cs @@ -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)}"; } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenShuffle.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenShuffle.cs index 6d3859ef..b72b94d9 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenShuffle.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenShuffle.cs @@ -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) { diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs index 70174a5b..a300c775 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenVector.cs @@ -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}]"; } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index 53ecc453..a350b089 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -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()); } diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs index 17c3eefe..2b1fdf44 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs @@ -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(); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs index b7482425..9633c522 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs @@ -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; + + 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, (imageType, imageVariable)); + 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); diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ImageDeclaration.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ImageDeclaration.cs new file mode 100644 index 00000000..1e0aee73 --- /dev/null +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ImageDeclaration.cs @@ -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; + } + } +} diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index 601753cb..409e466c 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -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); } - var resultType = colorIsVector ? context.TypeVector(context.TypeFP32(), 4) : context.TypeFP32(); - - (var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding]; + bool colorIsVector = isGather || !isShadow; - var image = context.Load(sampledImageType, sampledImageVariable); + var resultType = colorIsVector ? context.TypeVector(context.TypeFP32(), 4) : context.TypeFP32(); 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)); - } - - bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; + SpvInstruction textureIndex = context.GetS32(texOp.GetSource(0)); - if (isIndexed) - { - context.GetS32(texOp.GetSource(0)); + image = context.AccessChain(declaration.SampledImagePointerType, image, textureIndex); } - (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)); - } - - bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; + SpvInstruction textureIndex = context.GetS32(texOp.GetSource(0)); - if (isIndexed) - { - context.GetS32(texOp.GetSource(0)); + image = context.AccessChain(declaration.SampledImagePointerType, image, textureIndex); } - (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) diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SamplerDeclaration.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SamplerDeclaration.cs new file mode 100644 index 00000000..9e0ecd79 --- /dev/null +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SamplerDeclaration.cs @@ -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; + } + } +} |
