From e6961afca6f4ae0ff58f33a06f54f49aa467a433 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Fri, 4 Dec 2020 11:13:36 +0100 Subject: [PATCH] vkd3d-shader: Emit typed format for UAVs which use atomics. Mesa will assert if not, and the format must be known here. Signed-off-by: Hans-Kristian Arntzen --- include/vkd3d_shader.h | 1 + libs/vkd3d-shader/spirv.c | 9 +++++++-- libs/vkd3d-shader/vkd3d_shader_main.c | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 320986d4..6d1b1773 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -556,6 +556,7 @@ enum vkd3d_shader_uav_flag { VKD3D_SHADER_UAV_FLAG_READ_ACCESS = 0x00000001, VKD3D_SHADER_UAV_FLAG_ATOMIC_COUNTER = 0x00000002, + VKD3D_SHADER_UAV_FLAG_ATOMIC_ACCESS = 0x00000004, }; struct vkd3d_shader_scan_info diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 2b2471fb..3c94b99f 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6096,6 +6096,7 @@ static uint32_t vkd3d_dxbc_compiler_get_image_type_id(struct vkd3d_dxbc_compiler uint32_t sampled_type_id; unsigned int uav_flags; SpvImageFormat format; + bool uav_atomic; bool uav_read; bool is_uav; @@ -6104,7 +6105,8 @@ static uint32_t vkd3d_dxbc_compiler_get_image_type_id(struct vkd3d_dxbc_compiler { uav_flags = vkd3d_shader_scan_get_register_flags(scan_info, VKD3DSPR_UAV, reg->idx[0].offset); uav_read = (uav_flags & VKD3D_SHADER_UAV_FLAG_READ_ACCESS) != 0; - if (raw_structured || (uav_read && !vkd3d_dxbc_compiler_supports_typed_uav_load_without_format(compiler))) + uav_atomic = (uav_flags & VKD3D_SHADER_UAV_FLAG_ATOMIC_ACCESS) != 0; + if (raw_structured || uav_atomic || (uav_read && !vkd3d_dxbc_compiler_supports_typed_uav_load_without_format(compiler))) format = image_format_for_image_read(data_type); } @@ -6173,14 +6175,17 @@ static void vkd3d_dxbc_compiler_emit_resource_declaration(struct vkd3d_dxbc_comp { SpvImageFormat format = SpvImageFormatUnknown; unsigned int flags = 0; + bool uav_atomic; bool uav_read; if (is_uav) { uav_read = (uav_flags & VKD3D_SHADER_UAV_FLAG_READ_ACCESS) != 0; + uav_atomic = (uav_flags & VKD3D_SHADER_UAV_FLAG_ATOMIC_ACCESS) != 0; + if (structure_stride || raw || uav_read) { - if ((uav_read && !structure_stride && !raw) && + if ((uav_read && !structure_stride && !raw && !uav_atomic) && vkd3d_dxbc_compiler_supports_typed_uav_load_without_format(compiler)) { format = SpvImageFormatUnknown; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index faf81c8b..700ddb88 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -366,6 +366,14 @@ static bool vkd3d_shader_instruction_is_uav_read(const struct vkd3d_shader_instr || ((handler_idx == VKD3DSIH_LD_STRUCTURED || handler_idx == VKD3DSIH_LD_STRUCTURED_FEEDBACK) && instruction->src[2].reg.type == VKD3DSPR_UAV); } +static bool vkd3d_shader_instruction_is_uav_atomic(const struct vkd3d_shader_instruction *instruction) +{ + enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx; + return ((VKD3DSIH_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_ATOMIC_XOR) || + (VKD3DSIH_IMM_ATOMIC_AND <= handler_idx && handler_idx <= VKD3DSIH_IMM_ATOMIC_XOR)) && + handler_idx != VKD3DSIH_IMM_ATOMIC_CONSUME; +} + static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_info *scan_info, const struct vkd3d_shader_register *reg) { @@ -373,6 +381,13 @@ static void vkd3d_shader_scan_record_uav_read(struct vkd3d_shader_scan_info *sca reg->idx[0].offset, VKD3D_SHADER_UAV_FLAG_READ_ACCESS); } +static void vkd3d_shader_scan_record_uav_atomic(struct vkd3d_shader_scan_info *scan_info, + const struct vkd3d_shader_register *reg) +{ + vkd3d_shader_scan_set_register_flags(scan_info, VKD3DSPR_UAV, + reg->idx[0].offset, VKD3D_SHADER_UAV_FLAG_ATOMIC_ACCESS); +} + static bool vkd3d_shader_instruction_is_uav_counter(const struct vkd3d_shader_instruction *instruction) { enum VKD3D_SHADER_INSTRUCTION_HANDLER handler_idx = instruction->handler_idx; @@ -400,6 +415,7 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in const struct vkd3d_shader_instruction *instruction) { unsigned int i; + bool is_atomic; switch (instruction->handler_idx) { @@ -412,15 +428,25 @@ static void vkd3d_shader_scan_instruction(struct vkd3d_shader_scan_info *scan_in if (vkd3d_shader_instruction_is_uav_read(instruction)) { + is_atomic = vkd3d_shader_instruction_is_uav_atomic(instruction); + for (i = 0; i < instruction->dst_count; ++i) { if (instruction->dst[i].reg.type == VKD3DSPR_UAV) + { vkd3d_shader_scan_record_uav_read(scan_info, &instruction->dst[i].reg); + if (is_atomic) + vkd3d_shader_scan_record_uav_atomic(scan_info, &instruction->dst[i].reg); + } } for (i = 0; i < instruction->src_count; ++i) { if (instruction->src[i].reg.type == VKD3DSPR_UAV) + { vkd3d_shader_scan_record_uav_read(scan_info, &instruction->src[i].reg); + if (is_atomic) + vkd3d_shader_scan_record_uav_atomic(scan_info, &instruction->src[i].reg); + } } }