From 8d8de1db104d70de538a912c283e926ebea5ef09 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani <gmascellani@codeweavers.com> Date: Fri, 15 Nov 2024 14:10:16 +0100 Subject: [PATCH 1/5] vkd3d-shader/ir: Validate the semantic index for tessellation system values. --- libs/vkd3d-shader/ir.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index b0e89beded..4f5cc8e0ba 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -7471,6 +7471,7 @@ static void vsir_validate_signature_element(struct validation_context *ctx, { const char *signature_type_name = signature_type_names[signature_type]; const struct signature_element *element = &signature->elements[idx]; + unsigned int semantic_index_max = 0; bool integer_type = false; if (element->register_count == 0) @@ -7523,12 +7524,6 @@ static void vsir_validate_signature_element(struct validation_context *ctx, case VKD3D_SHADER_SV_INSTANCE_ID: case VKD3D_SHADER_SV_IS_FRONT_FACE: case VKD3D_SHADER_SV_SAMPLE_INDEX: - case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: - case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: - case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: - case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: - case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: - case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: case VKD3D_SHADER_SV_TARGET: case VKD3D_SHADER_SV_DEPTH: case VKD3D_SHADER_SV_COVERAGE: @@ -7537,6 +7532,27 @@ static void vsir_validate_signature_element(struct validation_context *ctx, case VKD3D_SHADER_SV_STENCIL_REF: break; + case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: + semantic_index_max = 4; + break; + + case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: + semantic_index_max = 2; + break; + + case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: + semantic_index_max = 3; + break; + + case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: + semantic_index_max = 1; + break; + + case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: + case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: + semantic_index_max = 2; + break; + default: validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, "element %u of %s signature: Invalid system value semantic %#x.", @@ -7544,6 +7560,11 @@ static void vsir_validate_signature_element(struct validation_context *ctx, break; } + if (semantic_index_max != 0 && element->semantic_index >= semantic_index_max) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid semantic index %u for system value semantic %#x.", + idx, signature_type_name, element->semantic_index, element->sysval_semantic); + if (element->sysval_semantic < ARRAY_SIZE(sysval_validation_data)) { const struct sysval_validation_data_element *data = &sysval_validation_data[element->sysval_semantic]; -- GitLab From 49ec9add386ad7304e0de4f99ee7258513ae4e57 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani <gmascellani@codeweavers.com> Date: Fri, 15 Nov 2024 14:26:43 +0100 Subject: [PATCH 2/5] vkd3d-shader/ir: Check that semantic indices for tessellation system values are not duplicated. --- libs/vkd3d-shader/ir.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 4f5cc8e0ba..1d49ef2752 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -6665,6 +6665,9 @@ struct validation_context enum vkd3d_shader_opcode *blocks; size_t depth; size_t blocks_capacity; + + unsigned int outer_tess_idxs[4]; + unsigned int inner_tess_idxs[2]; }; static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx, @@ -7471,8 +7474,8 @@ static void vsir_validate_signature_element(struct validation_context *ctx, { const char *signature_type_name = signature_type_names[signature_type]; const struct signature_element *element = &signature->elements[idx]; + bool integer_type = false, is_outer = false; unsigned int semantic_index_max = 0; - bool integer_type = false; if (element->register_count == 0) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, @@ -7534,23 +7537,28 @@ static void vsir_validate_signature_element(struct validation_context *ctx, case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: semantic_index_max = 4; + is_outer = true; break; case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: semantic_index_max = 2; + is_outer = false; break; case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: semantic_index_max = 3; + is_outer = true; break; case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: semantic_index_max = 1; + is_outer = false; break; case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: semantic_index_max = 2; + is_outer = true; break; default: @@ -7560,10 +7568,26 @@ static void vsir_validate_signature_element(struct validation_context *ctx, break; } - if (semantic_index_max != 0 && element->semantic_index >= semantic_index_max) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, - "element %u of %s signature: Invalid semantic index %u for system value semantic %#x.", - idx, signature_type_name, element->semantic_index, element->sysval_semantic); + if (semantic_index_max != 0) + { + if (element->semantic_index >= semantic_index_max) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid semantic index %u for system value semantic %#x.", + idx, signature_type_name, element->semantic_index, element->sysval_semantic); + } + else + { + unsigned int *idx_pos = &(is_outer ? ctx->outer_tess_idxs : ctx->inner_tess_idxs)[element->semantic_index]; + + if (*idx_pos != ~0u) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Duplicate semantic index %u for system value semantic %#x.", + idx, signature_type_name, element->semantic_index, element->sysval_semantic); + else + *idx_pos = idx; + } + } if (element->sysval_semantic < ARRAY_SIZE(sysval_validation_data)) { @@ -8198,6 +8222,12 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c .status = VKD3D_OK, .phase = VKD3DSIH_INVALID, .invalid_instruction_idx = true, + .outer_tess_idxs[0] = ~0u, + .outer_tess_idxs[1] = ~0u, + .outer_tess_idxs[2] = ~0u, + .outer_tess_idxs[3] = ~0u, + .inner_tess_idxs[0] = ~0u, + .inner_tess_idxs[1] = ~0u, }; unsigned int i; -- GitLab From 1ed8d907b3998b847daa26154ca0261f55f0de23 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani <gmascellani@codeweavers.com> Date: Fri, 15 Nov 2024 14:51:52 +0100 Subject: [PATCH 3/5] vkd3d-shader/ir: Keep track of the tessellator domain in struct vsir_program. --- libs/vkd3d-shader/dxil.c | 1 + libs/vkd3d-shader/ir.c | 14 ++++++++++++++ libs/vkd3d-shader/spirv.c | 14 +++++--------- libs/vkd3d-shader/tpf.c | 1 + libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 1cf01616ce..d467693bd5 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -9717,6 +9717,7 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6, ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_TESSELLATOR_DOMAIN); ins->declaration.tessellator_domain = tessellator_domain; + sm6->p.program->tess_domain = tessellator_domain; } static void sm6_parser_validate_control_point_count(struct sm6_parser *sm6, diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 1d49ef2752..127b912549 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -743,6 +743,7 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr case VKD3DSIH_DCL_GLOBAL_FLAGS: case VKD3DSIH_DCL_SAMPLER: case VKD3DSIH_DCL_TEMPS: + case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: case VKD3DSIH_DCL_THREAD_GROUP: case VKD3DSIH_DCL_UAV_TYPED: vkd3d_shader_instruction_make_nop(ins); @@ -7846,6 +7847,11 @@ static void vsir_validate_dcl_tessellator_domain(struct validation_context *ctx, || instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, "Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain); + + if (instruction->declaration.tessellator_domain != ctx->program->tess_domain) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, + "DCL_TESSELLATOR_DOMAIN argument %#x doesn't match the shader tessellator domain %#x.", + instruction->declaration.tessellator_domain, ctx->program->tess_domain); } static void vsir_validate_dcl_tessellator_output_primitive(struct validation_context *ctx, @@ -8238,12 +8244,20 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c { case VKD3D_SHADER_TYPE_HULL: case VKD3D_SHADER_TYPE_DOMAIN: + if (program->tess_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID + || program->tess_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT) + validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, + "Invalid tessellation domain %#x.", program->tess_domain); break; default: if (program->patch_constant_signature.element_count != 0) validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, "Patch constant signature is only valid for hull and domain shaders."); + + if (program->tess_domain != VKD3D_TESSELLATOR_DOMAIN_INVALID) + validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION, + "Invalid tessellation domain %#x.", program->tess_domain); } switch (program->shader_version.type) diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index b9876e743a..ef5456430c 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -6822,15 +6822,11 @@ static void spirv_compiler_emit_dcl_gs_instances(struct spirv_compiler *compiler compiler->spirv_builder.invocation_count = instruction->declaration.count; } -static void spirv_compiler_emit_dcl_tessellator_domain(struct spirv_compiler *compiler, - const struct vkd3d_shader_instruction *instruction) +static void spirv_compiler_emit_tessellator_domain(struct spirv_compiler *compiler, + enum vkd3d_tessellator_domain domain) { - enum vkd3d_tessellator_domain domain = instruction->declaration.tessellator_domain; SpvExecutionMode mode; - if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL && spirv_compiler_is_opengl_target(compiler)) - return; - switch (domain) { case VKD3D_TESSELLATOR_DOMAIN_LINE: @@ -10239,9 +10235,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT: spirv_compiler_emit_output_vertex_count(compiler, instruction); break; - case VKD3DSIH_DCL_TESSELLATOR_DOMAIN: - spirv_compiler_emit_dcl_tessellator_domain(compiler, instruction); - break; case VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE: spirv_compiler_emit_tessellator_output_primitive(compiler, instruction->declaration.tessellator_output_primitive); @@ -10743,6 +10736,9 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, struct compiler->input_control_point_count = program->input_control_point_count; compiler->output_control_point_count = program->output_control_point_count; + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL && !spirv_compiler_is_opengl_target(compiler)) + spirv_compiler_emit_tessellator_domain(compiler, program->tess_domain); + if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) spirv_compiler_emit_shader_signature_outputs(compiler); diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 0c20981b4d..e1ca5d6f0a 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -1268,6 +1268,7 @@ static void shader_sm5_read_dcl_tessellator_domain(struct vkd3d_shader_instructi { ins->declaration.tessellator_domain = (opcode_token & VKD3D_SM5_TESSELLATOR_MASK) >> VKD3D_SM5_TESSELLATOR_SHIFT; + priv->p.program->tess_domain = ins->declaration.tessellator_domain; } static void shader_sm5_read_dcl_tessellator_partitioning(struct vkd3d_shader_instruction *ins, uint32_t opcode, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index c3f9dc2e5a..b9f2b25c84 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1431,6 +1431,7 @@ struct vsir_program uint8_t diffuse_written_mask; enum vsir_control_flow_type cf_type; enum vsir_normalisation_level normalisation_level; + enum vkd3d_tessellator_domain tess_domain; const char **block_names; size_t block_name_count; -- GitLab From 018f3e8094b8f68a089b9fce9b2293c07f66ff44 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani <gmascellani@codeweavers.com> Date: Fri, 15 Nov 2024 15:01:08 +0100 Subject: [PATCH 4/5] vkd3d-shader/ir: Validate tessellation system values for the given tessellator domain. --- libs/vkd3d-shader/ir.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 127b912549..277268db27 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -7473,6 +7473,7 @@ static void vsir_validate_signature_element(struct validation_context *ctx, const struct shader_signature *signature, enum vsir_signature_type signature_type, unsigned int idx) { + enum vkd3d_tessellator_domain expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_INVALID; const char *signature_type_name = signature_type_names[signature_type]; const struct signature_element *element = &signature->elements[idx]; bool integer_type = false, is_outer = false; @@ -7537,27 +7538,32 @@ static void vsir_validate_signature_element(struct validation_context *ctx, break; case VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE: + expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_QUAD; semantic_index_max = 4; is_outer = true; break; case VKD3D_SHADER_SV_TESS_FACTOR_QUADINT: + expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_QUAD; semantic_index_max = 2; is_outer = false; break; case VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE: + expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_TRIANGLE; semantic_index_max = 3; is_outer = true; break; case VKD3D_SHADER_SV_TESS_FACTOR_TRIINT: + expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_TRIANGLE; semantic_index_max = 1; is_outer = false; break; case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: + expected_tess_domain = VKD3D_TESSELLATOR_DOMAIN_LINE; semantic_index_max = 2; is_outer = true; break; @@ -7569,8 +7575,13 @@ static void vsir_validate_signature_element(struct validation_context *ctx, break; } - if (semantic_index_max != 0) + if (expected_tess_domain != VKD3D_TESSELLATOR_DOMAIN_INVALID) { + if (ctx->program->tess_domain != expected_tess_domain) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: Invalid system value semantic %#x for tessellator domain %#x.", + idx, signature_type_name, element->sysval_semantic, ctx->program->tess_domain); + if (element->semantic_index >= semantic_index_max) { validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, -- GitLab From e383834049825dde8feb0a230c39d499e580cdf1 Mon Sep 17 00:00:00 2001 From: Giovanni Mascellani <gmascellani@codeweavers.com> Date: Fri, 15 Nov 2024 15:04:28 +0100 Subject: [PATCH 5/5] vkd3d-shader/ir: Check that tessellation system values only appear in the patch constant signature. --- libs/vkd3d-shader/ir.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 277268db27..56c98d3066 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -7577,6 +7577,12 @@ static void vsir_validate_signature_element(struct validation_context *ctx, if (expected_tess_domain != VKD3D_TESSELLATOR_DOMAIN_INVALID) { + if (signature_type != SIGNATURE_TYPE_PATCH_CONSTANT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, + "element %u of %s signature: System value semantic %#x is only valid " + "in the patch constant signature.", + idx, signature_type_name, element->sysval_semantic); + if (ctx->program->tess_domain != expected_tess_domain) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, "element %u of %s signature: Invalid system value semantic %#x for tessellator domain %#x.", -- GitLab