From b805c7bf058c6da04620cf75880509bdf6d5986c Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Fri, 19 Nov 2021 06:27:44 +0100
Subject: [PATCH] TextureCache: Implement additional D24S8 convertions.

---
 src/video_core/host_shaders/CMakeLists.txt    |  2 ++
 .../convert_d24s8_to_b10g11r11.frag           | 21 ++++++++++++++++++
 .../host_shaders/convert_d24s8_to_r16g16.frag | 21 ++++++++++++++++++
 src/video_core/renderer_vulkan/blit_image.cpp | 22 +++++++++++++++++++
 src/video_core/renderer_vulkan/blit_image.h   | 10 +++++++++
 .../renderer_vulkan/vk_texture_cache.cpp      | 10 +++++++++
 6 files changed, 86 insertions(+)
 create mode 100644 src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag
 create mode 100644 src/video_core/host_shaders/convert_d24s8_to_r16g16.frag

diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt
index fd3e41434..87042195a 100644
--- a/src/video_core/host_shaders/CMakeLists.txt
+++ b/src/video_core/host_shaders/CMakeLists.txt
@@ -12,6 +12,8 @@ set(SHADER_FILES
     block_linear_unswizzle_3d.comp
     convert_abgr8_to_d24s8.frag
     convert_d24s8_to_abgr8.frag
+    convert_d24s8_to_b10g11r11.frag
+    convert_d24s8_to_r16g16.frag
     convert_depth_to_float.frag
     convert_float_to_depth.frag
     full_screen_triangle.vert
diff --git a/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag b/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag
new file mode 100644
index 000000000..c743d3a13
--- /dev/null
+++ b/src/video_core/host_shaders/convert_d24s8_to_b10g11r11.frag
@@ -0,0 +1,21 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#version 450
+
+layout(binding = 0) uniform sampler2D depth_tex;
+layout(binding = 1) uniform isampler2D stencil_tex;
+
+layout(location = 0) out vec4 color;
+
+void main() {
+    ivec2 coord = ivec2(gl_FragCoord.xy);
+    uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
+    uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
+
+    color.b = float(depth >> 22) / (exp2(10) - 1.0);
+    color.g = float((depth >> 11) & 0x00FF) / (exp2(11) - 1.0);
+    color.r = float(depth & 0x00FF) / (exp2(11) - 1.0);
+    color.a = 1.0f;
+}
diff --git a/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag b/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag
new file mode 100644
index 000000000..2a9443d3d
--- /dev/null
+++ b/src/video_core/host_shaders/convert_d24s8_to_r16g16.frag
@@ -0,0 +1,21 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#version 450
+
+layout(binding = 0) uniform sampler2D depth_tex;
+layout(binding = 1) uniform isampler2D stencil_tex;
+
+layout(location = 0) out vec4 color;
+
+void main() {
+    ivec2 coord = ivec2(gl_FragCoord.xy);
+    uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
+    uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
+
+    color.r = float(depth >> 16) / (exp2(16) - 1.0);
+    color.g = float((depth >> 16) & 0x00FF) / (exp2(16) - 1.0);
+    color.b = 0.0f;
+    color.a = 1.0f;
+}
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index 01535d0c0..12b28aadd 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -6,6 +6,8 @@
 
 #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
 #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
+#include "video_core/host_shaders/convert_d24s8_to_b10g11r11_frag_spv.h"
+#include "video_core/host_shaders/convert_d24s8_to_r16g16_frag_spv.h"
 #include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
 #include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
 #include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
@@ -358,6 +360,8 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
       convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
       convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
       convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
+      convert_d24s8_to_b10g11r11_frag(BuildShader(device, CONVERT_D24S8_TO_B10G11R11_FRAG_SPV)),
+      convert_d24s8_to_r16g16_frag(BuildShader(device, CONVERT_D24S8_TO_R16G16_FRAG_SPV)),
       linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
       nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {
     if (device.IsExtShaderStencilExportSupported()) {
@@ -469,6 +473,24 @@ void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
                         down_shift);
 }
 
+void BlitImageHelper::ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer,
+                                              ImageView& src_image_view, u32 up_scale,
+                                              u32 down_shift) {
+    ConvertPipelineEx(convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer->RenderPass(),
+                      convert_d24s8_to_b10g11r11_frag, false);
+    ConvertDepthStencil(*convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer, src_image_view,
+                        up_scale, down_shift);
+}
+
+void BlitImageHelper::ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer,
+                                           ImageView& src_image_view, u32 up_scale,
+                                           u32 down_shift) {
+    ConvertPipelineEx(convert_d24s8_to_r16g16_pipeline, dst_framebuffer->RenderPass(),
+                      convert_d24s8_to_r16g16_frag, false);
+    ConvertDepthStencil(*convert_d24s8_to_r16g16_pipeline, dst_framebuffer, src_image_view,
+                        up_scale, down_shift);
+}
+
 void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
                               const ImageView& src_image_view, u32 up_scale, u32 down_shift) {
     const VkPipelineLayout layout = *one_texture_pipeline_layout;
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index f754a7294..10d24c4b7 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -62,6 +62,12 @@ public:
     void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
                              u32 up_scale, u32 down_shift);
 
+    void ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
+                                 u32 up_scale, u32 down_shift);
+
+    void ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
+                              u32 up_scale, u32 down_shift);
+
 private:
     void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
                  const ImageView& src_image_view, u32 up_scale, u32 down_shift);
@@ -97,6 +103,8 @@ private:
     vk::ShaderModule convert_float_to_depth_frag;
     vk::ShaderModule convert_abgr8_to_d24s8_frag;
     vk::ShaderModule convert_d24s8_to_abgr8_frag;
+    vk::ShaderModule convert_d24s8_to_b10g11r11_frag;
+    vk::ShaderModule convert_d24s8_to_r16g16_frag;
     vk::Sampler linear_sampler;
     vk::Sampler nearest_sampler;
 
@@ -110,6 +118,8 @@ private:
     vk::Pipeline convert_r16_to_d16_pipeline;
     vk::Pipeline convert_abgr8_to_d24s8_pipeline;
     vk::Pipeline convert_d24s8_to_abgr8_pipeline;
+    vk::Pipeline convert_d24s8_to_b10g11r11_pipeline;
+    vk::Pipeline convert_d24s8_to_r16g16_pipeline;
 };
 
 } // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 6dfd45f31..fd6064271 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -887,6 +887,16 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
             return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift);
         }
         break;
+    case PixelFormat::B10G11R11_FLOAT:
+        if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
+            return blit_image_helper.ConvertD24S8ToB10G11R11(dst, src_view, up_scale, down_shift);
+        }
+        break;
+    case PixelFormat::R16G16_UNORM:
+        if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
+            return blit_image_helper.ConvertD24S8ToR16G16(dst, src_view, up_scale, down_shift);
+        }
+        break;
     case PixelFormat::R32_FLOAT:
         if (src_view.format == PixelFormat::D32_FLOAT) {
             return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift);