mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/ir: Check that DCL_INDEX_RANGE ranges do not overlap with unrelated signature elements.
This commit is contained in:
committed by
Henri Verbeet
parent
aae0a74d60
commit
74fa51d57c
Notes:
Henri Verbeet
2024-12-05 21:36:37 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1301
@@ -8502,8 +8502,9 @@ static void vsir_validate_dcl_index_range(struct validation_context *ctx,
|
||||
const struct vkd3d_shader_instruction *instruction)
|
||||
{
|
||||
const struct vkd3d_shader_index_range *range = &instruction->declaration.index_range;
|
||||
unsigned int i, j, base_register_idx, effective_write_mask = 0, control_point_count;
|
||||
enum vkd3d_shader_sysval_semantic sysval = ~0u;
|
||||
const struct shader_signature *signature;
|
||||
unsigned int control_point_count;
|
||||
bool has_control_point;
|
||||
|
||||
if (ctx->program->normalisation_level >= VSIR_FULLY_NORMALISED_IO)
|
||||
@@ -8542,15 +8543,101 @@ static void vsir_validate_dcl_index_range(struct validation_context *ctx,
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
||||
"Invalid relative address in DCL_INDEX_RANGE instruction.");
|
||||
|
||||
if (has_control_point && range->dst.reg.idx[0].offset != control_point_count)
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
||||
"Invalid control point index %u in DCL_INDEX_RANGE instruction, expected %u.",
|
||||
range->dst.reg.idx[0].offset, control_point_count);
|
||||
if (has_control_point)
|
||||
{
|
||||
if (range->dst.reg.idx[0].offset != control_point_count)
|
||||
{
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
||||
"Invalid control point index %u in DCL_INDEX_RANGE instruction, expected %u.",
|
||||
range->dst.reg.idx[0].offset, control_point_count);
|
||||
}
|
||||
|
||||
base_register_idx = range->dst.reg.idx[1].offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
base_register_idx = range->dst.reg.idx[0].offset;
|
||||
}
|
||||
|
||||
if (range->register_count < 2)
|
||||
{
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_RANGE,
|
||||
"Invalid register count %u in DCL_INDEX_RANGE instruction, expected at least 2.",
|
||||
range->register_count);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that for each register in the range the write mask intersects at
|
||||
* most one (and possibly zero) signature elements. Keep track of the union
|
||||
* of all signature element masks. */
|
||||
for (i = 0; i < range->register_count; ++i)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for (j = 0; j < signature->element_count; ++j)
|
||||
{
|
||||
const struct signature_element *element = &signature->elements[j];
|
||||
|
||||
if (base_register_idx + i != element->register_index || !(range->dst.write_mask & element->mask))
|
||||
continue;
|
||||
|
||||
if (found)
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK,
|
||||
"Invalid write mask %#x on a DCL_INDEX_RANGE destination parameter.",
|
||||
range->dst.write_mask);
|
||||
|
||||
found = true;
|
||||
|
||||
effective_write_mask |= element->mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check again to have at most one intersection for each register, but this
|
||||
* time using the effective write mask. This important for being able to
|
||||
* merge all the signature elements in a single one without conflicts. */
|
||||
for (i = 0; i < range->register_count; ++i)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
for (j = 0; j < signature->element_count; ++j)
|
||||
{
|
||||
const struct signature_element *element = &signature->elements[j];
|
||||
|
||||
if (base_register_idx + i != element->register_index || !(effective_write_mask & element->mask))
|
||||
continue;
|
||||
|
||||
if (element->sysval_semantic != VKD3D_SHADER_SV_NONE
|
||||
&& !vsir_sysval_semantic_is_tess_factor(element->sysval_semantic))
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
||||
"Invalid sysval semantic %#x on a signature element touched by DCL_INDEX_RANGE.",
|
||||
element->sysval_semantic);
|
||||
|
||||
if (sysval == ~0u)
|
||||
{
|
||||
sysval = element->sysval_semantic;
|
||||
/* Line density and line detail can be arrayed together. */
|
||||
if (sysval == VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN)
|
||||
sysval = VKD3D_SHADER_SV_TESS_FACTOR_LINEDET;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sysval != element->sysval_semantic)
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
|
||||
"Inconsistent sysval semantic %#x on a signature element touched by DCL_INDEX_RANGE, "
|
||||
"%#x was already seen.",
|
||||
element->sysval_semantic, sysval);
|
||||
}
|
||||
|
||||
if (found)
|
||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK,
|
||||
"Invalid write mask %#x on a DCL_INDEX_RANGE destination parameter.",
|
||||
range->dst.write_mask);
|
||||
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
VKD3D_ASSERT(sysval != ~0u);
|
||||
}
|
||||
|
||||
static void vsir_validate_dcl_input(struct validation_context *ctx,
|
||||
|
Reference in New Issue
Block a user