From bceb4d17edefad18e7aad211d5b3db61b1fb3513 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 9 Sep 2025 14:17:51 +0200 Subject: [PATCH] vkd3d-shader/ir: Move the instruction array helpers to ir.c. --- libs/vkd3d-shader/ir.c | 194 ++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 198 ----------------------- libs/vkd3d-shader/vkd3d_shader_private.h | 4 - 3 files changed, 194 insertions(+), 202 deletions(-) diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index d3f7dd70c..fb244789b 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -416,6 +416,200 @@ const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error) return error; } +static struct vkd3d_shader_param_node *shader_param_allocator_node_create( + struct vkd3d_shader_param_allocator *allocator) +{ + struct vkd3d_shader_param_node *node; + + if (!(node = vkd3d_malloc(offsetof(struct vkd3d_shader_param_node, param[allocator->count * allocator->stride])))) + return NULL; + node->next = NULL; + + return node; +} + +static void shader_param_allocator_init(struct vkd3d_shader_param_allocator *allocator, size_t count, size_t stride) +{ + allocator->count = max(count, MAX_REG_OUTPUT); + allocator->stride = stride; + allocator->head = NULL; + allocator->current = NULL; + allocator->index = allocator->count; +} + +static void shader_param_allocator_destroy(struct vkd3d_shader_param_allocator *allocator) +{ + struct vkd3d_shader_param_node *current = allocator->head; + + while (current) + { + struct vkd3d_shader_param_node *next = current->next; + vkd3d_free(current); + current = next; + } +} + +void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, size_t count) +{ + void *params; + + if (!allocator->current || count > allocator->count - allocator->index) + { + struct vkd3d_shader_param_node *next; + + allocator->count = max(allocator->count, count); + if (!(next = shader_param_allocator_node_create(allocator))) + return NULL; + if (allocator->current) + allocator->current->next = next; + else + allocator->head = next; + allocator->current = next; + allocator->index = 0; + } + + params = &allocator->current->param[allocator->index * allocator->stride]; + allocator->index += count; + + return params; +} + +bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *array, size_t reserve) +{ + if (!vkd3d_array_reserve((void **)&array->elements, &array->capacity, reserve, sizeof(*array->elements))) + { + ERR("Failed to allocate instructions.\n"); + return false; + } + + return true; +} + +bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *array, size_t idx, size_t count) +{ + VKD3D_ASSERT(idx <= array->count); + + if (!shader_instruction_array_reserve(array, array->count + count)) + return false; + + memmove(&array->elements[idx + count], &array->elements[idx], (array->count - idx) * sizeof(*array->elements)); + memset(&array->elements[idx], 0, count * sizeof(*array->elements)); + array->count += count; + + return true; +} + +bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *array, + struct vkd3d_shader_immediate_constant_buffer *icb) +{ + if (!vkd3d_array_reserve((void **)&array->icbs, &array->icb_capacity, array->icb_count + 1, sizeof(*array->icbs))) + return false; + + array->icbs[array->icb_count++] = icb; + + return true; +} + +static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( + struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_src_param *params, size_t count); + +static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, + struct vkd3d_shader_instruction_array *array) +{ + size_t i; + + for (i = 0; i < reg->idx_count; ++i) + { + if (!reg->idx[i].rel_addr) + continue; + + if (!(reg->idx[i].rel_addr = shader_instruction_array_clone_src_params(array, reg->idx[i].rel_addr, 1))) + return false; + } + + return true; +} + +static struct vkd3d_shader_dst_param *shader_instruction_array_clone_dst_params( + struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_dst_param *params, size_t count) +{ + struct vkd3d_shader_dst_param *dst_params; + size_t i; + + if (!(dst_params = shader_dst_param_allocator_get(&array->dst_params, count))) + return NULL; + + memcpy(dst_params, params, count * sizeof(*params)); + for (i = 0; i < count; ++i) + { + if (!shader_register_clone_relative_addresses(&dst_params[i].reg, array)) + return NULL; + } + + return dst_params; +} + +static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( + struct vkd3d_shader_instruction_array *array, const struct vkd3d_shader_src_param *params, size_t count) +{ + struct vkd3d_shader_src_param *src_params; + size_t i; + + if (!(src_params = shader_src_param_allocator_get(&array->src_params, count))) + return NULL; + + memcpy(src_params, params, count * sizeof(*params)); + for (i = 0; i < count; ++i) + { + if (!shader_register_clone_relative_addresses(&src_params[i].reg, array)) + return NULL; + } + + 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) +{ + unsigned int i; + + vkd3d_free(array->elements); + shader_param_allocator_destroy(&array->dst_params); + shader_param_allocator_destroy(&array->src_params); + for (i = 0; i < array->icb_count; ++i) + { + vkd3d_free(array->icbs[i]); + } + vkd3d_free(array->icbs); +} + +static bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *array, size_t reserve) +{ + memset(array, 0, sizeof(*array)); + /* Size the parameter initial allocations so they are large enough for most shaders. The + * code path for chained allocations will be tested if a few shaders need to use it. */ + shader_param_allocator_init(&array->dst_params, reserve - reserve / 8u, sizeof(struct vkd3d_shader_dst_param)); + shader_param_allocator_init(&array->src_params, reserve * 2u, sizeof(struct vkd3d_shader_src_param)); + + return shader_instruction_array_reserve(array, reserve); +} + static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info, unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index d04ae7733..b15dcf659 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -2297,204 +2297,6 @@ void vkd3d_shader_set_log_callback(PFN_vkd3d_log callback) vkd3d_dbg_set_log_callback(callback); } -static struct vkd3d_shader_param_node *shader_param_allocator_node_create( - struct vkd3d_shader_param_allocator *allocator) -{ - struct vkd3d_shader_param_node *node; - - if (!(node = vkd3d_malloc(offsetof(struct vkd3d_shader_param_node, param[allocator->count * allocator->stride])))) - return NULL; - node->next = NULL; - return node; -} - -static void shader_param_allocator_init(struct vkd3d_shader_param_allocator *allocator, - size_t count, size_t stride) -{ - allocator->count = max(count, MAX_REG_OUTPUT); - allocator->stride = stride; - allocator->head = NULL; - allocator->current = NULL; - allocator->index = allocator->count; -} - -static void shader_param_allocator_destroy(struct vkd3d_shader_param_allocator *allocator) -{ - struct vkd3d_shader_param_node *current = allocator->head; - - while (current) - { - struct vkd3d_shader_param_node *next = current->next; - vkd3d_free(current); - current = next; - } -} - -void *shader_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, size_t count) -{ - void *params; - - if (!allocator->current || count > allocator->count - allocator->index) - { - struct vkd3d_shader_param_node *next; - - /* Monolithic switch has no definite parameter count limit. */ - allocator->count = max(allocator->count, count); - - if (!(next = shader_param_allocator_node_create(allocator))) - return NULL; - if (allocator->current) - allocator->current->next = next; - else - allocator->head = next; - allocator->current = next; - allocator->index = 0; - } - - params = &allocator->current->param[allocator->index * allocator->stride]; - allocator->index += count; - return params; -} - -bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, size_t reserve) -{ - memset(instructions, 0, sizeof(*instructions)); - /* Size the parameter initial allocations so they are large enough for most shaders. The - * code path for chained allocations will be tested if a few shaders need to use it. */ - shader_param_allocator_init(&instructions->dst_params, reserve - reserve / 8u, - sizeof(struct vkd3d_shader_dst_param)); - shader_param_allocator_init(&instructions->src_params, reserve * 2u, sizeof(struct vkd3d_shader_src_param)); - return shader_instruction_array_reserve(instructions, reserve); -} - -bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve) -{ - if (!vkd3d_array_reserve((void **)&instructions->elements, &instructions->capacity, reserve, - sizeof(*instructions->elements))) - { - ERR("Failed to allocate instructions.\n"); - return false; - } - return true; -} - -bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, - size_t idx, size_t count) -{ - VKD3D_ASSERT(idx <= instructions->count); - - if (!shader_instruction_array_reserve(instructions, instructions->count + count)) - return false; - - memmove(&instructions->elements[idx + count], &instructions->elements[idx], - (instructions->count - idx) * sizeof(*instructions->elements)); - memset(&instructions->elements[idx], 0, count * sizeof(*instructions->elements)); - - instructions->count += count; - - return true; -} - -bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, - struct vkd3d_shader_immediate_constant_buffer *icb) -{ - if (!vkd3d_array_reserve((void **)&instructions->icbs, &instructions->icb_capacity, instructions->icb_count + 1, - sizeof(*instructions->icbs))) - return false; - instructions->icbs[instructions->icb_count++] = icb; - return true; -} - -static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( - struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_src_param *params, - size_t count); - -static bool shader_register_clone_relative_addresses(struct vkd3d_shader_register *reg, - struct vkd3d_shader_instruction_array *instructions) -{ - unsigned int i; - - for (i = 0; i < reg->idx_count; ++i) - { - if (!reg->idx[i].rel_addr) - continue; - - if (!(reg->idx[i].rel_addr = shader_instruction_array_clone_src_params(instructions, reg->idx[i].rel_addr, 1))) - return false; - } - - return true; -} - -static struct vkd3d_shader_dst_param *shader_instruction_array_clone_dst_params( - struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_dst_param *params, - size_t count) -{ - struct vkd3d_shader_dst_param *dst_params; - size_t i; - - if (!(dst_params = shader_dst_param_allocator_get(&instructions->dst_params, count))) - return NULL; - - memcpy(dst_params, params, count * sizeof(*params)); - for (i = 0; i < count; ++i) - { - if (!shader_register_clone_relative_addresses(&dst_params[i].reg, instructions)) - return NULL; - } - - return dst_params; -} - -static struct vkd3d_shader_src_param *shader_instruction_array_clone_src_params( - struct vkd3d_shader_instruction_array *instructions, const struct vkd3d_shader_src_param *params, - size_t count) -{ - struct vkd3d_shader_src_param *src_params; - size_t i; - - if (!(src_params = shader_src_param_allocator_get(&instructions->src_params, count))) - return NULL; - - memcpy(src_params, params, count * sizeof(*params)); - for (i = 0; i < count; ++i) - { - if (!shader_register_clone_relative_addresses(&src_params[i].reg, instructions)) - return NULL; - } - - 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. */ -bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, - size_t dst, size_t src) -{ - struct vkd3d_shader_instruction *ins = &instructions->elements[dst]; - - *ins = instructions->elements[src]; - - if (ins->dst_count && ins->dst && !(ins->dst = shader_instruction_array_clone_dst_params(instructions, - ins->dst, ins->dst_count))) - return false; - - return !ins->src_count || !!(ins->src = shader_instruction_array_clone_src_params(instructions, - ins->src, ins->src_count)); -} - -void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions) -{ - unsigned int i; - - vkd3d_free(instructions->elements); - shader_param_allocator_destroy(&instructions->dst_params); - shader_param_allocator_destroy(&instructions->src_params); - for (i = 0; i < instructions->icb_count; ++i) - vkd3d_free(instructions->icbs[i]); - vkd3d_free(instructions->icbs); -} - void vkd3d_shader_build_varying_map(const struct vkd3d_shader_signature *output_signature, const struct vkd3d_shader_signature *input_signature, unsigned int *ret_count, struct vkd3d_shader_varying_map *varyings) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 63cf5c653..d7c4228c8 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1441,15 +1441,11 @@ struct vkd3d_shader_instruction_array struct vkd3d_shader_src_param *outpointid_param; }; -bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, size_t reserve); bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, size_t reserve); bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, size_t idx, size_t count); bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *instructions, struct vkd3d_shader_immediate_constant_buffer *icb); -bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, - size_t dst, size_t src); -void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); struct vsir_program_iterator {