Skip to content
Snippets Groups Projects

vkd3d-shader/ir: Keep track of hull shader phases.

Merged Giovanni Mascellani requested to merge giomasce/vkd3d:stromboli into master
1 file
+ 6
0
Compare changes
  • Side-by-side
  • Inline
+ 78
22
@@ -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;
}
@@ -1472,6 +1462,8 @@ 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;
size_t depth;
@@ -1496,9 +1488,18 @@ 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, temp_count = ctx->temp_count;
/* SM1-3 shaders do not include a DCL_TEMPS instruction. */
if (ctx->parser->shader_version.major <= 3)
temp_count = ctx->parser->shader_desc.temp_count;
if (reg->type >= VKD3DSPR_COUNT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.",
reg->type);
@@ -1519,6 +1520,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:
@@ -1529,9 +1537,27 @@ 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)
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);
if (reg->idx_count >= 1 && reg->idx[0].offset >= temp_count)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, "TEMP register index %u exceeds the maximum count %u.",
reg->idx[0].offset, 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;
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;
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:
@@ -1620,20 +1646,46 @@ 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;
ctx->dcl_temps_found = false;
ctx->temp_count = 0;
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:
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:
@@ -1720,7 +1772,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;
Loading