[PATCH vkd3d 4/6] vkd3d-shader: Decorate SPIR-V for nonuniform access where flagged in dxbc.

Conor McCarthy cmccarthy at codeweavers.com
Wed May 26 03:10:53 CDT 2021


From: Philip Rebohle <philip.rebohle at tu-dortmund.de>
From: Hans-Kristian Arntzen <post at arntzen-software.no>

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d-shader/dxbc.c                 |  6 ++++
 libs/vkd3d-shader/spirv.c                | 39 ++++++++++++++++++++++++
 libs/vkd3d-shader/vkd3d_shader_private.h |  7 +++++
 3 files changed, 52 insertions(+)

diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index 60610f44..644ee0d6 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -366,6 +366,7 @@ enum vkd3d_sm4_register_modifier
     VKD3D_SM4_REGISTER_MODIFIER_NEGATE     = 0x40,
     VKD3D_SM4_REGISTER_MODIFIER_ABS        = 0x80,
     VKD3D_SM4_REGISTER_MODIFIER_ABS_NEGATE = 0xc0,
+    VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM = 0x20000,
 };
 
 enum vkd3d_sm4_output_primitive_type
@@ -1567,6 +1568,7 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr
     {
         param->type = register_type_table[register_type];
     }
+    param->modifier = VKD3DSPRM_NONE;
     param->data_type = data_type;
 
     if (token & VKD3D_SM4_REGISTER_MODIFIER)
@@ -1601,6 +1603,10 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr
                 *modifier = VKD3DSPSM_NONE;
                 break;
         }
+
+        if (m & VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM)
+            param->modifier = VKD3DSPRM_NONUNIFORM;
+
     }
     else
     {
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index b99615f4..f8c93a34 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -337,6 +337,7 @@ struct vkd3d_spirv_builder
     uint64_t capability_draw_parameters : 1;
     uint64_t capability_demote_to_helper_invocation : 1;
     uint64_t capability_descriptor_indexing : 1;
+    uint64_t capability_non_uniform : 1;
     uint32_t ext_instr_set_glsl_450;
     uint32_t invocation_count;
     SpvExecutionModel execution_model;
@@ -387,6 +388,10 @@ static void vkd3d_spirv_enable_capability(struct vkd3d_spirv_builder *builder,
     {
         builder->capability_demote_to_helper_invocation = 1;
     }
+    else if (cap == SpvCapabilityShaderNonUniformEXT)
+    {
+        builder->capability_non_uniform = 1;
+    }
     else
     {
         FIXME("Unhandled capability %#x.\n", cap);
@@ -1809,6 +1814,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder,
         vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDrawParameters);
     if (builder->capability_demote_to_helper_invocation)
         vkd3d_spirv_build_op_capability(&stream, SpvCapabilityDemoteToHelperInvocationEXT);
+    if (builder->capability_non_uniform)
+        vkd3d_spirv_build_op_capability(&stream, SpvCapabilityShaderNonUniformEXT);
 
     /* extensions */
     if (builder->capability_draw_parameters)
@@ -2670,6 +2677,15 @@ static void vkd3d_dxbc_compiler_emit_descriptor_binding_for_reg(struct vkd3d_dxb
     vkd3d_dxbc_compiler_emit_descriptor_binding(compiler, variable_id, &binding);
 }
 
+static void vkd3d_dxbc_compiler_decorate_nonuniform(struct vkd3d_dxbc_compiler *compiler,
+        uint32_t expression_id)
+{
+    struct vkd3d_spirv_builder *builder = &compiler->spirv_builder;
+
+    vkd3d_spirv_enable_capability(builder, SpvCapabilityShaderNonUniformEXT);
+    vkd3d_spirv_build_op_decorate(builder, expression_id, SpvDecorationNonUniformEXT, NULL, 0);
+}
+
 static void vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler,
         const struct vkd3d_symbol *symbol)
 {
@@ -3253,6 +3269,10 @@ static uint32_t vkd3d_dxbc_compiler_get_resource_index(struct vkd3d_dxbc_compile
         index_id = vkd3d_dxbc_compiler_get_constant_uint(compiler, reg->idx[0].offset + binding_offset);
     }
 
+    /* AMD drivers rely on the index being marked as nonuniform */
+    if (reg->modifier == VKD3DSPRM_NONUNIFORM)
+        vkd3d_dxbc_compiler_decorate_nonuniform(compiler, index_id);
+
     return index_id;
 }
 
@@ -3327,6 +3347,8 @@ static void vkd3d_dxbc_compiler_emit_dereference_register(struct vkd3d_dxbc_comp
         ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, register_info->storage_class, type_id);
         register_info->id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id,
                 register_info->id, indexes, index_count);
+        if (reg->modifier == VKD3DSPRM_NONUNIFORM)
+            vkd3d_dxbc_compiler_decorate_nonuniform(compiler, register_info->id);
     }
 }
 
@@ -7908,6 +7930,8 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
     {
         image->image_id = vkd3d_spirv_build_op_load(builder,
                 image->image_type_id, image->id, SpvMemoryAccessMaskNone);
+        if (resource_reg->modifier == VKD3DSPRM_NONUNIFORM)
+            vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image->image_id);
     }
     else
     {
@@ -7939,9 +7963,14 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
 
         sampler_id = vkd3d_spirv_build_op_load(builder,
                 vkd3d_spirv_get_op_type_sampler(builder), sampler_var_id, SpvMemoryAccessMaskNone);
+        if (sampler_reg->modifier == VKD3DSPRM_NONUNIFORM)
+            vkd3d_dxbc_compiler_decorate_nonuniform(compiler, sampler_id);
+
         sampled_image_type_id = vkd3d_spirv_get_op_type_sampled_image(builder, image->image_type_id);
         image->sampled_image_id = vkd3d_spirv_build_op_sampled_image(builder,
                 sampled_image_type_id, image->image_id, sampler_id);
+        if (resource_reg->modifier == VKD3DSPRM_NONUNIFORM)
+            vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image->sampled_image_id);
     }
     else
     {
@@ -8293,6 +8322,9 @@ static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc
 
             ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
             constituents[j++] = vkd3d_spirv_build_op_load(builder, texel_type_id, ptr_id, SpvMemoryAccessMaskNone);
+
+            if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM)
+                vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
         }
     }
     else
@@ -8435,6 +8467,9 @@ static void vkd3d_dxbc_compiler_emit_store_uav_raw_structured(struct vkd3d_dxbc_
 
             ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
             vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone);
+
+            if (dst->reg.modifier == VKD3DSPRM_NONUNIFORM)
+                vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
         }
     }
     else
@@ -8811,6 +8846,8 @@ static void vkd3d_dxbc_compiler_emit_atomic_instruction(struct vkd3d_dxbc_compil
             pointer_id = vkd3d_spirv_build_op_image_texel_pointer(builder,
                     ptr_type_id, image.id, coordinate_id, sample_id);
         }
+        if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM)
+            vkd3d_dxbc_compiler_decorate_nonuniform(compiler, pointer_id);
     }
 
     val_id = vkd3d_dxbc_compiler_emit_load_src_with_type(compiler, &src[1], VKD3DSP_WRITEMASK_0, component_type);
@@ -8859,6 +8896,8 @@ static void vkd3d_dxbc_compiler_emit_bufinfo(struct vkd3d_dxbc_compiler *compile
 
         type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_UINT, 1);
         val_id = vkd3d_spirv_build_op_image_query_size(builder, type_id, image.image_id);
+        if (src->reg.modifier == VKD3DSPRM_NONUNIFORM)
+            vkd3d_dxbc_compiler_decorate_nonuniform(compiler, image.id);
         write_mask = VKD3DSP_WRITEMASK_0;
     }
 
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 54930fa2..453d3fb7 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -436,6 +436,12 @@ enum vkd3d_immconst_type
     VKD3D_IMMCONST_VEC4,
 };
 
+enum vkd3d_shader_register_modifier
+{
+    VKD3DSPRM_NONE = 0,
+    VKD3DSPRM_NONUNIFORM = 1,
+};
+
 enum vkd3d_shader_src_modifier
 {
     VKD3DSPSM_NONE = 0,
@@ -604,6 +610,7 @@ struct vkd3d_shader_register_index
 struct vkd3d_shader_register
 {
     enum vkd3d_shader_register_type type;
+    enum vkd3d_shader_register_modifier modifier;
     enum vkd3d_data_type data_type;
     struct vkd3d_shader_register_index idx[3];
     enum vkd3d_immconst_type immconst_type;
-- 
2.31.1




More information about the wine-devel mailing list