aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/CodeGen
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-10-12 21:40:50 -0300
committerGitHub <noreply@github.com>2020-10-12 21:40:50 -0300
commitb066cfc1a3e31bf7197ddbd0f4d774b886cd9d65 (patch)
tree95a1d0bb640948c184857fd1bccb56cad90839fb /Ryujinx.Graphics.Shader/CodeGen
parent14fd9aa640936d2455c9f0929fc904a5bdb2fada (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')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/CodeGenContext.cs11
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs87
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs2
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs2
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs11
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs42
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)