From 1a919e99b29fff4e2158e622cb3dfbee21293b6d Mon Sep 17 00:00:00 2001 From: riperiperi Date: Thu, 18 Jul 2024 00:21:32 +0100 Subject: Vulkan: Defer guest barriers, and improve image barrier timings (#7012) * More guarantees for buffer correct placement, defer guest requested buffers * Split RP on indirect barrier rn * Better handling for feedback loops. * Qualcomm barriers suck too * Fix condition * Remove unused field * Allow render pass barriers on turnip for now --- src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs | 71 +++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs') diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index b1547b79..c9aab401 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -27,6 +27,9 @@ namespace Ryujinx.Graphics.Vulkan public uint Stages { get; } + public PipelineStageFlags IncoherentBufferWriteStages { get; } + public PipelineStageFlags IncoherentTextureWriteStages { get; } + public ResourceBindingSegment[][] ClearSegments { get; } public ResourceBindingSegment[][] BindingSegments { get; } public DescriptorSetTemplate[] Templates { get; } @@ -131,6 +134,7 @@ namespace Ryujinx.Graphics.Vulkan ClearSegments = BuildClearSegments(sets); BindingSegments = BuildBindingSegments(resourceLayout.SetUsages, out bool usesBufferTextures); Templates = BuildTemplates(usePushDescriptors); + (IncoherentBufferWriteStages, IncoherentTextureWriteStages) = BuildIncoherentStages(resourceLayout.SetUsages); // Updating buffer texture bindings using template updates crashes the Adreno driver on Windows. UpdateTexturesWithoutTemplate = gd.IsQualcommProprietary && usesBufferTextures; @@ -377,6 +381,73 @@ namespace Ryujinx.Graphics.Vulkan return templates; } + private PipelineStageFlags GetPipelineStages(ResourceStages stages) + { + PipelineStageFlags result = 0; + + if ((stages & ResourceStages.Compute) != 0) + { + result |= PipelineStageFlags.ComputeShaderBit; + } + + if ((stages & ResourceStages.Vertex) != 0) + { + result |= PipelineStageFlags.VertexShaderBit; + } + + if ((stages & ResourceStages.Fragment) != 0) + { + result |= PipelineStageFlags.FragmentShaderBit; + } + + if ((stages & ResourceStages.Geometry) != 0) + { + result |= PipelineStageFlags.GeometryShaderBit; + } + + if ((stages & ResourceStages.TessellationControl) != 0) + { + result |= PipelineStageFlags.TessellationControlShaderBit; + } + + if ((stages & ResourceStages.TessellationEvaluation) != 0) + { + result |= PipelineStageFlags.TessellationEvaluationShaderBit; + } + + return result; + } + + private (PipelineStageFlags Buffer, PipelineStageFlags Texture) BuildIncoherentStages(ReadOnlyCollection setUsages) + { + PipelineStageFlags buffer = PipelineStageFlags.None; + PipelineStageFlags texture = PipelineStageFlags.None; + + foreach (var set in setUsages) + { + foreach (var range in set.Usages) + { + if (range.Write) + { + PipelineStageFlags stages = GetPipelineStages(range.Stages); + + switch (range.Type) + { + case ResourceType.Image: + texture |= stages; + break; + case ResourceType.StorageBuffer: + case ResourceType.BufferImage: + buffer |= stages; + break; + } + } + } + } + + return (buffer, texture); + } + private async Task BackgroundCompilation() { await Task.WhenAll(_shaders.Select(shader => shader.CompileTask)); -- cgit v1.2.3