diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 33d2bdbe16..ed48ed7973 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -209,6 +209,7 @@ endforeach() set(SHADER_DEFINE_VARIANTS "block_linear_unswizzle_2d.comp|nonarrow|HAS_EXTENDED_TYPES=0" "pitch_unswizzle.comp|nonarrow|HAS_EXTENDED_TYPES=0" + "block_linear_unswizzle_3d.comp|nonarrow|HAS_EXTENDED_TYPES=0" ) foreach(VARIANT IN ITEMS ${SHADER_DEFINE_VARIANTS}) diff --git a/src/video_core/host_shaders/block_linear_unswizzle_3d.comp b/src/video_core/host_shaders/block_linear_unswizzle_3d.comp index 34e4f93307..f89ed10858 100644 --- a/src/video_core/host_shaders/block_linear_unswizzle_3d.comp +++ b/src/video_core/host_shaders/block_linear_unswizzle_3d.comp @@ -5,9 +5,13 @@ #ifdef VULKAN +#ifndef HAS_EXTENDED_TYPES +#define HAS_EXTENDED_TYPES 1 +#endif +#if HAS_EXTENDED_TYPES #extension GL_EXT_shader_16bit_storage : require #extension GL_EXT_shader_8bit_storage : require -#define HAS_EXTENDED_TYPES 1 +#endif #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { #define END_PUSH_CONSTANTS }; #define UNIFORM(n) diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 68ec866109..5f0d3b0f2f 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -25,6 +25,8 @@ #include "video_core/host_shaders/block_linear_unswizzle_2d_comp_spv.h" #include "video_core/host_shaders/block_linear_unswizzle_2d_nonarrow_comp_spv.h" #include "video_core/host_shaders/block_linear_unswizzle_3d_bcn_comp_spv.h" +#include "video_core/host_shaders/block_linear_unswizzle_3d_comp_spv.h" +#include "video_core/host_shaders/block_linear_unswizzle_3d_nonarrow_comp_spv.h" #include "video_core/host_shaders/pitch_unswizzle_comp_spv.h" #include "video_core/host_shaders/pitch_unswizzle_nonarrow_comp_spv.h" #include "video_core/renderer_vulkan/vk_compute_pass.h" @@ -1063,6 +1065,54 @@ void BlockLinearUnswizzle2DPass::Unswizzle( RecordUnswizzleExitBarrier(scheduler, vk_image, aspect_mask); } +BlockLinearUnswizzleImage3DPass::BlockLinearUnswizzleImage3DPass( + const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, + ComputePassDescriptorQueue& compute_pass_descriptor_queue_) + : ComputePass(device_, scheduler_, descriptor_pool_, UNSWIZZLE_DESCRIPTOR_SET_BINDINGS, + UNSWIZZLE_DESCRIPTOR_UPDATE_TEMPLATE, UNSWIZZLE_BANK_INFO, + COMPUTE_PUSH_CONSTANT_RANGE, + UnswizzleSpv(device_, BLOCK_LINEAR_UNSWIZZLE_3D_COMP_SPV, + BLOCK_LINEAR_UNSWIZZLE_3D_NONARROW_COMP_SPV)), + scheduler{scheduler_}, compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {} + +BlockLinearUnswizzleImage3DPass::~BlockLinearUnswizzleImage3DPass() = default; + +void BlockLinearUnswizzleImage3DPass::Unswizzle( + Image& image, const StagingBufferRef& map, + std::span swizzles) { + using namespace VideoCommon::Accelerated; + scheduler.RequestOutsideRenderPassOperationContext(); + const VkPipeline vk_pipeline = *pipeline; + const VkImageAspectFlags aspect_mask = image.AspectMask(); + const VkImage vk_image = image.Handle(); + const bool is_initialized = image.ExchangeInitialization(); + RecordUnswizzleEntryBarrier(scheduler, vk_pipeline, vk_image, aspect_mask, is_initialized); + + for (const VideoCommon::SwizzleParameters& swizzle : swizzles) { + const size_t input_offset = swizzle.buffer_offset + map.offset; + const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 16U); + const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 8U); + const u32 num_dispatches_z = Common::DivCeil(swizzle.num_tiles.depth, 8U); + + compute_pass_descriptor_queue.Acquire(scheduler, 2); + compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset, + image.guest_size_bytes - swizzle.buffer_offset); + compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level)); + const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()}; + + const auto params = MakeBlockLinearSwizzle3DParams(swizzle, image.info); + scheduler.Record([this, num_dispatches_x, num_dispatches_y, num_dispatches_z, params, + descriptor_data](vk::CommandBuffer cmdbuf) { + const VkDescriptorSet set = descriptor_allocator.Commit(); + device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); + cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); + cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, params); + cmdbuf.Dispatch(num_dispatches_x, num_dispatches_y, num_dispatches_z); + }); + } + RecordUnswizzleExitBarrier(scheduler, vk_image, aspect_mask); +} + PitchUnswizzlePass::PitchUnswizzlePass( const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, ComputePassDescriptorQueue& compute_pass_descriptor_queue_) diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 117f228bee..519ca078ab 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -179,6 +179,21 @@ private: ComputePassDescriptorQueue& compute_pass_descriptor_queue; }; +class BlockLinearUnswizzleImage3DPass final : public ComputePass { +public: + explicit BlockLinearUnswizzleImage3DPass( + const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, + ComputePassDescriptorQueue& compute_pass_descriptor_queue_); + ~BlockLinearUnswizzleImage3DPass(); + + void Unswizzle(Image& image, const StagingBufferRef& map, + std::span swizzles); + +private: + Scheduler& scheduler; + ComputePassDescriptorQueue& compute_pass_descriptor_queue; +}; + class PitchUnswizzlePass final : public ComputePass { public: explicit PitchUnswizzlePass(const Device& device_, Scheduler& scheduler_, diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index e92f6e5e18..0d740a87be 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -191,7 +191,8 @@ constexpr u32 UNSWIZZLE_WORKGROUP_INVOCATIONS = 32 * 32; if (info.num_samples > 1) { return false; } - if (info.type != ImageType::e2D && info.type != ImageType::Linear) { + if (info.type != ImageType::e2D && info.type != ImageType::e3D && + info.type != ImageType::Linear) { return false; } const PixelFormat view_format = @@ -1029,6 +1030,8 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched if (SupportsAcceleratedUnswizzleDevice(device)) { bl_unswizzle_2d_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue); + bl_unswizzle_image_3d_pass.emplace(device, scheduler, descriptor_pool, + compute_pass_descriptor_queue); pitch_unswizzle_pass.emplace(device, scheduler, descriptor_pool, compute_pass_descriptor_queue); } @@ -3228,6 +3231,11 @@ void TextureCacheRuntime::AccelerateImageUpload( return bl_unswizzle_2d_pass->Unswizzle(image, map, swizzles); } + if (bl_unswizzle_image_3d_pass && image.info.type == ImageType::e3D && + !IsPixelFormatBCn(image.info.format)) { + return bl_unswizzle_image_3d_pass->Unswizzle(image, map, swizzles); + } + if (pitch_unswizzle_pass && image.info.type == ImageType::Linear) { return pitch_unswizzle_pass->Unswizzle(image, map, swizzles); } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index be7f56cf3c..8eef0e273c 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -160,6 +160,7 @@ public: std::optional bl3d_unswizzle_pass; std::optional bl_unswizzle_2d_pass; + std::optional bl_unswizzle_image_3d_pass; std::optional pitch_unswizzle_pass; const Settings::ResolutionScalingInfo& resolution; std::array, VideoCore::Surface::MaxPixelFormat> view_formats;