From f08a280adef015e9a9a0e9273b4edffeb1157f3a Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sun, 19 Sep 2021 09:38:39 -0300 Subject: [PATCH] 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 --- Ryujinx.Graphics.GAL/Capabilities.cs | 3 + Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs | 2 +- .../TextureDescriptorCapableGpuAccessor.cs | 6 ++ Ryujinx.Graphics.OpenGL/HwCapabilities.cs | 2 + Ryujinx.Graphics.OpenGL/Renderer.cs | 1 + .../CodeGen/Glsl/Declarations.cs | 23 +++++++- .../CodeGen/Glsl/HelperFunctions/Shuffle.glsl | 4 +- .../Glsl/HelperFunctions/ShuffleDown.glsl | 6 +- .../Glsl/HelperFunctions/ShuffleUp.glsl | 6 +- .../Glsl/HelperFunctions/ShuffleXor.glsl | 6 +- .../Glsl/HelperFunctions/SwizzleAdd.glsl | 2 +- .../CodeGen/Glsl/Instructions/InstGen.cs | 13 ++--- .../Glsl/Instructions/InstGenBallot.cs | 26 +++++++++ .../Glsl/Instructions/InstGenHelper.cs | 2 +- .../CodeGen/Glsl/OperandManager.cs | 56 +++++++++++++------ Ryujinx.Graphics.Shader/IGpuAccessor.cs | 9 ++- 16 files changed, 125 insertions(+), 42 deletions(-) create mode 100644 Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenBallot.cs diff --git a/Ryujinx.Graphics.GAL/Capabilities.cs b/Ryujinx.Graphics.GAL/Capabilities.cs index 78a99554..6e5329b2 100644 --- a/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/Ryujinx.Graphics.GAL/Capabilities.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.GAL public bool SupportsImageLoadFormatted { get; } public bool SupportsMismatchingViewFormat { get; } public bool SupportsNonConstantTextureOffset { get; } + public bool SupportsShaderBallot { get; } public bool SupportsTextureShadowLod { get; } public bool SupportsViewportSwizzle { get; } public bool SupportsIndirectParameters { get; } @@ -24,6 +25,7 @@ namespace Ryujinx.Graphics.GAL bool supportsImageLoadFormatted, bool supportsMismatchingViewFormat, bool supportsNonConstantTextureOffset, + bool supportsShaderBallot, bool supportsTextureShadowLod, bool supportsViewportSwizzle, bool supportsIndirectParameters, @@ -37,6 +39,7 @@ namespace Ryujinx.Graphics.GAL SupportsImageLoadFormatted = supportsImageLoadFormatted; SupportsMismatchingViewFormat = supportsMismatchingViewFormat; SupportsNonConstantTextureOffset = supportsNonConstantTextureOffset; + SupportsShaderBallot = supportsShaderBallot; SupportsTextureShadowLod = supportsTextureShadowLod; SupportsViewportSwizzle = supportsViewportSwizzle; SupportsIndirectParameters = supportsIndirectParameters; diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs index cda3ecb3..926a673a 100644 --- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs +++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs @@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader /// /// Version of the codegen (to be changed when codegen or guest format change). /// - private const ulong ShaderCodeGenVersion = 2613; + private const ulong ShaderCodeGenVersion = 2627; // Progress reporting helpers private volatile int _shaderCount; diff --git a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs index 7c4eea02..dfb67f35 100644 --- a/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs +++ b/Ryujinx.Graphics.Gpu/Shader/TextureDescriptorCapableGpuAccessor.cs @@ -47,6 +47,12 @@ namespace Ryujinx.Graphics.Gpu.Shader /// True if the GPU and driver supports non-constant texture offsets, false otherwise public bool QueryHostSupportsNonConstantTextureOffset() => _context.Capabilities.SupportsNonConstantTextureOffset; + /// + /// Queries host GPU shader ballot support. + /// + /// True if the GPU and driver supports shader ballot, false otherwise + public bool QueryHostSupportsShaderBallot() => _context.Capabilities.SupportsShaderBallot; + /// /// Queries host GPU texture shadow LOD support. /// diff --git a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs index dd917b7b..9a62bb2e 100644 --- a/Ryujinx.Graphics.OpenGL/HwCapabilities.cs +++ b/Ryujinx.Graphics.OpenGL/HwCapabilities.cs @@ -11,6 +11,7 @@ namespace Ryujinx.Graphics.OpenGL private static readonly Lazy _supportsPolygonOffsetClamp = new Lazy(() => HasExtension("GL_EXT_polygon_offset_clamp")); private static readonly Lazy _supportsQuads = new Lazy(SupportsQuadsCheck); private static readonly Lazy _supportsSeamlessCubemapPerTexture = new Lazy(() => HasExtension("GL_ARB_seamless_cubemap_per_texture")); + private static readonly Lazy _supportsShaderBallot = new Lazy(() => HasExtension("GL_ARB_shader_ballot")); private static readonly Lazy _supportsTextureShadowLod = new Lazy(() => HasExtension("GL_EXT_texture_shadow_lod")); private static readonly Lazy _supportsViewportSwizzle = new Lazy(() => HasExtension("GL_NV_viewport_swizzle")); private static readonly Lazy _supportsIndirectParameters = new Lazy(() => HasExtension("GL_ARB_indirect_parameters")); @@ -45,6 +46,7 @@ namespace Ryujinx.Graphics.OpenGL public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value; public static bool SupportsQuads => _supportsQuads.Value; public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value; + public static bool SupportsShaderBallot => _supportsShaderBallot.Value; public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value; public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value; public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value; diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index 92f65083..768c7450 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -107,6 +107,7 @@ namespace Ryujinx.Graphics.OpenGL HwCapabilities.SupportsImageLoadFormatted, HwCapabilities.SupportsMismatchingViewFormat, HwCapabilities.SupportsNonConstantTextureOffset, + HwCapabilities.SupportsShaderBallot, HwCapabilities.SupportsTextureShadowLod, HwCapabilities.SupportsViewportSwizzle, HwCapabilities.SupportsIndirectParameters, 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])"; diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs index 9ae399f7..a74782c8 100644 --- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs +++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs @@ -1,6 +1,4 @@ -using Ryujinx.Graphics.Shader.Decoders; - -namespace Ryujinx.Graphics.Shader +namespace Ryujinx.Graphics.Shader { public interface IGpuAccessor { @@ -76,6 +74,11 @@ namespace Ryujinx.Graphics.Shader return true; } + bool QueryHostSupportsShaderBallot() + { + return true; + } + bool QueryHostSupportsTextureShadowLod() { return true;