Specifying R32ui for UAVs created with a vector format, e.g. R32G32B32A32_FLOAT, results in only the red being loaded/stored, potentially causing images to contain only the red component.
Signed-off-by: Conor McCarthy cmccarthy@codeweavers.com --- include/vkd3d_shader.h | 18 ++++++++++++++++++ libs/vkd3d-shader/spirv.c | 16 +++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index ebddbba7..4175223f 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -99,6 +99,22 @@ enum vkd3d_shader_compile_option_buffer_uav VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV), };
+/** + * Determines how typed UAVs are declared. + */ +enum vkd3d_shader_compile_option_typed_uav +{ + /** Use R32ui format for UAVs which are read from. This is the default value. */ + VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32UI = 0x00000000, + /** + * Use Unknown format for UAVs which are read from. This should only be set if + * shaderStorageImageReadWithoutFormat is enabled in the target environment. + */ + VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_UNKNOWN = 0x00000001, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV), +}; + enum vkd3d_shader_compile_option_formatting_flags { VKD3D_SHADER_COMPILE_OPTION_FORMATTING_NONE = 0x00000000, @@ -127,6 +143,8 @@ enum vkd3d_shader_compile_option_name VKD3D_SHADER_COMPILE_OPTION_FORMATTING = 0x00000003, /** \a value is a member of enum vkd3d_shader_api_version. \since 1.3 */ VKD3D_SHADER_COMPILE_OPTION_API_VERSION = 0x00000004, + /** \a value is a member of enum vkd3d_shader_compile_option_typed_uav. \since 1.5 */ + VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV = 0x00000005,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), }; diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 776533cb..6450f818 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -2228,6 +2228,7 @@ struct vkd3d_dxbc_compiler
bool strip_debug; bool ssbo_uavs; + bool uav_read_without_format;
struct rb_tree symbol_table; uint32_t temp_id; @@ -2379,6 +2380,15 @@ struct vkd3d_dxbc_compiler *vkd3d_dxbc_compiler_create(const struct vkd3d_shader
case VKD3D_SHADER_COMPILE_OPTION_API_VERSION: break; + + case VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV: + if (option->value == VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_R32UI) + compiler->uav_read_without_format = false; + else if (option->value == VKD3D_SHADER_COMPILE_OPTION_TYPED_UAV_READ_FORMAT_UNKNOWN) + compiler->uav_read_without_format = true; + else + WARN("Ignoring unrecognised value %#x for option %#x.\n", option->value, option->name); + break; } }
@@ -5856,14 +5866,18 @@ static uint32_t vkd3d_dxbc_compiler_get_image_type_id(struct vkd3d_dxbc_compiler const struct vkd3d_shader_descriptor_info *d; uint32_t sampled_type_id; SpvImageFormat format; + bool uav_read;
format = SpvImageFormatUnknown; if (reg->type == VKD3DSPR_UAV) { d = vkd3d_dxbc_compiler_get_descriptor_info(compiler, VKD3D_SHADER_DESCRIPTOR_TYPE_UAV, range); - if (raw_structured || (d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ)) + uav_read = !!(d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_UAV_READ); + if (raw_structured || (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); }
sampled_type_id = vkd3d_spirv_get_type_id(builder, data_type, 1);