From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 16e5948f5..5f37b1767 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1472,6 +1472,7 @@ struct validation_context struct vkd3d_shader_parser *parser; size_t instruction_idx; bool dcl_temps_found; + enum vkd3d_shader_opcode phase;
enum vkd3d_shader_opcode *blocks; size_t depth; @@ -1620,6 +1621,32 @@ static void vsir_validate_instruction(struct validation_context *ctx) instruction->handler_idx); }
+ switch (instruction->handler_idx) + { + case VKD3DSIH_HS_DECLS: + case VKD3DSIH_HS_CONTROL_POINT_PHASE: + case VKD3DSIH_HS_FORK_PHASE: + case VKD3DSIH_HS_JOIN_PHASE: + vsir_validate_dst_count(ctx, instruction, 0); + vsir_validate_src_count(ctx, instruction, 0); + if (ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Phase instruction %#x is only valid in a hull shader.", + instruction->handler_idx); + if (ctx->depth != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "Phase instruction %#x must appear to top level.", + instruction->handler_idx); + ctx->phase = instruction->handler_idx; + return; + + default: + break; + } + + if (ctx->parser->shader_version.type == VKD3D_SHADER_TYPE_HULL && + ctx->phase == VKD3DSIH_INVALID) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Instruction %#x appear before any phase instruction in a hull shader.", + instruction->handler_idx); + switch (instruction->handler_idx) { case VKD3DSIH_DCL_TEMPS: @@ -1720,7 +1747,11 @@ static void vsir_validate_instruction(struct validation_context *ctx)
void vsir_validate(struct vkd3d_shader_parser *parser) { - struct validation_context ctx = { .parser = parser }; + struct validation_context ctx = + { + .parser = parser, + .phase = VKD3DSIH_INVALID, + };
if (!(parser->config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION)) return;
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 5f37b1767..6e234d010 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1472,6 +1472,7 @@ struct validation_context struct vkd3d_shader_parser *parser; size_t instruction_idx; bool dcl_temps_found; + unsigned int temp_count; enum vkd3d_shader_opcode phase;
enum vkd3d_shader_opcode *blocks; @@ -1530,9 +1531,9 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->idx_count >= 1 && reg->idx[0].rel_addr) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Non-NULL relative address for a TEMP register.");
- if (reg->idx_count >= 1 && reg->idx[0].offset >= ctx->parser->shader_desc.temp_count) + if (reg->idx_count >= 1 && reg->idx[0].offset >= ctx->temp_count) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the declared count %u.", - reg->idx[0].offset, ctx->parser->shader_desc.temp_count); + reg->idx[0].offset, ctx->temp_count); break;
default: @@ -1636,6 +1637,8 @@ static void vsir_validate_instruction(struct validation_context *ctx) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INSTRUCTION_NESTING, "Phase instruction %#x must appear to top level.", instruction->handler_idx); ctx->phase = instruction->handler_idx; + ctx->dcl_temps_found = false; + ctx->temp_count = 0; return;
default: @@ -1652,15 +1655,13 @@ static void vsir_validate_instruction(struct validation_context *ctx) case VKD3DSIH_DCL_TEMPS: vsir_validate_dst_count(ctx, instruction, 0); vsir_validate_src_count(ctx, instruction, 0); - /* TODO Check that each phase in a hull shader has at most - * one occurrence. */ - if (ctx->dcl_temps_found && ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL) + if (ctx->dcl_temps_found) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction."); - ctx->dcl_temps_found = true; - if (instruction->declaration.count != ctx->parser->shader_desc.temp_count && - ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, "Invalid DCL_TEMPS count %u, expected %u.", + if (instruction->declaration.count > ctx->parser->shader_desc.temp_count) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS, "Invalid DCL_TEMPS count %u, expected at most %u.", instruction->declaration.count, ctx->parser->shader_desc.temp_count); + ctx->dcl_temps_found = true; + ctx->temp_count = instruction->declaration.count; break;
case VKD3DSIH_IF:
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 6e234d010..3756c9ccc 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -62,17 +62,7 @@ static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_i reg = (struct vkd3d_shader_register *)&ins->src[i].reg; if (shader_register_is_phase_instance_id(reg)) { - reg->type = VKD3DSPR_IMMCONST; - reg->precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; - reg->non_uniform = false; - reg->idx[0].offset = ~0u; - reg->idx[0].rel_addr = NULL; - reg->idx[1].offset = ~0u; - reg->idx[1].rel_addr = NULL; - reg->idx[2].offset = ~0u; - reg->idx[2].rel_addr = NULL; - reg->idx_count = 0; - reg->dimension = VSIR_DIMENSION_SCALAR; + vsir_register_init(reg, VKD3DSPR_IMMCONST, reg->data_type, 0); reg->u.immconst_uint[0] = instance_id; continue; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 3756c9ccc..9ae16f7f9 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1488,9 +1488,14 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c vkd3d_string_buffer_cleanup(&buf); }
+static void vsir_validate_src_param(struct validation_context *ctx, + const struct vkd3d_shader_src_param *src); + static void vsir_validate_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg) { + unsigned int i; + if (reg->type >= VKD3DSPR_COUNT) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.", reg->type); @@ -1511,6 +1516,13 @@ static void vsir_validate_register(struct validation_context *ctx, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid register index count %u.", reg->idx_count);
+ for (i = 0; i < min(reg->idx_count, ARRAY_SIZE(reg->idx)); ++i) + { + const struct vkd3d_shader_src_param *param = reg->idx[i].rel_addr; + if (reg->idx[i].rel_addr) + vsir_validate_src_param(ctx, param); + } + switch (reg->type) { case VKD3DSPR_TEMP:
From: Giovanni Mascellani gmascellani@codeweavers.com
--- 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 9ae16f7f9..2634548a8 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1538,6 +1538,12 @@ static void vsir_validate_register(struct validation_context *ctx, reg->idx[0].offset, ctx->temp_count); break;
+ case VKD3DSPR_NULL: + if (reg->idx_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a NULL register.", + reg->idx_count); + break; + default: break; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- 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 2634548a8..f324e82b7 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1544,6 +1544,12 @@ static void vsir_validate_register(struct validation_context *ctx, reg->idx_count); break;
+ case VKD3DSPR_IMMCONST: + if (reg->idx_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a IMMCONST register.", + reg->idx_count); + break; + default: break; }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- 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 f324e82b7..dd46ed77b 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1550,6 +1550,12 @@ static void vsir_validate_register(struct validation_context *ctx, reg->idx_count); break;
+ case VKD3DSPR_IMMCONST64: + if (reg->idx_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a IMMCONST64 register.", + reg->idx_count); + break; + default: break; }