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_instruction *instruction)
|
||||||
{
|
{
|
||||||
const struct vkd3d_shader_index_range *range = &instruction->declaration.index_range;
|
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;
|
const struct shader_signature *signature;
|
||||||
unsigned int control_point_count;
|
|
||||||
bool has_control_point;
|
bool has_control_point;
|
||||||
|
|
||||||
if (ctx->program->normalisation_level >= VSIR_FULLY_NORMALISED_IO)
|
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,
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
||||||
"Invalid relative address in DCL_INDEX_RANGE instruction.");
|
"Invalid relative address in DCL_INDEX_RANGE instruction.");
|
||||||
|
|
||||||
if (has_control_point && range->dst.reg.idx[0].offset != control_point_count)
|
if (has_control_point)
|
||||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX,
|
{
|
||||||
"Invalid control point index %u in DCL_INDEX_RANGE instruction, expected %u.",
|
if (range->dst.reg.idx[0].offset != control_point_count)
|
||||||
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)
|
if (range->register_count < 2)
|
||||||
|
{
|
||||||
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_RANGE,
|
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_RANGE,
|
||||||
"Invalid register count %u in DCL_INDEX_RANGE instruction, expected at least 2.",
|
"Invalid register count %u in DCL_INDEX_RANGE instruction, expected at least 2.",
|
||||||
range->register_count);
|
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,
|
static void vsir_validate_dcl_input(struct validation_context *ctx,
|
||||||
|
Reference in New Issue
Block a user