diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index be46842cd9..35d092c3bc 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -19,6 +19,7 @@ set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d.comp ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_2d_buffer.comp ${CMAKE_CURRENT_SOURCE_DIR}/blit_color_msaa.frag + ${CMAKE_CURRENT_SOURCE_DIR}/blit_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/blit_depth_stencil_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/block_linear_unswizzle_3d.comp diff --git a/src/video_core/host_shaders/blit_depth.frag b/src/video_core/host_shaders/blit_depth.frag new file mode 100644 index 0000000000..9e19c767aa --- /dev/null +++ b/src/video_core/host_shaders/blit_depth.frag @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#version 450 core + +layout(binding = 0) uniform sampler2D depth_tex; + +layout(location = 0) in vec2 texcoord; + +void main() { + gl_FragDepth = textureLod(depth_tex, texcoord, 0).r; +} diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index d0d64d936a..1f3d452e16 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -12,6 +12,7 @@ #include "common/settings.h" #include "video_core/host_shaders/blit_color_float_frag_spv.h" #include "video_core/host_shaders/blit_color_msaa_frag_spv.h" +#include "video_core/host_shaders/blit_depth_frag_spv.h" #include "video_core/host_shaders/blit_depth_msaa_frag_spv.h" #include "video_core/host_shaders/blit_depth_stencil_msaa_frag_spv.h" #include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" @@ -599,6 +600,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, blit_depth_stencil_frag(device.IsExtShaderStencilExportSupported() ? BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV) : vk::ShaderModule{}), + blit_depth_frag(BuildShader(device, BLIT_DEPTH_FRAG_SPV)), blit_depth_msaa_frag(BuildShader(device, BLIT_DEPTH_MSAA_FRAG_SPV)), blit_depth_stencil_msaa_frag(device.IsExtShaderStencilExportSupported() ? BuildShader(device, BLIT_DEPTH_STENCIL_MSAA_FRAG_SPV) @@ -750,6 +752,28 @@ void BlitImageHelper::BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer, scheduler.InvalidateState(); } +void BlitImageHelper::BlitDepth(const Framebuffer* dst_framebuffer, ImageView& src_image_view, + const Region2D& dst_region, const Region2D& src_region) { + const VkPipeline pipeline = FindOrEmplaceBlitDepthPipeline(dst_framebuffer->RenderPass()); + const VkPipelineLayout layout = *one_texture_pipeline_layout; + const VkSampler sampler = *nearest_sampler; + const VkImageView src_depth_view = src_image_view.DepthView(); + + RecordShaderReadBarrier(scheduler, src_image_view); + scheduler.RequestRenderpass(dst_framebuffer); + scheduler.Record([this, dst_region, src_region, pipeline, layout, sampler, + src_depth_view](vk::CommandBuffer cmdbuf) { + const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); + UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_depth_view); + cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set, + nullptr); + BindBlitState(cmdbuf, layout, dst_region, src_region); + cmdbuf.Draw(3, 1, 0, 0); + }); + scheduler.InvalidateState(); +} + void BlitImageHelper::ResolveDepthStencil(const Framebuffer* dst_framebuffer, ImageView& src_image_view, const Region2D& dst_region, const Region2D& src_region) { @@ -1483,6 +1507,38 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthStencilMSAAPipeline( return *pipelines.back(); } +VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpass) { + const auto it = std::ranges::find(blit_depth_keys, renderpass); + if (it != blit_depth_keys.end()) { + return *blit_depth_pipelines[std::distance(blit_depth_keys.begin(), it)]; + } + blit_depth_keys.push_back(renderpass); + const std::array stages = MakeStages(*full_screen_vert, *blit_depth_frag); + const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + blit_depth_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stageCount = static_cast(stages.size()), + .pStages = stages.data(), + .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .pInputAssemblyState = &input_assembly_ci, + .pTessellationState = nullptr, + .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pDepthStencilState = &PIPELINE_DEPTH_ONLY_STATE_CREATE_INFO, + .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, + .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .layout = *one_texture_pipeline_layout, + .renderPass = renderpass, + .subpass = 0, + .basePipelineHandle = VK_NULL_HANDLE, + .basePipelineIndex = 0, + }, device.StaticPipelineCache())); + return *blit_depth_pipelines.back(); +} + VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, bool resolve_stencil) { auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys; diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 0ff73064a1..3b073f2825 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -81,6 +81,9 @@ public: void BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer, ImageView& src_image_view, const Region2D& dst_region, const Region2D& src_region); + void BlitDepth(const Framebuffer* dst_framebuffer, ImageView& src_image_view, + const Region2D& dst_region, const Region2D& src_region); + void ResolveDepthStencil(const Framebuffer* dst_framebuffer, ImageView& src_image_view, const Region2D& dst_region, const Region2D& src_region); @@ -145,6 +148,7 @@ private: [[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceBlitDepthStencilMSAAPipeline( const BlitMSAAPipelineKey& key, bool blit_stencil); + [[nodiscard]] VkPipeline FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpass); [[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, bool resolve_stencil); @@ -180,6 +184,7 @@ private: vk::ShaderModule blit_color_to_color_frag; vk::ShaderModule blit_color_msaa_frag; vk::ShaderModule blit_depth_stencil_frag; + vk::ShaderModule blit_depth_frag; vk::ShaderModule blit_depth_msaa_frag; vk::ShaderModule blit_depth_stencil_msaa_frag; vk::ShaderModule clear_color_vert; @@ -215,6 +220,8 @@ private: std::vector msaa_copy_depth_stencil_pipelines; std::vector blit_msaa_color_keys; std::vector blit_msaa_color_pipelines; + std::vector blit_depth_keys; + std::vector blit_depth_pipelines; std::vector blit_msaa_depth_keys; std::vector blit_msaa_depth_pipelines; std::vector blit_msaa_depth_stencil_keys; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index bfac4c5071..2713840d60 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -2265,7 +2265,10 @@ bool Image::ScaleUp(bool ignore) { aspect_mask = ImageAspectMask(info.format); } if (NeedsScaleHelper()) { - return BlitScaleHelper(true); + if (!BlitScaleHelper(true)) { + current_image = &Image::original_image; + return false; + } } else { BlitScale(*scheduler, *original_image, *scaled_image, info, aspect_mask, resolution); } @@ -2290,7 +2293,11 @@ bool Image::ScaleDown(bool ignore) { aspect_mask = ImageAspectMask(info.format); } if (NeedsScaleHelper()) { - return BlitScaleHelper(false); + if (!BlitScaleHelper(false)) { + current_image = &Image::scaled_image; + flags |= ImageFlagBits::Rescaled; + return false; + } } else { BlitScale(*scheduler, *scaled_image, *original_image, info, aspect_mask, resolution, false); } @@ -2345,21 +2352,22 @@ bool Image::BlitScaleHelper(bool scale_up) { runtime->blit_image_helper.BlitColor(&*blit_framebuffer, *blit_view, dst_region, src_region, operation, BLIT_OPERATION); } - } else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { + } else if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) { if (!blit_framebuffer) blit_framebuffer.emplace(*runtime, nullptr, view_ptr, extent, scale_up); + const bool has_stencil = (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; + const bool can_blit_stencil = + has_stencil && runtime->device.IsExtShaderStencilExportSupported(); if (info.num_samples > 1) { runtime->blit_image_helper.BlitDepthStencilMSAA(&*blit_framebuffer, *blit_view, dst_region, src_region); - } else { + } else if (can_blit_stencil) { runtime->blit_image_helper.BlitDepthStencil(&*blit_framebuffer, *blit_view, dst_region, src_region, operation, BLIT_OPERATION); + } else { + runtime->blit_image_helper.BlitDepth(&*blit_framebuffer, *blit_view, dst_region, + src_region); } - } else if (aspect_mask == VK_IMAGE_ASPECT_DEPTH_BIT && info.num_samples > 1) { - if (!blit_framebuffer) - blit_framebuffer.emplace(*runtime, nullptr, view_ptr, extent, scale_up); - runtime->blit_image_helper.BlitDepthStencilMSAA(&*blit_framebuffer, *blit_view, dst_region, - src_region); } else { // TODO: Use helper blits where applicable flags &= ~ImageFlagBits::Rescaled; diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 98a5e053a7..9ffe0cbb25 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -1476,12 +1476,12 @@ template bool TextureCache

::ScaleUp(Image& image) { const bool has_copy = image.HasScaled(); const bool rescaled = image.ScaleUp(); + if (!has_copy && image.HasScaled()) { + total_used_memory += GetScaledImageSizeBytes(image); + } if (!rescaled) { return false; } - if (!has_copy) { - total_used_memory += GetScaledImageSizeBytes(image); - } InvalidateScale(image); return true; }