diff --git a/src/video_core/host_shaders/convert_depth_to_float.frag b/src/video_core/host_shaders/convert_depth_to_float.frag index 57f0ce5a61..b963e86f66 100644 --- a/src/video_core/host_shaders/convert_depth_to_float.frag +++ b/src/video_core/host_shaders/convert_depth_to_float.frag @@ -4,9 +4,15 @@ #version 450 layout(binding = 0) uniform sampler2D depth_texture; -layout(location = 0) out float output_color; +layout(location = 0) out vec4 output_color; void main() { ivec2 coord = ivec2(gl_FragCoord.xy); - output_color = texelFetch(depth_texture, coord, 0).r; + float depth = texelFetch(depth_texture, coord, 0).r; + bool invalid = isnan(depth) || isinf(depth); + float sanitized_depth = clamp(depth, 0.0, 1.0); + if (invalid) { + sanitized_depth = 0.0; + } + output_color = vec4(sanitized_depth, sanitized_depth, sanitized_depth, 1.0); } diff --git a/src/video_core/host_shaders/convert_float_to_depth.frag b/src/video_core/host_shaders/convert_float_to_depth.frag index 5d403b1ec8..85c6428232 100644 --- a/src/video_core/host_shaders/convert_float_to_depth.frag +++ b/src/video_core/host_shaders/convert_float_to_depth.frag @@ -7,6 +7,11 @@ layout(binding = 0) uniform sampler2D color_texture; void main() { ivec2 coord = ivec2(gl_FragCoord.xy); - float color = texelFetch(color_texture, coord, 0).r; - gl_FragDepth = color; + vec4 color = texelFetch(color_texture, coord, 0); + bool invalid = any(isnan(color)) || any(isinf(color)); + float depth = color.r; + if (invalid) { + depth = 1.0; + } + gl_FragDepth = clamp(depth, 0.0, 1.0); } diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 96829c7905..252ac79fa5 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -5,6 +5,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include "video_core/renderer_vulkan/vk_texture_cache.h" @@ -46,7 +47,18 @@ namespace Vulkan { using VideoCommon::ImageViewType; namespace { - + +[[nodiscard]] bool IsQualcommStockDevice(const Device& device) { + const VkDriverIdKHR driver_id = device.GetDriverID(); + if (driver_id == VK_DRIVER_ID_MESA_TURNIP) { + return false; + } + if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { + return true; + } + return false; +} + [[nodiscard]] VkImageAspectFlags AspectMaskFromFormat(VideoCore::Surface::PixelFormat format) { using VideoCore::Surface::SurfaceType; switch (VideoCore::Surface::GetFormatType(format)) { @@ -546,7 +558,8 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, dither_temporal_frag(BuildShader(device, DITHER_TEMPORAL_FRAG_SPV)), dynamic_resolution_scale_comp(BuildShader(device, DYNAMIC_RESOLUTION_SCALE_COMP_SPV)), linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO)), - nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO)) {} + nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO)), + is_qualcomm_stock(IsQualcommStockDevice(device)) {} BlitImageHelper::~BlitImageHelper() = default; @@ -765,7 +778,8 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb RecordShaderReadBarrier(scheduler, src_image_view); scheduler.RequestRenderpass(dst_framebuffer); - scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) { + scheduler.Record([pipeline, layout, sampler, src_view, extent, dst_framebuffer, this]( + vk::CommandBuffer cmdbuf) { const VkOffset2D offset{ .x = 0, .y = 0, @@ -776,7 +790,7 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb .width = static_cast(extent.width), .height = static_cast(extent.height), .minDepth = 0.0f, - .maxDepth = 0.0f, + .maxDepth = 1.0f, }; const VkRect2D scissor{ .offset = offset, @@ -789,6 +803,43 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view); + std::array clear_attachments{}; + u32 clear_attachment_count = 0; + if (dst_framebuffer->NumColorBuffers() > 0) { + for (u32 i = 0; i < dst_framebuffer->NumColorBuffers(); ++i) { + if (!dst_framebuffer->HasAspectColorBit(i)) { + continue; + } + VkClearAttachment& color_attachment = clear_attachments.at(clear_attachment_count++); + color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + color_attachment.colorAttachment = i; + color_attachment.clearValue.color = VkClearColorValue{{0.0f, 0.0f, 0.0f, 0.0f}}; + } + } + if (dst_framebuffer->HasAspectDepthBit()) { + VkClearAttachment& depth_attachment = clear_attachments.at(clear_attachment_count++); + depth_attachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (dst_framebuffer->HasAspectStencilBit()) { + depth_attachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + depth_attachment.clearValue.depthStencil = VkClearDepthStencilValue{1.0f, 0}; + } + if (clear_attachment_count > 0) { + const VkClearRect clear_rect{ + .rect = + { + .offset = offset, + .extent = extent, + }, + .baseArrayLayer = 0, + .layerCount = 1, + }; + const std::array clear_rects{clear_rect}; + cmdbuf.ClearAttachments(vk::Span(clear_attachments.data(), + clear_attachment_count), + clear_rects); + } + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, nullptr); @@ -811,7 +862,7 @@ void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer RecordShaderReadBarrier(scheduler, src_image_view); scheduler.RequestRenderpass(dst_framebuffer); scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, - this](vk::CommandBuffer cmdbuf) { + dst_framebuffer, this](vk::CommandBuffer cmdbuf) { const VkOffset2D offset{ .x = 0, .y = 0, @@ -822,7 +873,7 @@ void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer .width = static_cast(extent.width), .height = static_cast(extent.height), .minDepth = 0.0f, - .maxDepth = 0.0f, + .maxDepth = 1.0f, }; const VkRect2D scissor{ .offset = offset, @@ -835,6 +886,42 @@ void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit(); UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view, src_stencil_view); + std::array clear_attachments{}; + u32 clear_attachment_count = 0; + if (dst_framebuffer->NumColorBuffers() > 0) { + for (u32 i = 0; i < dst_framebuffer->NumColorBuffers(); ++i) { + if (!dst_framebuffer->HasAspectColorBit(i)) { + continue; + } + VkClearAttachment& color_attachment = clear_attachments[clear_attachment_count++]; + color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + color_attachment.colorAttachment = i; + color_attachment.clearValue.color = VkClearColorValue{{0.0f, 0.0f, 0.0f, 0.0f}}; + } + } + if (dst_framebuffer->HasAspectDepthBit()) { + VkClearAttachment& depth_attachment = clear_attachments[clear_attachment_count++]; + depth_attachment.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + if (dst_framebuffer->HasAspectStencilBit()) { + depth_attachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; + } + depth_attachment.clearValue.depthStencil = VkClearDepthStencilValue{1.0f, 0}; + } + if (clear_attachment_count > 0) { + const VkClearRect clear_rect{ + .rect = + { + .offset = offset, + .extent = extent, + }, + .baseArrayLayer = 0, + .layerCount = 1, + }; + const std::array clear_rects{clear_rect}; + cmdbuf.ClearAttachments(vk::Span(clear_attachments.data(), + clear_attachment_count), + clear_rects); + } cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, nullptr); @@ -1079,6 +1166,11 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend VkShaderModule frag_shader = *convert_float_to_depth_frag; const std::array stages = MakeStages(*full_screen_vert, frag_shader); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + VkPipelineDepthStencilStateCreateInfo depth_stencil_ci = PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil_ci.depthTestEnable = VK_TRUE; + depth_stencil_ci.depthWriteEnable = VK_TRUE; + depth_stencil_ci.depthCompareOp = VK_COMPARE_OP_ALWAYS; + depth_stencil_ci.stencilTestEnable = VK_FALSE; pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -1091,7 +1183,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .pDepthStencilState = &depth_stencil_ci, .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *one_texture_pipeline_layout, @@ -1152,6 +1244,11 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; const std::array stages = MakeStages(*full_screen_vert, frag_shader); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + VkPipelineDepthStencilStateCreateInfo depth_stencil_ci = PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil_ci.depthTestEnable = VK_TRUE; + depth_stencil_ci.depthWriteEnable = VK_TRUE; + depth_stencil_ci.depthCompareOp = VK_COMPARE_OP_ALWAYS; + depth_stencil_ci.stencilTestEnable = VK_FALSE; pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = nullptr, @@ -1164,7 +1261,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr, + .pDepthStencilState = is_target_depth ? &depth_stencil_ci : nullptr, .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index bdb8cce883..e79bb31ab0 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -188,6 +188,8 @@ private: vk::Pipeline convert_rgba16f_to_rgba8_pipeline; vk::Pipeline dither_temporal_pipeline; vk::Pipeline dynamic_resolution_scale_pipeline; + + [[maybe_unused]] const bool is_qualcomm_stock; }; } // namespace Vulkan