mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/ir: Use iterators in flattener_flatten_phases().
This commit is contained in:
committed by
Henri Verbeet
parent
bceb4d17ed
commit
434d9dd117
Notes:
Henri Verbeet
2025-09-09 15:10:17 +02:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1707
@@ -568,23 +568,6 @@ static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params(
|
|||||||
return src_params;
|
return src_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: Immediate constant buffers are not cloned, so the source must not be destroyed while the
|
|
||||||
* destination is in use. This seems like a reasonable requirement given how this is currently used. */
|
|
||||||
static bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *array,
|
|
||||||
size_t dst, size_t src)
|
|
||||||
{
|
|
||||||
struct vkd3d_shader_instruction *ins = &array->elements[dst];
|
|
||||||
|
|
||||||
*ins = array->elements[src];
|
|
||||||
|
|
||||||
if (ins->dst_count && ins->dst && !(ins->dst = shader_instruction_array_clone_dst_params(array,
|
|
||||||
ins->dst, ins->dst_count)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !ins->src_count || !!(ins->src = shader_instruction_array_clone_src_params(array,
|
|
||||||
ins->src, ins->src_count));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *array)
|
static void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *array)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -1101,6 +1084,23 @@ static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *i
|
|||||||
vsir_instruction_init(ins, &location, VSIR_OP_NOP);
|
vsir_instruction_init(ins, &location, VSIR_OP_NOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NOTE: Immediate constant buffers are not cloned, so the source must not be destroyed while the
|
||||||
|
* destination is in use. This seems like a reasonable requirement given how this is currently used. */
|
||||||
|
static bool vsir_program_iterator_clone_instruction(struct vsir_program_iterator *dst_it,
|
||||||
|
const struct vkd3d_shader_instruction *src)
|
||||||
|
{
|
||||||
|
struct vkd3d_shader_instruction *dst = vsir_program_iterator_current(dst_it);
|
||||||
|
|
||||||
|
*dst = *src;
|
||||||
|
|
||||||
|
if (dst->dst_count && !(dst->dst = shader_instruction_array_clone_dst_params(dst_it->array,
|
||||||
|
dst->dst, dst->dst_count)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !dst->src_count || !!(dst->src = shader_instruction_array_clone_src_params(dst_it->array,
|
||||||
|
dst->src, dst->src_count));
|
||||||
|
}
|
||||||
|
|
||||||
static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op,
|
static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op,
|
||||||
enum vsir_data_type data_type, enum vkd3d_shader_opcode *opcode, bool *requires_swap)
|
enum vsir_data_type data_type, enum vkd3d_shader_opcode *opcode, bool *requires_swap)
|
||||||
{
|
{
|
||||||
@@ -2573,50 +2573,60 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali
|
|||||||
struct shader_phase_location_array *locations)
|
struct shader_phase_location_array *locations)
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_instruction_array *instructions = &normaliser->program->instructions;
|
struct vkd3d_shader_instruction_array *instructions = &normaliser->program->instructions;
|
||||||
|
struct vsir_program_iterator it = vsir_program_iterator(instructions);
|
||||||
|
unsigned int i, j, k, loc_i, count, added_count;
|
||||||
|
struct vkd3d_shader_instruction *ins;
|
||||||
struct shader_phase_location *loc;
|
struct shader_phase_location *loc;
|
||||||
unsigned int i, j, k, end, count;
|
|
||||||
|
|
||||||
for (i = 0, count = 0; i < locations->count; ++i)
|
loc_i = 0;
|
||||||
count += (locations->locations[i].instance_count - 1) * locations->locations[i].instruction_count;
|
added_count = 0;
|
||||||
|
for (ins = vsir_program_iterator_head(&it), i = 0; ins; ins = vsir_program_iterator_next(&it), ++i)
|
||||||
if (!shader_instruction_array_reserve(instructions, instructions->count + count))
|
|
||||||
return VKD3D_ERROR_OUT_OF_MEMORY;
|
|
||||||
end = instructions->count;
|
|
||||||
instructions->count += count;
|
|
||||||
|
|
||||||
for (i = locations->count; i > 0; --i)
|
|
||||||
{
|
{
|
||||||
loc = &locations->locations[i - 1];
|
if (loc_i >= locations->count)
|
||||||
j = loc->index + loc->instruction_count;
|
break;
|
||||||
memmove(&instructions->elements[j + count], &instructions->elements[j],
|
loc = &locations->locations[loc_i];
|
||||||
(end - j) * sizeof(*instructions->elements));
|
|
||||||
end = j;
|
|
||||||
count -= (loc->instance_count - 1) * loc->instruction_count;
|
|
||||||
loc->index += count;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, count = 0; i < locations->count; ++i)
|
if (i == loc->index + added_count)
|
||||||
{
|
|
||||||
loc = &locations->locations[i];
|
|
||||||
/* Make a copy of the non-dcl instructions for each instance. */
|
|
||||||
for (j = 1; j < loc->instance_count; ++j)
|
|
||||||
{
|
{
|
||||||
for (k = 0; k < loc->instruction_count; ++k)
|
struct vsir_program_iterator dst_it, src_it, first_it;
|
||||||
|
|
||||||
|
count = (loc->instance_count - 1) * loc->instruction_count;
|
||||||
|
if (!vsir_program_iterator_insert_before(&it, &first_it, count))
|
||||||
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||||
|
added_count += count;
|
||||||
|
|
||||||
|
/* Make a copy of the non-dcl instructions for each instance. */
|
||||||
|
dst_it = first_it;
|
||||||
|
for (j = 1; j < loc->instance_count; ++j)
|
||||||
{
|
{
|
||||||
if (!shader_instruction_array_clone_instruction(instructions,
|
src_it = it;
|
||||||
loc->index + loc->instruction_count * j + k, loc->index + k))
|
for (k = 0; k < loc->instruction_count; ++k)
|
||||||
return VKD3D_ERROR_OUT_OF_MEMORY;
|
{
|
||||||
}
|
if (!vsir_program_iterator_clone_instruction(&dst_it, vsir_program_iterator_current(&src_it)))
|
||||||
}
|
return VKD3D_ERROR_OUT_OF_MEMORY;
|
||||||
/* Replace each reference to the instance id with a constant instance id. */
|
|
||||||
for (j = 0; j < loc->instance_count; ++j)
|
|
||||||
{
|
|
||||||
if (j != 0)
|
|
||||||
memset(normaliser->ssa_map, 0xff, normaliser->orig_ssa_count * sizeof(*normaliser->ssa_map));
|
|
||||||
|
|
||||||
for (k = 0; k < loc->instruction_count; ++k)
|
vsir_program_iterator_next(&dst_it);
|
||||||
flattener_fixup_registers(normaliser,
|
vsir_program_iterator_next(&src_it);
|
||||||
&instructions->elements[loc->index + loc->instruction_count * j + k], j);
|
}
|
||||||
|
}
|
||||||
|
/* Replace each reference to the instance id with a constant instance id. */
|
||||||
|
it = first_it;
|
||||||
|
for (j = 0; j < loc->instance_count; ++j)
|
||||||
|
{
|
||||||
|
if (j != 0)
|
||||||
|
memset(normaliser->ssa_map, 0xff, normaliser->orig_ssa_count * sizeof(*normaliser->ssa_map));
|
||||||
|
|
||||||
|
for (k = 0; k < loc->instruction_count; ++k)
|
||||||
|
{
|
||||||
|
ins = vsir_program_iterator_current(&it);
|
||||||
|
flattener_fixup_registers(normaliser, ins, j);
|
||||||
|
vsir_program_iterator_next(&it);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loc->index += added_count - (loc->instance_count - 1) * loc->instruction_count;
|
||||||
|
++loc_i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1508,6 +1508,28 @@ static inline bool vsir_program_iterator_insert_after(struct vsir_program_iterat
|
|||||||
return shader_instruction_array_insert_at(it->array, it->idx + 1, count);
|
return shader_instruction_array_insert_at(it->array, it->idx + 1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When insertion takes place, argument `it' is updated to point to the same
|
||||||
|
* instruction as before the insertion, and the optional argument `ins_it' is
|
||||||
|
* initialized to point to the first inserted instruction.
|
||||||
|
* A pointer to the first inserted instruction is returned. */
|
||||||
|
static inline struct vkd3d_shader_instruction *vsir_program_iterator_insert_before(
|
||||||
|
struct vsir_program_iterator *it, struct vsir_program_iterator *ins_it, size_t count)
|
||||||
|
{
|
||||||
|
VKD3D_ASSERT(it != ins_it);
|
||||||
|
VKD3D_ASSERT(it->idx != SIZE_MAX);
|
||||||
|
|
||||||
|
if (!shader_instruction_array_insert_at(it->array, it->idx, count))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*ins_it = *it;
|
||||||
|
it->idx += count;
|
||||||
|
|
||||||
|
return vsir_program_iterator_current(ins_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When insertion takes place, argument `it' is updated to point to the first
|
||||||
|
* inserted instruction. A pointer to this first inserted instruction is
|
||||||
|
* returned. */
|
||||||
static inline struct vkd3d_shader_instruction *vsir_program_iterator_insert_before_and_move(
|
static inline struct vkd3d_shader_instruction *vsir_program_iterator_insert_before_and_move(
|
||||||
struct vsir_program_iterator *it, size_t count)
|
struct vsir_program_iterator *it, size_t count)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user