-- v4: vkd3d-shader/spirv: No longer handle builtin array size mismatch in spirv_compiler_emit_input(). vkd3d-shader/spirv: Remove handling of VKD3DSPR_OUTCONTROLPOINT. vkd3d-shader/ir: Check for vocp usage during IR normalization. vkd3d-shader/ir: Pass a vkd3d_shader_parser to instruction_array_normalise_io_registers().
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/ir.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index c8cbf1e46..df8db66bb 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1071,24 +1071,22 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi } }
-static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_shader_instruction_array *instructions, - enum vkd3d_shader_type shader_type, struct shader_signature *input_signature, - struct shader_signature *output_signature, struct shader_signature *patch_constant_signature) +static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parser *parser) { - struct io_normaliser normaliser = {*instructions}; + struct io_normaliser normaliser = {parser->instructions}; struct vkd3d_shader_instruction *ins; bool has_control_point_phase; unsigned int i, j;
normaliser.phase = VKD3DSIH_INVALID; - normaliser.shader_type = shader_type; - normaliser.input_signature = input_signature; - normaliser.output_signature = output_signature; - normaliser.patch_constant_signature = patch_constant_signature; + normaliser.shader_type = parser->shader_version.type; + normaliser.input_signature = &parser->shader_desc.input_signature; + normaliser.output_signature = &parser->shader_desc.output_signature; + normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature;
- for (i = 0, has_control_point_phase = false; i < instructions->count; ++i) + for (i = 0, has_control_point_phase = false; i < parser->instructions.count; ++i) { - ins = &instructions->elements[i]; + ins = &parser->instructions.elements[i];
switch (ins->handler_idx) { @@ -1127,11 +1125,11 @@ static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_s } }
- if (!shader_signature_merge(input_signature, normaliser.input_range_map, false) - || !shader_signature_merge(output_signature, normaliser.output_range_map, false) - || !shader_signature_merge(patch_constant_signature, normaliser.pc_range_map, true)) + if (!shader_signature_merge(&parser->shader_desc.input_signature, normaliser.input_range_map, false) + || !shader_signature_merge(&parser->shader_desc.output_signature, normaliser.output_range_map, false) + || !shader_signature_merge(&parser->shader_desc.patch_constant_signature, normaliser.pc_range_map, true)) { - *instructions = normaliser.instructions; + parser->instructions = normaliser.instructions; return VKD3D_ERROR_OUT_OF_MEMORY; }
@@ -1139,7 +1137,7 @@ static enum vkd3d_result instruction_array_normalise_io_registers(struct vkd3d_s for (i = 0; i < normaliser.instructions.count; ++i) shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser);
- *instructions = normaliser.instructions; + parser->instructions = normaliser.instructions; return VKD3D_OK; }
@@ -1444,9 +1442,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, &parser->shader_desc.input_signature); } if (result >= 0) - result = instruction_array_normalise_io_registers(instructions, parser->shader_version.type, - &parser->shader_desc.input_signature, &parser->shader_desc.output_signature, - &parser->shader_desc.patch_constant_signature); + result = shader_normalise_io_registers(parser);
if (result >= 0) result = instruction_array_normalise_flat_constants(parser);
From: Zebediah Figura zfigura@codeweavers.com
The hull shader barrier used for this was broken by I/O normalization, since vocp is no longer exposed to the spirv backend.
Restore this barrier by checking for vocp during normalization instead. --- libs/vkd3d-shader/ir.c | 7 +++++++ libs/vkd3d-shader/spirv.c | 4 +--- libs/vkd3d-shader/vkd3d_shader_private.h | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index df8db66bb..9f4a084e3 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -550,6 +550,8 @@ struct io_normaliser uint8_t input_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE]; uint8_t output_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE]; uint8_t pc_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE]; + + bool use_vocp; };
static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser) @@ -1031,6 +1033,10 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi if (normaliser->shader_type == VKD3D_SHADER_TYPE_HULL) { reg = &ins->declaration.dst.reg; + + if (reg->type == VKD3DSPR_OUTCONTROLPOINT) + normaliser->use_vocp = true; + /* We don't need to keep OUTCONTROLPOINT or PATCHCONST input declarations since their * equivalents were declared earlier, but INCONTROLPOINT may be the first occurrence. */ if (reg->type == VKD3DSPR_OUTCONTROLPOINT || reg->type == VKD3DSPR_PATCHCONST) @@ -1138,6 +1144,7 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser);
parser->instructions = normaliser.instructions; + parser->shader_desc.use_vocp = normaliser.use_vocp; return VKD3D_OK; }
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index 6faac0ccd..a43d1c004 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6146,9 +6146,6 @@ static void spirv_compiler_emit_dcl_input(struct spirv_compiler *compiler, spirv_compiler_emit_input(compiler, dst); else spirv_compiler_emit_input_register(compiler, dst); - - if (dst->reg.type == VKD3DSPR_OUTCONTROLPOINT) - compiler->use_vocp = true; }
static void spirv_compiler_emit_dcl_input_sysval(struct spirv_compiler *compiler, @@ -9722,6 +9719,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, memset(&shader_desc->input_signature, 0, sizeof(shader_desc->input_signature)); memset(&shader_desc->output_signature, 0, sizeof(shader_desc->output_signature)); memset(&shader_desc->patch_constant_signature, 0, sizeof(shader_desc->patch_constant_signature)); + compiler->use_vocp = parser->shader_desc.use_vocp;
if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) spirv_compiler_emit_shader_signature_outputs(compiler); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f6421cc8a..f72b8df47 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -943,6 +943,8 @@ struct vkd3d_shader_desc { uint32_t used, external; } flat_constant_count[3]; + + bool use_vocp; };
struct vkd3d_shader_register_semantic
From: Zebediah Figura zfigura@codeweavers.com
I/O normalization removes this register type. --- libs/vkd3d-shader/spirv.c | 1 - libs/vkd3d-shader/vkd3d_shader_private.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index a43d1c004..d6cbab703 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4862,7 +4862,6 @@ static void spirv_compiler_emit_shader_phase_input(struct spirv_compiler *compil spirv_compiler_emit_input_register(compiler, dst); return; case VKD3DSPR_OUTPOINTID: /* Emitted in spirv_compiler_emit_initial_declarations(). */ - case VKD3DSPR_OUTCONTROLPOINT: /* See spirv_compiler_leave_shader_phase(). */ return; default: FIXME("Unhandled shader phase input register %#x.\n", reg->type); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f72b8df47..9603c2e22 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1094,7 +1094,7 @@ static inline bool vkd3d_shader_instruction_has_texel_offset(const struct vkd3d_
static inline bool vkd3d_shader_register_is_input(const struct vkd3d_shader_register *reg) { - return reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT; + return reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_INCONTROLPOINT; }
static inline bool vkd3d_shader_register_is_output(const struct vkd3d_shader_register *reg)
From: Zebediah Figura zfigura@codeweavers.com
This is taken care of by prior I/O lowering. We no longer need to deal with this here. --- libs/vkd3d-shader/spirv.c | 53 ++++++++++++--------------------------- 1 file changed, 16 insertions(+), 37 deletions(-)
diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index d6cbab703..aa037b621 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4649,18 +4649,17 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler, const struct shader_signature *shader_signature; enum vkd3d_shader_component_type component_type; enum vkd3d_shader_input_sysval_semantic sysval; - uint32_t type_id, ptr_type_id, float_type_id; const struct vkd3d_spirv_builtin *builtin; unsigned int write_mask, reg_write_mask; struct vkd3d_symbol *symbol = NULL; uint32_t val_id, input_id, var_id; + uint32_t type_id, float_type_id; struct vkd3d_symbol reg_symbol; SpvStorageClass storage_class; struct rb_entry *entry = NULL; bool use_private_var = false; unsigned int array_sizes[2]; unsigned int element_idx; - uint32_t i, index;
assert(!reg->idx_count || !reg->idx[0].rel_addr); assert(reg->idx_count < 2 || !reg->idx[1].rel_addr); @@ -4765,47 +4764,27 @@ static uint32_t spirv_compiler_emit_input(struct spirv_compiler *compiler,
if (use_private_var) { + struct vkd3d_shader_register dst_reg = *reg; + dst_reg.data_type = VKD3D_DATA_FLOAT; + type_id = vkd3d_spirv_get_type_id(builder, component_type, input_component_count); - for (i = 0; i < max(array_sizes[0], 1); ++i) - { - struct vkd3d_shader_register dst_reg = *reg; - dst_reg.data_type = VKD3D_DATA_FLOAT;
- val_id = input_id; - if (array_sizes[0]) - { - ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassInput, type_id); - index = spirv_compiler_get_constant_uint(compiler, i); - 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 = spirv_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 = element_idx + i; - } - val_id = vkd3d_spirv_build_op_load(builder, type_id, val_id, SpvMemoryAccessMaskNone); + val_id = vkd3d_spirv_build_op_load(builder, type_id, input_id, SpvMemoryAccessMaskNone);
- if (builtin && builtin->fixup_pfn) - val_id = builtin->fixup_pfn(compiler, val_id); + if (builtin && builtin->fixup_pfn) + val_id = builtin->fixup_pfn(compiler, val_id);
- if (component_type != VKD3D_SHADER_COMPONENT_FLOAT) - { - float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, input_component_count); - val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id); - } + if (component_type != VKD3D_SHADER_COMPONENT_FLOAT) + { + float_type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, input_component_count); + val_id = vkd3d_spirv_build_op_bitcast(builder, float_type_id, val_id); + }
- val_id = spirv_compiler_emit_swizzle(compiler, val_id, - vkd3d_write_mask_from_component_count(input_component_count), - VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx); + val_id = spirv_compiler_emit_swizzle(compiler, val_id, + vkd3d_write_mask_from_component_count(input_component_count), + VKD3D_SHADER_COMPONENT_FLOAT, VKD3D_SHADER_NO_SWIZZLE, dst->write_mask >> component_idx);
- spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id); - } + spirv_compiler_emit_store_reg(compiler, &dst_reg, dst->write_mask, val_id); }
return input_id;
Seems fine to me like this, but note that this is failing CI on Windows; possibly because it's still missing Giovanni's commit ca7fa0c0150fd0defb1459ac74f58e393e341a78.
Rebased on top of master again, then.
This merge request was approved by Henri Verbeet.