diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index e87c502342..ad983bd749 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -39,9 +39,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"), RENDERER_SAMPLE_SHADING("sample_shading"), GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"), - GPU_COMPUTE_UNSWIZZLE_2D("gpu_compute_unswizzle_2d"), - GPU_COMPUTE_UNSWIZZLE_3D("gpu_compute_unswizzle_3d"), - GPU_COMPUTE_UNSWIZZLE_PITCH("gpu_compute_unswizzle_pitch"), PICTURE_IN_PICTURE("picture_in_picture"), USE_CUSTOM_RTC("custom_rtc_enabled"), BLACK_BACKGROUNDS("black_backgrounds"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 6f6282aa30..67cf392fef 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -724,27 +724,6 @@ abstract class SettingsItem( chunkSizeValuesId = R.array.gpuSwizzleChunkValues ) ) - put( - SwitchSetting( - BooleanSetting.GPU_COMPUTE_UNSWIZZLE_2D, - titleId = R.string.gpu_compute_unswizzle_2d, - descriptionId = R.string.gpu_compute_unswizzle_2d_description - ) - ) - put( - SwitchSetting( - BooleanSetting.GPU_COMPUTE_UNSWIZZLE_3D, - titleId = R.string.gpu_compute_unswizzle_3d, - descriptionId = R.string.gpu_compute_unswizzle_3d_description - ) - ) - put( - SwitchSetting( - BooleanSetting.GPU_COMPUTE_UNSWIZZLE_PITCH, - titleId = R.string.gpu_compute_unswizzle_pitch, - descriptionId = R.string.gpu_compute_unswizzle_pitch_description - ) - ) put( SingleChoiceSetting( IntSetting.FAST_CPU_TIME, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 70d52c2121..7b7762520d 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -308,9 +308,6 @@ class SettingsFragmentPresenter( add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key) add(BooleanSetting.RENDERER_ASYNC_PRESENTATION.key) add(SettingsItem.GPU_UNSWIZZLE_COMBINED) - add(BooleanSetting.GPU_COMPUTE_UNSWIZZLE_2D.key) - add(BooleanSetting.GPU_COMPUTE_UNSWIZZLE_3D.key) - add(BooleanSetting.GPU_COMPUTE_UNSWIZZLE_PITCH.key) add(HeaderSetting(R.string.extensions)) diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 89e2f0b0ad..c67c2f279f 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -527,12 +527,6 @@ GPU Unswizzle Settings Configure GPU-based texture unswizzling parameters or disable it entirely. Adjust these settings to balance performance and texture loading quality. Enable GPU Unswizzle - GPU Compute Unswizzle (2D) - Unswizzles block-linear 2D textures with a compute shader instead of the CPU. Disable to upload 2D textures through the CPU path. - GPU Compute Unswizzle (3D) - Unswizzles block-linear 3D textures with a compute shader instead of the CPU. Disable to upload 3D textures through the CPU path. - GPU Compute Unswizzle (Pitch) - Unswizzles pitch-linear textures with a compute shader instead of the CPU. Disable to upload linear textures through the CPU path. Disabled GPU Unswizzle Max Texture Size Sets the maximum size (MB) for GPU-based texture unswizzling. While the GPU is faster for medium and large textures, the CPU may be more efficient for very small ones. Adjust this to find the balance between GPU acceleration and CPU overhead. diff --git a/src/common/settings.h b/src/common/settings.h index 8a290e526d..b80d6a5ec7 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -605,16 +605,6 @@ struct Values { SwitchableSetting gpu_unswizzle_enabled{linkage, false, "gpu_unswizzle_enabled", Category::RendererHacks}; - SwitchableSetting gpu_compute_unswizzle_2d{linkage, true, "gpu_compute_unswizzle_2d", - Category::RendererHacks}; - - SwitchableSetting gpu_compute_unswizzle_3d{linkage, true, "gpu_compute_unswizzle_3d", - Category::RendererHacks}; - - SwitchableSetting gpu_compute_unswizzle_pitch{linkage, true, - "gpu_compute_unswizzle_pitch", - Category::RendererHacks}; - SwitchableSetting dyna_state{linkage, #if defined(__ANDROID__) ExtendedDynamicState::Disabled, diff --git a/src/video_core/host_shaders/block_linear_unswizzle_3d_bcn.comp b/src/video_core/host_shaders/block_linear_unswizzle_3d_bcn.comp index 0f6d1ad059..e084837f25 100644 --- a/src/video_core/host_shaders/block_linear_unswizzle_3d_bcn.comp +++ b/src/video_core/host_shaders/block_linear_unswizzle_3d_bcn.comp @@ -1,10 +1,12 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later #version 430 #ifdef VULKAN - #define HAS_EXTENDED_TYPES 0 + #extension GL_EXT_shader_16bit_storage : require + #extension GL_EXT_shader_8bit_storage : require + #define HAS_EXTENDED_TYPES 1 #define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants { #define END_PUSH_CONSTANTS }; #define UNIFORM(n) @@ -40,6 +42,9 @@ layout(push_constant) uniform PushConstants { uint block_depth; // Offset 48 uint block_depth_mask; // Offset 52 + int _pad; // Offset 56 + + ivec3 destination; // Offset 60 } pc; #else BEGIN_PUSH_CONSTANTS diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 88e2895598..b0a7d0c579 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -169,7 +169,6 @@ try } RendererVulkan::~RendererVulkan() { - scheduler.WaitWorker(); scheduler.RegisterOnSubmit([] {}); void(device.GetLogical().WaitIdle()); } diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 243bc1af5e..f361c34f44 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -24,10 +24,7 @@ #include "video_core/host_shaders/resolve_conditional_render_comp_spv.h" #include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h" #include "video_core/host_shaders/vulkan_uint8_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/block_linear_unswizzle_3d_bcn_comp_spv.h" -#include "video_core/host_shaders/pitch_unswizzle_comp_spv.h" #include "video_core/renderer_vulkan/vk_compute_pass.h" #include "video_core/surface.h" #include "video_core/renderer_vulkan/vk_descriptor_pool.h" @@ -236,26 +233,6 @@ struct QueriesPrefixScanPushConstants { struct ConditionalRenderingResolvePushConstants { u32 compare_to_zero; }; - -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 PitchUnswizzlePushConstants { - std::array origin; - std::array destination; - u32 bytes_per_block; - u32 pitch; -}; } // Anonymous namespace ComputePass::ComputePass(const Device& device_, Scheduler& scheduler, DescriptorPool& descriptor_pool, @@ -677,235 +654,6 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, scheduler.Finish(); } -namespace { - -void RecordUnswizzleImageEntry(vk::CommandBuffer cmdbuf, VkPipeline pipeline, VkImage image, - VkImageAspectFlags aspect_mask, bool is_initialized) { - const VkImageMemoryBarrier image_barrier{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = static_cast(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT - : VK_ACCESS_NONE), - .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, - .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange{ - .aspectMask = aspect_mask, - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }; - cmdbuf.PipelineBarrier(is_initialized ? vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER - : VkPipelineStageFlags(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT), - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); - cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline); -} - -void RecordUnswizzleImageExit(vk::CommandBuffer cmdbuf, VkImage image, - VkImageAspectFlags aspect_mask) { - const VkImageMemoryBarrier image_barrier{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .pNext = nullptr, - .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, - .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | - VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_GENERAL, - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image, - .subresourceRange{ - .aspectMask = aspect_mask, - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }; - cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, - vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, 0, image_barrier); -} -} // Anonymous namespace - -BlockLinearUnswizzleImage2DPass::BlockLinearUnswizzleImage2DPass( - 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_2D_COMP_SPV), - scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, - compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {} - -BlockLinearUnswizzleImage2DPass::~BlockLinearUnswizzleImage2DPass() = default; - -void BlockLinearUnswizzleImage2DPass::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(); - scheduler.Record([vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) { - RecordUnswizzleImageEntry(cmdbuf, 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, 32U); - const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 32U); - const u32 num_dispatches_z = image.info.resources.layers; - - 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 = MakeBlockLinearSwizzle2DParams(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); - }); - } - scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) { - RecordUnswizzleImageExit(cmdbuf, vk_image, aspect_mask); - }); - scheduler.Finish(); -} - -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 VkPipeline vk_pipeline = *pipeline; - const VkImageAspectFlags aspect_mask = image.AspectMask(); - const VkImage vk_image = image.Handle(); - const bool is_initialized = image.ExchangeInitialization(); - scheduler.Record([vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) { - RecordUnswizzleImageEntry(cmdbuf, 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 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); - }); - } - scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) { - RecordUnswizzleImageExit(cmdbuf, vk_image, aspect_mask); - }); - scheduler.Finish(); -} - -PitchUnswizzlePass::PitchUnswizzlePass(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, - PITCH_UNSWIZZLE_COMP_SPV), - scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_}, - compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {} - -PitchUnswizzlePass::~PitchUnswizzlePass() = default; - -void PitchUnswizzlePass::Unswizzle(Image& image, const StagingBufferRef& map, - std::span swizzles) { - 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(); - scheduler.Record([vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) { - RecordUnswizzleImageEntry(cmdbuf, vk_pipeline, vk_image, aspect_mask, is_initialized); - }); - const u32 bytes_per_block = VideoCore::Surface::BytesPerBlock(image.info.format); - 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, 32U); - const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 32U); - - 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 PitchUnswizzlePushConstants params{ - .origin = {0, 0}, - .destination = {0, 0}, - .bytes_per_block = bytes_per_block, - .pitch = image.info.pitch, - }; - scheduler.Record([this, num_dispatches_x, num_dispatches_y, 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, 1); - }); - } - scheduler.Record([vk_image, aspect_mask](vk::CommandBuffer cmdbuf) { - RecordUnswizzleImageExit(cmdbuf, vk_image, aspect_mask); - }); - scheduler.Finish(); -} - constexpr u32 BL3D_BINDING_INPUT_BUFFER = 0; constexpr u32 BL3D_BINDING_OUTPUT_BUFFER = 1; @@ -923,6 +671,10 @@ struct alignas(16) BlockLinearUnswizzle3DPushConstants { u32 block_depth; // Offset 48 u32 block_depth_mask; // Offset 52 + s32 _pad; // Offset 56 + + s32 destination[3]; // Offset 60 + s32 _pad_end; // Offset 72 }; static_assert(sizeof(BlockLinearUnswizzle3DPushConstants) <= 128); @@ -1029,6 +781,10 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( pc.origin[1] = params.origin[1]; pc.origin[2] = z_start; // Current chunk's Z start + pc.destination[0] = params.destination[0]; + pc.destination[1] = params.destination[1]; + pc.destination[2] = 0; // Shader writes to start of output buffer + pc.bytes_per_block_log2 = params.bytes_per_block_log2; pc.slice_size = params.slice_size; pc.block_size = params.block_size; diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index 34aa762ff9..cb213dae7e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -25,7 +25,6 @@ struct SwizzleParameters; namespace Vulkan { -using VideoCommon::Accelerated::BlockLinearSwizzle2DParams; using VideoCommon::Accelerated::BlockLinearSwizzle3DParams; class Device; @@ -166,57 +165,6 @@ private: }; -class BlockLinearUnswizzleImage2DPass final : public ComputePass { -public: - explicit BlockLinearUnswizzleImage2DPass( - const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, - StagingBufferPool& staging_buffer_pool_, - ComputePassDescriptorQueue& compute_pass_descriptor_queue_); - ~BlockLinearUnswizzleImage2DPass(); - - void Unswizzle(Image& image, const StagingBufferRef& map, - std::span swizzles); - -private: - Scheduler& scheduler; - StagingBufferPool& staging_buffer_pool; - ComputePassDescriptorQueue& compute_pass_descriptor_queue; -}; - -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 PitchUnswizzlePass final : public ComputePass { -public: - explicit PitchUnswizzlePass(const Device& device_, Scheduler& scheduler_, - DescriptorPool& descriptor_pool_, - StagingBufferPool& staging_buffer_pool_, - ComputePassDescriptorQueue& compute_pass_descriptor_queue_); - ~PitchUnswizzlePass(); - - void Unswizzle(Image& image, const StagingBufferRef& map, - std::span swizzles); - -private: - Scheduler& scheduler; - StagingBufferPool& staging_buffer_pool; - ComputePassDescriptorQueue& compute_pass_descriptor_queue; -}; - class MSAACopyPass final : public ComputePass { public: explicit MSAACopyPass(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 305cec454a..f789c989d8 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -6,9 +6,7 @@ #include #include -#include #include -#include #include #include #include @@ -222,50 +220,8 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { return allocator.CreateImage(image_ci); } -[[nodiscard]] VkFormat UnswizzleStorageFormat(u32 bytes_per_block) { - switch (bytes_per_block) { - case 1: - return VK_FORMAT_R8_UINT; - case 2: - return VK_FORMAT_R16_UINT; - case 4: - return VK_FORMAT_R32_UINT; - case 8: - return VK_FORMAT_R32G32_UINT; - case 16: - return VK_FORMAT_R32G32B32A32_UINT; - default: - ASSERT_MSG(false, "Invalid bytes_per_block={} for accelerated unswizzle", bytes_per_block); - return VK_FORMAT_R32_UINT; - } -} - -[[nodiscard]] bool IsUnswizzleStorageFormatSupported(const Device& device, u32 bytes_per_block) { - switch (bytes_per_block) { - case 1: - if (!device.IsStorageBuffer8BitAccessSupported()) { - return false; - } - break; - case 2: - if (!device.IsStorageBuffer16BitAccessSupported()) { - return false; - } - break; - case 4: - case 8: - case 16: - break; - default: - return false; - } - return device.IsFormatSupported(UnswizzleStorageFormat(bytes_per_block), - VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT, FormatType::Optimal); -} - [[nodiscard]] vk::ImageView MakeStorageView(const vk::Device& device, u32 level, VkImage image, - VkFormat format, - VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D_ARRAY) { + VkFormat format) { static constexpr VkImageViewUsageCreateInfo storage_image_view_usage_create_info{ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO, .pNext = nullptr, @@ -276,7 +232,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array& color) { .pNext = &storage_image_view_usage_create_info, .flags = 0, .image = image, - .viewType = view_type, + .viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY, .format = format, .components{ .r = VK_COMPONENT_SWIZZLE_IDENTITY, @@ -959,56 +915,10 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched if (!device.IsKhrImageFormatListSupported()) { return; } - - bool enable_2d = Settings::values.gpu_compute_unswizzle_2d.GetValue(); - bool enable_3d = Settings::values.gpu_compute_unswizzle_3d.GetValue(); - bool enable_pitch = Settings::values.gpu_compute_unswizzle_pitch.GetValue(); - if (const char* const unswizzle_env = std::getenv("GPU_COMPUTE_UNSWIZZLE")) { - const std::string_view selection{unswizzle_env}; - if (selection == "0" || selection == "none") { - enable_2d = enable_3d = enable_pitch = false; - } else if (selection != "1" && selection != "all") { - enable_2d = selection.find("2d") != std::string_view::npos; - enable_3d = selection.find("3d") != std::string_view::npos; - enable_pitch = selection.find("pitch") != std::string_view::npos; - } - LOG_INFO(Render_Vulkan, "GPU_COMPUTE_UNSWIZZLE={} (2d={}, 3d={}, pitch={})", selection, - enable_2d, enable_3d, enable_pitch); - } - const bool unswizzle_caps_ok = device.IsStorageBuffer8BitAccessSupported() && - device.IsStorageBuffer16BitAccessSupported() && - device.IsFormatlessImageStoreSupported(); - if (!unswizzle_caps_ok) { - LOG_INFO(Render_Vulkan, - "GPU image unswizzle passes unsupported (8bit={}, 16bit={}, formatless={})", - device.IsStorageBuffer8BitAccessSupported(), - device.IsStorageBuffer16BitAccessSupported(), - device.IsFormatlessImageStoreSupported()); - } else { - if (enable_2d) { - bl_unswizzle_2d_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, - compute_pass_descriptor_queue); - } - if (enable_3d) { - bl_unswizzle_3d_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, - compute_pass_descriptor_queue); - } - if (enable_pitch) { - pitch_unswizzle_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, - compute_pass_descriptor_queue); - } - } for (size_t index_a = 0; index_a < VideoCore::Surface::MaxPixelFormat; index_a++) { const auto image_format = static_cast(index_a); if (IsPixelFormatASTC(image_format) && !device.IsOptimalAstcSupported()) { view_formats[index_a].push_back(VK_FORMAT_A8B8G8R8_UNORM_PACK32); - } else if (HasImageUnswizzlePasses() && !IsPixelFormatBCn(image_format) && - VideoCore::Surface::GetFormatType(image_format) == - VideoCore::Surface::SurfaceType::ColorTexture) { - const u32 bytes_per_block = VideoCore::Surface::BytesPerBlock(image_format); - if (IsUnswizzleStorageFormatSupported(device, bytes_per_block)) { - view_formats[index_a].push_back(UnswizzleStorageFormat(bytes_per_block)); - } } for (size_t index_b = 0; index_b < VideoCore::Surface::MaxPixelFormat; index_b++) { const auto view_format = static_cast(index_b); @@ -1701,14 +1611,6 @@ Image::Image(TextureCacheRuntime& runtime_, const ImageInfo& info_, GPUVAddr gpu flags |= VideoCommon::ImageFlagBits::Converted; flags |= VideoCommon::ImageFlagBits::CostlyLoad; } - if (runtime->HasUnswizzlePassFor(info.type) && !IsPixelFormatASTC(info.format) && - !IsPixelFormatBCn(info.format) && info.num_samples == 1 && - VideoCore::Surface::GetFormatType(info.format) == - VideoCore::Surface::SurfaceType::ColorTexture) { - if (IsUnswizzleStorageFormatSupported(runtime->device, BytesPerBlock(info.format))) { - flags |= VideoCommon::ImageFlagBits::AcceleratedUpload; - } - } if (runtime->device.HasDebuggingToolAttached()) { original_image.SetObjectNameEXT(VideoCommon::Name(*this).c_str()); } @@ -2074,20 +1976,13 @@ 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 = WillUseWidenedAstcFormat(runtime->device, info) ? VK_FORMAT_R32G32B32A32_SFLOAT : VK_FORMAT_A8B8G8R8_UNORM_PACK32; - } else if (True(flags & ImageFlagBits::AcceleratedUpload) && - !IsPixelFormatASTC(info.format) && !IsPixelFormatBCn(info.format)) { - format_info.format = UnswizzleStorageFormat(BytesPerBlock(info.format)); - view_type = info.type == ImageType::e3D ? VK_IMAGE_VIEW_TYPE_3D - : info.type == ImageType::Linear ? VK_IMAGE_VIEW_TYPE_2D - : VK_IMAGE_VIEW_TYPE_2D_ARRAY; } view = MakeStorageView(runtime->device.GetLogical(), level, *(this->*current_image), - format_info.format, view_type); + format_info.format); } return *view; } @@ -2621,36 +2516,16 @@ void TextureCacheRuntime::AccelerateImageUpload( return astc_decoder_pass->Assemble(image, map, swizzles); } - if (IsPixelFormatBCn(image.info.format)) { - if (Settings::values.gpu_unswizzle_enabled.GetValue() && bl3d_unswizzle_pass && - image.info.type == ImageType::e3D && image.info.resources.levels == 1 && - image.info.resources.layers == 1) { - return bl3d_unswizzle_pass->Unswizzle(image, map, swizzles, z_start, z_count); + if (!Settings::values.gpu_unswizzle_enabled.GetValue() || !bl3d_unswizzle_pass) { + if (IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D) { + ASSERT(false && "GPU unswizzle is disabled for BCn 3D texture"); } - ASSERT(false && "GPU unswizzle is disabled for BCn 3D texture"); + ASSERT(false); return; } - if (HasImageUnswizzlePasses()) { - switch (image.info.type) { - case ImageType::e2D: - if (bl_unswizzle_2d_pass) { - return bl_unswizzle_2d_pass->Unswizzle(image, map, swizzles); - } - break; - case ImageType::e3D: - if (bl_unswizzle_3d_pass) { - return bl_unswizzle_3d_pass->Unswizzle(image, map, swizzles); - } - break; - case ImageType::Linear: - if (pitch_unswizzle_pass) { - return pitch_unswizzle_pass->Unswizzle(image, map, swizzles); - } - break; - default: - break; - } + if (bl3d_unswizzle_pass && IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D && image.info.resources.levels == 1 && image.info.resources.layers == 1) { + return bl3d_unswizzle_pass->Unswizzle(image, map, swizzles, z_start, z_count); } ASSERT(false); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 9e36561417..027143fdbc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -130,30 +130,7 @@ public: std::optional astc_decoder_pass; std::optional bl3d_unswizzle_pass; - std::optional bl_unswizzle_2d_pass; - std::optional bl_unswizzle_3d_pass; - std::optional pitch_unswizzle_pass; std::optional msaa_copy_pass; - - /// True when the buffer->image unswizzle pass for this image type is active. - bool HasUnswizzlePassFor(VideoCommon::ImageType type) const noexcept { - switch (type) { - case VideoCommon::ImageType::e2D: - return bl_unswizzle_2d_pass.has_value(); - case VideoCommon::ImageType::e3D: - return bl_unswizzle_3d_pass.has_value(); - case VideoCommon::ImageType::Linear: - return pitch_unswizzle_pass.has_value(); - default: - return false; - } - } - - /// True when any buffer->image unswizzle pass is active on this device. - bool HasImageUnswizzlePasses() const noexcept { - return bl_unswizzle_2d_pass.has_value() || bl_unswizzle_3d_pass.has_value() || - pitch_unswizzle_pass.has_value(); - } const Settings::ResolutionScalingInfo& resolution; std::array, VideoCore::Surface::MaxPixelFormat> view_formats; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 709fc49a6b..a944e7e297 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -400,16 +400,6 @@ FN_MAX_LIMIT_LIST return features.bit16_storage.uniformAndStorageBuffer16BitAccess; } - /// Returns true if the device supports reading 8-bit values from a storage buffer. - bool IsStorageBuffer8BitAccessSupported() const { - return features.bit8_storage.storageBuffer8BitAccess; - } - - /// Returns true if the device supports reading 16-bit values from a storage buffer. - bool IsStorageBuffer16BitAccessSupported() const { - return features.bit16_storage.storageBuffer16BitAccess; - } - /// Returns true if the device supports binding multisample images as storage images. bool IsStorageImageMultisampleSupported() const { return features.features.shaderStorageImageMultisample; @@ -440,11 +430,6 @@ FN_MAX_LIMIT_LIST return features.features.shaderStorageImageReadWithoutFormat; } - /// Returns true if formatless image store is supported. - bool IsFormatlessImageStoreSupported() const { - return features.features.shaderStorageImageWriteWithoutFormat; - } - /// Returns true if shader int64 is supported. bool IsShaderInt64Supported() const { return features.features.shaderInt64;