-- v2: vkd3d-shader/ir: Validate the index of a TEMP register. vkd3d-shader/ir: Validate the DCL_TEMPS instruction. vkd3d-shader/ir: Validate unused indices in a register. vkd3d-shader/ir: Validate the register index count. vkd3d-shader/ir: Validate the register dimension. vkd3d-shader/ir: Validate the register data type. vkd3d-shader/ir: Validate the register precision. vkd3d-shader/dxil: Use vsir_register_init() to initialize registers. vkd3d-shader: Deduplicate profile version comparison functions.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/d3d_asm.c | 19 +++++++------------ libs/vkd3d-shader/d3dbc.c | 16 +++------------- libs/vkd3d-shader/vkd3d_shader_private.h | 10 ++++++++++ 3 files changed, 20 insertions(+), 25 deletions(-)
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 40daa5354..eae7e6b70 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -358,11 +358,6 @@ struct vkd3d_d3d_asm_compiler struct vkd3d_d3d_asm_colours colours; };
-static int shader_ver_ge(const struct vkd3d_shader_version *v, int major, int minor) -{ - return v->major > major || (v->major == major && v->minor >= minor); -} - static int VKD3D_PRINTF_FUNC(2, 3) shader_addline(struct vkd3d_string_buffer *buffer, const char *format, ...) { va_list args; @@ -684,7 +679,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, else { /* Pixel shaders 3.0 don't have usage semantics. */ - if (!shader_ver_ge(&compiler->shader_version, 3, 0) + if (!vkd3d_shader_ver_ge(&compiler->shader_version, 3, 0) && compiler->shader_version.type == VKD3D_SHADER_TYPE_PIXEL) return; else @@ -908,7 +903,7 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const case VKD3DSPR_TEXCRDOUT: /* Vertex shaders >= 3.0 use general purpose output registers * (VKD3DSPR_OUTPUT), which can include an address token. */ - if (shader_ver_ge(&compiler->shader_version, 3, 0)) + if (vkd3d_shader_ver_ge(&compiler->shader_version, 3, 0)) shader_addline(buffer, "o"); else shader_addline(buffer, "oT"); @@ -1174,7 +1169,7 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const { if (offset != ~0u) { - bool is_sm_5_1 = shader_ver_ge(&compiler->shader_version, 5, 1); + bool is_sm_5_1 = vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1);
if (reg->idx[0].rel_addr || reg->type == VKD3DSPR_IMMCONSTBUFFER || reg->type == VKD3DSPR_INCONTROLPOINT || (reg->type == VKD3DSPR_INPUT @@ -1570,7 +1565,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile break;
case VKD3DSIH_TEX: - if (shader_ver_ge(&compiler->shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT)) + if (vkd3d_shader_ver_ge(&compiler->shader_version, 2, 0) && (ins->flags & VKD3DSI_TEXLD_PROJECT)) shader_addline(buffer, "p"); break;
@@ -1582,7 +1577,7 @@ static void shader_dump_instruction_flags(struct vkd3d_d3d_asm_compiler *compile
static void shader_dump_register_space(struct vkd3d_d3d_asm_compiler *compiler, unsigned int register_space) { - if (shader_ver_ge(&compiler->shader_version, 5, 1)) + if (vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1)) shader_print_uint_literal(compiler, ", space=", register_space, ""); }
@@ -1626,9 +1621,9 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, case VKD3DSIH_DCL_CONSTANT_BUFFER: vkd3d_string_buffer_printf(buffer, " "); shader_dump_register(compiler, &ins->declaration.cb.src.reg, true); - if (shader_ver_ge(&compiler->shader_version, 6, 0)) + if (vkd3d_shader_ver_ge(&compiler->shader_version, 6, 0)) shader_print_subscript(compiler, ins->declaration.cb.size, NULL); - else if (shader_ver_ge(&compiler->shader_version, 5, 1)) + else if (vkd3d_shader_ver_ge(&compiler->shader_version, 5, 1)) shader_print_subscript(compiler, ins->declaration.cb.size / VKD3D_VEC4_SIZE / sizeof(float), NULL); shader_addline(buffer, ", %s", ins->flags & VKD3DSI_INDEXED_DYNAMIC ? "dynamicIndexed" : "immediateIndexed"); diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 67fa32710..df65bed8c 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -402,16 +402,6 @@ static uint32_t read_u32(const uint32_t **ptr) return *(*ptr)++; }
-static bool shader_ver_ge(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor) -{ - return v->major > major || (v->major == major && v->minor >= minor); -} - -static bool shader_ver_le(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor) -{ - return v->major < major || (v->major == major && v->minor <= minor); -} - static bool has_relative_address(uint32_t param) { enum vkd3d_sm1_address_mode_type address_mode; @@ -434,8 +424,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info( return NULL;
if (opcode == info->sm1_opcode - && shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor) - && (shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor) + && vkd3d_shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor) + && (vkd3d_shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor) || !info->max_version.major)) return info; } @@ -1262,7 +1252,7 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, return VKD3D_ERROR_INVALID_SHADER; }
- if (!shader_ver_le(&version, 3, 0)) + if (!vkd3d_shader_ver_le(&version, 3, 0)) { vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN, "Invalid shader version %u.%u (token 0x%08x).", version.major, version.minor, code[0]); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index c9d2dec8b..5ab272e22 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1072,6 +1072,16 @@ struct vkd3d_shader_instruction } declaration; };
+static inline bool vkd3d_shader_ver_ge(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor) +{ + return v->major > major || (v->major == major && v->minor >= minor); +} + +static inline bool vkd3d_shader_ver_le(const struct vkd3d_shader_version *v, unsigned int major, unsigned int minor) +{ + return v->major < major || (v->major == major && v->minor <= minor); +} + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode handler_idx);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/dxil.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/dxil.c b/libs/vkd3d-shader/dxil.c index 19ce2936a..e1e6eb4ff 100644 --- a/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d-shader/dxil.c @@ -2230,9 +2230,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const dst = sm6_parser_get_current_value(sm6); dst->type = type; dst->value_type = VALUE_TYPE_REG; - dst->u.reg.type = reg_type; - dst->u.reg.dimension = VSIR_DIMENSION_SCALAR; - dst->u.reg.data_type = reg_data_type; + vsir_register_init(&dst->u.reg, reg_type, reg_data_type, 0);
switch (record->code) {
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 4 ++++ libs/vkd3d-shader/vkd3d_shader_private.h | 3 +++ 2 files changed, 7 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 511b0e8fa..9c95d2d9d 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1492,6 +1492,10 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->type >= VKD3DSPR_COUNT) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.", reg->type); + + if (reg->precision >= VKD3D_SHADER_REGISTER_PRECISION_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid register precision %#x.", + reg->precision); }
static void vsir_validate_dst_param(struct validation_context *ctx, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 5ab272e22..a13850e61 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -198,6 +198,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS = 9004, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT = 9005, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE = 9006, + VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION = 9007, };
enum vkd3d_shader_opcode @@ -554,6 +555,8 @@ enum vkd3d_shader_register_precision VKD3D_SHADER_REGISTER_PRECISION_MIN_INT_16, VKD3D_SHADER_REGISTER_PRECISION_MIN_UINT_16,
+ VKD3D_SHADER_REGISTER_PRECISION_COUNT, + VKD3D_SHADER_REGISTER_PRECISION_INVALID = ~0u, };
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 4 ++++ libs/vkd3d-shader/vkd3d_shader_private.h | 3 +++ 2 files changed, 7 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 9c95d2d9d..f97287e9d 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1496,6 +1496,10 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->precision >= VKD3D_SHADER_REGISTER_PRECISION_COUNT) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid register precision %#x.", reg->precision); + + if (reg->data_type >= VKD3D_DATA_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid register data type %#x.", + reg->data_type); }
static void vsir_validate_dst_param(struct validation_context *ctx, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index a13850e61..ba1eb2ff4 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -199,6 +199,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT = 9005, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE = 9006, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION = 9007, + VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE = 9008, };
enum vkd3d_shader_opcode @@ -577,6 +578,8 @@ enum vkd3d_data_type VKD3D_DATA_UNUSED, VKD3D_DATA_UINT8, VKD3D_DATA_UINT64, + + VKD3D_DATA_COUNT, };
static inline bool data_type_is_integer(enum vkd3d_data_type data_type)
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 4 ++++ libs/vkd3d-shader/tpf.c | 2 ++ libs/vkd3d-shader/vkd3d_shader_private.h | 3 +++ 3 files changed, 9 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index f97287e9d..f5e4b6a47 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1500,6 +1500,10 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->data_type >= VKD3D_DATA_COUNT) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid register data type %#x.", reg->data_type); + + if (reg->dimension >= VSIR_DIMENSION_COUNT) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid register dimension %#x.", + reg->dimension); }
static void vsir_validate_dst_param(struct validation_context *ctx, diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 0ea5a682f..4a098cf81 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -549,6 +549,8 @@ static enum vkd3d_sm4_dimension sm4_dimension_from_vsir_dimension(enum vsir_dime return VKD3D_SM4_DIMENSION_SCALAR; case VSIR_DIMENSION_VEC4: return VKD3D_SM4_DIMENSION_VEC4; + case VSIR_DIMENSION_COUNT: + vkd3d_unreachable(); } vkd3d_unreachable(); } diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index ba1eb2ff4..b3fefdc8f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -200,6 +200,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE = 9006, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION = 9007, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE = 9008, + VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION = 9009, };
enum vkd3d_shader_opcode @@ -593,6 +594,8 @@ enum vsir_dimension VSIR_DIMENSION_NONE, VSIR_DIMENSION_SCALAR, VSIR_DIMENSION_VEC4, + + VSIR_DIMENSION_COUNT, };
enum vkd3d_shader_src_modifier
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 4 ++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 5 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index f5e4b6a47..70961718a 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1504,6 +1504,10 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->dimension >= VSIR_DIMENSION_COUNT) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid register dimension %#x.", reg->dimension); + + if (reg->idx_count > ARRAY_SIZE(reg->idx)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid register index count %u.", + reg->idx_count); }
static void vsir_validate_dst_param(struct validation_context *ctx, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index b3fefdc8f..a9d6bd747 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -201,6 +201,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION = 9007, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE = 9008, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION = 9009, + VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT = 9010, };
enum vkd3d_shader_opcode
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 9 +++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 10 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 70961718a..8907fe5fc 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1489,6 +1489,8 @@ static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *c 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); @@ -1508,6 +1510,13 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->idx_count > ARRAY_SIZE(reg->idx)) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid register index count %u.", reg->idx_count); + + for (i = reg->idx_count; i < ARRAY_SIZE(reg->idx); ++i) + { + if (reg->idx[i].offset != ~0u || reg->idx[i].rel_addr != NULL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Unused index %u has offset %#x and non-NULL relative address.", + i, reg->idx[i].offset); + } }
static void vsir_validate_dst_param(struct validation_context *ctx, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index a9d6bd747..1b06ffe67 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -202,6 +202,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE = 9008, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION = 9009, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT = 9010, + VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9011, };
enum vkd3d_shader_opcode
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 27 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 2 ++ 2 files changed, 29 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 8907fe5fc..80eb06bdb 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1563,6 +1563,22 @@ static void vsir_validate_src_param(struct validation_context *ctx, src->modifiers); }
+static void vsir_validate_dst_count(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction, unsigned int count) +{ + if (instruction->dst_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, + "Invalid destination count %u for an instruction of type %#x.", instruction->dst_count, instruction->handler_idx); +} + +static void vsir_validate_src_count(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction, unsigned int count) +{ + if (instruction->src_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, + "Invalid source count %u for an instruction of type %#x.", instruction->src_count, instruction->handler_idx); +} + static void vsir_validate_instruction(struct validation_context *ctx) { const struct vkd3d_shader_instruction *instruction = &ctx->parser->instructions.elements[ctx->instruction_idx]; @@ -1581,6 +1597,17 @@ static void vsir_validate_instruction(struct validation_context *ctx) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.", instruction->handler_idx); } + + switch (instruction->handler_idx) + { + case VKD3DSIH_DCL_TEMPS: + vsir_validate_dst_count(ctx, instruction, 0); + vsir_validate_src_count(ctx, instruction, 0); + break; + + default: + break; + } }
void vsir_validate(struct vkd3d_shader_parser *parser) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 1b06ffe67..fd89b22d4 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -203,6 +203,8 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION = 9009, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT = 9010, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9011, + VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT = 9012, + VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT = 9013, };
enum vkd3d_shader_opcode
From: Giovanni Mascellani gmascellani@codeweavers.com
--- libs/vkd3d-shader/ir.c | 28 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 29 insertions(+)
diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 80eb06bdb..8b9171086 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -1467,6 +1467,8 @@ struct validation_context { struct vkd3d_shader_parser *parser; size_t instruction_idx; + bool dcl_temps_found; + unsigned int temp_count; };
static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx, @@ -1517,6 +1519,26 @@ static void vsir_validate_register(struct validation_context *ctx, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Unused index %u has offset %#x and non-NULL relative address.", i, reg->idx[i].offset); } + + switch (reg->type) + { + case VKD3DSPR_TEMP: + if (reg->idx_count != 1) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid index count %u for a TEMP register.", + reg->idx_count); + + 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."); + + /* There is not DCL_TEMPS in SM1-3. */ + if (vkd3d_shader_ver_ge(&ctx->parser->shader_version, 4, 0) && 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->temp_count); + break; + + default: + break; + } }
static void vsir_validate_dst_param(struct validation_context *ctx, @@ -1603,6 +1625,12 @@ 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 a at + * most one occurrence. */ + if (ctx->dcl_temps_found && ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction."); + ctx->dcl_temps_found = true; + ctx->temp_count = instruction->declaration.count; break;
default: diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index fd89b22d4..86e495243 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -205,6 +205,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX = 9011, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT = 9012, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT = 9013, + VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS = 9014, };
enum vkd3d_shader_opcode
+ for (i = reg->idx_count; i < ARRAY_SIZE(reg->idx); ++i) + { + if (reg->idx[i].offset != ~0u || reg->idx[i].rel_addr != NULL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "Unused index %u has offset %#x and non-NULL relative address.", + i, reg->idx[i].offset); + }
I don't know about that one. There are probably still a few places left that depend on this property, but we should get rid of them and just use "idx_count".
+static void vsir_validate_dst_count(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction, unsigned int count) +{ + if (instruction->dst_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT, + "Invalid destination count %u for an instruction of type %#x.", instruction->dst_count, instruction->handler_idx); +} + +static void vsir_validate_src_count(struct validation_context *ctx, + const struct vkd3d_shader_instruction *instruction, unsigned int count) +{ + if (instruction->src_count != 0) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT, + "Invalid source count %u for an instruction of type %#x.", instruction->src_count, instruction->handler_idx); +}
"count" is not used here.
+ /* There is not DCL_TEMPS in SM1-3. */ + if (vkd3d_shader_ver_ge(&ctx->parser->shader_version, 4, 0) && 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->temp_count); + break;
We do have "ctx->parser->shader_desc.temp_count" though, and that's what we should use here.
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 a at + * most one occurrence. */ + if (ctx->dcl_temps_found && ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS, "Duplicate DCL_TEMPS instruction."); + ctx->dcl_temps_found = true; + ctx->temp_count = instruction->declaration.count; break;
And we should probably just validate that DCL_TEMPS is consistent with "ctx->parser->shader_desc.temp_count" here.