diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-10-12 21:40:50 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-12 21:40:50 -0300 |
| commit | b066cfc1a3e31bf7197ddbd0f4d774b886cd9d65 (patch) | |
| tree | 95a1d0bb640948c184857fd1bccb56cad90839fb /Ryujinx.Graphics.Shader/CodeGen | |
| parent | 14fd9aa640936d2455c9f0929fc904a5bdb2fada (diff) | |
Add support for shader constant buffer slot indexing (#1608)
* Add support for shader constant buffer slot indexing
* Fix typo
Diffstat (limited to 'Ryujinx.Graphics.Shader/CodeGen')
6 files changed, 99 insertions, 56 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs index 91ab7ad5..50b9bc9f 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs @@ -12,6 +12,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl public ShaderConfig Config { get; } + public bool CbIndexable { get; } + public List<BufferDescriptor> CBufferDescriptors { get; } public List<BufferDescriptor> SBufferDescriptors { get; } public List<TextureDescriptor> TextureDescriptors { get; } @@ -25,9 +27,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private string _indentation; - public CodeGenContext(ShaderConfig config) + public CodeGenContext(ShaderConfig config, bool cbIndexable) { Config = config; + CbIndexable = cbIndexable; CBufferDescriptors = new List<BufferDescriptor>(); SBufferDescriptors = new List<BufferDescriptor>(); @@ -85,9 +88,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl int cBufSlot = bindless ? operand.CbufSlot : 0; int cBufOffset = bindless ? operand.CbufOffset : 0; - return TextureDescriptors.FindIndex(descriptor => - descriptor.Type == texOp.Type && - descriptor.HandleIndex == texOp.Handle && + return TextureDescriptors.FindIndex(descriptor => + descriptor.Type == texOp.Type && + descriptor.HandleIndex == texOp.Handle && descriptor.CbufSlot == cBufSlot && descriptor.CbufOffset == cBufOffset); } diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs index a7b67a60..cd82aa02 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs @@ -213,51 +213,57 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private static void DeclareUniforms(CodeGenContext context, StructuredProgramInfo info) { - foreach (int cbufSlot in info.CBuffers.OrderBy(x => x)) + string ubSize = "[" + NumberFormatter.FormatInt(Constants.ConstantBufferSize / 16) + "]"; + + if (info.UsesCbIndexing) { string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage); - ubName += "_" + DefaultNames.UniformNamePrefix + cbufSlot; + ubName += "_" + DefaultNames.UniformNamePrefix; + + string blockName = $"{ubName}_{DefaultNames.BlockSuffix}"; + + int maxSlot = 0; + + foreach (int cbufSlot in info.CBuffers.OrderBy(x => x)) + { + context.CBufferDescriptors.Add(new BufferDescriptor($"{blockName}[{cbufSlot}]", cbufSlot)); - context.CBufferDescriptors.Add(new BufferDescriptor(ubName, cbufSlot)); + if (maxSlot < cbufSlot) + { + maxSlot = cbufSlot; + } + } - context.AppendLine("layout (std140) uniform " + ubName); + context.AppendLine("layout (std140) uniform " + blockName); context.EnterScope(); - string ubSize = "[" + NumberFormatter.FormatInt(Constants.ConstantBufferSize / 16) + "]"; + context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";"); - context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, cbufSlot) + ubSize + ";"); + string arraySize = NumberFormatter.FormatInt(maxSlot + 1); - context.LeaveScope(";"); + context.LeaveScope($" {ubName}[{arraySize}];"); } - } - - private static bool DeclareRenderScale(CodeGenContext context) - { - if ((context.Config.UsedFeatures & (FeatureFlags.FragCoordXY | FeatureFlags.IntegerSampling)) != 0) + else { - string stage = OperandManager.GetShaderStagePrefix(context.Config.Stage); + foreach (int cbufSlot in info.CBuffers.OrderBy(x => x)) + { + string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage); - int scaleElements = context.TextureDescriptors.Count; + ubName += "_" + DefaultNames.UniformNamePrefix + cbufSlot; - if (context.Config.Stage == ShaderStage.Fragment) - { - scaleElements++; // Also includes render target scale, for gl_FragCoord. - } + context.CBufferDescriptors.Add(new BufferDescriptor(ubName, cbufSlot)); - context.AppendLine($"uniform float {stage}_renderScale[{scaleElements}];"); + context.AppendLine("layout (std140) uniform " + ubName); - if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling)) - { - context.AppendLine(); - AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl"); - } + context.EnterScope(); - return true; - } + context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, cbufSlot, false) + ubSize + ";"); - return false; + context.LeaveScope(";"); + } + } } private static void DeclareStorages(CodeGenContext context, StructuredProgramInfo info) @@ -500,6 +506,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } + private static bool DeclareRenderScale(CodeGenContext context) + { + if ((context.Config.UsedFeatures & (FeatureFlags.FragCoordXY | FeatureFlags.IntegerSampling)) != 0) + { + string stage = OperandManager.GetShaderStagePrefix(context.Config.Stage); + + int scaleElements = context.TextureDescriptors.Count; + + if (context.Config.Stage == ShaderStage.Fragment) + { + scaleElements++; // Also includes render target scale, for gl_FragCoord. + } + + context.AppendLine($"uniform float {stage}_renderScale[{scaleElements}];"); + + if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling)) + { + context.AppendLine(); + AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl"); + } + + return true; + } + + return false; + } + private static void AppendHelperFunction(CodeGenContext context, string filename) { string code = EmbeddedResources.ReadAllText(filename); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs index 673fe6a3..00a32262 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { public static GlslProgram Generate(StructuredProgramInfo info, ShaderConfig config) { - CodeGenContext context = new CodeGenContext(config); + CodeGenContext context = new CodeGenContext(config, info.UsesCbIndexing); Declarations.Declare(context, info); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs index 551fb229..f1c741e6 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions } else if (node is AstOperand operand) { - return context.OperandManager.GetExpression(operand, context.Config); + return context.OperandManager.GetExpression(operand, context.Config, context.CbIndexable); } throw new ArgumentException($"Invalid node type \"{node?.GetType().Name ?? "null"}\"."); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs index 8866cd25..cb339f05 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs @@ -125,7 +125,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions offsetExpr = Enclose(offsetExpr, src2, Instruction.ShiftRightS32, isLhs: true); - return OperandManager.GetConstantBufferName(src1, offsetExpr, context.Config.Stage); + if (src1 is AstOperand oper && oper.Type == OperandType.Constant) + { + return OperandManager.GetConstantBufferName(oper.Value, offsetExpr, context.Config.Stage, context.CbIndexable); + } + else + { + string slotExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0)); + + return OperandManager.GetConstantBufferName(slotExpr, offsetExpr, context.Config.Stage); + } } public static string LoadLocal(CodeGenContext context, AstOperation operation) diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs index e04ce649..d6f30b48 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs @@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return name; } - public string GetExpression(AstOperand operand, ShaderConfig config) + public string GetExpression(AstOperand operand, ShaderConfig config, bool cbIndexable) { switch (operand.Type) { @@ -103,7 +103,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return NumberFormatter.FormatInt(operand.Value); case OperandType.ConstantBuffer: - return GetConstantBufferName(operand.CbufSlot, operand.CbufOffset, config.Stage); + return GetConstantBufferName(operand.CbufSlot, operand.CbufOffset, config.Stage, cbIndexable); case OperandType.LocalVariable: return _locals[operand]; @@ -115,13 +115,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."); } - public static string GetConstantBufferName(int slot, int offset, ShaderStage stage) + public static string GetConstantBufferName(int slot, int offset, ShaderStage stage, bool cbIndexable) { - string ubName = GetUbName(stage, slot); - - ubName += "[" + (offset >> 2) + "]"; - - return ubName + "." + GetSwizzleMask(offset & 3); + return $"{GetUbName(stage, slot, cbIndexable)}[{offset >> 2}].{GetSwizzleMask(offset & 3)}"; } private static string GetVec4Indexed(string vectorName, string indexExpr) @@ -134,18 +130,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return $"({result})"; } - public static string GetConstantBufferName(IAstNode slot, string offsetExpr, ShaderStage stage) + public static string GetConstantBufferName(int slot, string offsetExpr, ShaderStage stage, bool cbIndexable) { - // Non-constant slots are not supported. - // It is expected that upstream stages are never going to generate non-constant - // slot access. - AstOperand operand = (AstOperand)slot; - - string ubName = GetUbName(stage, operand.Value); - - string index0 = "[" + offsetExpr + " >> 2]"; + return GetVec4Indexed(GetUbName(stage, slot, cbIndexable) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3"); + } - return GetVec4Indexed(ubName + index0, offsetExpr + " & 3"); + public static string GetConstantBufferName(string slotExpr, string offsetExpr, ShaderStage stage) + { + return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3"); } public static string GetOutAttributeName(AstOperand attr, ShaderConfig config) @@ -228,13 +220,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl return isOutAttr ? "// bad_attr0x" + value.ToString("X") : "0.0"; } - public static string GetUbName(ShaderStage stage, int slot) + public static string GetUbName(ShaderStage stage, int slot, bool cbIndexable) { - string ubName = GetShaderStagePrefix(stage); + if (cbIndexable) + { + return GetUbName(stage, NumberFormatter.FormatInt(slot, VariableType.S32)); + } - ubName += "_" + DefaultNames.UniformNamePrefix + slot; + return $"{GetShaderStagePrefix(stage)}_{DefaultNames.UniformNamePrefix}{slot}_{DefaultNames.UniformNameSuffix}"; + } - return ubName + "_" + DefaultNames.UniformNameSuffix; + private static string GetUbName(ShaderStage stage, string slotExpr) + { + return $"{GetShaderStagePrefix(stage)}_{DefaultNames.UniformNamePrefix}[{slotExpr}].{DefaultNames.DataName}"; } public static string GetSamplerName(ShaderStage stage, AstTextureOperation texOp, string indexExpr) |
