diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs index 23f64ea5d..50ed91eef 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Declarations.cs @@ -243,7 +243,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv meta.Type.HasFlag(SamplerType.Shadow), meta.Type.HasFlag(SamplerType.Array), meta.Type.HasFlag(SamplerType.Multisample), - 2, + AccessQualifier.ReadWrite, GetImageFormat(meta.Format)); var nameSuffix = meta.CbufSlot < 0 ? @@ -258,6 +258,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv context.Name(imageVariable, $"{GetStagePrefix(context.Config.Stage)}_img{nameSuffix}"); context.Decorate(imageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex); context.Decorate(imageVariable, Decoration.Binding, (LiteralInteger)descriptor.Binding); + + if (descriptor.Flags.HasFlag(TextureUsageFlags.ImageCoherent)) + { + context.Decorate(imageVariable, Decoration.Coherent); + } + context.AddGlobalVariable(imageVariable); } } diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index 871de694a..54ad3c96d 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -76,6 +76,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv Add(Instruction.EmitVertex, GenerateEmitVertex); Add(Instruction.EndPrimitive, GenerateEndPrimitive); Add(Instruction.ExponentB2, GenerateExponentB2); + Add(Instruction.FSIBegin, GenerateFSIBegin); + Add(Instruction.FSIEnd, GenerateFSIEnd); Add(Instruction.FindLSB, GenerateFindLSB); Add(Instruction.FindMSBS32, GenerateFindMSBS32); Add(Instruction.FindMSBU32, GenerateFindMSBU32); @@ -521,6 +523,26 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv return GenerateUnary(context, operation, context.Delegates.GlslExp2, null); } + private static OperationResult GenerateFSIBegin(CodeGenContext context, AstOperation operation) + { + if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock()) + { + context.BeginInvocationInterlockEXT(); + } + + return OperationResult.Invalid; + } + + private static OperationResult GenerateFSIEnd(CodeGenContext context, AstOperation operation) + { + if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock()) + { + context.EndInvocationInterlockEXT(); + } + + return OperationResult.Invalid; + } + private static OperationResult GenerateFindLSB(CodeGenContext context, AstOperation operation) { var source = context.GetU32(operation.GetSource(0)); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs index 20b8fa0cb..fe47f4bbb 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs @@ -61,6 +61,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv context.AddCapability(Capability.TransformFeedback); } + if (config.Stage == ShaderStage.Fragment && context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock()) + { + context.AddCapability(Capability.FragmentShaderPixelInterlockEXT); + context.AddExtension("SPV_EXT_fragment_shader_interlock"); + } + if (config.Stage == ShaderStage.Geometry) { context.AddCapability(Capability.Geometry); @@ -184,6 +190,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv { context.AddExecutionMode(spvFunc, ExecutionMode.DepthReplacing); } + + if (context.Config.GpuAccessor.QueryHostSupportsFragmentShaderInterlock()) + { + context.AddExecutionMode(spvFunc, ExecutionMode.PixelInterlockOrderedEXT); + } } else if (context.Config.Stage == ShaderStage.Compute) {