diff --git a/src/vulkan/util/vk_cmd_queue_gen.py b/src/vulkan/util/vk_cmd_queue_gen.py index 922a8014ccb..e4f546899af 100644 --- a/src/vulkan/util/vk_cmd_queue_gen.py +++ b/src/vulkan/util/vk_cmd_queue_gen.py @@ -572,10 +572,31 @@ class ParamCategory(Enum): NULL = auto() PNEXT = auto() STRUCT = auto() + INLINE_STRUCT = auto() DESCRIPTOR_UPDATE_TEMPLATE_DATA = auto() DESCRIPTOR_UPDATE_TEMPLATE = auto() PIPELINE_LAYOUT = auto() +class StructInfo: + def __init__(self): + self.has_explicit_copy = False + self.needs_member_copy = False + self.additional_code = [] + +def get_struct_info(command, param, types, src=""): + info = StructInfo() + info.has_explicit_copy = param.type in EXPLICIT_PARAM_COPIES + info.needs_member_copy = info.has_explicit_copy + for member in types[param.type].members: + match categorize_param(command, types, param.type, member): + case ParamCategory.PNEXT | ParamCategory.STRUCT | ParamCategory.STRING | ParamCategory.INLINE_STRUCT: + info.needs_member_copy = True + case ParamCategory.PIPELINE_LAYOUT: + info.additional_code.append("enqueue_pipeline_layout(queue, %s->%s);" % (src, member.name)) + case ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE: + info.additional_code.append("enqueue_descriptor_template(queue, %s->%s);" % (src, member.name)) + return info + def categorize_param(command, types, parent_type, param): if param.name == 'pNext': return ParamCategory.PNEXT if not parent_type or types[parent_type].extended_by else ParamCategory.NULL @@ -599,6 +620,11 @@ def categorize_param(command, types, parent_type, param): return ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE if "*" not in param.decl: + if param.type in types: + struct_info = get_struct_info(command, param, types) + # If no member needs special handling, the assign/memcpy is enough + if struct_info.needs_member_copy: + return ParamCategory.INLINE_STRUCT return ParamCategory.ASSIGNABLE return ParamCategory.STRUCT @@ -641,7 +667,8 @@ def get_param_copy(builder, command, types, src_parent_access, dst_parent_access src = src_parent_access + param.name dst = dst_parent_access + (to_field_name(param.name) if dst_snake_case else param.name) - match categorize_param(command, types, None, param): + param_category = categorize_param(command, types, None, param) + match param_category: case ParamCategory.ASSIGNABLE: builder.add("%s = %s;" % (dst, src)) case ParamCategory.FLAT_ARRAY: @@ -658,7 +685,11 @@ def get_param_copy(builder, command, types, src_parent_access, dst_parent_access case ParamCategory.PIPELINE_LAYOUT: builder.add("%s = %s;" % (dst, src)) builder.add("enqueue_pipeline_layout(queue, %s);" % (src)) - case ParamCategory.STRUCT: + case ParamCategory.STRUCT | ParamCategory.INLINE_STRUCT: + if param_category == ParamCategory.INLINE_STRUCT: + nullable = False + src = "&%s" % (src) + dst = "&%s" % (dst) if nullable: builder.add("if (%s) {" % (src)) @@ -673,9 +704,11 @@ def get_param_copy(builder, command, types, src_parent_access, dst_parent_access if param.len and param.len != "struct-ptr" and not is_ndarray: size = "%s * ceil(%s%s)" % (size, src_parent_access, param.len) - builder.add("%s = linear_alloc_child(queue->ctx, %s);" % (dst, size)) - builder.add("if (%s == NULL) return NULL;" % (dst)) - builder.add("memcpy((void *)%s, %s, %s);" % (dst, src, size)) + if param_category != ParamCategory.INLINE_STRUCT: + builder.add("%s = linear_alloc_child(queue->ctx, %s);" % (dst, size)) + builder.add("if (%s == NULL) return NULL;" % (dst)) + builder.add("memcpy((void *)%s, %s, %s);" % (dst, src, size)) + if param.type == 'VkDescriptorSetLayout': array_index = builder.get_variable_name("i") builder.add("for (unsigned %s = 0; %s < %s%s; %s++) {" % (array_index, array_index, src_parent_access, param.len, array_index)) @@ -685,18 +718,11 @@ def get_param_copy(builder, command, types, src_parent_access, dst_parent_access builder.add("}") if param.type in types: - has_explicit_copy = param.type in EXPLICIT_PARAM_COPIES - needs_member_copy = has_explicit_copy - for member in types[param.type].members: - match categorize_param(command, types, param.type, member): - case ParamCategory.PNEXT | ParamCategory.STRUCT | ParamCategory.STRING: - needs_member_copy = True - case ParamCategory.PIPELINE_LAYOUT: - builder.add("enqueue_pipeline_layout(queue, %s->%s);" % (src, member.name)) - case ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE: - builder.add("enqueue_descriptor_template(queue, %s->%s);" % (src, member.name)) + struct_info = get_struct_info(command, param, types, src) + for code in struct_info.additional_code: + builder.add(code); - if needs_member_copy: + if struct_info.needs_member_copy: tmp_dst_name = builder.get_variable_name("tmp_dst") tmp_src_name = builder.get_variable_name("tmp_src") @@ -722,12 +748,12 @@ def get_param_copy(builder, command, types, src_parent_access, dst_parent_access elif category == ParamCategory.DESCRIPTOR_UPDATE_TEMPLATE_DATA: get_param_copy(builder, command, types, "%s->" % (tmp_src_name), "%s->" % (tmp_dst_name), member, dst_initialized=True) - if has_explicit_copy: + if struct_info.has_explicit_copy: builder.add("enqueue_%s(queue, %s, %s);" % (param.type, tmp_dst_name, tmp_src_name)) else: for member in types[param.type].members: category = categorize_param(command, types, param.type, member) - if category == ParamCategory.STRUCT or category == ParamCategory.STRING: + if category == ParamCategory.STRUCT or category == ParamCategory.STRING or category == ParamCategory.INLINE_STRUCT: get_param_copy(builder, command, types, "%s->" % (tmp_src_name), "%s->" % (tmp_dst_name), member, dst_initialized=True) if struct_array_copy: