@ -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 < u32 , 3 > origin ;
alignas ( 16 ) std : : array < s32 , 3 > 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 < u32 , 2 > origin ;
std : : array < s32 , 2 > 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 < VkAccessFlags > ( 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 < sizeof ( BlockLinearSwizzle2DParams ) > ,
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 < const VideoCommon : : SwizzleParameters > 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 < sizeof ( BlockLinear3DImagePushConstants ) > ,
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 < const VideoCommon : : SwizzleParameters > 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 < sizeof ( PitchUnswizzlePushConstants ) > ,
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 < const VideoCommon : : SwizzleParameters > 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 ;