From 1b11b57652b3c2cd785353c8ccd29d5f87b0993a Mon Sep 17 00:00:00 2001 From: Conor McCarthy Date: Fri, 18 Nov 2022 13:44:05 +1000 Subject: [PATCH] vkd3d-shader: Introduce DESCRIPTOR_INFO_FLAG_UAV_ATOMICS and always declare UAV images with known type for atomic ops. Atomic ops on images with Unknown type will cause SPIR-V validation failure, and assertion failure in Mesa debug builds. D3D12 allows atomics on typed buffers, and this requires a distinction to be made between UAV reads and atomic ops. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53874 --- include/vkd3d_shader.h | 3 +++ libs/vkd3d-shader/spirv.c | 5 +++-- libs/vkd3d-shader/vkd3d_shader_main.c | 28 +++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 7178ac5f..939ab42d 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -1263,6 +1263,9 @@ enum vkd3d_shader_descriptor_info_flag VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ = 0x00000002, /** The descriptor is a comparison sampler. */ VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE = 0x00000004, + /** The descriptor is a UAV resource, on which the shader performs + * atomic ops. \since 1.6 */ + VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_ATOMICS = 0x00000008, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_DESCRIPTOR_INFO_FLAG), }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 734ba315..2d1691c6 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -5864,9 +5864,9 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_descriptor_info *d; + bool uav_read, uav_atomics; uint32_t sampled_type_id; SpvImageFormat format; - bool uav_read; format = SpvImageFormatUnknown; if (reg->type == VKD3DSPR_UAV) @@ -5874,7 +5874,8 @@ static uint32_t spirv_compiler_get_image_type_id(struct spirv_compiler *compiler d = spirv_compiler_get_descriptor_info(compiler, VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, range); uav_read = !!(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ); - if (raw_structured || (uav_read && !compiler->uav_read_without_format)) + uav_atomics = !!(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_ATOMICS); + if (raw_structured || uav_atomics || (uav_read && !compiler->uav_read_without_format)) format = image_format_for_image_read(data_type); else if (uav_read) vkd3d_spirv_enable_capability(builder, SpvCapabilityStorageImageReadWithoutFormat); diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 5e25dde8..72a6d2d8 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -692,6 +692,25 @@ static void vkd3d_shader_scan_record_uav_counter(struct vkd3d_shader_scan_contex d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_COUNTER; } +static bool vkd3d_shader_instruction_is_uav_atomic_op(const struct vkd3d_shader_instruction *instruction) +{ + enum vkd3d_shader_opcode handler_idx = instruction->handler_idx; + return (VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR) + || (VKD3DSIH_IMM_ATOMIC_ALLOC <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR); +} + +static void vkd3d_shader_scan_record_uav_atomic_op(struct vkd3d_shader_scan_context *context, + const struct vkd3d_shader_register *reg) +{ + struct vkd3d_shader_descriptor_info *d; + + if (!context->scan_descriptor_info) + return; + + d = vkd3d_shader_scan_get_uav_descriptor_info(context, reg->idx[0].offset); + d->flags |= VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_ATOMICS; +} + static bool vkd3d_shader_scan_add_descriptor(struct vkd3d_shader_scan_context *context, enum vkd3d_shader_descriptor_type type, const struct vkd3d_shader_register_range *range, enum vkd3d_shader_resource_type resource_type, enum vkd3d_shader_resource_data_type resource_data_type, @@ -1019,6 +1038,15 @@ static int vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_context *conte if (vkd3d_shader_instruction_is_uav_counter(instruction)) vkd3d_shader_scan_record_uav_counter(context, &instruction->src[0].reg); + if (vkd3d_shader_instruction_is_uav_atomic_op(instruction)) + { + for (i = 0; i < instruction->dst_count; ++i) + { + if (instruction->dst[i].reg.type == VKD3DSPR_UAV) + vkd3d_shader_scan_record_uav_atomic_op(context, &instruction->dst[i].reg); + } + } + ++context->location.line; return VKD3D_OK; }