Conor McCarthy : vkd3d-shader/spirv: Handle arrayed builtin inputs.

Alexandre Julliard julliard at winehq.org
Wed Nov 17 16:25:40 CST 2021


Module: vkd3d
Branch: master
Commit: c41931c7508e0f2e6467db55319438ec2b24e16b
URL:    https://source.winehq.org/git/vkd3d.git/?a=commit;h=c41931c7508e0f2e6467db55319438ec2b24e16b

Author: Conor McCarthy <cmccarthy at codeweavers.com>
Date:   Wed Nov 17 13:05:59 2021 +0100

vkd3d-shader/spirv: Handle arrayed builtin inputs.

Fixes invalid SPIR-V being generated in Monster Hunter: World.
Based on vkd3d-proton patches by Hans-Kristian Arntzen and Philip Rebohle.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 libs/vkd3d-shader/spirv.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c
index 8827c43..e1a7dd3 100644
--- a/libs/vkd3d-shader/spirv.c
+++ b/libs/vkd3d-shader/spirv.c
@@ -4416,6 +4416,13 @@ static bool needs_private_io_variable(const struct vkd3d_shader_signature *signa
     bool have_sysval = false;
     unsigned int i, count;
 
+    /* Always use private variables for arrayed builtins. These are generally
+     * scalars on the D3D side, so would need extra array indices when
+     * accessing them. It may be feasible to insert those indices at the point
+     * where the builtins are used, but it's not clear it's worth the effort. */
+    if (builtin && (builtin->spirv_array_size || builtin->fixup_pfn))
+        return true;
+
     if (*component_count == VKD3D_VEC4_SIZE)
         return false;
 
@@ -4519,8 +4526,7 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
         component_idx = vkd3d_write_mask_get_component_idx(signature_element->mask);
     }
 
-    if (!(use_private_var = builtin && builtin->fixup_pfn)
-            && needs_private_io_variable(shader_signature, reg_idx, builtin, &input_component_count, &write_mask)
+    if (needs_private_io_variable(shader_signature, reg_idx, builtin, &input_component_count, &write_mask)
             && (compiler->shader_type != VKD3D_SHADER_TYPE_HULL
             || (reg->type != VKD3DSPR_INCONTROLPOINT && reg->type != VKD3DSPR_PATCHCONST)))
         use_private_var = true;
@@ -4644,6 +4650,16 @@ static uint32_t vkd3d_dxbc_compiler_emit_input(struct vkd3d_dxbc_compiler *compi
                 val_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, input_id, index);
                 dst_reg.idx[0].offset = i;
             }
+            else if (builtin && builtin->spirv_array_size)
+            {
+                /* The D3D builtin is not an array, but the SPIR-V builtin is,
+                 * so we'll need to index into the SPIR-V builtin when loading
+                 * it. This happens when reading TessLevel in domain shaders. */
+                ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id);
+                index = vkd3d_dxbc_compiler_get_constant_uint(compiler, builtin->member_idx);
+                val_id = vkd3d_spirv_build_op_in_bounds_access_chain1(builder, ptr_type_id, input_id, index);
+                dst_reg.idx[0].offset = reg_idx + i;
+            }
             val_id = vkd3d_spirv_build_op_load(builder, type_id, val_id, SpvMemoryAccessMaskNone);
 
             if (builtin && builtin->fixup_pfn)
@@ -4947,11 +4963,11 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
     const struct vkd3d_spirv_builtin *builtin;
     const struct vkd3d_shader_phase *phase;
     struct vkd3d_symbol *symbol = NULL;
+    bool use_private_variable = false;
     struct vkd3d_symbol reg_symbol;
     SpvStorageClass storage_class;
     struct rb_entry *entry = NULL;
     unsigned int signature_idx;
-    bool use_private_variable;
     unsigned int write_mask;
     unsigned int array_size;
     bool is_patch_constant;
@@ -4991,11 +5007,10 @@ static void vkd3d_dxbc_compiler_emit_output(struct vkd3d_dxbc_compiler *compiler
 
     storage_class = SpvStorageClassOutput;
 
-    if (!(use_private_variable = builtin && builtin->spirv_array_size)
-            && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE
+    if (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE
             || needs_private_io_variable(shader_signature, signature_element->register_index,
                     builtin, &output_component_count, &write_mask)
-            || is_patch_constant))
+            || is_patch_constant)
         use_private_variable = true;
     else
         component_idx = vkd3d_write_mask_get_component_idx(write_mask);




More information about the wine-cvs mailing list