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

Conor McCarthy cmccarthy at codeweavers.com
Fri Aug 13 09:55:43 CDT 2021


Based on vkd3d-proton patches by Philip Rebohle and Hans-Kristian Arntzen.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d-shader/dxbc.c                 |  7 ++++
 libs/vkd3d-shader/sm4.h                  |  1 +
 libs/vkd3d-shader/spirv.c                | 42 ++++++++++++++++++++++--
 libs/vkd3d-shader/vkd3d_shader_private.h |  7 ++++
 tests/d3d12.c                            |  3 +-
 5 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/libs/vkd3d-shader/dxbc.c b/libs/vkd3d-shader/dxbc.c
index 412b9267..9371e262 100644
--- a/libs/vkd3d-shader/dxbc.c
+++ b/libs/vkd3d-shader/dxbc.c
@@ -1121,6 +1121,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)
@@ -1155,6 +1156,12 @@ static bool shader_sm4_read_param(struct vkd3d_sm4_data *priv, const DWORD **ptr
         }
         m &= ~(VKD3D_SM4_REGISTER_MODIFIER_ABS | VKD3D_SM4_REGISTER_MODIFIER_NEGATE);
 
+        if (m & VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM)
+        {
+            param->modifier = VKD3DSPRM_NONUNIFORM;
+            m &= ~VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM;
+        }
+
         if (m)
             FIXME("Skipping modifier flags 0x%08x.\n", m);
 
diff --git a/libs/vkd3d-shader/sm4.h b/libs/vkd3d-shader/sm4.h
index e8dbeb4b..8dbbeb3d 100644
--- a/libs/vkd3d-shader/sm4.h
+++ b/libs/vkd3d-shader/sm4.h
@@ -387,6 +387,7 @@ enum vkd3d_sm4_register_modifier
 {
     VKD3D_SM4_REGISTER_MODIFIER_NEGATE     = 0x20,
     VKD3D_SM4_REGISTER_MODIFIER_ABS        = 0x40,
+    VKD3D_SM4_REGISTER_MODIFIER_NONUNIFORM = 0x10000,
 };
 
 enum vkd3d_sm4_output_primitive_type
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 4e67af49..a0c60972 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -1842,7 +1842,8 @@ static bool vkd3d_spirv_compile_module(struct vkd3d_spirv_builder *builder,
             || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilitySampledImageArrayDynamicIndexing)
             || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageBufferArrayDynamicIndexing)
             || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT)
-            || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageImageArrayDynamicIndexing))
+            || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityStorageImageArrayDynamicIndexing)
+            || vkd3d_spirv_capability_is_enabled(builder, SpvCapabilityShaderNonUniformEXT))
         vkd3d_spirv_build_op_extension(&stream, "SPV_EXT_descriptor_indexing");
 
     if (builder->ext_instr_set_glsl_450)
@@ -2675,6 +2676,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 const struct vkd3d_symbol *vkd3d_dxbc_compiler_put_symbol(struct vkd3d_dxbc_compiler *compiler,
         const struct vkd3d_symbol *symbol)
 {
@@ -3242,6 +3252,9 @@ static uint32_t vkd3d_dxbc_compiler_get_descriptor_index(struct vkd3d_dxbc_compi
 
     index.offset -= binding_base_idx;
     index_id = vkd3d_dxbc_compiler_emit_register_addressing(compiler, &index);
+    /* 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;
 }
@@ -3319,6 +3332,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);
     }
 }
 
@@ -7992,8 +8007,16 @@ static void vkd3d_dxbc_compiler_prepare_image(struct vkd3d_dxbc_compiler *compil
         return;
     }
 
-    image->image_id = load ? vkd3d_spirv_build_op_load(builder,
-            image->image_type_id, image->id, SpvMemoryAccessMaskNone) : 0;
+    if (load)
+    {
+        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
+    {
+        image->image_id = 0;
+    }
 
     image->image_type_id = vkd3d_dxbc_compiler_get_image_type_id(compiler, resource_reg,
             &symbol->info.resource.range, image->resource_type_info,
@@ -8022,9 +8045,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
     {
@@ -8375,6 +8403,8 @@ static void vkd3d_dxbc_compiler_emit_ld_raw_structured_srv_uav(struct vkd3d_dxbc
             indices[1] = coordinate_id;
 
             ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+            if (resource->reg.modifier == VKD3DSPRM_NONUNIFORM)
+                vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
             constituents[j++] = vkd3d_spirv_build_op_load(builder, texel_type_id, ptr_id, SpvMemoryAccessMaskNone);
         }
     }
@@ -8517,6 +8547,8 @@ static void vkd3d_dxbc_compiler_emit_store_uav_raw_structured(struct vkd3d_dxbc_
             indices[1] = coordinate_id;
 
             ptr_id = vkd3d_spirv_build_op_access_chain(builder, ptr_type_id, resource_symbol->id, indices, 2);
+            if (dst->reg.modifier == VKD3DSPRM_NONUNIFORM)
+                vkd3d_dxbc_compiler_decorate_nonuniform(compiler, ptr_id);
             vkd3d_spirv_build_op_store(builder, ptr_id, data_id, SpvMemoryAccessMaskNone);
         }
     }
@@ -8894,6 +8926,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);
@@ -8942,6 +8976,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 9948045e..a70cab59 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -455,6 +455,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,
@@ -612,6 +618,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;
diff --git a/tests/d3d12.c b/tests/d3d12.c
index bd3ef624..ecda1272 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -34960,7 +34960,7 @@ static void test_unbounded_resource_arrays(void)
                 D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE);
         get_buffer_readback_with_command_list(output_buffers[i], DXGI_FORMAT_R32_UINT, &rb, queue, command_list);
         /* Buffers at index >= 64 are aliased. */
-        todo_if(i != 10 && i != 74)
+        todo_if(i != 74)
         check_readback_data_uint(&rb, NULL, (i < 64 ? 63 - i : 127 - i) ^ 0x35, 0);
         release_resource_readback(&rb);
         reset_command_list(command_list, context.allocator);
@@ -35107,7 +35107,6 @@ static void test_unbounded_samplers(void)
     {
         unsigned int value = get_readback_uint(&rb, i, 0, 0);
         unsigned int expected = (i & 1) ? 100 : 10;
-        todo_if(i & 1)
         ok(value == expected, "Got %u, expected %u at %u.\n", value, expected, i);
     }
     release_resource_readback(&rb);
-- 
2.32.0




More information about the wine-devel mailing list