summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorGravatar bunnei2021-11-20 16:51:13 -0800
committerGravatar GitHub2021-11-20 16:51:13 -0800
commitea6fa044f3e55de3b542c6c1b7ca581cbf76d77e (patch)
tree3eb75c6d43296f2a4cbb41099b4f4e787918b1a1 /src/video_core/renderer_vulkan
parentMerge pull request #7294 from vonchenplus/fix_image_update_error_when_width_t... (diff)
parentTextureCache: Refactor and fix linux compiling. (diff)
downloadyuzu-ea6fa044f3e55de3b542c6c1b7ca581cbf76d77e.tar.gz
yuzu-ea6fa044f3e55de3b542c6c1b7ca581cbf76d77e.tar.xz
yuzu-ea6fa044f3e55de3b542c6c1b7ca581cbf76d77e.zip
Merge pull request #7368 from FernandoS27/vulkan-conv
Fix ART Blit detection regression and add D24S8 <-> RGBA8 conv to Vulkan
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp171
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h39
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp199
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h11
4 files changed, 419 insertions, 1 deletions
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index b3884a4f5..28b631f73 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -4,8 +4,14 @@
4 4
5#include <algorithm> 5#include <algorithm>
6 6
7#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
8#include "video_core/host_shaders/convert_b10g11r11_to_d24s8_frag_spv.h"
9#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
10#include "video_core/host_shaders/convert_d24s8_to_b10g11r11_frag_spv.h"
11#include "video_core/host_shaders/convert_d24s8_to_r16g16_frag_spv.h"
7#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" 12#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
8#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h" 13#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
14#include "video_core/host_shaders/convert_r16g16_to_d24s8_frag_spv.h"
9#include "video_core/host_shaders/full_screen_triangle_vert_spv.h" 15#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
10#include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h" 16#include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h"
11#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h" 17#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
@@ -354,6 +360,12 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
354 blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), 360 blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)),
355 convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)), 361 convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)),
356 convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)), 362 convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
363 convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
364 convert_b10g11r11_to_d24s8_frag(BuildShader(device, CONVERT_B10G11R11_TO_D24S8_FRAG_SPV)),
365 convert_r16g16_to_d24s8_frag(BuildShader(device, CONVERT_R16G16_TO_D24S8_FRAG_SPV)),
366 convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
367 convert_d24s8_to_b10g11r11_frag(BuildShader(device, CONVERT_D24S8_TO_B10G11R11_FRAG_SPV)),
368 convert_d24s8_to_r16g16_frag(BuildShader(device, CONVERT_D24S8_TO_R16G16_FRAG_SPV)),
357 linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), 369 linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
358 nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { 370 nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {
359 if (device.IsExtShaderStencilExportSupported()) { 371 if (device.IsExtShaderStencilExportSupported()) {
@@ -448,6 +460,59 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
448 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 460 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift);
449} 461}
450 462
463void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
464 const ImageView& src_image_view, u32 up_scale,
465 u32 down_shift) {
466 ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
467 convert_abgr8_to_d24s8_frag, true);
468 Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
469 down_shift);
470}
471
472void BlitImageHelper::ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer,
473 const ImageView& src_image_view, u32 up_scale,
474 u32 down_shift) {
475 ConvertPipelineDepthTargetEx(convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
476 convert_b10g11r11_to_d24s8_frag, true);
477 Convert(*convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
478 down_shift);
479}
480
481void BlitImageHelper::ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer,
482 const ImageView& src_image_view, u32 up_scale,
483 u32 down_shift) {
484 ConvertPipelineDepthTargetEx(convert_r16g16_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
485 convert_r16g16_to_d24s8_frag, true);
486 Convert(*convert_r16g16_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
487 down_shift);
488}
489
490void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
491 ImageView& src_image_view, u32 up_scale, u32 down_shift) {
492 ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
493 convert_d24s8_to_abgr8_frag, false);
494 ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale,
495 down_shift);
496}
497
498void BlitImageHelper::ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer,
499 ImageView& src_image_view, u32 up_scale,
500 u32 down_shift) {
501 ConvertPipelineColorTargetEx(convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer->RenderPass(),
502 convert_d24s8_to_b10g11r11_frag, false);
503 ConvertDepthStencil(*convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer, src_image_view,
504 up_scale, down_shift);
505}
506
507void BlitImageHelper::ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer,
508 ImageView& src_image_view, u32 up_scale,
509 u32 down_shift) {
510 ConvertPipelineColorTargetEx(convert_d24s8_to_r16g16_pipeline, dst_framebuffer->RenderPass(),
511 convert_d24s8_to_r16g16_frag, false);
512 ConvertDepthStencil(*convert_d24s8_to_r16g16_pipeline, dst_framebuffer, src_image_view,
513 up_scale, down_shift);
514}
515
451void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 516void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
452 const ImageView& src_image_view, u32 up_scale, u32 down_shift) { 517 const ImageView& src_image_view, u32 up_scale, u32 down_shift) {
453 const VkPipelineLayout layout = *one_texture_pipeline_layout; 518 const VkPipelineLayout layout = *one_texture_pipeline_layout;
@@ -495,6 +560,54 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
495 scheduler.InvalidateState(); 560 scheduler.InvalidateState();
496} 561}
497 562
563void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
564 ImageView& src_image_view, u32 up_scale, u32 down_shift) {
565 const VkPipelineLayout layout = *two_textures_pipeline_layout;
566 const VkImageView src_depth_view = src_image_view.DepthView();
567 const VkImageView src_stencil_view = src_image_view.StencilView();
568 const VkSampler sampler = *nearest_sampler;
569 const VkExtent2D extent{
570 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
571 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
572 };
573 scheduler.RequestRenderpass(dst_framebuffer);
574 scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale,
575 down_shift, this](vk::CommandBuffer cmdbuf) {
576 const VkOffset2D offset{
577 .x = 0,
578 .y = 0,
579 };
580 const VkViewport viewport{
581 .x = 0.0f,
582 .y = 0.0f,
583 .width = static_cast<float>(extent.width),
584 .height = static_cast<float>(extent.height),
585 .minDepth = 0.0f,
586 .maxDepth = 0.0f,
587 };
588 const VkRect2D scissor{
589 .offset = offset,
590 .extent = extent,
591 };
592 const PushConstants push_constants{
593 .tex_scale = {viewport.width, viewport.height},
594 .tex_offset = {0.0f, 0.0f},
595 };
596 const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit();
597 UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
598 src_stencil_view);
599 // TODO: Barriers
600 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
601 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
602 nullptr);
603 cmdbuf.SetViewport(0, viewport);
604 cmdbuf.SetScissor(0, scissor);
605 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
606 cmdbuf.Draw(3, 1, 0, 0);
607 });
608 scheduler.InvalidateState();
609}
610
498VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { 611VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) {
499 const auto it = std::ranges::find(blit_color_keys, key); 612 const auto it = std::ranges::find(blit_color_keys, key);
500 if (it != blit_color_keys.end()) { 613 if (it != blit_color_keys.end()) {
@@ -636,4 +749,62 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
636 }); 749 });
637} 750}
638 751
752void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
753 vk::ShaderModule& module, bool single_texture) {
754 if (pipeline) {
755 return;
756 }
757 const std::array stages = MakeStages(*full_screen_vert, *module);
758 pipeline = device.GetLogical().CreateGraphicsPipeline({
759 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
760 .pNext = nullptr,
761 .flags = 0,
762 .stageCount = static_cast<u32>(stages.size()),
763 .pStages = stages.data(),
764 .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
765 .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
766 .pTessellationState = nullptr,
767 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
768 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
769 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
770 .pDepthStencilState = nullptr,
771 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
772 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
773 .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout,
774 .renderPass = renderpass,
775 .subpass = 0,
776 .basePipelineHandle = VK_NULL_HANDLE,
777 .basePipelineIndex = 0,
778 });
779}
780
781void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
782 vk::ShaderModule& module, bool single_texture) {
783 if (pipeline) {
784 return;
785 }
786 const std::array stages = MakeStages(*full_screen_vert, *module);
787 pipeline = device.GetLogical().CreateGraphicsPipeline({
788 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
789 .pNext = nullptr,
790 .flags = 0,
791 .stageCount = static_cast<u32>(stages.size()),
792 .pStages = stages.data(),
793 .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
794 .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
795 .pTessellationState = nullptr,
796 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
797 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
798 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
799 .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
800 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
801 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
802 .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout,
803 .renderPass = renderpass,
804 .subpass = 0,
805 .basePipelineHandle = VK_NULL_HANDLE,
806 .basePipelineIndex = 0,
807 });
808}
809
639} // namespace Vulkan 810} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index d77f76678..cec095341 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -56,10 +56,31 @@ public:
56 void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 56 void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
57 u32 up_scale, u32 down_shift); 57 u32 up_scale, u32 down_shift);
58 58
59 void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
60 u32 up_scale, u32 down_shift);
61
62 void ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer,
63 const ImageView& src_image_view, u32 up_scale, u32 down_shift);
64
65 void ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
66 u32 up_scale, u32 down_shift);
67
68 void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
69 u32 up_scale, u32 down_shift);
70
71 void ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
72 u32 up_scale, u32 down_shift);
73
74 void ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
75 u32 up_scale, u32 down_shift);
76
59private: 77private:
60 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 78 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
61 const ImageView& src_image_view, u32 up_scale, u32 down_shift); 79 const ImageView& src_image_view, u32 up_scale, u32 down_shift);
62 80
81 void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
82 ImageView& src_image_view, u32 up_scale, u32 down_shift);
83
63 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); 84 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key);
64 85
65 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); 86 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key);
@@ -68,6 +89,12 @@ private:
68 89
69 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); 90 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
70 91
92 void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
93 vk::ShaderModule& module, bool single_texture);
94
95 void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
96 vk::ShaderModule& module, bool single_texture);
97
71 const Device& device; 98 const Device& device;
72 VKScheduler& scheduler; 99 VKScheduler& scheduler;
73 StateTracker& state_tracker; 100 StateTracker& state_tracker;
@@ -83,6 +110,12 @@ private:
83 vk::ShaderModule blit_depth_stencil_frag; 110 vk::ShaderModule blit_depth_stencil_frag;
84 vk::ShaderModule convert_depth_to_float_frag; 111 vk::ShaderModule convert_depth_to_float_frag;
85 vk::ShaderModule convert_float_to_depth_frag; 112 vk::ShaderModule convert_float_to_depth_frag;
113 vk::ShaderModule convert_abgr8_to_d24s8_frag;
114 vk::ShaderModule convert_b10g11r11_to_d24s8_frag;
115 vk::ShaderModule convert_r16g16_to_d24s8_frag;
116 vk::ShaderModule convert_d24s8_to_abgr8_frag;
117 vk::ShaderModule convert_d24s8_to_b10g11r11_frag;
118 vk::ShaderModule convert_d24s8_to_r16g16_frag;
86 vk::Sampler linear_sampler; 119 vk::Sampler linear_sampler;
87 vk::Sampler nearest_sampler; 120 vk::Sampler nearest_sampler;
88 121
@@ -94,6 +127,12 @@ private:
94 vk::Pipeline convert_r32_to_d32_pipeline; 127 vk::Pipeline convert_r32_to_d32_pipeline;
95 vk::Pipeline convert_d16_to_r16_pipeline; 128 vk::Pipeline convert_d16_to_r16_pipeline;
96 vk::Pipeline convert_r16_to_d16_pipeline; 129 vk::Pipeline convert_r16_to_d16_pipeline;
130 vk::Pipeline convert_abgr8_to_d24s8_pipeline;
131 vk::Pipeline convert_b10g11r11_to_d24s8_pipeline;
132 vk::Pipeline convert_r16g16_to_d24s8_pipeline;
133 vk::Pipeline convert_d24s8_to_abgr8_pipeline;
134 vk::Pipeline convert_d24s8_to_b10g11r11_pipeline;
135 vk::Pipeline convert_d24s8_to_r16g16_pipeline;
97}; 136};
98 137
99} // namespace Vulkan 138} // 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 9bc846b94..3964424af 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -8,6 +8,7 @@
8#include <vector> 8#include <vector>
9 9
10#include "common/bit_cast.h" 10#include "common/bit_cast.h"
11#include "common/bit_util.h"
11#include "common/settings.h" 12#include "common/settings.h"
12 13
13#include "video_core/engines/fermi_2d.h" 14#include "video_core/engines/fermi_2d.h"
@@ -313,6 +314,19 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
313 }; 314 };
314} 315}
315 316
317[[nodiscard]] VkBufferImageCopy MakeBufferImageCopy(const VideoCommon::ImageCopy& copy, bool is_src,
318 VkImageAspectFlags aspect_mask) noexcept {
319 return VkBufferImageCopy{
320 .bufferOffset = 0,
321 .bufferRowLength = 0,
322 .bufferImageHeight = 0,
323 .imageSubresource = MakeImageSubresourceLayers(
324 is_src ? copy.src_subresource : copy.dst_subresource, aspect_mask),
325 .imageOffset = MakeOffset3D(is_src ? copy.src_offset : copy.dst_offset),
326 .imageExtent = MakeExtent3D(copy.extent),
327 };
328}
329
316[[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( 330[[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies(
317 std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { 331 std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) {
318 std::vector<VkBufferCopy> result(copies.size()); 332 std::vector<VkBufferCopy> result(copies.size());
@@ -759,6 +773,163 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) {
759 return staging_buffer_pool.Request(size, MemoryUsage::Download); 773 return staging_buffer_pool.Request(size, MemoryUsage::Download);
760} 774}
761 775
776bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) {
777 if (VideoCore::Surface::GetFormatType(dst.info.format) ==
778 VideoCore::Surface::SurfaceType::DepthStencil) {
779 return !device.IsExtShaderStencilExportSupported();
780 }
781 return false;
782}
783
784VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
785 const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL);
786 if (buffer_commits[level]) {
787 return *buffers[level];
788 }
789 const auto new_size = Common::NextPow2(needed_size);
790 VkBufferUsageFlags flags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
791 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT |
792 VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
793 buffers[level] = device.GetLogical().CreateBuffer({
794 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
795 .pNext = nullptr,
796 .flags = 0,
797 .size = new_size,
798 .usage = flags,
799 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
800 .queueFamilyIndexCount = 0,
801 .pQueueFamilyIndices = nullptr,
802 });
803 buffer_commits[level] = std::make_unique<MemoryCommit>(
804 memory_allocator.Commit(buffers[level], MemoryUsage::DeviceLocal));
805 return *buffers[level];
806}
807
808void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
809 std::span<const VideoCommon::ImageCopy> copies) {
810 std::vector<VkBufferImageCopy> vk_in_copies(copies.size());
811 std::vector<VkBufferImageCopy> vk_out_copies(copies.size());
812 const VkImageAspectFlags src_aspect_mask = src.AspectMask();
813 const VkImageAspectFlags dst_aspect_mask = dst.AspectMask();
814
815 std::ranges::transform(copies, vk_in_copies.begin(), [src_aspect_mask](const auto& copy) {
816 return MakeBufferImageCopy(copy, true, src_aspect_mask);
817 });
818 std::ranges::transform(copies, vk_out_copies.begin(), [dst_aspect_mask](const auto& copy) {
819 return MakeBufferImageCopy(copy, false, dst_aspect_mask);
820 });
821 const u32 img_bpp = BytesPerBlock(src.info.format);
822 size_t total_size = 0;
823 for (const auto& copy : copies) {
824 total_size += copy.extent.width * copy.extent.height * copy.extent.depth * img_bpp;
825 }
826 const VkBuffer copy_buffer = GetTemporaryBuffer(total_size);
827 const VkImage dst_image = dst.Handle();
828 const VkImage src_image = src.Handle();
829 scheduler.RequestOutsideRenderPassOperationContext();
830 scheduler.Record([dst_image, src_image, copy_buffer, src_aspect_mask, dst_aspect_mask,
831 vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) {
832 RangedBarrierRange dst_range;
833 RangedBarrierRange src_range;
834 for (const VkBufferImageCopy& copy : vk_in_copies) {
835 src_range.AddLayers(copy.imageSubresource);
836 }
837 for (const VkBufferImageCopy& copy : vk_out_copies) {
838 dst_range.AddLayers(copy.imageSubresource);
839 }
840 static constexpr VkMemoryBarrier READ_BARRIER{
841 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
842 .pNext = nullptr,
843 .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
844 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
845 };
846 static constexpr VkMemoryBarrier WRITE_BARRIER{
847 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
848 .pNext = nullptr,
849 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
850 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
851 };
852 const std::array pre_barriers{
853 VkImageMemoryBarrier{
854 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
855 .pNext = nullptr,
856 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
857 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
858 VK_ACCESS_TRANSFER_WRITE_BIT,
859 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
860 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
861 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
862 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
863 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
864 .image = src_image,
865 .subresourceRange = src_range.SubresourceRange(src_aspect_mask),
866 },
867 };
868 const std::array middle_in_barrier{
869 VkImageMemoryBarrier{
870 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
871 .pNext = nullptr,
872 .srcAccessMask = 0,
873 .dstAccessMask = 0,
874 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
875 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
876 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
877 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
878 .image = src_image,
879 .subresourceRange = src_range.SubresourceRange(src_aspect_mask),
880 },
881 };
882 const std::array middle_out_barrier{
883 VkImageMemoryBarrier{
884 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
885 .pNext = nullptr,
886 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
887 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
888 VK_ACCESS_TRANSFER_WRITE_BIT,
889 .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
890 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
891 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
892 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
893 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
894 .image = dst_image,
895 .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
896 },
897 };
898 const std::array post_barriers{
899 VkImageMemoryBarrier{
900 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
901 .pNext = nullptr,
902 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
903 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
904 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
905 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
906 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
907 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
908 VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
909 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
910 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
911 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
912 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
913 .image = dst_image,
914 .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
915 },
916 };
917 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
918 0, {}, {}, pre_barriers);
919
920 cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer,
921 vk_in_copies);
922 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
923 0, WRITE_BARRIER, nullptr, middle_in_barrier);
924
925 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
926 0, READ_BARRIER, {}, middle_out_barrier);
927 cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies);
928 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
929 0, {}, {}, post_barriers);
930 });
931}
932
762void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 933void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
763 const Region2D& dst_region, const Region2D& src_region, 934 const Region2D& dst_region, const Region2D& src_region,
764 Tegra::Engines::Fermi2D::Filter filter, 935 Tegra::Engines::Fermi2D::Filter filter,
@@ -886,6 +1057,22 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
886 return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); 1057 return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift);
887 } 1058 }
888 break; 1059 break;
1060 case PixelFormat::A8B8G8R8_UNORM:
1061 case PixelFormat::B8G8R8A8_UNORM:
1062 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
1063 return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift);
1064 }
1065 break;
1066 case PixelFormat::B10G11R11_FLOAT:
1067 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
1068 return blit_image_helper.ConvertD24S8ToB10G11R11(dst, src_view, up_scale, down_shift);
1069 }
1070 break;
1071 case PixelFormat::R16G16_UNORM:
1072 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
1073 return blit_image_helper.ConvertD24S8ToR16G16(dst, src_view, up_scale, down_shift);
1074 }
1075 break;
889 case PixelFormat::R32_FLOAT: 1076 case PixelFormat::R32_FLOAT:
890 if (src_view.format == PixelFormat::D32_FLOAT) { 1077 if (src_view.format == PixelFormat::D32_FLOAT) {
891 return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); 1078 return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift);
@@ -896,6 +1083,18 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
896 return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); 1083 return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift);
897 } 1084 }
898 break; 1085 break;
1086 case PixelFormat::S8_UINT_D24_UNORM:
1087 if (src_view.format == PixelFormat::A8B8G8R8_UNORM ||
1088 src_view.format == PixelFormat::B8G8R8A8_UNORM) {
1089 return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift);
1090 }
1091 if (src_view.format == PixelFormat::B10G11R11_FLOAT) {
1092 return blit_image_helper.ConvertB10G11R11ToD24S8(dst, src_view, up_scale, down_shift);
1093 }
1094 if (src_view.format == PixelFormat::R16G16_UNORM) {
1095 return blit_image_helper.ConvertR16G16ToD24S8(dst, src_view, up_scale, down_shift);
1096 }
1097 break;
899 case PixelFormat::D32_FLOAT: 1098 case PixelFormat::D32_FLOAT:
900 if (src_view.format == PixelFormat::R32_FLOAT) { 1099 if (src_view.format == PixelFormat::R32_FLOAT) {
901 return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); 1100 return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift);
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index f5f8f9a74..44e9dcee4 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -61,6 +61,10 @@ public:
61 61
62 void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 62 void CopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
63 63
64 bool ShouldReinterpret(Image& dst, Image& src);
65
66 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
67
64 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); 68 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled);
65 69
66 bool CanAccelerateImageUpload(Image&) const noexcept { 70 bool CanAccelerateImageUpload(Image&) const noexcept {
@@ -82,6 +86,8 @@ public:
82 return true; 86 return true;
83 } 87 }
84 88
89 [[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size);
90
85 const Device& device; 91 const Device& device;
86 VKScheduler& scheduler; 92 VKScheduler& scheduler;
87 MemoryAllocator& memory_allocator; 93 MemoryAllocator& memory_allocator;
@@ -90,6 +96,10 @@ public:
90 ASTCDecoderPass& astc_decoder_pass; 96 ASTCDecoderPass& astc_decoder_pass;
91 RenderPassCache& render_pass_cache; 97 RenderPassCache& render_pass_cache;
92 const Settings::ResolutionScalingInfo& resolution; 98 const Settings::ResolutionScalingInfo& resolution;
99
100 constexpr static size_t indexing_slots = 8 * sizeof(size_t);
101 std::array<vk::Buffer, indexing_slots> buffers{};
102 std::array<std::unique_ptr<MemoryCommit>, indexing_slots> buffer_commits{};
93}; 103};
94 104
95class Image : public VideoCommon::ImageBase { 105class Image : public VideoCommon::ImageBase {
@@ -316,7 +326,6 @@ struct TextureCacheParams {
316 static constexpr bool FRAMEBUFFER_BLITS = false; 326 static constexpr bool FRAMEBUFFER_BLITS = false;
317 static constexpr bool HAS_EMULATED_COPIES = false; 327 static constexpr bool HAS_EMULATED_COPIES = false;
318 static constexpr bool HAS_DEVICE_MEMORY_INFO = true; 328 static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
319 static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = false;
320 329
321 using Runtime = Vulkan::TextureCacheRuntime; 330 using Runtime = Vulkan::TextureCacheRuntime;
322 using Image = Vulkan::Image; 331 using Image = Vulkan::Image;