summaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp155
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h25
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp202
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h14
5 files changed, 401 insertions, 4 deletions
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index b3884a4f5..9a38b6b34 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -4,6 +4,8 @@
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_d24s8_to_abgr8_frag_spv.h"
7#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" 9#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" 10#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
9#include "video_core/host_shaders/full_screen_triangle_vert_spv.h" 11#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
@@ -354,6 +356,8 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
354 blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)), 356 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)), 357 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)), 358 convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
359 convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
360 convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
357 linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)), 361 linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
358 nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) { 362 nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {
359 if (device.IsExtShaderStencilExportSupported()) { 363 if (device.IsExtShaderStencilExportSupported()) {
@@ -448,6 +452,22 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
448 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 452 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift);
449} 453}
450 454
455void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
456 ImageView& src_image_view, u32 up_scale, u32 down_shift) {
457 ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
458 convert_abgr8_to_d24s8_frag, true);
459 ConvertColor(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
460 down_shift);
461}
462
463void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
464 ImageView& src_image_view, u32 up_scale, u32 down_shift) {
465 ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
466 convert_d24s8_to_abgr8_frag, false);
467 ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale,
468 down_shift);
469}
470
451void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 471void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
452 const ImageView& src_image_view, u32 up_scale, u32 down_shift) { 472 const ImageView& src_image_view, u32 up_scale, u32 down_shift) {
453 const VkPipelineLayout layout = *one_texture_pipeline_layout; 473 const VkPipelineLayout layout = *one_texture_pipeline_layout;
@@ -495,6 +515,101 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
495 scheduler.InvalidateState(); 515 scheduler.InvalidateState();
496} 516}
497 517
518void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
519 ImageView& src_image_view, u32 up_scale, u32 down_shift) {
520 const VkPipelineLayout layout = *one_texture_pipeline_layout;
521 const VkImageView src_view = src_image_view.ColorView();
522 const VkSampler sampler = *nearest_sampler;
523 const VkExtent2D extent{
524 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
525 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
526 };
527 scheduler.RequestRenderpass(dst_framebuffer);
528 scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift,
529 this](vk::CommandBuffer cmdbuf) {
530 const VkOffset2D offset{
531 .x = 0,
532 .y = 0,
533 };
534 const VkViewport viewport{
535 .x = 0.0f,
536 .y = 0.0f,
537 .width = static_cast<float>(extent.width),
538 .height = static_cast<float>(extent.height),
539 .minDepth = 0.0f,
540 .maxDepth = 0.0f,
541 };
542 const VkRect2D scissor{
543 .offset = offset,
544 .extent = extent,
545 };
546 const PushConstants push_constants{
547 .tex_scale = {viewport.width, viewport.height},
548 .tex_offset = {0.0f, 0.0f},
549 };
550 const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
551 UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
552
553 // TODO: Barriers
554 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
555 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
556 nullptr);
557 cmdbuf.SetViewport(0, viewport);
558 cmdbuf.SetScissor(0, scissor);
559 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
560 cmdbuf.Draw(3, 1, 0, 0);
561 });
562 scheduler.InvalidateState();
563}
564
565void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
566 ImageView& src_image_view, u32 up_scale, u32 down_shift) {
567 const VkPipelineLayout layout = *two_textures_pipeline_layout;
568 const VkImageView src_depth_view = src_image_view.DepthView();
569 const VkImageView src_stencil_view = src_image_view.StencilView();
570 const VkSampler sampler = *nearest_sampler;
571 const VkExtent2D extent{
572 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
573 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
574 };
575 scheduler.RequestRenderpass(dst_framebuffer);
576 scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale,
577 down_shift, this](vk::CommandBuffer cmdbuf) {
578 const VkOffset2D offset{
579 .x = 0,
580 .y = 0,
581 };
582 const VkViewport viewport{
583 .x = 0.0f,
584 .y = 0.0f,
585 .width = static_cast<float>(extent.width),
586 .height = static_cast<float>(extent.height),
587 .minDepth = 0.0f,
588 .maxDepth = 0.0f,
589 };
590 const VkRect2D scissor{
591 .offset = offset,
592 .extent = extent,
593 };
594 const PushConstants push_constants{
595 .tex_scale = {viewport.width, viewport.height},
596 .tex_offset = {0.0f, 0.0f},
597 };
598 const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit();
599 UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
600 src_stencil_view);
601 // TODO: Barriers
602 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
603 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
604 nullptr);
605 cmdbuf.SetViewport(0, viewport);
606 cmdbuf.SetScissor(0, scissor);
607 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
608 cmdbuf.Draw(3, 1, 0, 0);
609 });
610 scheduler.InvalidateState();
611}
612
498VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { 613VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) {
499 const auto it = std::ranges::find(blit_color_keys, key); 614 const auto it = std::ranges::find(blit_color_keys, key);
500 if (it != blit_color_keys.end()) { 615 if (it != blit_color_keys.end()) {
@@ -636,4 +751,44 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
636 }); 751 });
637} 752}
638 753
754void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
755 vk::ShaderModule& module, bool is_target_depth,
756 bool single_texture) {
757 if (pipeline) {
758 return;
759 }
760 const std::array stages = MakeStages(*full_screen_vert, *module);
761 pipeline = device.GetLogical().CreateGraphicsPipeline({
762 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
763 .pNext = nullptr,
764 .flags = 0,
765 .stageCount = static_cast<u32>(stages.size()),
766 .pStages = stages.data(),
767 .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
768 .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
769 .pTessellationState = nullptr,
770 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
771 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
772 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
773 .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr,
774 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
775 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
776 .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout,
777 .renderPass = renderpass,
778 .subpass = 0,
779 .basePipelineHandle = VK_NULL_HANDLE,
780 .basePipelineIndex = 0,
781 });
782}
783
784void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
785 vk::ShaderModule& module, bool single_texture) {
786 ConvertPipelineEx(pipeline, renderpass, module, false, single_texture);
787}
788
789void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
790 vk::ShaderModule& module, bool single_texture) {
791 ConvertPipelineEx(pipeline, renderpass, module, true, single_texture);
792}
793
639} // namespace Vulkan 794} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index d77f76678..b1a717090 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -56,10 +56,22 @@ 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, ImageView& src_image_view,
60 u32 up_scale, u32 down_shift);
61
62 void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
63 u32 up_scale, u32 down_shift);
64
59private: 65private:
60 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 66 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
61 const ImageView& src_image_view, u32 up_scale, u32 down_shift); 67 const ImageView& src_image_view, u32 up_scale, u32 down_shift);
62 68
69 void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
70 ImageView& src_image_view, u32 up_scale, u32 down_shift);
71
72 void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
73 ImageView& src_image_view, u32 up_scale, u32 down_shift);
74
63 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); 75 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key);
64 76
65 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); 77 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key);
@@ -68,6 +80,15 @@ private:
68 80
69 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); 81 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
70 82
83 void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
84 vk::ShaderModule& module, bool is_target_depth, bool single_texture);
85
86 void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
87 vk::ShaderModule& module, bool single_texture);
88
89 void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
90 vk::ShaderModule& module, bool single_texture);
91
71 const Device& device; 92 const Device& device;
72 VKScheduler& scheduler; 93 VKScheduler& scheduler;
73 StateTracker& state_tracker; 94 StateTracker& state_tracker;
@@ -83,6 +104,8 @@ private:
83 vk::ShaderModule blit_depth_stencil_frag; 104 vk::ShaderModule blit_depth_stencil_frag;
84 vk::ShaderModule convert_depth_to_float_frag; 105 vk::ShaderModule convert_depth_to_float_frag;
85 vk::ShaderModule convert_float_to_depth_frag; 106 vk::ShaderModule convert_float_to_depth_frag;
107 vk::ShaderModule convert_abgr8_to_d24s8_frag;
108 vk::ShaderModule convert_d24s8_to_abgr8_frag;
86 vk::Sampler linear_sampler; 109 vk::Sampler linear_sampler;
87 vk::Sampler nearest_sampler; 110 vk::Sampler nearest_sampler;
88 111
@@ -94,6 +117,8 @@ private:
94 vk::Pipeline convert_r32_to_d32_pipeline; 117 vk::Pipeline convert_r32_to_d32_pipeline;
95 vk::Pipeline convert_d16_to_r16_pipeline; 118 vk::Pipeline convert_d16_to_r16_pipeline;
96 vk::Pipeline convert_r16_to_d16_pipeline; 119 vk::Pipeline convert_r16_to_d16_pipeline;
120 vk::Pipeline convert_abgr8_to_d24s8_pipeline;
121 vk::Pipeline convert_d24s8_to_abgr8_pipeline;
97}; 122};
98 123
99} // namespace Vulkan 124} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 68a23b602..751e4792b 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -162,7 +162,7 @@ struct FormatTuple {
162 {VK_FORMAT_UNDEFINED}, // R16_SINT 162 {VK_FORMAT_UNDEFINED}, // R16_SINT
163 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM 163 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM
164 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT 164 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT
165 {VK_FORMAT_UNDEFINED}, // R16G16_UINT 165 {VK_FORMAT_R16G16_UINT, Attachable | Storage}, // R16G16_UINT
166 {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT 166 {VK_FORMAT_R16G16_SINT, Attachable | Storage}, // R16G16_SINT
167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM 167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM
168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT 168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT
@@ -176,8 +176,8 @@ struct FormatTuple {
176 {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32_UINT 176 {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32_UINT
177 {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32_SINT 177 {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32_SINT
178 {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8_UNORM 178 {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8_UNORM
179 {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5_UNORM 179 {VK_FORMAT_ASTC_8x5_UNORM_BLOCK}, // ASTC_2D_8X5_UNORM
180 {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4_UNORM 180 {VK_FORMAT_ASTC_5x4_UNORM_BLOCK}, // ASTC_2D_5X4_UNORM
181 {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // B8G8R8A8_SRGB 181 {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // B8G8R8A8_SRGB
182 {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // BC1_RGBA_SRGB 182 {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // BC1_RGBA_SRGB
183 {VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB 183 {VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB
@@ -208,6 +208,9 @@ struct FormatTuple {
208 {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT 208 {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT
209 {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM 209 {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM
210 210
211 // Stencil formats
212 {VK_FORMAT_S8_UINT, Attachable}, // S8_UINT
213
211 // DepthStencil formats 214 // DepthStencil formats
212 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT 215 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT
213 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated) 216 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated)
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 407fd2a15..197cba8e3 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"
@@ -102,6 +103,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
102 usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 103 usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
103 break; 104 break;
104 case VideoCore::Surface::SurfaceType::Depth: 105 case VideoCore::Surface::SurfaceType::Depth:
106 case VideoCore::Surface::SurfaceType::Stencil:
105 case VideoCore::Surface::SurfaceType::DepthStencil: 107 case VideoCore::Surface::SurfaceType::DepthStencil:
106 usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 108 usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
107 break; 109 break;
@@ -173,6 +175,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
173 return VK_IMAGE_ASPECT_COLOR_BIT; 175 return VK_IMAGE_ASPECT_COLOR_BIT;
174 case VideoCore::Surface::SurfaceType::Depth: 176 case VideoCore::Surface::SurfaceType::Depth:
175 return VK_IMAGE_ASPECT_DEPTH_BIT; 177 return VK_IMAGE_ASPECT_DEPTH_BIT;
178 case VideoCore::Surface::SurfaceType::Stencil:
179 return VK_IMAGE_ASPECT_STENCIL_BIT;
176 case VideoCore::Surface::SurfaceType::DepthStencil: 180 case VideoCore::Surface::SurfaceType::DepthStencil:
177 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 181 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
178 default: 182 default:
@@ -195,6 +199,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
195 case PixelFormat::D16_UNORM: 199 case PixelFormat::D16_UNORM:
196 case PixelFormat::D32_FLOAT: 200 case PixelFormat::D32_FLOAT:
197 return VK_IMAGE_ASPECT_DEPTH_BIT; 201 return VK_IMAGE_ASPECT_DEPTH_BIT;
202 case PixelFormat::S8_UINT:
203 return VK_IMAGE_ASPECT_STENCIL_BIT;
198 default: 204 default:
199 return VK_IMAGE_ASPECT_COLOR_BIT; 205 return VK_IMAGE_ASPECT_COLOR_BIT;
200 } 206 }
@@ -308,6 +314,19 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
308 }; 314 };
309} 315}
310 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
311[[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies( 330[[maybe_unused]] [[nodiscard]] std::vector<VkBufferCopy> TransformBufferCopies(
312 std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) { 331 std::span<const VideoCommon::BufferCopy> copies, size_t buffer_offset) {
313 std::vector<VkBufferCopy> result(copies.size()); 332 std::vector<VkBufferCopy> result(copies.size());
@@ -754,6 +773,173 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) {
754 return staging_buffer_pool.Request(size, MemoryUsage::Download); 773 return staging_buffer_pool.Request(size, MemoryUsage::Download);
755} 774}
756 775
776bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) {
777 if (VideoCore::Surface::GetFormatType(dst.info.format) ==
778 VideoCore::Surface::SurfaceType::DepthStencil &&
779 !device.IsExtShaderStencilExportSupported()) {
780 return true;
781 }
782 if (VideoCore::Surface::GetFormatType(src.info.format) ==
783 VideoCore::Surface::SurfaceType::DepthStencil &&
784 !device.IsExtShaderStencilExportSupported()) {
785 return true;
786 }
787 if (dst.info.format == PixelFormat::D32_FLOAT_S8_UINT ||
788 src.info.format == PixelFormat::D32_FLOAT_S8_UINT) {
789 return true;
790 }
791 return false;
792}
793
794VkBuffer TextureCacheRuntime::GetTemporaryBuffer(size_t needed_size) {
795 const auto level = (8 * sizeof(size_t)) - std::countl_zero(needed_size - 1ULL);
796 if (buffer_commits[level]) {
797 return *buffers[level];
798 }
799 const auto new_size = Common::NextPow2(needed_size);
800 static constexpr VkBufferUsageFlags flags =
801 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
802 VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT;
803 buffers[level] = device.GetLogical().CreateBuffer({
804 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
805 .pNext = nullptr,
806 .flags = 0,
807 .size = new_size,
808 .usage = flags,
809 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
810 .queueFamilyIndexCount = 0,
811 .pQueueFamilyIndices = nullptr,
812 });
813 buffer_commits[level] = std::make_unique<MemoryCommit>(
814 memory_allocator.Commit(buffers[level], MemoryUsage::DeviceLocal));
815 return *buffers[level];
816}
817
818void TextureCacheRuntime::ReinterpretImage(Image& dst, Image& src,
819 std::span<const VideoCommon::ImageCopy> copies) {
820 std::vector<VkBufferImageCopy> vk_in_copies(copies.size());
821 std::vector<VkBufferImageCopy> vk_out_copies(copies.size());
822 const VkImageAspectFlags src_aspect_mask = src.AspectMask();
823 const VkImageAspectFlags dst_aspect_mask = dst.AspectMask();
824
825 std::ranges::transform(copies, vk_in_copies.begin(), [src_aspect_mask](const auto& copy) {
826 return MakeBufferImageCopy(copy, true, src_aspect_mask);
827 });
828 std::ranges::transform(copies, vk_out_copies.begin(), [dst_aspect_mask](const auto& copy) {
829 return MakeBufferImageCopy(copy, false, dst_aspect_mask);
830 });
831 const u32 img_bpp = BytesPerBlock(src.info.format);
832 size_t total_size = 0;
833 for (const auto& copy : copies) {
834 total_size += copy.extent.width * copy.extent.height * copy.extent.depth * img_bpp;
835 }
836 const VkBuffer copy_buffer = GetTemporaryBuffer(total_size);
837 const VkImage dst_image = dst.Handle();
838 const VkImage src_image = src.Handle();
839 scheduler.RequestOutsideRenderPassOperationContext();
840 scheduler.Record([dst_image, src_image, copy_buffer, src_aspect_mask, dst_aspect_mask,
841 vk_in_copies, vk_out_copies](vk::CommandBuffer cmdbuf) {
842 RangedBarrierRange dst_range;
843 RangedBarrierRange src_range;
844 for (const VkBufferImageCopy& copy : vk_in_copies) {
845 src_range.AddLayers(copy.imageSubresource);
846 }
847 for (const VkBufferImageCopy& copy : vk_out_copies) {
848 dst_range.AddLayers(copy.imageSubresource);
849 }
850 static constexpr VkMemoryBarrier READ_BARRIER{
851 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
852 .pNext = nullptr,
853 .srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
854 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
855 };
856 static constexpr VkMemoryBarrier WRITE_BARRIER{
857 .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
858 .pNext = nullptr,
859 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
860 .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
861 };
862 const std::array pre_barriers{
863 VkImageMemoryBarrier{
864 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
865 .pNext = nullptr,
866 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
867 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
868 VK_ACCESS_TRANSFER_WRITE_BIT,
869 .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
870 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
871 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
872 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
873 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
874 .image = src_image,
875 .subresourceRange = src_range.SubresourceRange(src_aspect_mask),
876 },
877 };
878 const std::array middle_in_barrier{
879 VkImageMemoryBarrier{
880 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
881 .pNext = nullptr,
882 .srcAccessMask = 0,
883 .dstAccessMask = 0,
884 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
885 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
886 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
887 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
888 .image = src_image,
889 .subresourceRange = src_range.SubresourceRange(src_aspect_mask),
890 },
891 };
892 const std::array middle_out_barrier{
893 VkImageMemoryBarrier{
894 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
895 .pNext = nullptr,
896 .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
897 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
898 VK_ACCESS_TRANSFER_WRITE_BIT,
899 .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
900 .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
901 .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
902 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
903 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
904 .image = dst_image,
905 .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
906 },
907 };
908 const std::array post_barriers{
909 VkImageMemoryBarrier{
910 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
911 .pNext = nullptr,
912 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
913 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
914 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
915 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
916 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
917 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
918 VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
919 .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
920 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
921 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
922 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
923 .image = dst_image,
924 .subresourceRange = dst_range.SubresourceRange(dst_aspect_mask),
925 },
926 };
927 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
928 0, {}, {}, pre_barriers);
929
930 cmdbuf.CopyImageToBuffer(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, copy_buffer,
931 vk_in_copies);
932 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
933 0, WRITE_BARRIER, nullptr, middle_in_barrier);
934
935 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
936 0, READ_BARRIER, {}, middle_out_barrier);
937 cmdbuf.CopyBufferToImage(copy_buffer, dst_image, VK_IMAGE_LAYOUT_GENERAL, vk_out_copies);
938 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
939 0, {}, {}, post_barriers);
940 });
941}
942
757void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 943void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src,
758 const Region2D& dst_region, const Region2D& src_region, 944 const Region2D& dst_region, const Region2D& src_region,
759 Tegra::Engines::Fermi2D::Filter filter, 945 Tegra::Engines::Fermi2D::Filter filter,
@@ -881,6 +1067,11 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
881 return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); 1067 return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift);
882 } 1068 }
883 break; 1069 break;
1070 case PixelFormat::A8B8G8R8_UNORM:
1071 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
1072 return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift);
1073 }
1074 break;
884 case PixelFormat::R32_FLOAT: 1075 case PixelFormat::R32_FLOAT:
885 if (src_view.format == PixelFormat::D32_FLOAT) { 1076 if (src_view.format == PixelFormat::D32_FLOAT) {
886 return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); 1077 return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift);
@@ -891,6 +1082,9 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
891 return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); 1082 return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift);
892 } 1083 }
893 break; 1084 break;
1085 case PixelFormat::S8_UINT_D24_UNORM:
1086 return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift);
1087 break;
894 case PixelFormat::D32_FLOAT: 1088 case PixelFormat::D32_FLOAT:
895 if (src_view.format == PixelFormat::R32_FLOAT) { 1089 if (src_view.format == PixelFormat::R32_FLOAT) {
896 return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); 1090 return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift);
@@ -1386,6 +1580,14 @@ VkImageView ImageView::StencilView() {
1386 return *stencil_view; 1580 return *stencil_view;
1387} 1581}
1388 1582
1583VkImageView ImageView::ColorView() {
1584 if (color_view) {
1585 return *color_view;
1586 }
1587 color_view = MakeView(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
1588 return *color_view;
1589}
1590
1389VkImageView ImageView::StorageView(Shader::TextureType texture_type, 1591VkImageView ImageView::StorageView(Shader::TextureType texture_type,
1390 Shader::ImageFormat image_format) { 1592 Shader::ImageFormat image_format) {
1391 if (image_format == Shader::ImageFormat::Typeless) { 1593 if (image_format == Shader::ImageFormat::Typeless) {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index f5f8f9a74..753e3e8a1 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 {
@@ -174,6 +184,8 @@ public:
174 184
175 [[nodiscard]] VkImageView StencilView(); 185 [[nodiscard]] VkImageView StencilView();
176 186
187 [[nodiscard]] VkImageView ColorView();
188
177 [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type, 189 [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type,
178 Shader::ImageFormat image_format); 190 Shader::ImageFormat image_format);
179 191
@@ -214,6 +226,7 @@ private:
214 std::unique_ptr<StorageViews> storage_views; 226 std::unique_ptr<StorageViews> storage_views;
215 vk::ImageView depth_view; 227 vk::ImageView depth_view;
216 vk::ImageView stencil_view; 228 vk::ImageView stencil_view;
229 vk::ImageView color_view;
217 VkImage image_handle = VK_NULL_HANDLE; 230 VkImage image_handle = VK_NULL_HANDLE;
218 VkImageView render_target = VK_NULL_HANDLE; 231 VkImageView render_target = VK_NULL_HANDLE;
219 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; 232 VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
@@ -316,7 +329,6 @@ struct TextureCacheParams {
316 static constexpr bool FRAMEBUFFER_BLITS = false; 329 static constexpr bool FRAMEBUFFER_BLITS = false;
317 static constexpr bool HAS_EMULATED_COPIES = false; 330 static constexpr bool HAS_EMULATED_COPIES = false;
318 static constexpr bool HAS_DEVICE_MEMORY_INFO = true; 331 static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
319 static constexpr bool HAS_PIXEL_FORMAT_CONVERSIONS = false;
320 332
321 using Runtime = Vulkan::TextureCacheRuntime; 333 using Runtime = Vulkan::TextureCacheRuntime;
322 using Image = Vulkan::Image; 334 using Image = Vulkan::Image;