mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
vkd3d-shader/tpf: Validate index range declarations.
This commit is contained in:
parent
d565fbdcd6
commit
6dd1b01284
Notes:
Alexandre Julliard
2023-05-09 22:25:51 +02:00
Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/198
@ -6195,8 +6195,6 @@ static bool spirv_compiler_check_index_range(struct spirv_compiler *compiler,
|
||||
struct vkd3d_shader_register_info reg_info;
|
||||
struct vkd3d_shader_register current_reg;
|
||||
struct vkd3d_symbol reg_symbol;
|
||||
unsigned int i;
|
||||
uint32_t id;
|
||||
|
||||
current_reg = *reg;
|
||||
vkd3d_symbol_make_register(®_symbol, ¤t_reg);
|
||||
@ -6212,27 +6210,6 @@ static bool spirv_compiler_check_index_range(struct spirv_compiler *compiler,
|
||||
FIXME("Unhandled register %#x.\n", reg->type);
|
||||
return false;
|
||||
}
|
||||
id = reg_info.id;
|
||||
|
||||
for (i = reg->idx[0].offset; i < reg->idx[0].offset + range->register_count; ++i)
|
||||
{
|
||||
current_reg.idx[0].offset = i;
|
||||
vkd3d_symbol_make_register(®_symbol, ¤t_reg);
|
||||
|
||||
if (range->dst.write_mask != reg_info.write_mask
|
||||
|| vkd3d_write_mask_component_count(reg_info.write_mask) != 1)
|
||||
{
|
||||
FIXME("Unhandled index range write mask %#x (%#x).\n",
|
||||
range->dst.write_mask, reg_info.write_mask);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reg_info.id != id)
|
||||
{
|
||||
FIXME("Unhandled index range %#x, %u.\n", reg->type, i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -558,6 +558,19 @@ enum vkd3d_sm4_shader_data_type
|
||||
VKD3D_SM4_SHADER_DATA_MESSAGE = 0x4,
|
||||
};
|
||||
|
||||
struct sm4_index_range
|
||||
{
|
||||
unsigned int index;
|
||||
unsigned int count;
|
||||
unsigned int mask;
|
||||
};
|
||||
|
||||
struct sm4_index_range_array
|
||||
{
|
||||
unsigned int count;
|
||||
struct sm4_index_range ranges[MAX_REG_OUTPUT * 2];
|
||||
};
|
||||
|
||||
struct vkd3d_shader_sm4_parser
|
||||
{
|
||||
const uint32_t *start, *end, *ptr;
|
||||
@ -569,6 +582,10 @@ struct vkd3d_shader_sm4_parser
|
||||
unsigned int output_register_masks[MAX_REG_OUTPUT];
|
||||
unsigned int patch_constant_register_masks[MAX_REG_OUTPUT];
|
||||
|
||||
struct sm4_index_range_array input_index_ranges;
|
||||
struct sm4_index_range_array output_index_ranges;
|
||||
struct sm4_index_range_array patch_constant_index_ranges;
|
||||
|
||||
struct vkd3d_shader_parser p;
|
||||
};
|
||||
|
||||
@ -823,12 +840,109 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui
|
||||
shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.range.space);
|
||||
}
|
||||
|
||||
static bool sm4_parser_is_in_fork_or_join_phase(const struct vkd3d_shader_sm4_parser *sm4)
|
||||
{
|
||||
return sm4->phase == VKD3DSIH_HS_FORK_PHASE || sm4->phase == VKD3DSIH_HS_JOIN_PHASE;
|
||||
}
|
||||
|
||||
static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins, uint32_t opcode,
|
||||
uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv)
|
||||
{
|
||||
struct vkd3d_shader_index_range *index_range = &ins->declaration.index_range;
|
||||
unsigned int i, register_idx, register_count, write_mask;
|
||||
enum vkd3d_shader_register_type type;
|
||||
struct sm4_index_range_array *ranges;
|
||||
unsigned int *io_masks;
|
||||
|
||||
shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE,
|
||||
&ins->declaration.index_range.dst);
|
||||
ins->declaration.index_range.register_count = *tokens;
|
||||
&index_range->dst);
|
||||
index_range->register_count = *tokens;
|
||||
|
||||
register_idx = index_range->dst.reg.idx[index_range->dst.reg.idx_count - 1].offset;
|
||||
register_count = index_range->register_count;
|
||||
write_mask = index_range->dst.write_mask;
|
||||
|
||||
if (vkd3d_write_mask_component_count(write_mask) != 1)
|
||||
{
|
||||
WARN("Unhandled write mask %#x.\n", write_mask);
|
||||
vkd3d_shader_parser_warning(&priv->p, VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK,
|
||||
"Index range mask %#x is not scalar.", write_mask);
|
||||
}
|
||||
|
||||
switch ((type = index_range->dst.reg.type))
|
||||
{
|
||||
case VKD3DSPR_INPUT:
|
||||
case VKD3DSPR_INCONTROLPOINT:
|
||||
io_masks = priv->input_register_masks;
|
||||
ranges = &priv->input_index_ranges;
|
||||
break;
|
||||
case VKD3DSPR_OUTPUT:
|
||||
if (sm4_parser_is_in_fork_or_join_phase(priv))
|
||||
{
|
||||
io_masks = priv->patch_constant_register_masks;
|
||||
ranges = &priv->patch_constant_index_ranges;
|
||||
}
|
||||
else
|
||||
{
|
||||
io_masks = priv->output_register_masks;
|
||||
ranges = &priv->output_index_ranges;
|
||||
}
|
||||
break;
|
||||
case VKD3DSPR_COLOROUT:
|
||||
case VKD3DSPR_OUTCONTROLPOINT:
|
||||
io_masks = priv->output_register_masks;
|
||||
ranges = &priv->output_index_ranges;
|
||||
break;
|
||||
case VKD3DSPR_PATCHCONST:
|
||||
io_masks = priv->patch_constant_register_masks;
|
||||
ranges = &priv->patch_constant_index_ranges;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN("Unhandled register type %#x.\n", type);
|
||||
vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_INDEX_RANGE_DCL,
|
||||
"Invalid register type %#x for index range base %u, count %u, mask %#x.",
|
||||
type, register_idx, register_count, write_mask);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ranges->count; ++i)
|
||||
{
|
||||
struct sm4_index_range r = ranges->ranges[i];
|
||||
|
||||
if (!(r.mask & write_mask))
|
||||
continue;
|
||||
/* Ranges with the same base but different lengths are not an issue. */
|
||||
if (register_idx == r.index)
|
||||
continue;
|
||||
|
||||
if ((r.index <= register_idx && register_idx - r.index < r.count)
|
||||
|| (register_idx < r.index && r.index - register_idx < register_count))
|
||||
{
|
||||
WARN("Detected index range collision for base %u, count %u, mask %#x.\n",
|
||||
register_idx, register_count, write_mask);
|
||||
vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_INDEX_RANGE_DCL,
|
||||
"Register index range base %u, count %u, mask %#x collides with a previous declaration.",
|
||||
register_idx, register_count, write_mask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ranges->ranges[ranges->count].index = register_idx;
|
||||
ranges->ranges[ranges->count].count = register_count;
|
||||
ranges->ranges[ranges->count++].mask = write_mask;
|
||||
|
||||
for (i = 0; i < register_count; ++i)
|
||||
{
|
||||
if ((io_masks[register_idx + i] & write_mask) != write_mask)
|
||||
{
|
||||
WARN("No matching declaration for index range base %u, count %u, mask %#x.\n",
|
||||
register_idx, register_count, write_mask);
|
||||
vkd3d_shader_parser_error(&priv->p, VKD3D_SHADER_ERROR_TPF_INVALID_INDEX_RANGE_DCL,
|
||||
"Input/output registers matching index range base %u, count %u, mask %#x were not declared.",
|
||||
register_idx, register_count, write_mask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void shader_sm4_read_dcl_output_topology(struct vkd3d_shader_instruction *ins, uint32_t opcode,
|
||||
@ -1805,8 +1919,7 @@ static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_pa
|
||||
masks = priv->input_register_masks;
|
||||
break;
|
||||
case VKD3DSPR_OUTPUT:
|
||||
masks = (priv->phase == VKD3DSIH_HS_FORK_PHASE || priv->phase == VKD3DSIH_HS_JOIN_PHASE)
|
||||
? priv->patch_constant_register_masks
|
||||
masks = sm4_parser_is_in_fork_or_join_phase(priv) ? priv->patch_constant_register_masks
|
||||
: priv->output_register_masks;
|
||||
break;
|
||||
case VKD3DSPR_COLOROUT:
|
||||
|
@ -77,8 +77,10 @@ enum vkd3d_shader_error
|
||||
VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT = 1003,
|
||||
VKD3D_SHADER_ERROR_TPF_TOO_MANY_REGISTERS = 1004,
|
||||
VKD3D_SHADER_ERROR_TPF_INVALID_IO_REGISTER = 1005,
|
||||
VKD3D_SHADER_ERROR_TPF_INVALID_INDEX_RANGE_DCL = 1006,
|
||||
|
||||
VKD3D_SHADER_WARNING_TPF_MASK_NOT_CONTIGUOUS = 1300,
|
||||
VKD3D_SHADER_WARNING_TPF_UNHANDLED_INDEX_RANGE_MASK = 1301,
|
||||
|
||||
VKD3D_SHADER_ERROR_SPV_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
|
||||
VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
|
||||
|
Loading…
x
Reference in New Issue
Block a user