From f864a490142c4da608dab8d2025fc18da857f93f Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Thu, 18 May 2023 18:16:03 -0300
Subject: Fix Vulkan blit-like operations swizzle (#5003)

---
 .../DescriptorSetUpdater.cs                        | 29 +++++++++++++++++++++-
 src/Ryujinx.Graphics.Vulkan/HelperShader.cs        | 12 ++++-----
 src/Ryujinx.Graphics.Vulkan/PipelineBase.cs        |  5 ++++
 3 files changed, 39 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
index ab3befd8..a47ea5ff 100644
--- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
+++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs
@@ -228,7 +228,12 @@ namespace Ryujinx.Graphics.Vulkan
             SignalDirty(DirtyFlags.Storage);
         }
 
-        public void SetTextureAndSampler(CommandBufferScoped cbs, ShaderStage stage, int binding, ITexture texture, ISampler sampler)
+        public void SetTextureAndSampler(
+            CommandBufferScoped cbs,
+            ShaderStage stage,
+            int binding,
+            ITexture texture,
+            ISampler sampler)
         {
             if (texture is TextureBuffer textureBuffer)
             {
@@ -251,6 +256,28 @@ namespace Ryujinx.Graphics.Vulkan
             SignalDirty(DirtyFlags.Texture);
         }
 
+        public void SetTextureAndSamplerIdentitySwizzle(
+            CommandBufferScoped cbs,
+            ShaderStage stage,
+            int binding,
+            ITexture texture,
+            ISampler sampler)
+        {
+            if (texture is TextureView view)
+            {
+                view.Storage.InsertWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
+
+                _textureRefs[binding] = view.GetIdentityImageView();
+                _samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler();
+
+                SignalDirty(DirtyFlags.Texture);
+            }
+            else
+            {
+                SetTextureAndSampler(cbs, stage, binding, texture, sampler);
+            }
+        }
+
         public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan<BufferAssignment> buffers)
         {
             for (int i = 0; i < buffers.Length; i++)
diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
index 155c7f6f..c064696d 100644
--- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
+++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs
@@ -415,7 +415,7 @@ namespace Ryujinx.Graphics.Vulkan
 
             var sampler = linearFilter ? _samplerLinear : _samplerNearest;
 
-            _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, sampler);
+            _pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, src, sampler);
 
             Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
 
@@ -625,7 +625,7 @@ namespace Ryujinx.Graphics.Vulkan
 
         private void BlitDepthStencilDraw(TextureView src, bool isDepth)
         {
-            _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest);
+            _pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, src, _samplerNearest);
 
             if (isDepth)
             {
@@ -1037,7 +1037,7 @@ namespace Ryujinx.Graphics.Vulkan
                     var srcView = Create2DLayerView(src, srcLayer + z, srcLevel + l, srcFormat);
                     var dstView = Create2DLayerView(dst, dstLayer + z, dstLevel + l);
 
-                    _pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
+                    _pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Compute, 0, srcView, null);
                     _pipeline.SetImage(0, dstView, dstFormat);
 
                     int dispatchX = (Math.Min(srcView.Info.Width, dstView.Info.Width) + 31) / 32;
@@ -1177,7 +1177,7 @@ namespace Ryujinx.Graphics.Vulkan
                     var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
                     var dstView = Create2DLayerView(dst, dstLayer + z, 0);
 
-                    _pipeline.SetTextureAndSampler(ShaderStage.Compute, 0, srcView, null);
+                    _pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Compute, 0, srcView, null);
                     _pipeline.SetImage(0, dstView, format);
 
                     _pipeline.DispatchCompute(dispatchX, dispatchY, 1);
@@ -1313,7 +1313,7 @@ namespace Ryujinx.Graphics.Vulkan
                     var srcView = Create2DLayerView(src, srcLayer + z, 0, format);
                     var dstView = Create2DLayerView(dst, dstLayer + z, 0);
 
-                    _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, srcView, null);
+                    _pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, srcView, null);
                     _pipeline.SetRenderTarget(
                         ((TextureView)dstView).GetView(format).GetImageViewForAttachment(),
                         (uint)dst.Width,
@@ -1384,7 +1384,7 @@ namespace Ryujinx.Graphics.Vulkan
 
         private void CopyMSAspectDraw(TextureView src, bool fromMS, bool isDepth)
         {
-            _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, src, _samplerNearest);
+            _pipeline.SetTextureAndSamplerIdentitySwizzle(ShaderStage.Fragment, 0, src, _samplerNearest);
 
             if (isDepth)
             {
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index 4aec0dbc..ce6148e2 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -1098,6 +1098,11 @@ namespace Ryujinx.Graphics.Vulkan
             _descriptorSetUpdater.SetTextureAndSampler(Cbs, stage, binding, texture, sampler);
         }
 
+        public void SetTextureAndSamplerIdentitySwizzle(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
+        {
+            _descriptorSetUpdater.SetTextureAndSamplerIdentitySwizzle(Cbs, stage, binding, texture, sampler);
+        }
+
         public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
         {
             PauseTransformFeedbackInternal();
-- 
cgit v1.2.3-70-g09d2