vkd3d-shader/ir: Validate the allowed signatures and stages for SV_Position.

This commit is contained in:
Giovanni Mascellani 2024-10-10 21:31:01 +02:00 committed by Henri Verbeet
parent 2d452842ed
commit 962ce961d4
Notes: Henri Verbeet 2024-10-14 19:45:15 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1173

View File

@ -6749,20 +6749,53 @@ static bool vsir_validate_src_max_count(struct validation_context *ctx,
return true; return true;
} }
enum vsir_signature_type
{
SIGNATURE_TYPE_INPUT,
SIGNATURE_TYPE_OUTPUT,
SIGNATURE_TYPE_PATCH_CONSTANT,
};
static const char * const signature_type_names[] =
{
[SIGNATURE_TYPE_INPUT] = "input",
[SIGNATURE_TYPE_OUTPUT] = "output",
[SIGNATURE_TYPE_PATCH_CONSTANT] = "patch constant",
};
#define PS_BIT (1u << VKD3D_SHADER_TYPE_PIXEL)
#define VS_BIT (1u << VKD3D_SHADER_TYPE_VERTEX)
#define GS_BIT (1u << VKD3D_SHADER_TYPE_GEOMETRY)
#define HS_BIT (1u << VKD3D_SHADER_TYPE_HULL)
#define DS_BIT (1u << VKD3D_SHADER_TYPE_DOMAIN)
#define CS_BIT (1u << VKD3D_SHADER_TYPE_COMPUTE)
static const struct sysval_validation_data_element
{
unsigned int input;
unsigned int output;
unsigned int patch_constant;
}
sysval_validation_data[] =
{
[VKD3D_SHADER_SV_POSITION] = {PS_BIT | GS_BIT | HS_BIT | DS_BIT, VS_BIT | GS_BIT | HS_BIT | DS_BIT},
};
static void vsir_validate_signature_element(struct validation_context *ctx, static void vsir_validate_signature_element(struct validation_context *ctx,
const struct shader_signature *signature, const char *signature_type, const struct shader_signature *signature, enum vsir_signature_type signature_type,
unsigned int idx) unsigned int idx)
{ {
const char *signature_type_name = signature_type_names[signature_type];
const struct signature_element *element = &signature->elements[idx]; const struct signature_element *element = &signature->elements[idx];
bool integer_type = false; bool integer_type = false;
if (element->register_count == 0) if (element->register_count == 0)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid zero register count.", idx, signature_type); "element %u of %s signature: Invalid zero register count.", idx, signature_type_name);
if (element->mask == 0 || (element->mask & ~0xf)) if (element->mask == 0 || (element->mask & ~0xf))
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid mask %#x.", idx, signature_type, element->mask); "element %u of %s signature: Invalid mask %#x.", idx, signature_type_name, element->mask);
/* Here we'd likely want to validate that the usage mask is a subset of the /* Here we'd likely want to validate that the usage mask is a subset of the
* signature mask. Unfortunately the D3DBC parser sometimes violates this. * signature mask. Unfortunately the D3DBC parser sometimes violates this.
@ -6786,7 +6819,7 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
if (element->used_mask & ~0xf) if (element->used_mask & ~0xf)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid usage mask %#x.", "element %u of %s signature: Invalid usage mask %#x.",
idx, signature_type, element->used_mask); idx, signature_type_name, element->used_mask);
switch (element->sysval_semantic) switch (element->sysval_semantic)
{ {
@ -6818,10 +6851,43 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
default: default:
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid system value semantic %#x.", "element %u of %s signature: Invalid system value semantic %#x.",
idx, signature_type, element->sysval_semantic); idx, signature_type_name, element->sysval_semantic);
break; break;
} }
if (element->sysval_semantic < ARRAY_SIZE(sysval_validation_data))
{
const struct sysval_validation_data_element *data = &sysval_validation_data[element->sysval_semantic];
if (data->input || data->output || data->patch_constant)
{
unsigned int mask;
switch (signature_type)
{
case SIGNATURE_TYPE_INPUT:
mask = data->input;
break;
case SIGNATURE_TYPE_OUTPUT:
mask = data->output;
break;
case SIGNATURE_TYPE_PATCH_CONSTANT:
mask = data->patch_constant;
break;
default:
vkd3d_unreachable();
}
if (!(mask & (1u << ctx->program->shader_version.type)))
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid system value semantic %#x.",
idx, signature_type_name, element->sysval_semantic);
}
}
switch (element->component_type) switch (element->component_type)
{ {
case VKD3D_SHADER_COMPONENT_INT: case VKD3D_SHADER_COMPONENT_INT:
@ -6835,29 +6901,29 @@ static void vsir_validate_signature_element(struct validation_context *ctx,
default: default:
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid component type %#x.", "element %u of %s signature: Invalid component type %#x.",
idx, signature_type, element->component_type); idx, signature_type_name, element->component_type);
break; break;
} }
if (element->min_precision >= VKD3D_SHADER_MINIMUM_PRECISION_COUNT) if (element->min_precision >= VKD3D_SHADER_MINIMUM_PRECISION_COUNT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid minimum precision %#x.", "element %u of %s signature: Invalid minimum precision %#x.",
idx, signature_type, element->min_precision); idx, signature_type_name, element->min_precision);
if (element->interpolation_mode >= VKD3DSIM_COUNT) if (element->interpolation_mode >= VKD3DSIM_COUNT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid interpolation mode %#x.", "element %u of %s signature: Invalid interpolation mode %#x.",
idx, signature_type, element->interpolation_mode); idx, signature_type_name, element->interpolation_mode);
if (integer_type && element->interpolation_mode != VKD3DSIM_NONE if (integer_type && element->interpolation_mode != VKD3DSIM_NONE
&& element->interpolation_mode != VKD3DSIM_CONSTANT) && element->interpolation_mode != VKD3DSIM_CONSTANT)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE,
"element %u of %s signature: Invalid interpolation mode %#x for integer component type.", "element %u of %s signature: Invalid interpolation mode %#x for integer component type.",
idx, signature_type, element->interpolation_mode); idx, signature_type_name, element->interpolation_mode);
} }
static void vsir_validate_signature(struct validation_context *ctx, static void vsir_validate_signature(struct validation_context *ctx,
const struct shader_signature *signature, const char *signature_type) const struct shader_signature *signature, enum vsir_signature_type signature_type)
{ {
unsigned int i; unsigned int i;
@ -7415,9 +7481,9 @@ enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t c
"Patch constant signature is only valid for hull and domain shaders."); "Patch constant signature is only valid for hull and domain shaders.");
} }
vsir_validate_signature(&ctx, &program->input_signature, "input"); vsir_validate_signature(&ctx, &program->input_signature, SIGNATURE_TYPE_INPUT);
vsir_validate_signature(&ctx, &program->output_signature, "output"); vsir_validate_signature(&ctx, &program->output_signature, SIGNATURE_TYPE_OUTPUT);
vsir_validate_signature(&ctx, &program->patch_constant_signature, "patch constant"); vsir_validate_signature(&ctx, &program->patch_constant_signature, SIGNATURE_TYPE_PATCH_CONSTANT);
if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps)))) if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps))))
goto fail; goto fail;