From 0dd78bbd07828f2d1c67b58eca3f3204352a0e9d Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 19 Sep 2026 06:12:59 -0400 Subject: [PATCH] Re-add unswizzle 3D pass --- .../renderer_vulkan/maxwell_to_vk.cpp | 16 +--- .../renderer_vulkan/vk_compute_pass.cpp | 73 +++++++++++++++++++ .../renderer_vulkan/vk_compute_pass.h | 17 +++++ .../renderer_vulkan/vk_texture_cache.cpp | 24 ++++-- .../renderer_vulkan/vk_texture_cache.h | 1 + src/video_core/surface.cpp | 4 - src/video_core/surface.h | 4 - .../texture_cache/format_lookup_table.cpp | 9 --- .../vulkan_common/vulkan_device.cpp | 4 - 9 files changed, 111 insertions(+), 41 deletions(-) diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index dae9fe0269..12c311ad35 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -224,10 +224,6 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, 0, ETC2_RGB_SRGB) \ SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, 0, ETC2_RGBA_SRGB) \ SURFACE_FORMAT_ELEM(VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, 0, ETC2_RGB_PTA_SRGB) \ - SURFACE_FORMAT_ELEM(VK_FORMAT_EAC_R11_UNORM_BLOCK, 0, EAC_R11_UNORM) \ - SURFACE_FORMAT_ELEM(VK_FORMAT_EAC_R11_SNORM_BLOCK, 0, EAC_R11_SNORM) \ - SURFACE_FORMAT_ELEM(VK_FORMAT_EAC_R11G11_UNORM_BLOCK, 0, EAC_R11G11_UNORM) \ - SURFACE_FORMAT_ELEM(VK_FORMAT_EAC_R11G11_SNORM_BLOCK, 0, EAC_R11G11_SNORM) \ /* Depth formats */ \ SURFACE_FORMAT_ELEM(VK_FORMAT_D32_SFLOAT, usage_attachable, D32_FLOAT) \ SURFACE_FORMAT_ELEM(VK_FORMAT_D16_UNORM, usage_attachable, D16_UNORM) \ @@ -273,17 +269,7 @@ FormatInfo SurfaceFormat(const Device& device, FormatType format_type, bool with } } else if (!device.IsOptimalEtc2Supported() && VideoCore::Surface::IsPixelFormatETC2(pixel_format)) { // Transcode on hardware that doesn't support ETC2 natively - if (pixel_format == PixelFormat::EAC_R11_SNORM) { - tuple.format = VK_FORMAT_R8_SNORM; - } else if (pixel_format == PixelFormat::EAC_R11_UNORM) { - tuple.format = VK_FORMAT_R8_UNORM; - } else if (pixel_format == PixelFormat::EAC_R11G11_SNORM) { - tuple.format = VK_FORMAT_R8G8_SNORM; - } else if (pixel_format == PixelFormat::EAC_R11G11_UNORM) { - tuple.format = VK_FORMAT_R8G8_UNORM; - } else { - tuple.format = is_srgb ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 : VK_FORMAT_A8B8G8R8_UNORM_PACK32; - } + tuple.format = is_srgb ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 : VK_FORMAT_A8B8G8R8_UNORM_PACK32; } bool const attachable = (tuple.usage & usage_attachable) != 0; bool const storage = (tuple.usage & usage_storage) != 0; diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index b542ccceb5..d8137d6fab 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -18,6 +18,7 @@ #include "common/vector_math.h" #include "video_core/host_shaders/astc_decoder_comp_spv.h" #include "video_core/host_shaders/block_linear_unswizzle_2d_comp_spv.h" +#include "video_core/host_shaders/block_linear_unswizzle_3d_comp_spv.h" #include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h" #include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h" #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" @@ -186,6 +187,19 @@ struct AstcPushConstants { u32 block_height_mask; }; +struct BlockLinear3DImagePushConstants { + alignas(16) std::array origin; + alignas(16) std::array destination; + u32 bytes_per_block_log2; + u32 slice_size; + u32 block_size; + u32 x_shift; + u32 block_height; + u32 block_height_mask; + u32 block_depth; + u32 block_depth_mask; +}; + struct QueriesPrefixScanPushConstants { u32 min_accumulation_base; u32 max_accumulation_base; @@ -743,4 +757,63 @@ void BlockLinearUnswizzleImage2DPass::Unswizzle( RecordUnswizzleEndBarrier(scheduler, vk_image, aspect_mask); } +BlockLinearUnswizzleImage3DPass::BlockLinearUnswizzleImage3DPass( + const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, + StagingBufferPool& staging_buffer_pool_, + ComputePassDescriptorQueue& compute_pass_descriptor_queue_) + : ComputePass(device_, scheduler_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, + ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO, + COMPUTE_PUSH_CONSTANT_RANGE, + BLOCK_LINEAR_UNSWIZZLE_3D_COMP_SPV), + scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, + 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 VkImageAspectFlags aspect_mask = image.AspectMask(); + const VkImage vk_image = image.Handle(); + RecordUnswizzleBeginBarrier(scheduler, *pipeline, vk_image, aspect_mask, + image.ExchangeInitialization()); + 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, 2U); + + 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 p = MakeBlockLinearSwizzle3DParams(swizzle, image.info); + const BlockLinear3DImagePushConstants params{ + .origin = p.origin, + .destination = p.destination, + .bytes_per_block_log2 = p.bytes_per_block_log2, + .slice_size = p.slice_size, + .block_size = p.block_size, + .x_shift = p.x_shift, + .block_height = p.block_height, + .block_height_mask = p.block_height_mask, + .block_depth = p.block_depth, + .block_depth_mask = p.block_depth_mask, + }; + 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); + }); + } + RecordUnswizzleEndBarrier(scheduler, vk_image, aspect_mask); +} + } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index c0bc1e6e88..d791554d32 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -153,6 +153,23 @@ private: MemoryAllocator& memory_allocator; }; +class BlockLinearUnswizzleImage3DPass final : public ComputePass { +public: + explicit BlockLinearUnswizzleImage3DPass( + const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, + StagingBufferPool& staging_buffer_pool_, + ComputePassDescriptorQueue& compute_pass_descriptor_queue_); + ~BlockLinearUnswizzleImage3DPass(); + + void Unswizzle(Image& image, const StagingBufferRef& map, + std::span swizzles); + +private: + Scheduler& scheduler; + StagingBufferPool& staging_buffer_pool; + ComputePassDescriptorQueue& compute_pass_descriptor_queue; +}; + class BlockLinearUnswizzleImage2DPass final : public ComputePass { public: explicit BlockLinearUnswizzleImage2DPass( diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 4c2617144e..fb64e89574 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -195,7 +195,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { } [[nodiscard]] bool WillUseAcceleratedUnswizzle(const Device& device, const ImageInfo& info) { - if (info.type != ImageType::e2D || info.num_samples > 1) { + const bool supported_type = info.type == ImageType::e2D || info.type == ImageType::e3D; + if (!supported_type || info.num_samples > 1) { return false; } if (!device.IsKhrImageFormatListSupported()) { @@ -313,7 +314,12 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { } [[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image, - VkFormat format) { + VkFormat format, + VkImageViewType view_type) { + u32 layer_count = VK_REMAINING_ARRAY_LAYERS; + if (view_type == VK_IMAGE_VIEW_TYPE_3D) { + layer_count = 1; + } static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, .pNext = nullptr, @@ -324,7 +330,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { .pNext = &storage_image_view_usage_create_info, .flags = 0, .image = image, - .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, + .viewType = view_type, .format = format, .components{ .r = VK_COMPONENT_SWIZZLE_IDENTITY, @@ -337,7 +343,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { .baseMipLevel = level, .levelCount = 1, .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, + .layerCount = layer_count, }, }); } @@ -1014,6 +1020,8 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched device.IsStorageBuffer16BitAccessSupported()) { bl_unswizzle_2d_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue); + bl_unswizzle_3d_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, + compute_pass_descriptor_queue); } if (!device.IsKhrImageFormatListSupported()) { return; @@ -2354,13 +2362,17 @@ VkImageView Image::StorageImageView(s32 level) noexcept { if (!view) { auto format_info = MaxwellToVK::SurfaceFormat(runtime->device, FormatType::Optimal, true, info.format); + VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; if (WillUseAcceleratedAstcDecode(runtime->device, info)) { format_info.format = VK_FORMAT_A8B8G8R8_UNORM_PACK32; } else if (True(flags & VideoCommon::ImageFlagBits::AcceleratedUpload)) { format_info.format = UnswizzleStorageFormat(BytesPerBlock(info.format)); + if (info.type == ImageType::e3D) { + view_type = VK_IMAGE_VIEW_TYPE_3D; + } } view = MakeStorageView(runtime->device.GetLogical(), level, *original_image, - format_info.format); + format_info.format, view_type); } return *view; } @@ -3166,6 +3178,8 @@ void TextureCacheRuntime::AccelerateImageUpload( } if (IsPixelFormatASTC(image.info.format)) { astc_decoder_pass->Assemble(image, map, swizzles); + } else if (image.info.type == ImageType::e3D) { + bl_unswizzle_3d_pass->Unswizzle(image, map, swizzles); } else { bl_unswizzle_2d_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 8c86bdd5d2..5023a94b8b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -157,6 +157,7 @@ public: RenderPassCache& render_pass_cache; std::optional astc_decoder_pass; std::optional bl_unswizzle_2d_pass; + std::optional bl_unswizzle_3d_pass; const Settings::ResolutionScalingInfo& resolution; std::array, VideoCore::Surface::MaxPixelFormat> view_formats; diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index fa9554db59..d1b9bf4151 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -343,10 +343,6 @@ bool IsPixelFormatETC2(PixelFormat format) { case PixelFormat::ETC2_RGB_SRGB: case PixelFormat::ETC2_RGBA_SRGB: case PixelFormat::ETC2_RGB_PTA_SRGB: - case PixelFormat::EAC_R11_UNORM: - case PixelFormat::EAC_R11_SNORM: - case PixelFormat::EAC_R11G11_UNORM: - case PixelFormat::EAC_R11G11_SNORM: return true; default: return false; diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 8e1973d3b9..5611dbdffa 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h @@ -119,10 +119,6 @@ namespace VideoCore::Surface { PIXEL_FORMAT_ELEM(ETC2_RGB_SRGB, 4, 4, 64) \ PIXEL_FORMAT_ELEM(ETC2_RGBA_SRGB, 4, 4, 128) \ PIXEL_FORMAT_ELEM(ETC2_RGB_PTA_SRGB, 4, 4, 64) \ - PIXEL_FORMAT_ELEM(EAC_R11_UNORM, 4, 4, 64) \ - PIXEL_FORMAT_ELEM(EAC_R11_SNORM, 4, 4, 64) \ - PIXEL_FORMAT_ELEM(EAC_R11G11_UNORM, 4, 4, 128) \ - PIXEL_FORMAT_ELEM(EAC_R11G11_SNORM, 4, 4, 128) \ /* Depth formats */ \ PIXEL_FORMAT_ELEM(D32_FLOAT, 1, 1, 32) \ PIXEL_FORMAT_ELEM(D16_UNORM, 1, 1, 16) \ diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp index d6e019cddf..ea68a1c063 100644 --- a/src/video_core/texture_cache/format_lookup_table.cpp +++ b/src/video_core/texture_cache/format_lookup_table.cpp @@ -204,15 +204,6 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red, return PixelFormat::ETC2_RGB_PTA_SRGB; case Hash(TextureFormat::ETC2_RGBA, UNORM, SRGB): return PixelFormat::ETC2_RGBA_SRGB; - /* EAC */ - case Hash(TextureFormat::EAC, UNORM): - return PixelFormat::EAC_R11_UNORM; - case Hash(TextureFormat::EAC, SNORM): - return PixelFormat::EAC_R11_SNORM; - case Hash(TextureFormat::EACX2, UNORM): - return PixelFormat::EAC_R11G11_UNORM; - case Hash(TextureFormat::EACX2, SNORM): - return PixelFormat::EAC_R11G11_SNORM; /* ASTC */ case Hash(TextureFormat::ASTC_2D_4X4, UNORM, LINEAR): return PixelFormat::ASTC_2D_4X4_UNORM; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 27379be506..1e15f05156 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -301,10 +301,6 @@ VkFormatFeatureFlags GetFormatFeatures(VkFormatProperties properties, FormatType VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, - VK_FORMAT_EAC_R11_UNORM_BLOCK, - VK_FORMAT_EAC_R11_SNORM_BLOCK, - VK_FORMAT_EAC_R11G11_UNORM_BLOCK, - VK_FORMAT_EAC_R11G11_SNORM_BLOCK, }; ::Common::unordered_map format_properties; for (const auto format : formats) {