diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 969f21d50..18c04390e 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -18,6 +18,7 @@ set(SHADER_FILES blit_color_float.frag block_linear_unswizzle_2d.comp block_linear_unswizzle_3d.comp + convert_abgr8_srgb_to_d24s8.frag convert_abgr8_to_d24s8.frag convert_abgr8_to_d32f.frag convert_d32f_to_abgr8.frag diff --git a/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag b/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag new file mode 100644 index 000000000..3e037af74 --- /dev/null +++ b/src/video_core/host_shaders/convert_abgr8_srgb_to_d24s8.frag @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#version 450 +#extension GL_ARB_shader_stencil_export : require + +precision highp int; +precision highp float; + +layout(binding = 0) uniform sampler2D color_texture; + +// Utility function to convert sRGB to linear space +highp float srgbToLinear(highp float srgb) { + if (srgb <= 0.04045) + return srgb / 12.92; + else + return pow((srgb + 0.055) / 1.055, 2.4); +} + +void main() { + ivec2 coord = ivec2(gl_FragCoord.xy); + + // Fetch sRGB color and convert to linear space + vec4 srgbColor = texelFetch(color_texture, coord, 0); + highp float r_linear = srgbToLinear(srgbColor.r); + highp float g_linear = srgbToLinear(srgbColor.g); + highp float b_linear = srgbToLinear(srgbColor.b); + + // Compute luminance for depth + highp float luminance = 0.2126 * r_linear + 0.7152 * g_linear + 0.0722 * b_linear; + highp uint depth_val = uint(luminance * (exp2(24.0) - 1.0)); + + // Extract the stencil value from the alpha component + highp uint stencil_val = uint(srgbColor.a * (exp2(8) - 1.0)); + + // Pack stencil and depth values into a single uint + highp uint byte0 = stencil_val << 24; + highp uint byte1 = (depth_val & 0x00FF0000u) >> 16; + highp uint byte2 = (depth_val & 0x0000FF00u) >> 8; + highp uint byte3 = depth_val & 0x000000FFu; + highp uint depth_stencil_unorm = byte0 | (byte1 << 16) | (byte2 << 8) | byte3; + + // Set depth and stencil values for the fragment + gl_FragDepth = float(depth_stencil_unorm & 0x00FFFFFFu) / (exp2(24.0) - 1.0); + gl_FragStencilRefARB = int(depth_stencil_unorm >> 24); +} diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index c3db09424..23bf2b73b 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -7,6 +7,7 @@ #include "common/settings.h" #include "video_core/host_shaders/blit_color_float_frag_spv.h" +#include "video_core/host_shaders/convert_abgr8_srgb_to_d24s8_frag_spv.h" #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" #include "video_core/host_shaders/convert_abgr8_to_d32f_frag_spv.h" #include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" @@ -434,6 +435,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, clear_stencil_frag(BuildShader(device, VULKAN_DEPTHSTENCIL_CLEAR_FRAG_SPV)), convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), + convert_abgr8_srgb_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_SRGB_TO_D24S8_FRAG_SPV)), convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)), convert_abgr8_to_d32f_frag(BuildShader(device, CONVERT_ABGR8_TO_D32F_FRAG_SPV)), convert_d32f_to_abgr8_frag(BuildShader(device, CONVERT_D32F_TO_ABGR8_FRAG_SPV)), @@ -554,6 +556,13 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); } +void BlitImageHelper::ConvertABGR8SRGBToD24S8(const Framebuffer* dst_framebuffer, + const ImageView& src_image_view) { + ConvertPipelineDepthTargetEx(convert_abgr8_srgb_to_d24s8_pipeline, + dst_framebuffer->RenderPass(), convert_abgr8_srgb_to_d24s8_frag); + Convert(*convert_abgr8_srgb_to_d24s8_pipeline, dst_framebuffer, src_image_view); +} + void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index b2104a59e..76d384dd6 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -67,6 +67,9 @@ public: void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); + void ConvertABGR8SRGBToD24S8(const Framebuffer* dst_framebuffer, + const ImageView& src_image_view); + void ConvertABGR8ToD32F(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); void ConvertD32FToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view); @@ -131,6 +134,7 @@ private: vk::ShaderModule clear_stencil_frag; vk::ShaderModule convert_depth_to_float_frag; vk::ShaderModule convert_float_to_depth_frag; + vk::ShaderModule convert_abgr8_srgb_to_d24s8_frag; vk::ShaderModule convert_abgr8_to_d24s8_frag; vk::ShaderModule convert_abgr8_to_d32f_frag; vk::ShaderModule convert_d32f_to_abgr8_frag; @@ -151,6 +155,7 @@ private: vk::Pipeline convert_r32_to_d32_pipeline; vk::Pipeline convert_d16_to_r16_pipeline; vk::Pipeline convert_r16_to_d16_pipeline; + vk::Pipeline convert_abgr8_srgb_to_d24s8_pipeline; vk::Pipeline convert_abgr8_to_d24s8_pipeline; vk::Pipeline convert_abgr8_to_d32f_pipeline; vk::Pipeline convert_d32f_to_abgr8_pipeline; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 1426a0870..2280f9174 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1235,6 +1235,9 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im src_view.format == PixelFormat::B8G8R8A8_UNORM) { return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view); } + if (src_view.format == PixelFormat::A8B8G8R8_SRGB) { + return blit_image_helper.ConvertABGR8SRGBToD24S8(dst, src_view); + } break; case PixelFormat::D32_FLOAT: if (src_view.format == PixelFormat::A8B8G8R8_UNORM ||