mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-12 00:20:43 +01:00
vulkan/cmd_queue: Rework copy codegen
The new code handles pNext chanis correctly. Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39902>
This commit is contained in:
parent
ecb6c5d555
commit
f2bb6103c3
2 changed files with 109 additions and 93 deletions
|
|
@ -5069,7 +5069,6 @@ void lvp_add_enqueue_cmd_entrypoints(struct vk_device_dispatch_table *disp)
|
|||
ENQUEUE_CMD(CmdCopyAccelerationStructureKHR)
|
||||
ENQUEUE_CMD(CmdCopyMemoryToAccelerationStructureKHR)
|
||||
ENQUEUE_CMD(CmdCopyAccelerationStructureToMemoryKHR)
|
||||
ENQUEUE_CMD(CmdBuildAccelerationStructuresIndirectKHR)
|
||||
ENQUEUE_CMD(CmdWriteAccelerationStructuresPropertiesKHR)
|
||||
|
||||
ENQUEUE_CMD(CmdSetRayTracingPipelineStackSizeKHR)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import argparse
|
|||
import os
|
||||
import re
|
||||
from collections import namedtuple
|
||||
from enum import Enum, auto
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
from mako.template import Template
|
||||
|
|
@ -69,6 +70,8 @@ NO_ENQUEUE_COMMANDS = [
|
|||
'CmdSetPerformanceMarkerINTEL',
|
||||
'CmdSetPerformanceStreamMarkerINTEL',
|
||||
'CmdSetPerformanceOverrideINTEL',
|
||||
|
||||
'CmdBuildAccelerationStructuresIndirectKHR',
|
||||
]
|
||||
|
||||
TEMPLATE_H = Template(COPYRIGHT + """\
|
||||
|
|
@ -421,135 +424,149 @@ def to_struct_name(name):
|
|||
def get_array_len(param):
|
||||
return param.decl[param.decl.find("[") + 1:param.decl.find("]")]
|
||||
|
||||
def get_array_copy(builder, command, param, field_name):
|
||||
if param.type == "void":
|
||||
field_size = "1"
|
||||
else:
|
||||
field_size = "sizeof(*%s)" % field_name
|
||||
class ParamCategory(Enum):
|
||||
ASSIGNABLE = auto()
|
||||
FLAT_ARRAY = auto()
|
||||
UNSIZED_RAW_POINTER = auto()
|
||||
STRING = auto()
|
||||
NULL = auto()
|
||||
PNEXT = auto()
|
||||
STRUCT = auto()
|
||||
|
||||
builder.add("%s = linear_alloc_child(queue->ctx, %s * (%s));\n if (%s == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY;" % (
|
||||
field_name, field_size, param.len, field_name
|
||||
))
|
||||
builder.add("memcpy((void*)%s, %s, %s * (%s));" % (field_name, param.name, field_size, param.len))
|
||||
def categorize_param(types, parent_type, param):
|
||||
if param.name == 'pNext':
|
||||
return ParamCategory.PNEXT if not parent_type or types[parent_type].extended_by else ParamCategory.NULL
|
||||
|
||||
def get_pnext_member_copy(builder, struct, src_type, member, types):
|
||||
if not types[src_type].extended_by:
|
||||
if '[' in param.decl:
|
||||
return ParamCategory.FLAT_ARRAY
|
||||
|
||||
if param.type == "void" and not param.len:
|
||||
return ParamCategory.UNSIZED_RAW_POINTER
|
||||
|
||||
if param.len == 'null-terminated':
|
||||
return ParamCategory.STRING
|
||||
|
||||
if "*" not in param.decl:
|
||||
return ParamCategory.ASSIGNABLE
|
||||
|
||||
return ParamCategory.STRUCT
|
||||
|
||||
def get_pnext_copy(builder, types, parent_type, src, dst):
|
||||
if not types[parent_type].extended_by:
|
||||
return
|
||||
|
||||
field_name = "%s->%s" % (struct, member.name)
|
||||
|
||||
builder.add("const VkBaseInStructure *pnext = %s;" % (field_name))
|
||||
builder.add("if (pnext) {")
|
||||
builder.add("const VkBaseInStructure *pnext = %s;" % (src))
|
||||
builder.add("void **dst_pnext_link = (void **)&%s;" % (dst))
|
||||
builder.add("while (pnext) {")
|
||||
builder.level += 1
|
||||
builder.add("switch ((int32_t)pnext->sType) {")
|
||||
|
||||
for type in types[src_type].extended_by:
|
||||
for type in types[parent_type].extended_by:
|
||||
if type.guard is not None:
|
||||
builder.code += "#ifdef %s\n" % (type.guard)
|
||||
|
||||
builder.add("case %s:" % (type.enum))
|
||||
builder.level += 1
|
||||
get_struct_copy(builder, field_name, "pnext", type.name, types)
|
||||
member = EntrypointParam(type=type.name, name="", decl="%s *" % (type.name), len=None)
|
||||
get_param_copy(builder, types, "pnext", "(*dst_pnext_link)", member, nullable=False)
|
||||
builder.add("break;")
|
||||
builder.level -= 1
|
||||
|
||||
if type.guard is not None:
|
||||
builder.code += "#endif\n"
|
||||
|
||||
|
||||
builder.add("}")
|
||||
builder.add("pnext = pnext->pNext;")
|
||||
builder.add("dst_pnext_link = (void **)&((VkBaseOutStructure *)*dst_pnext_link)->pNext;")
|
||||
builder.level -= 1
|
||||
builder.add("}")
|
||||
|
||||
def get_struct_copy(builder, dst, src_name, src_type, types, parent_name=None, len=None):
|
||||
tmp_dst_name = builder.get_variable_name("tmp_dst")
|
||||
tmp_src_name = builder.get_variable_name("tmp_src")
|
||||
|
||||
builder.add("if (%s) {" % (src_name))
|
||||
builder.level += 1
|
||||
def get_param_copy(builder, types, src_parent_access, dst_parent_access, param, nullable=True, dst_snake_case=False):
|
||||
src = src_parent_access + param.name
|
||||
dst = dst_parent_access + (to_field_name(param.name) if dst_snake_case else param.name)
|
||||
|
||||
if src_type == "void":
|
||||
size = "1"
|
||||
else:
|
||||
size = "sizeof(%s)" % src_type
|
||||
match categorize_param(types, None, param):
|
||||
case ParamCategory.ASSIGNABLE:
|
||||
builder.add("%s = %s;" % (dst, src))
|
||||
case ParamCategory.FLAT_ARRAY:
|
||||
builder.add("memcpy(%s, %s, sizeof(*%s) * %s);" % (dst, src, src, get_array_len(param)))
|
||||
case ParamCategory.UNSIZED_RAW_POINTER:
|
||||
builder.add("%s = (%s)%s;" % (dst, remove_suffix(param.decl.replace("const", ""), param.name), src))
|
||||
case ParamCategory.STRING:
|
||||
builder.add("%s = linear_strdup(queue->ctx, %s);" % (dst, src))
|
||||
case ParamCategory.STRUCT:
|
||||
if nullable:
|
||||
builder.add("if (%s) {" % (src))
|
||||
builder.level += 1
|
||||
|
||||
if len and len != "struct-ptr":
|
||||
size = "%s * %s->%s" % (size, parent_name, len)
|
||||
if param.type == "void":
|
||||
size = 1
|
||||
else:
|
||||
size = "sizeof(%s)" % param.type
|
||||
|
||||
builder.add("%s = linear_alloc_child(queue->ctx, %s);" % (dst, size))
|
||||
builder.add("if (%s == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY;" % (dst))
|
||||
builder.add("%s *%s = (void *)%s;" % (src_type, tmp_dst_name, dst))
|
||||
builder.add("%s *%s = (void *)%s;" % (src_type, tmp_src_name, src_name))
|
||||
builder.add("memcpy(%s, %s, %s);" % (tmp_dst_name, tmp_src_name, size))
|
||||
is_ndarray = param.len and "," in param.len
|
||||
if param.len and param.len != "struct-ptr" and not is_ndarray:
|
||||
size = "%s * %s%s" % (size, src_parent_access, param.len)
|
||||
|
||||
struct_array_copy = len and len != "struct-ptr" and src_type != "void"
|
||||
if struct_array_copy:
|
||||
array_index = builder.get_variable_name("i")
|
||||
builder.add("for (uint32_t %s = 0; %s < %s->%s; %s++) {" % (array_index, array_index, parent_name, len, array_index))
|
||||
builder.level += 1
|
||||
prev_tmp_dst_name = tmp_dst_name
|
||||
prev_tmp_src_name = tmp_src_name
|
||||
tmp_dst_name = builder.get_variable_name("tmp_dst")
|
||||
tmp_src_name = builder.get_variable_name("tmp_src")
|
||||
builder.add("%s *%s = %s + %s; (void)%s;" % (src_type, tmp_dst_name, prev_tmp_dst_name, array_index, tmp_dst_name))
|
||||
builder.add("%s *%s = %s + %s; (void)%s;" % (src_type, tmp_src_name, prev_tmp_src_name, array_index, tmp_src_name))
|
||||
builder.add("%s = linear_alloc_child(queue->ctx, %s);" % (dst, size))
|
||||
builder.add("if (%s == NULL) return VK_ERROR_OUT_OF_HOST_MEMORY;" % (dst))
|
||||
builder.add("memcpy((void *)%s, %s, %s);" % (dst, src, size))
|
||||
|
||||
if src_type in types:
|
||||
for member in types[src_type].members:
|
||||
if member.len and member.len != 'null-terminated':
|
||||
get_struct_copy(builder, "%s->%s" % (tmp_dst_name, member.name), "%s->%s" % (
|
||||
tmp_src_name, member.name
|
||||
), member.type, types, tmp_src_name, member.len)
|
||||
elif member.len and member.len == 'null-terminated':
|
||||
builder.add("%s->%s = linear_strdup(queue->ctx, %s->%s);" % (tmp_dst_name, member.name, tmp_src_name, member.name))
|
||||
elif member.name == 'pNext':
|
||||
get_pnext_member_copy(builder, tmp_dst_name, src_type, member, types)
|
||||
if param.type in types:
|
||||
needs_member_copy = False
|
||||
for member in types[param.type].members:
|
||||
category = categorize_param(types, param.type, member)
|
||||
if category == ParamCategory.PNEXT or category == ParamCategory.STRUCT or category == ParamCategory.STRING:
|
||||
needs_member_copy = True
|
||||
|
||||
if struct_array_copy:
|
||||
builder.level -= 1
|
||||
builder.add("}")
|
||||
if needs_member_copy:
|
||||
tmp_dst_name = builder.get_variable_name("tmp_dst")
|
||||
tmp_src_name = builder.get_variable_name("tmp_src")
|
||||
|
||||
builder.level -= 1
|
||||
builder.add("} else {")
|
||||
builder.level += 1
|
||||
builder.add("%s = NULL;" % (dst))
|
||||
builder.level -= 1
|
||||
builder.add("}")
|
||||
builder.add("%s *%s = (void *)%s;" % (param.type, tmp_dst_name, dst))
|
||||
builder.add("%s *%s = (void *)%s;" % (param.type, tmp_src_name, src))
|
||||
|
||||
def get_param_copy(builder, command, param, types):
|
||||
dst = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name))
|
||||
struct_array_copy = param.len and param.len != "struct-ptr" and param.type != "void"
|
||||
if struct_array_copy:
|
||||
array_index = builder.get_variable_name("i")
|
||||
builder.add("for (uint32_t %s = 0; %s < %s%s; %s++) {" % (array_index, array_index, src_parent_access, param.len, array_index))
|
||||
builder.level += 1
|
||||
prev_tmp_dst_name = tmp_dst_name
|
||||
prev_tmp_src_name = tmp_src_name
|
||||
tmp_dst_name = builder.get_variable_name("tmp_dst")
|
||||
tmp_src_name = builder.get_variable_name("tmp_src")
|
||||
builder.add("%s *%s = %s + %s;" % (param.type, tmp_dst_name, prev_tmp_dst_name, array_index))
|
||||
builder.add("%s *%s = %s + %s;" % (param.type, tmp_src_name, prev_tmp_src_name, array_index))
|
||||
|
||||
if param.len:
|
||||
builder.add("if (%s) {" % (param.name))
|
||||
builder.level += 1
|
||||
get_array_copy(builder, command, param, dst)
|
||||
builder.level -= 1
|
||||
builder.add("} else {")
|
||||
builder.level += 1
|
||||
builder.add("%s = NULL;" % (dst))
|
||||
builder.level -= 1
|
||||
builder.add("}")
|
||||
return True
|
||||
for member in types[param.type].members:
|
||||
category = categorize_param(types, param.type, member)
|
||||
if category == ParamCategory.STRUCT or category == ParamCategory.STRING:
|
||||
get_param_copy(builder, types, "%s->" % (tmp_src_name), "%s->" % (tmp_dst_name), member)
|
||||
elif category == ParamCategory.PNEXT:
|
||||
get_pnext_copy(builder, types, param.type, "%s->pNext" % (tmp_src_name), "%s->pNext" % (tmp_dst_name))
|
||||
|
||||
if '[' in param.decl:
|
||||
builder.add("memcpy(%s, %s, sizeof(*%s) * %s);" % (dst, param.name, param.name, get_array_len(param)))
|
||||
return False
|
||||
if struct_array_copy:
|
||||
builder.level -= 1
|
||||
builder.add("}")
|
||||
|
||||
if param.type == "void":
|
||||
builder.add("%s = (%s)%s;" % (dst, remove_suffix(param.decl.replace("const", ""), param.name), param.name))
|
||||
return False
|
||||
|
||||
if '*' in param.decl:
|
||||
get_struct_copy(builder, dst, param.name, param.type, types)
|
||||
return True
|
||||
|
||||
builder.add("cmd->u.%s.%s = %s;" % (to_struct_field_name(command.name), to_field_name(param.name), param.name))
|
||||
return False
|
||||
if nullable:
|
||||
builder.level -= 1
|
||||
builder.add("} else {")
|
||||
builder.level += 1
|
||||
builder.add("%s = NULL;" % (dst))
|
||||
builder.level -= 1
|
||||
builder.add("}")
|
||||
case ParamCategory.NULL:
|
||||
assert False
|
||||
case ParamCategory.PNEXT:
|
||||
assert False
|
||||
|
||||
def get_params_copy(command, types):
|
||||
builder = CodeBuilder(1)
|
||||
|
||||
struct_access = "cmd->u.%s." % (to_struct_field_name(command.name))
|
||||
for param in command.params[1:]:
|
||||
get_param_copy(builder, command, param, types)
|
||||
get_param_copy(builder, types, "", struct_access, param, dst_snake_case=True)
|
||||
|
||||
builder.code += "\n"
|
||||
builder.add("list_addtail(&cmd->cmd_link, &queue->cmds);")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue