mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/tpf: Validate index range declarations.
This commit is contained in:
committed by
Alexandre Julliard
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_info reg_info;
|
||||||
struct vkd3d_shader_register current_reg;
|
struct vkd3d_shader_register current_reg;
|
||||||
struct vkd3d_symbol reg_symbol;
|
struct vkd3d_symbol reg_symbol;
|
||||||
unsigned int i;
|
|
||||||
uint32_t id;
|
|
||||||
|
|
||||||
current_reg = *reg;
|
current_reg = *reg;
|
||||||
vkd3d_symbol_make_register(®_symbol, ¤t_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);
|
FIXME("Unhandled register %#x.\n", reg->type);
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -558,6 +558,19 @@ enum vkd3d_sm4_shader_data_type
|
|||||||
VKD3D_SM4_SHADER_DATA_MESSAGE = 0x4,
|
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
|
struct vkd3d_shader_sm4_parser
|
||||||
{
|
{
|
||||||
const uint32_t *start, *end, *ptr;
|
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 output_register_masks[MAX_REG_OUTPUT];
|
||||||
unsigned int patch_constant_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;
|
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);
|
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,
|
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)
|
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,
|
shader_sm4_read_dst_param(priv, &tokens, &tokens[token_count], VKD3D_DATA_OPAQUE,
|
||||||
&ins->declaration.index_range.dst);
|
&index_range->dst);
|
||||||
ins->declaration.index_range.register_count = *tokens;
|
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,
|
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;
|
masks = priv->input_register_masks;
|
||||||
break;
|
break;
|
||||||
case VKD3DSPR_OUTPUT:
|
case VKD3DSPR_OUTPUT:
|
||||||
masks = (priv->phase == VKD3DSIH_HS_FORK_PHASE || priv->phase == VKD3DSIH_HS_JOIN_PHASE)
|
masks = sm4_parser_is_in_fork_or_join_phase(priv) ? priv->patch_constant_register_masks
|
||||||
? priv->patch_constant_register_masks
|
|
||||||
: priv->output_register_masks;
|
: priv->output_register_masks;
|
||||||
break;
|
break;
|
||||||
case VKD3DSPR_COLOROUT:
|
case VKD3DSPR_COLOROUT:
|
||||||
|
@ -77,8 +77,10 @@ enum vkd3d_shader_error
|
|||||||
VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT = 1003,
|
VKD3D_SHADER_ERROR_TPF_INVALID_REGISTER_INDEX_COUNT = 1003,
|
||||||
VKD3D_SHADER_ERROR_TPF_TOO_MANY_REGISTERS = 1004,
|
VKD3D_SHADER_ERROR_TPF_TOO_MANY_REGISTERS = 1004,
|
||||||
VKD3D_SHADER_ERROR_TPF_INVALID_IO_REGISTER = 1005,
|
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_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_DESCRIPTOR_BINDING_NOT_FOUND = 2000,
|
||||||
VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
|
VKD3D_SHADER_ERROR_SPV_INVALID_REGISTER_TYPE = 2001,
|
||||||
|
Reference in New Issue
Block a user