aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/CodeGen')
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs94
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs10
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl4
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl4
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl4
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs3
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs1
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs98
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs3
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs67
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs30
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs129
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs193
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ScalingHelpers.cs8
14 files changed, 211 insertions, 437 deletions
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 81b79ec4..8d805e32 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -3,6 +3,7 @@ using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Numerics;
@@ -102,13 +103,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine();
}
- var cBufferDescriptors = context.Config.GetConstantBufferDescriptors();
- if (cBufferDescriptors.Length != 0)
- {
- DeclareUniforms(context, cBufferDescriptors);
-
- context.AppendLine();
- }
+ DeclareConstantBuffers(context, context.Config.Properties.ConstantBuffers.Values);
var sBufferDescriptors = context.Config.GetStorageBufferDescriptors();
if (sBufferDescriptors.Length != 0)
@@ -265,18 +260,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
scaleElements++; // Also includes render target scale, for gl_FragCoord.
}
- DeclareSupportUniformBlock(context, context.Config.Stage, scaleElements);
-
if (context.Config.UsedFeatures.HasFlag(FeatureFlags.IntegerSampling) && scaleElements != 0)
{
AppendHelperFunction(context, $"Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_{stage}.glsl");
context.AppendLine();
}
}
- else if (isFragment || context.Config.Stage == ShaderStage.Vertex)
- {
- DeclareSupportUniformBlock(context, context.Config.Stage, 0);
- }
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0)
@@ -389,36 +378,38 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
};
}
- private static void DeclareUniforms(CodeGenContext context, BufferDescriptor[] descriptors)
+ private static void DeclareConstantBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers)
{
- string ubSize = "[" + NumberFormatter.FormatInt(Constants.ConstantBufferSize / 16) + "]";
-
- if (context.Config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing))
+ foreach (BufferDefinition buffer in buffers)
{
- string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
-
- ubName += "_" + DefaultNames.UniformNamePrefix;
-
- string blockName = $"{ubName}_{DefaultNames.BlockSuffix}";
+ string layout = buffer.Layout switch
+ {
+ BufferLayout.Std140 => "std140",
+ _ => "std430"
+ };
- context.AppendLine($"layout (binding = {context.Config.FirstConstantBufferBinding}, std140) uniform {blockName}");
+ context.AppendLine($"layout (binding = {buffer.Binding}, {layout}) uniform _{buffer.Name}");
context.EnterScope();
- context.AppendLine("vec4 " + DefaultNames.DataName + ubSize + ";");
- context.LeaveScope($" {ubName}[{NumberFormatter.FormatInt(descriptors.Max(x => x.Slot) + 1)}];");
- }
- else
- {
- foreach (var descriptor in descriptors)
+
+ foreach (StructureField field in buffer.Type.Fields)
{
- string ubName = OperandManager.GetShaderStagePrefix(context.Config.Stage);
+ if (field.Type.HasFlag(AggregateType.Array))
+ {
+ string typeName = GetVarTypeName(context, field.Type & ~AggregateType.Array);
+ string arraySize = field.ArrayLength.ToString(CultureInfo.InvariantCulture);
- ubName += "_" + DefaultNames.UniformNamePrefix + descriptor.Slot;
+ context.AppendLine($"{typeName} {field.Name}[{arraySize}];");
+ }
+ else
+ {
+ string typeName = GetVarTypeName(context, field.Type);
- context.AppendLine($"layout (binding = {descriptor.Binding}, std140) uniform {ubName}");
- context.EnterScope();
- context.AppendLine("vec4 " + OperandManager.GetUbName(context.Config.Stage, descriptor.Slot, false) + ubSize + ";");
- context.LeaveScope(";");
+ context.AppendLine($"{typeName} {field.Name};");
+ }
}
+
+ context.LeaveScope($" {buffer.Name};");
+ context.AppendLine();
}
}
@@ -759,39 +750,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine($"layout (location = {location}) patch out vec4 {name};");
}
- private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements)
- {
- bool needsSupportBlock = stage == ShaderStage.Fragment ||
- (context.Config.LastInVertexPipeline && context.Config.GpuAccessor.QueryViewportTransformDisable());
-
- if (!needsSupportBlock && scaleElements == 0)
- {
- return;
- }
-
- context.AppendLine($"layout (binding = 0, std140) uniform {DefaultNames.SupportBlockName}");
- context.EnterScope();
-
- switch (stage)
- {
- case ShaderStage.Fragment:
- case ShaderStage.Vertex:
- context.AppendLine($"uint {DefaultNames.SupportBlockAlphaTestName};");
- context.AppendLine($"bool {DefaultNames.SupportBlockIsBgraName}[{SupportBuffer.FragmentIsBgraCount}];");
- context.AppendLine($"vec4 {DefaultNames.SupportBlockViewportInverse};");
- context.AppendLine($"int {DefaultNames.SupportBlockFragmentScaleCount};");
- break;
- case ShaderStage.Compute:
- context.AppendLine($"uint s_reserved[{SupportBuffer.ComputeRenderScaleOffset / SupportBuffer.FieldSize}];");
- break;
- }
-
- context.AppendLine($"float {DefaultNames.SupportBlockRenderScaleName}[{SupportBuffer.RenderScaleMaxCount}];");
-
- context.LeaveScope(";");
- context.AppendLine();
- }
-
private static void AppendHelperFunction(CodeGenContext context, string filename)
{
string code = EmbeddedResources.ReadAllText(filename);
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
index 3ab4814c..fc3004a8 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/DefaultNames.cs
@@ -15,18 +15,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public const string DataName = "data";
- public const string SupportBlockName = "support_block";
- public const string SupportBlockAlphaTestName = "s_alpha_test";
- public const string SupportBlockIsBgraName = "s_is_bgra";
- public const string SupportBlockViewportInverse = "s_viewport_inverse";
- public const string SupportBlockFragmentScaleCount = "s_frag_scale_count";
- public const string SupportBlockRenderScaleName = "s_render_scale";
-
public const string BlockSuffix = "block";
- public const string UniformNamePrefix = "c";
- public const string UniformNameSuffix = "data";
-
public const string LocalMemoryName = "local_mem";
public const string SharedMemoryName = "shared_mem";
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl
index 4ebade5e..08c62548 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_cp.glsl
@@ -1,6 +1,6 @@
ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex)
{
- float scale = s_render_scale[samplerIndex];
+ float scale = support_buffer.s_render_scale[1 + samplerIndex];
if (scale == 1.0)
{
return inputVec;
@@ -10,7 +10,7 @@
int Helper_TextureSizeUnscale(int size, int samplerIndex)
{
- float scale = s_render_scale[samplerIndex];
+ float scale = support_buffer.s_render_scale[1 + samplerIndex];
if (scale == 1.0)
{
return size;
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl
index 6c670f91..07a38a7a 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_fp.glsl
@@ -1,6 +1,6 @@
ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex)
{
- float scale = s_render_scale[1 + samplerIndex];
+ float scale = support_buffer.s_render_scale[1 + samplerIndex];
if (scale == 1.0)
{
return inputVec;
@@ -17,7 +17,7 @@
int Helper_TextureSizeUnscale(int size, int samplerIndex)
{
- float scale = abs(s_render_scale[1 + samplerIndex]);
+ float scale = abs(support_buffer.s_render_scale[1 + samplerIndex]);
if (scale == 1.0)
{
return size;
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl
index 19eb119d..72baa441 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/TexelFetchScale_vp.glsl
@@ -1,6 +1,6 @@
ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex)
{
- float scale = abs(s_render_scale[1 + samplerIndex + s_frag_scale_count]);
+ float scale = abs(support_buffer.s_render_scale[1 + samplerIndex + support_buffer.s_frag_scale_count]);
if (scale == 1.0)
{
return inputVec;
@@ -11,7 +11,7 @@
int Helper_TextureSizeUnscale(int size, int samplerIndex)
{
- float scale = abs(s_render_scale[1 + samplerIndex + s_frag_scale_count]);
+ float scale = abs(support_buffer.s_render_scale[1 + samplerIndex + support_buffer.s_frag_scale_count]);
if (scale == 1.0)
{
return size;
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
index 01bd11e5..24ea66d0 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
@@ -167,9 +167,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case Instruction.Load:
return Load(context, operation);
- case Instruction.LoadConstant:
- return LoadConstant(context, operation);
-
case Instruction.LoadLocal:
return LoadLocal(context, operation);
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index 00478f6a..71e40fe7 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
@@ -83,7 +83,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.ImageAtomic, InstType.Special);
Add(Instruction.IsNan, InstType.CallUnary, "isnan");
Add(Instruction.Load, InstType.Special);
- Add(Instruction.LoadConstant, InstType.Special);
Add(Instruction.LoadLocal, InstType.Special);
Add(Instruction.LoadShared, InstType.Special);
Add(Instruction.LoadStorage, InstType.Special);
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
index 99519837..ef5260d1 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenMemory.cs
@@ -215,29 +215,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return GenerateLoadOrStore(context, operation, isStore: false);
}
- public static string LoadConstant(CodeGenContext context, AstOperation operation)
- {
- IAstNode src1 = operation.GetSource(0);
- IAstNode src2 = operation.GetSource(1);
-
- string offsetExpr = GetSoureExpr(context, src2, GetSrcVarType(operation.Inst, 1));
- offsetExpr = Enclose(offsetExpr, src2, Instruction.ShiftRightS32, isLhs: true);
-
- var config = context.Config;
- bool indexElement = !config.GpuAccessor.QueryHostHasVectorIndexingBug();
-
- if (src1 is AstOperand operand && operand.Type == OperandType.Constant)
- {
- bool cbIndexable = config.UsedFeatures.HasFlag(Translation.FeatureFlags.CbIndexing);
- return OperandManager.GetConstantBufferName(operand.Value, offsetExpr, config.Stage, cbIndexable, indexElement);
- }
- else
- {
- string slotExpr = GetSoureExpr(context, src1, GetSrcVarType(operation.Inst, 0));
- return OperandManager.GetConstantBufferName(slotExpr, offsetExpr, config.Stage, indexElement);
- }
- }
-
public static string LoadLocal(CodeGenContext context, AstOperation operation)
{
return LoadLocalOrShared(context, operation, DefaultNames.LocalMemoryName);
@@ -809,9 +786,29 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string varName;
AggregateType varType;
int srcIndex = 0;
+ int inputsCount = isStore ? operation.SourcesCount - 1 : operation.SourcesCount;
switch (storageKind)
{
+ case StorageKind.ConstantBuffer:
+ if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
+ }
+
+ int binding = bindingIndex.Value;
+ BufferDefinition buffer = context.Config.Properties.ConstantBuffers[binding];
+
+ if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
+ }
+
+ StructureField field = buffer.Type.Fields[fieldIndex.Value];
+ varName = $"{buffer.Name}.{field.Name}";
+ varType = field.Type;
+ break;
+
case StorageKind.Input:
case StorageKind.InputPerPatch:
case StorageKind.Output:
@@ -864,40 +861,39 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
varName = $"gl_out[{expr}].{varName}";
}
}
-
- int firstSrcIndex = srcIndex;
- int inputsCount = isStore ? operation.SourcesCount - 1 : operation.SourcesCount;
-
- for (; srcIndex < inputsCount; srcIndex++)
- {
- IAstNode src = operation.GetSource(srcIndex);
-
- if ((varType & AggregateType.ElementCountMask) != 0 &&
- srcIndex == inputsCount - 1 &&
- src is AstOperand elementIndex &&
- elementIndex.Type == OperandType.Constant)
- {
- varName += "." + "xyzw"[elementIndex.Value & 3];
- }
- else if (srcIndex == firstSrcIndex && context.Config.Stage == ShaderStage.TessellationControl && storageKind == StorageKind.Output)
- {
- // GLSL requires that for tessellation control shader outputs,
- // that the index expression must be *exactly* "gl_InvocationID",
- // otherwise the compilation fails.
- // TODO: Get rid of this and use expression propagation to make sure we generate the correct code from IR.
- varName += "[gl_InvocationID]";
- }
- else
- {
- varName += $"[{GetSoureExpr(context, src, AggregateType.S32)}]";
- }
- }
break;
default:
throw new InvalidOperationException($"Invalid storage kind {storageKind}.");
}
+ int firstSrcIndex = srcIndex;
+
+ for (; srcIndex < inputsCount; srcIndex++)
+ {
+ IAstNode src = operation.GetSource(srcIndex);
+
+ if ((varType & AggregateType.ElementCountMask) != 0 &&
+ srcIndex == inputsCount - 1 &&
+ src is AstOperand elementIndex &&
+ elementIndex.Type == OperandType.Constant)
+ {
+ varName += "." + "xyzw"[elementIndex.Value & 3];
+ }
+ else if (srcIndex == firstSrcIndex && context.Config.Stage == ShaderStage.TessellationControl && storageKind == StorageKind.Output)
+ {
+ // GLSL requires that for tessellation control shader outputs,
+ // that the index expression must be *exactly* "gl_InvocationID",
+ // otherwise the compilation fails.
+ // TODO: Get rid of this and use expression propagation to make sure we generate the correct code from IR.
+ varName += "[gl_InvocationID]";
+ }
+ else
+ {
+ varName += $"[{GetSoureExpr(context, src, AggregateType.S32)}]";
+ }
+ }
+
if (isStore)
{
varType &= AggregateType.ElementTypeMask;
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs
index 093ee232..2a73b8b0 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/IoMap.cs
@@ -27,7 +27,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
IoVariable.FragmentCoord => ("gl_FragCoord", AggregateType.Vector4 | AggregateType.FP32),
IoVariable.FragmentOutputColor => GetFragmentOutputColorVariableName(config, location),
IoVariable.FragmentOutputDepth => ("gl_FragDepth", AggregateType.FP32),
- IoVariable.FragmentOutputIsBgra => (DefaultNames.SupportBlockIsBgraName, AggregateType.Array | AggregateType.Bool),
IoVariable.FrontColorDiffuse => ("gl_FrontColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
IoVariable.FrontFacing => ("gl_FrontFacing", AggregateType.Bool),
@@ -46,8 +45,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
IoVariable.SubgroupLaneId => GetSubgroupInvocationIdVariableName(config),
IoVariable.SubgroupLeMask => GetSubgroupMaskVariableName(config, "Le"),
IoVariable.SubgroupLtMask => GetSubgroupMaskVariableName(config, "Lt"),
- IoVariable.SupportBlockRenderScale => (DefaultNames.SupportBlockRenderScaleName, AggregateType.Array | AggregateType.FP32),
- IoVariable.SupportBlockViewInverse => (DefaultNames.SupportBlockViewportInverse, AggregateType.Vector2 | AggregateType.FP32),
IoVariable.TessellationCoord => ("gl_TessCoord", AggregateType.Vector3 | AggregateType.FP32),
IoVariable.TessellationLevelInner => ("gl_TessLevelInner", AggregateType.Array | AggregateType.FP32),
IoVariable.TessellationLevelOuter => ("gl_TessLevelOuter", AggregateType.Array | AggregateType.FP32),
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index 92e83358..e34e4e07 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -36,63 +36,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
OperandType.Argument => GetArgumentName(operand.Value),
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
- OperandType.ConstantBuffer => GetConstantBufferName(operand, context.Config),
OperandType.LocalVariable => _locals[operand],
OperandType.Undefined => DefaultNames.UndefinedName,
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
};
}
- private static string GetConstantBufferName(AstOperand operand, ShaderConfig config)
- {
- return GetConstantBufferName(operand.CbufSlot, operand.CbufOffset, config.Stage, config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing));
- }
-
- public static string GetConstantBufferName(int slot, int offset, ShaderStage stage, bool cbIndexable)
- {
- return $"{GetUbName(stage, slot, cbIndexable)}[{offset >> 2}].{GetSwizzleMask(offset & 3)}";
- }
-
- private static string GetVec4Indexed(string vectorName, string indexExpr, bool indexElement)
- {
- if (indexElement)
- {
- return $"{vectorName}[{indexExpr}]";
- }
-
- string result = $"{vectorName}.x";
- for (int i = 1; i < 4; i++)
- {
- result = $"(({indexExpr}) == {i}) ? ({vectorName}.{GetSwizzleMask(i)}) : ({result})";
- }
- return $"({result})";
- }
-
- public static string GetConstantBufferName(int slot, string offsetExpr, ShaderStage stage, bool cbIndexable, bool indexElement)
- {
- return GetVec4Indexed(GetUbName(stage, slot, cbIndexable) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
- }
-
- public static string GetConstantBufferName(string slotExpr, string offsetExpr, ShaderStage stage, bool indexElement)
- {
- return GetVec4Indexed(GetUbName(stage, slotExpr) + $"[{offsetExpr} >> 2]", offsetExpr + " & 3", indexElement);
- }
-
- public static string GetUbName(ShaderStage stage, int slot, bool cbIndexable)
- {
- if (cbIndexable)
- {
- return GetUbName(stage, NumberFormatter.FormatInt(slot, AggregateType.S32));
- }
-
- return $"{GetShaderStagePrefix(stage)}_{DefaultNames.UniformNamePrefix}{slot}_{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)
{
return GetSamplerName(stage, texOp.CbufSlot, texOp.Handle, texOp.Type.HasFlag(SamplerType.Indexed), indexExpr);
@@ -168,6 +117,22 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
switch (operation.StorageKind)
{
+ case StorageKind.ConstantBuffer:
+ if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
+ }
+
+ if (!(operation.GetSource(1) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
+ }
+
+ BufferDefinition buffer = context.Config.Properties.ConstantBuffers[bindingIndex.Value];
+ StructureField field = buffer.Type.Fields[fieldIndex.Value];
+
+ return field.Type & AggregateType.ElementTypeMask;
+
case StorageKind.Input:
case StorageKind.InputPerPatch:
case StorageKind.Output:
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
index ed292ef1..0ef89b39 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
@@ -23,9 +23,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public int InputVertices { get; }
- public Dictionary<int, Instruction> UniformBuffers { get; } = new Dictionary<int, Instruction>();
- public Instruction SupportBuffer { get; set; }
- public Instruction UniformBuffersArray { get; set; }
+ public Dictionary<int, Instruction> ConstantBuffers { get; } = new Dictionary<int, Instruction>();
public Instruction StorageBuffersArray { get; set; }
public Instruction LocalMemory { get; set; }
public Instruction SharedMemory { get; set; }
@@ -217,7 +215,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
IrOperandType.Argument => GetArgument(type, operand),
IrOperandType.Constant => GetConstant(type, operand),
- IrOperandType.ConstantBuffer => GetConstantBuffer(type, operand),
IrOperandType.LocalVariable => GetLocal(type, operand),
IrOperandType.Undefined => GetUndefined(type),
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
@@ -274,31 +271,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
};
}
- public Instruction GetConstantBuffer(AggregateType type, AstOperand operand)
- {
- var i1 = Constant(TypeS32(), 0);
- var i2 = Constant(TypeS32(), operand.CbufOffset >> 2);
- var i3 = Constant(TypeU32(), operand.CbufOffset & 3);
-
- Instruction elemPointer;
-
- if (UniformBuffersArray != null)
- {
- var ubVariable = UniformBuffersArray;
- var i0 = Constant(TypeS32(), operand.CbufSlot);
-
- elemPointer = AccessChain(TypePointer(StorageClass.Uniform, TypeFP32()), ubVariable, i0, i1, i2, i3);
- }
- else
- {
- var ubVariable = UniformBuffers[operand.CbufSlot];
-
- elemPointer = AccessChain(TypePointer(StorageClass.Uniform, TypeFP32()), ubVariable, i1, i2, i3);
- }
-
- return BitcastIfNeeded(type, AggregateType.FP32, Load(TypeFP32(), elemPointer));
- }
-
public Instruction GetLocalPointer(AstOperand local)
{
return _locals[local];
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
index 821da477..7c242589 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs
@@ -98,8 +98,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
DeclareLocalMemory(context, localMemorySize);
}
- DeclareSupportBuffer(context);
- DeclareUniformBuffers(context, context.Config.GetConstantBufferDescriptors());
+ DeclareConstantBuffers(context, context.Config.Properties.ConstantBuffers.Values);
DeclareStorageBuffers(context, context.Config.GetStorageBufferDescriptors());
DeclareSamplers(context, context.Config.GetTextureDescriptors());
DeclareImages(context, context.Config.GetImageDescriptors());
@@ -127,84 +126,63 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return variable;
}
- private static void DeclareSupportBuffer(CodeGenContext context)
+ private static void DeclareConstantBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers)
{
- if (!context.Config.Stage.SupportsRenderScale() && !(context.Config.LastInVertexPipeline && context.Config.GpuAccessor.QueryViewportTransformDisable()))
- {
- return;
- }
-
- var isBgraArrayType = context.TypeArray(context.TypeU32(), context.Constant(context.TypeU32(), SupportBuffer.FragmentIsBgraCount));
- var viewportInverseVectorType = context.TypeVector(context.TypeFP32(), 4);
- var renderScaleArrayType = context.TypeArray(context.TypeFP32(), context.Constant(context.TypeU32(), SupportBuffer.RenderScaleMaxCount));
-
- context.Decorate(isBgraArrayType, Decoration.ArrayStride, (LiteralInteger)SupportBuffer.FieldSize);
- context.Decorate(renderScaleArrayType, Decoration.ArrayStride, (LiteralInteger)SupportBuffer.FieldSize);
-
- var supportBufferStructType = context.TypeStruct(false, context.TypeU32(), isBgraArrayType, viewportInverseVectorType, context.TypeS32(), renderScaleArrayType);
+ HashSet<SpvInstruction> decoratedTypes = new HashSet<SpvInstruction>();
- context.MemberDecorate(supportBufferStructType, 0, Decoration.Offset, (LiteralInteger)SupportBuffer.FragmentAlphaTestOffset);
- context.MemberDecorate(supportBufferStructType, 1, Decoration.Offset, (LiteralInteger)SupportBuffer.FragmentIsBgraOffset);
- context.MemberDecorate(supportBufferStructType, 2, Decoration.Offset, (LiteralInteger)SupportBuffer.ViewportInverseOffset);
- context.MemberDecorate(supportBufferStructType, 3, Decoration.Offset, (LiteralInteger)SupportBuffer.FragmentRenderScaleCountOffset);
- context.MemberDecorate(supportBufferStructType, 4, Decoration.Offset, (LiteralInteger)SupportBuffer.GraphicsRenderScaleOffset);
- context.Decorate(supportBufferStructType, Decoration.Block);
+ foreach (BufferDefinition buffer in buffers)
+ {
+ int alignment = buffer.Layout == BufferLayout.Std140 ? 16 : 4;
+ int alignmentMask = alignment - 1;
+ int offset = 0;
- var supportBufferPointerType = context.TypePointer(StorageClass.Uniform, supportBufferStructType);
- var supportBufferVariable = context.Variable(supportBufferPointerType, StorageClass.Uniform);
+ SpvInstruction[] structFieldTypes = new SpvInstruction[buffer.Type.Fields.Length];
+ int[] structFieldOffsets = new int[buffer.Type.Fields.Length];
- context.Decorate(supportBufferVariable, Decoration.DescriptorSet, (LiteralInteger)0);
- context.Decorate(supportBufferVariable, Decoration.Binding, (LiteralInteger)0);
+ for (int fieldIndex = 0; fieldIndex < buffer.Type.Fields.Length; fieldIndex++)
+ {
+ StructureField field = buffer.Type.Fields[fieldIndex];
+ int fieldSize = (field.Type.GetSizeInBytes() + alignmentMask) & ~alignmentMask;
- context.AddGlobalVariable(supportBufferVariable);
+ structFieldTypes[fieldIndex] = context.GetType(field.Type, field.ArrayLength);
+ structFieldOffsets[fieldIndex] = offset;
- context.SupportBuffer = supportBufferVariable;
- }
+ if (field.Type.HasFlag(AggregateType.Array))
+ {
+ // We can't decorate the type more than once.
+ if (decoratedTypes.Add(structFieldTypes[fieldIndex]))
+ {
+ context.Decorate(structFieldTypes[fieldIndex], Decoration.ArrayStride, (LiteralInteger)fieldSize);
+ }
- private static void DeclareUniformBuffers(CodeGenContext context, BufferDescriptor[] descriptors)
- {
- if (descriptors.Length == 0)
- {
- return;
- }
+ offset += fieldSize * field.ArrayLength;
+ }
+ else
+ {
+ offset += fieldSize;
+ }
+ }
- uint ubSize = Constants.ConstantBufferSize / 16;
+ var ubStructType = context.TypeStruct(false, structFieldTypes);
- var ubArrayType = context.TypeArray(context.TypeVector(context.TypeFP32(), 4), context.Constant(context.TypeU32(), ubSize), true);
- context.Decorate(ubArrayType, Decoration.ArrayStride, (LiteralInteger)16);
- var ubStructType = context.TypeStruct(true, ubArrayType);
- context.Decorate(ubStructType, Decoration.Block);
- context.MemberDecorate(ubStructType, 0, Decoration.Offset, (LiteralInteger)0);
+ if (decoratedTypes.Add(ubStructType))
+ {
+ context.Decorate(ubStructType, Decoration.Block);
- if (context.Config.UsedFeatures.HasFlag(FeatureFlags.CbIndexing))
- {
- int count = descriptors.Max(x => x.Slot) + 1;
+ for (int fieldIndex = 0; fieldIndex < structFieldOffsets.Length; fieldIndex++)
+ {
+ context.MemberDecorate(ubStructType, fieldIndex, Decoration.Offset, (LiteralInteger)structFieldOffsets[fieldIndex]);
+ }
+ }
- var ubStructArrayType = context.TypeArray(ubStructType, context.Constant(context.TypeU32(), count));
- var ubPointerType = context.TypePointer(StorageClass.Uniform, ubStructArrayType);
+ var ubPointerType = context.TypePointer(StorageClass.Uniform, ubStructType);
var ubVariable = context.Variable(ubPointerType, StorageClass.Uniform);
- context.Name(ubVariable, $"{GetStagePrefix(context.Config.Stage)}_u");
- context.Decorate(ubVariable, Decoration.DescriptorSet, (LiteralInteger)0);
- context.Decorate(ubVariable, Decoration.Binding, (LiteralInteger)context.Config.FirstConstantBufferBinding);
+ context.Name(ubVariable, buffer.Name);
+ context.Decorate(ubVariable, Decoration.DescriptorSet, (LiteralInteger)buffer.Set);
+ context.Decorate(ubVariable, Decoration.Binding, (LiteralInteger)buffer.Binding);
context.AddGlobalVariable(ubVariable);
-
- context.UniformBuffersArray = ubVariable;
- }
- else
- {
- var ubPointerType = context.TypePointer(StorageClass.Uniform, ubStructType);
-
- foreach (var descriptor in descriptors)
- {
- var ubVariable = context.Variable(ubPointerType, StorageClass.Uniform);
-
- context.Name(ubVariable, $"{GetStagePrefix(context.Config.Stage)}_c{descriptor.Slot}");
- context.Decorate(ubVariable, Decoration.DescriptorSet, (LiteralInteger)0);
- context.Decorate(ubVariable, Decoration.Binding, (LiteralInteger)descriptor.Binding);
- context.AddGlobalVariable(ubVariable);
- context.UniformBuffers.Add(descriptor.Slot, ubVariable);
- }
+ context.ConstantBuffers.Add(buffer.Binding, ubVariable);
}
}
@@ -394,25 +372,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
foreach (var ioDefinition in info.IoDefinitions)
{
- var ioVariable = ioDefinition.IoVariable;
-
- // Those are actually from constant buffer, rather than being actual inputs or outputs,
- // so we must ignore them here as they are declared as part of the support buffer.
- // TODO: Delete this after we represent this properly on the IR (as a constant buffer rather than "input").
- if (ioVariable == IoVariable.FragmentOutputIsBgra ||
- ioVariable == IoVariable.SupportBlockRenderScale ||
- ioVariable == IoVariable.SupportBlockViewInverse)
- {
- continue;
- }
-
- bool isOutput = ioDefinition.StorageKind.IsOutput();
- bool isPerPatch = ioDefinition.StorageKind.IsPerPatch();
-
PixelImap iq = PixelImap.Unused;
if (context.Config.Stage == ShaderStage.Fragment)
{
+ var ioVariable = ioDefinition.IoVariable;
if (ioVariable == IoVariable.UserDefined)
{
iq = context.Config.ImapTypes[ioDefinition.Location].GetFirstUsedType();
@@ -429,6 +393,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}
}
+ bool isOutput = ioDefinition.StorageKind.IsOutput();
+ bool isPerPatch = ioDefinition.StorageKind.IsPerPatch();
+
DeclareInputOrOutput(context, ioDefinition, isOutput, isPerPatch, iq);
}
}
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
index 6da8f29d..fda0dc47 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
@@ -98,7 +98,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.ImageStore, GenerateImageStore);
Add(Instruction.IsNan, GenerateIsNan);
Add(Instruction.Load, GenerateLoad);
- Add(Instruction.LoadConstant, GenerateLoadConstant);
Add(Instruction.LoadLocal, GenerateLoadLocal);
Add(Instruction.LoadShared, GenerateLoadShared);
Add(Instruction.LoadStorage, GenerateLoadStorage);
@@ -313,10 +312,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
for (int i = 0; i < args.Length; i++)
{
- var operand = (AstOperand)operation.GetSource(i + 1);
+ var operand = operation.GetSource(i + 1);
+
if (i >= function.InArguments.Length)
{
- args[i] = context.GetLocalPointer(operand);
+ args[i] = context.GetLocalPointer((AstOperand)operand);
}
else
{
@@ -867,68 +867,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return GenerateLoadOrStore(context, operation, isStore: false);
}
- private static OperationResult GenerateLoadConstant(CodeGenContext context, AstOperation operation)
- {
- var src1 = operation.GetSource(0);
- var src2 = context.Get(AggregateType.S32, operation.GetSource(1));
-
- var i1 = context.Constant(context.TypeS32(), 0);
- var i2 = context.ShiftRightArithmetic(context.TypeS32(), src2, context.Constant(context.TypeS32(), 2));
- var i3 = context.BitwiseAnd(context.TypeS32(), src2, context.Constant(context.TypeS32(), 3));
-
- SpvInstruction value = null;
-
- if (context.Config.GpuAccessor.QueryHostHasVectorIndexingBug())
- {
- // Test for each component individually.
- for (int i = 0; i < 4; i++)
- {
- var component = context.Constant(context.TypeS32(), i);
-
- SpvInstruction elemPointer;
- if (context.UniformBuffersArray != null)
- {
- var ubVariable = context.UniformBuffersArray;
- var i0 = context.Get(AggregateType.S32, src1);
-
- elemPointer = context.AccessChain(context.TypePointer(StorageClass.Uniform, context.TypeFP32()), ubVariable, i0, i1, i2, component);
- }
- else
- {
- var ubVariable = context.UniformBuffers[((AstOperand)src1).Value];
-
- elemPointer = context.AccessChain(context.TypePointer(StorageClass.Uniform, context.TypeFP32()), ubVariable, i1, i2, component);
- }
-
- SpvInstruction newValue = context.Load(context.TypeFP32(), elemPointer);
-
- value = value != null ? context.Select(context.TypeFP32(), context.IEqual(context.TypeBool(), i3, component), newValue, value) : newValue;
- }
- }
- else
- {
- SpvInstruction elemPointer;
-
- if (context.UniformBuffersArray != null)
- {
- var ubVariable = context.UniformBuffersArray;
- var i0 = context.Get(AggregateType.S32, src1);
-
- elemPointer = context.AccessChain(context.TypePointer(StorageClass.Uniform, context.TypeFP32()), ubVariable, i0, i1, i2, i3);
- }
- else
- {
- var ubVariable = context.UniformBuffers[((AstOperand)src1).Value];
-
- elemPointer = context.AccessChain(context.TypePointer(StorageClass.Uniform, context.TypeFP32()), ubVariable, i1, i2, i3);
- }
-
- value = context.Load(context.TypeFP32(), elemPointer);
- }
-
- return new OperationResult(AggregateType.FP32, value);
- }
-
private static OperationResult GenerateLoadLocal(CodeGenContext context, AstOperation operation)
{
return GenerateLoadLocalOrShared(context, operation, StorageClass.Private, context.LocalMemory);
@@ -1990,12 +1928,32 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
StorageKind storageKind = operation.StorageKind;
- SpvInstruction pointer;
+ StorageClass storageClass;
+ SpvInstruction baseObj;
AggregateType varType;
int srcIndex = 0;
switch (storageKind)
{
+ case StorageKind.ConstantBuffer:
+ if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
+ }
+
+ if (!(operation.GetSource(srcIndex) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
+ {
+ throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
+ }
+
+ BufferDefinition buffer = context.Config.Properties.ConstantBuffers[bindingIndex.Value];
+ StructureField field = buffer.Type.Fields[fieldIndex.Value];
+
+ storageClass = StorageClass.Uniform;
+ varType = field.Type & AggregateType.ElementTypeMask;
+ baseObj = context.ConstantBuffers[bindingIndex.Value];
+ break;
+
case StorageKind.Input:
case StorageKind.InputPerPatch:
case StorageKind.Output:
@@ -2038,33 +1996,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{
varType = context.Config.GetFragmentOutputColorType(location);
}
- else if (ioVariable == IoVariable.FragmentOutputIsBgra)
- {
- var pointerType = context.TypePointer(StorageClass.Uniform, context.TypeU32());
- var elemIndex = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- pointer = context.AccessChain(pointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 1), elemIndex);
- varType = AggregateType.U32;
-
- break;
- }
- else if (ioVariable == IoVariable.SupportBlockRenderScale)
- {
- var pointerType = context.TypePointer(StorageClass.Uniform, context.TypeFP32());
- var elemIndex = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- pointer = context.AccessChain(pointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 4), elemIndex);
- varType = AggregateType.FP32;
-
- break;
- }
- else if (ioVariable == IoVariable.SupportBlockViewInverse)
- {
- var pointerType = context.TypePointer(StorageClass.Uniform, context.TypeFP32());
- var elemIndex = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- pointer = context.AccessChain(pointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 2), elemIndex);
- varType = AggregateType.FP32;
-
- break;
- }
else
{
(_, varType) = IoMap.GetSpirvBuiltIn(ioVariable);
@@ -2072,55 +2003,57 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
varType &= AggregateType.ElementTypeMask;
- int inputsCount = (isStore ? operation.SourcesCount - 1 : operation.SourcesCount) - srcIndex;
- var storageClass = isOutput ? StorageClass.Output : StorageClass.Input;
+ storageClass = isOutput ? StorageClass.Output : StorageClass.Input;
var ioDefinition = new IoDefinition(storageKind, ioVariable, location, component);
var dict = isPerPatch
? (isOutput ? context.OutputsPerPatch : context.InputsPerPatch)
: (isOutput ? context.Outputs : context.Inputs);
- SpvInstruction baseObj = dict[ioDefinition];
- SpvInstruction e0, e1, e2;
-
- switch (inputsCount)
- {
- case 0:
- pointer = baseObj;
- break;
- case 1:
- e0 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, e0);
- break;
- case 2:
- e0 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- e1 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, e0, e1);
- break;
- case 3:
- e0 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- e1 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- e2 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
- pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, e0, e1, e2);
- break;
- default:
- var indexes = new SpvInstruction[inputsCount];
- int index = 0;
-
- for (; index < inputsCount; srcIndex++, index++)
- {
- indexes[index] = context.Get(AggregateType.S32, operation.GetSource(srcIndex));
- }
-
- pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, indexes);
- break;
- }
+ baseObj = dict[ioDefinition];
break;
default:
throw new InvalidOperationException($"Invalid storage kind {storageKind}.");
}
+ int inputsCount = (isStore ? operation.SourcesCount - 1 : operation.SourcesCount) - srcIndex;
+ SpvInstruction e0, e1, e2;
+ SpvInstruction pointer;
+
+ switch (inputsCount)
+ {
+ case 0:
+ pointer = baseObj;
+ break;
+ case 1:
+ e0 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
+ pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, e0);
+ break;
+ case 2:
+ e0 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
+ e1 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
+ pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, e0, e1);
+ break;
+ case 3:
+ e0 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
+ e1 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
+ e2 = context.Get(AggregateType.S32, operation.GetSource(srcIndex++));
+ pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, e0, e1, e2);
+ break;
+ default:
+ var indexes = new SpvInstruction[inputsCount];
+ int index = 0;
+
+ for (; index < inputsCount; srcIndex++, index++)
+ {
+ indexes[index] = context.Get(AggregateType.S32, operation.GetSource(srcIndex));
+ }
+
+ pointer = context.AccessChain(context.TypePointer(storageClass, context.GetType(varType)), baseObj, indexes);
+ break;
+ }
+
if (isStore)
{
context.Store(pointer, context.Get(varType, operation.GetSource(srcIndex)));
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ScalingHelpers.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ScalingHelpers.cs
index f6c218c6..c8b21e88 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ScalingHelpers.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/ScalingHelpers.cs
@@ -63,7 +63,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (context.Config.Stage == ShaderStage.Vertex)
{
var scaleCountPointerType = context.TypePointer(StorageClass.Uniform, context.TypeS32());
- var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 3));
+ var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.ConstantBuffers[0], context.Constant(context.TypeU32(), 3));
var scaleCount = context.Load(context.TypeS32(), scaleCountElemPointer);
scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, scaleCount);
@@ -71,7 +71,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, context.Constant(context.TypeU32(), 1));
- var scaleElemPointer = context.AccessChain(pointerType, context.SupportBuffer, fieldIndex, scaleIndex);
+ var scaleElemPointer = context.AccessChain(pointerType, context.ConstantBuffers[0], fieldIndex, scaleIndex);
var scale = context.Load(context.TypeFP32(), scaleElemPointer);
var ivector2Type = context.TypeVector(context.TypeS32(), 2);
@@ -201,7 +201,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (context.Config.Stage == ShaderStage.Vertex)
{
var scaleCountPointerType = context.TypePointer(StorageClass.Uniform, context.TypeS32());
- var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.SupportBuffer, context.Constant(context.TypeU32(), 3));
+ var scaleCountElemPointer = context.AccessChain(scaleCountPointerType, context.ConstantBuffers[0], context.Constant(context.TypeU32(), 3));
var scaleCount = context.Load(context.TypeS32(), scaleCountElemPointer);
scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, scaleCount);
@@ -209,7 +209,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
scaleIndex = context.IAdd(context.TypeU32(), scaleIndex, context.Constant(context.TypeU32(), 1));
- var scaleElemPointer = context.AccessChain(pointerType, context.SupportBuffer, fieldIndex, scaleIndex);
+ var scaleElemPointer = context.AccessChain(pointerType, context.ConstantBuffers[0], fieldIndex, scaleIndex);
var scale = context.GlslFAbs(context.TypeFP32(), context.Load(context.TypeFP32(), scaleElemPointer));
var passthrough = context.FOrdEqual(context.TypeBool(), scale, context.Constant(context.TypeFP32(), 1f));