aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/CodeGen
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-09-19 09:38:39 -0300
committerGitHub <noreply@github.com>2021-09-19 14:38:39 +0200
commitf08a280adef015e9a9a0e9273b4edffeb1157f3a (patch)
tree26baeacb8b094e77aa0d8cde15073d12e080305a /Ryujinx.Graphics.Shader/CodeGen
parent7379bc2f39557929f283a423fe7f4b7390d08261 (diff)
Use shader subgroup extensions if shader ballot is not supported (#2627)
* Use shader subgroup extensions if shader ballot is not supported * Shader cache version bump + cleanup * The type is still required on the table
Diffstat (limited to 'Ryujinx.Graphics.Shader/CodeGen')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs23
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl4
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl6
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl6
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl6
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl2
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs13
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs26
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs2
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs56
10 files changed, 106 insertions, 38 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 7b26801a..e29ff486 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -13,7 +13,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{
context.AppendLine("#version 450 core");
context.AppendLine("#extension GL_ARB_gpu_shader_int64 : enable");
- context.AppendLine("#extension GL_ARB_shader_ballot : enable");
+
+ if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot())
+ {
+ context.AppendLine("#extension GL_ARB_shader_ballot : enable");
+ }
+ else
+ {
+ context.AppendLine("#extension GL_KHR_shader_subgroup_basic : enable");
+ context.AppendLine("#extension GL_KHR_shader_subgroup_ballot : enable");
+ }
+
context.AppendLine("#extension GL_ARB_shader_group_vote : enable");
context.AppendLine("#extension GL_EXT_shader_image_load_formatted : enable");
context.AppendLine("#extension GL_EXT_texture_shadow_lod : enable");
@@ -531,6 +541,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
code = code.Replace("$SHARED_MEM$", DefaultNames.SharedMemoryName);
code = code.Replace("$STORAGE_MEM$", OperandManager.GetShaderStagePrefix(context.Config.Stage) + "_" + DefaultNames.StorageNamePrefix);
+ if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot())
+ {
+ code = code.Replace("$SUBGROUP_INVOCATION$", "gl_SubGroupInvocationARB");
+ code = code.Replace("$SUBGROUP_BROADCAST$", "readInvocationARB");
+ }
+ else
+ {
+ code = code.Replace("$SUBGROUP_INVOCATION$", "gl_SubgroupInvocationID");
+ code = code.Replace("$SUBGROUP_BROADCAST$", "subgroupBroadcast");
+ }
+
context.AppendLine(code);
context.AppendLine();
}
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl
index cb7c8d43..7cb4764d 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/Shuffle.glsl
@@ -2,10 +2,10 @@ float Helper_Shuffle(float x, uint index, uint mask, out bool valid)
{
uint clamp = mask & 0x1fu;
uint segMask = (mask >> 8) & 0x1fu;
- uint minThreadId = gl_SubGroupInvocationARB & segMask;
+ uint minThreadId = $SUBGROUP_INVOCATION$ & segMask;
uint maxThreadId = minThreadId | (clamp & ~segMask);
uint srcThreadId = (index & ~segMask) | minThreadId;
valid = srcThreadId <= maxThreadId;
- float v = readInvocationARB(x, srcThreadId);
+ float v = $SUBGROUP_BROADCAST$(x, srcThreadId);
return valid ? v : x;
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl
index 45012550..71d901d5 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleDown.glsl
@@ -2,10 +2,10 @@ float Helper_ShuffleDown(float x, uint index, uint mask, out bool valid)
{
uint clamp = mask & 0x1fu;
uint segMask = (mask >> 8) & 0x1fu;
- uint minThreadId = gl_SubGroupInvocationARB & segMask;
+ uint minThreadId = $SUBGROUP_INVOCATION$ & segMask;
uint maxThreadId = minThreadId | (clamp & ~segMask);
- uint srcThreadId = gl_SubGroupInvocationARB + index;
+ uint srcThreadId = $SUBGROUP_INVOCATION$ + index;
valid = srcThreadId <= maxThreadId;
- float v = readInvocationARB(x, srcThreadId);
+ float v = $SUBGROUP_BROADCAST$(x, srcThreadId);
return valid ? v : x;
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl
index 0781678a..ae264d87 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleUp.glsl
@@ -1,9 +1,9 @@
float Helper_ShuffleUp(float x, uint index, uint mask, out bool valid)
{
uint segMask = (mask >> 8) & 0x1fu;
- uint minThreadId = gl_SubGroupInvocationARB & segMask;
- uint srcThreadId = gl_SubGroupInvocationARB - index;
+ uint minThreadId = $SUBGROUP_INVOCATION$ & segMask;
+ uint srcThreadId = $SUBGROUP_INVOCATION$ - index;
valid = int(srcThreadId) >= int(minThreadId);
- float v = readInvocationARB(x, srcThreadId);
+ float v = $SUBGROUP_BROADCAST$(x, srcThreadId);
return valid ? v : x;
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl
index 59db5444..789089d6 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/ShuffleXor.glsl
@@ -2,10 +2,10 @@ float Helper_ShuffleXor(float x, uint index, uint mask, out bool valid)
{
uint clamp = mask & 0x1fu;
uint segMask = (mask >> 8) & 0x1fu;
- uint minThreadId = gl_SubGroupInvocationARB & segMask;
+ uint minThreadId = $SUBGROUP_INVOCATION$ & segMask;
uint maxThreadId = minThreadId | (clamp & ~segMask);
- uint srcThreadId = gl_SubGroupInvocationARB ^ index;
+ uint srcThreadId = $SUBGROUP_INVOCATION$ ^ index;
valid = srcThreadId <= maxThreadId;
- float v = readInvocationARB(x, srcThreadId);
+ float v = $SUBGROUP_BROADCAST$(x, srcThreadId);
return valid ? v : x;
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl
index 7df3e57f..ed00dfec 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/SwizzleAdd.glsl
@@ -2,6 +2,6 @@ float Helper_SwizzleAdd(float x, float y, int mask)
{
vec4 xLut = vec4(1.0, -1.0, 1.0, 0.0);
vec4 yLut = vec4(1.0, 1.0, -1.0, 1.0);
- int lutIdx = mask >> int(gl_SubGroupInvocationARB & 3u) * 2;
+ int lutIdx = mask >> int($SUBGROUP_INVOCATION$ & 3u) * 2;
return x * xLut[lutIdx] + y * yLut[lutIdx];
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
index 24d4cabd..3fa13eb5 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGen.cs
@@ -2,6 +2,7 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using System;
+using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenBallot;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenCall;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenMemory;
@@ -75,14 +76,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
}
}
- if (inst == Instruction.Ballot)
- {
- return $"unpackUint2x32({info.OpName}({args})).x";
- }
- else
- {
- return info.OpName + "(" + args + ")";
- }
+ return info.OpName + '(' + args + ')';
}
else if ((info.Type & InstType.Op) != 0)
{
@@ -128,6 +122,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
switch (inst)
{
+ case Instruction.Ballot:
+ return Ballot(context, operation);
+
case Instruction.Call:
return Call(context, operation);
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs
new file mode 100644
index 00000000..51e7bd21
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs
@@ -0,0 +1,26 @@
+using Ryujinx.Graphics.Shader.StructuredIr;
+
+using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
+using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
+
+namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
+{
+ static class InstGenBallot
+ {
+ public static string Ballot(CodeGenContext context, AstOperation operation)
+ {
+ VariableType dstType = GetSrcVarType(operation.Inst, 0);
+
+ string arg = GetSoureExpr(context, operation.GetSource(0), dstType);
+
+ if (context.Config.GpuAccessor.QueryHostSupportsShaderBallot())
+ {
+ return $"unpackUint2x32(ballotARB({arg})).x";
+ }
+ else
+ {
+ return $"subgroupBallot({arg}).x";
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
index 6f4f0c4e..424a1c4f 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs
@@ -25,7 +25,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.AtomicXor, InstType.AtomicBinary, "atomicXor");
Add(Instruction.Absolute, InstType.CallUnary, "abs");
Add(Instruction.Add, InstType.OpBinaryCom, "+", 2);
- Add(Instruction.Ballot, InstType.CallUnary, "ballotARB");
+ Add(Instruction.Ballot, InstType.Special);
Add(Instruction.Barrier, InstType.CallNullary, "barrier");
Add(Instruction.BitCount, InstType.CallUnary, "bitCount");
Add(Instruction.BitfieldExtractS32, InstType.CallTernary, "bitfieldExtract");
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index deea6c72..d35525f9 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -52,20 +52,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ AttributeConsts.FrontFacing, new BuiltInAttribute("gl_FrontFacing", VariableType.Bool) },
// Special.
- { AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", VariableType.F32) },
- { AttributeConsts.ThreadKill, new BuiltInAttribute("gl_HelperInvocation", VariableType.Bool) },
- { AttributeConsts.ThreadIdX, new BuiltInAttribute("gl_LocalInvocationID.x", VariableType.U32) },
- { AttributeConsts.ThreadIdY, new BuiltInAttribute("gl_LocalInvocationID.y", VariableType.U32) },
- { AttributeConsts.ThreadIdZ, new BuiltInAttribute("gl_LocalInvocationID.z", VariableType.U32) },
- { AttributeConsts.CtaIdX, new BuiltInAttribute("gl_WorkGroupID.x", VariableType.U32) },
- { AttributeConsts.CtaIdY, new BuiltInAttribute("gl_WorkGroupID.y", VariableType.U32) },
- { AttributeConsts.CtaIdZ, new BuiltInAttribute("gl_WorkGroupID.z", VariableType.U32) },
- { AttributeConsts.LaneId, new BuiltInAttribute("gl_SubGroupInvocationARB", VariableType.U32) },
- { AttributeConsts.EqMask, new BuiltInAttribute("unpackUint2x32(gl_SubGroupEqMaskARB).x", VariableType.U32) },
- { AttributeConsts.GeMask, new BuiltInAttribute("unpackUint2x32(gl_SubGroupGeMaskARB).x", VariableType.U32) },
- { AttributeConsts.GtMask, new BuiltInAttribute("unpackUint2x32(gl_SubGroupGtMaskARB).x", VariableType.U32) },
- { AttributeConsts.LeMask, new BuiltInAttribute("unpackUint2x32(gl_SubGroupLeMaskARB).x", VariableType.U32) },
- { AttributeConsts.LtMask, new BuiltInAttribute("unpackUint2x32(gl_SubGroupLtMaskARB).x", VariableType.U32) },
+ { AttributeConsts.FragmentOutputDepth, new BuiltInAttribute("gl_FragDepth", VariableType.F32) },
+ { AttributeConsts.ThreadKill, new BuiltInAttribute("gl_HelperInvocation", VariableType.Bool) },
+ { AttributeConsts.ThreadIdX, new BuiltInAttribute("gl_LocalInvocationID.x", VariableType.U32) },
+ { AttributeConsts.ThreadIdY, new BuiltInAttribute("gl_LocalInvocationID.y", VariableType.U32) },
+ { AttributeConsts.ThreadIdZ, new BuiltInAttribute("gl_LocalInvocationID.z", VariableType.U32) },
+ { AttributeConsts.CtaIdX, new BuiltInAttribute("gl_WorkGroupID.x", VariableType.U32) },
+ { AttributeConsts.CtaIdY, new BuiltInAttribute("gl_WorkGroupID.y", VariableType.U32) },
+ { AttributeConsts.CtaIdZ, new BuiltInAttribute("gl_WorkGroupID.z", VariableType.U32) },
+ { AttributeConsts.LaneId, new BuiltInAttribute(null, VariableType.U32) },
+ { AttributeConsts.EqMask, new BuiltInAttribute(null, VariableType.U32) },
+ { AttributeConsts.GeMask, new BuiltInAttribute(null, VariableType.U32) },
+ { AttributeConsts.GtMask, new BuiltInAttribute(null, VariableType.U32) },
+ { AttributeConsts.LeMask, new BuiltInAttribute(null, VariableType.U32) },
+ { AttributeConsts.LtMask, new BuiltInAttribute(null, VariableType.U32) },
// Support uniforms.
{ AttributeConsts.FragmentOutputIsBgraBase + 0, new BuiltInAttribute($"{DefaultNames.SupportBlockIsBgraName}[0]", VariableType.Bool) },
@@ -149,6 +149,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public static string GetAttributeName(int value, ShaderConfig config, bool isOutAttr = false, string indexExpr = "0")
{
+ value &= ~3;
char swzMask = GetSwizzleMask((value >> 2) & 3);
if (value >= AttributeConsts.UserAttributeBase && value < AttributeConsts.UserAttributeEnd)
@@ -201,12 +202,35 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return $"{DefaultNames.OAttributePrefix}{(value >> 4)}.{swzMask}";
}
- else if (_builtInAttributes.TryGetValue(value & ~3, out BuiltInAttribute builtInAttr))
+ else if (_builtInAttributes.TryGetValue(value, out BuiltInAttribute builtInAttr))
{
+ string subgroupMask = value switch
+ {
+ AttributeConsts.EqMask => "Eq",
+ AttributeConsts.GeMask => "Ge",
+ AttributeConsts.GtMask => "Gt",
+ AttributeConsts.LeMask => "Le",
+ AttributeConsts.LtMask => "Lt",
+ _ => null
+ };
+
+ if (subgroupMask != null)
+ {
+ return config.GpuAccessor.QueryHostSupportsShaderBallot()
+ ? $"unpackUint2x32(gl_SubGroup{subgroupMask}MaskARB).x"
+ : $"gl_Subgroup{subgroupMask}Mask.x";
+ }
+ else if (value == AttributeConsts.LaneId)
+ {
+ return config.GpuAccessor.QueryHostSupportsShaderBallot()
+ ? "gl_SubGroupInvocationARB"
+ : "gl_SubgroupInvocationID";
+ }
+
// TODO: There must be a better way to handle this...
if (config.Stage == ShaderStage.Fragment)
{
- switch (value & ~3)
+ switch (value)
{
case AttributeConsts.PositionX: return $"(gl_FragCoord.x / {DefaultNames.SupportBlockRenderScaleName}[0])";
case AttributeConsts.PositionY: return $"(gl_FragCoord.y / {DefaultNames.SupportBlockRenderScaleName}[0])";