1bf215546Sopenharmony_ciCOPYRIGHT=u""" 2bf215546Sopenharmony_ci/* Copyright © 2015-2021 Intel Corporation 3bf215546Sopenharmony_ci * Copyright © 2021 Collabora, Ltd. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22bf215546Sopenharmony_ci * IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci""" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ciimport argparse 27bf215546Sopenharmony_ciimport os 28bf215546Sopenharmony_ciimport re 29bf215546Sopenharmony_cifrom collections import namedtuple 30bf215546Sopenharmony_ciimport xml.etree.ElementTree as et 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_cifrom mako.template import Template 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci# Mesa-local imports must be declared in meson variable 35bf215546Sopenharmony_ci# '{file_without_suffix}_depend_files'. 36bf215546Sopenharmony_cifrom vk_entrypoints import get_entrypoints_from_xml, EntrypointParam 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci# These have hand-typed implementations in vk_cmd_enqueue.c 39bf215546Sopenharmony_ciMANUAL_COMMANDS = [ 40bf215546Sopenharmony_ci # This script doesn't know how to copy arrays in structs in arrays 41bf215546Sopenharmony_ci 'CmdPushDescriptorSetKHR', 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci # The size of the elements is specified in a stride param 44bf215546Sopenharmony_ci 'CmdDrawMultiEXT', 45bf215546Sopenharmony_ci 'CmdDrawMultiIndexedEXT', 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci # The VkPipelineLayout object could be released before the command is 48bf215546Sopenharmony_ci # executed 49bf215546Sopenharmony_ci 'CmdBindDescriptorSets', 50bf215546Sopenharmony_ci] 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ciNO_ENQUEUE_COMMANDS = [ 53bf215546Sopenharmony_ci # pData's size cannot be calculated from the xml 54bf215546Sopenharmony_ci 'CmdPushDescriptorSetWithTemplateKHR', 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci # These don't return void 57bf215546Sopenharmony_ci 'CmdSetPerformanceMarkerINTEL', 58bf215546Sopenharmony_ci 'CmdSetPerformanceStreamMarkerINTEL', 59bf215546Sopenharmony_ci 'CmdSetPerformanceOverrideINTEL', 60bf215546Sopenharmony_ci] 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ciTEMPLATE_H = Template(COPYRIGHT + """\ 63bf215546Sopenharmony_ci/* This file generated from ${filename}, don't edit directly. */ 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci#pragma once 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci#include "util/list.h" 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci#define VK_PROTOTYPES 70bf215546Sopenharmony_ci#include <vulkan/vulkan.h> 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci#ifdef __cplusplus 73bf215546Sopenharmony_ciextern "C" { 74bf215546Sopenharmony_ci#endif 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistruct vk_device_dispatch_table; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistruct vk_cmd_queue { 79bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc; 80bf215546Sopenharmony_ci struct list_head cmds; 81bf215546Sopenharmony_ci VkResult error; 82bf215546Sopenharmony_ci}; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_cienum vk_cmd_type { 85bf215546Sopenharmony_ci% for c in commands: 86bf215546Sopenharmony_ci% if c.guard is not None: 87bf215546Sopenharmony_ci#ifdef ${c.guard} 88bf215546Sopenharmony_ci% endif 89bf215546Sopenharmony_ci ${to_enum_name(c.name)}, 90bf215546Sopenharmony_ci% if c.guard is not None: 91bf215546Sopenharmony_ci#endif // ${c.guard} 92bf215546Sopenharmony_ci% endif 93bf215546Sopenharmony_ci% endfor 94bf215546Sopenharmony_ci}; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ciextern const char *vk_cmd_queue_type_names[]; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci% for c in commands: 99bf215546Sopenharmony_ci% if len(c.params) <= 1: # Avoid "error C2016: C requires that a struct or union have at least one member" 100bf215546Sopenharmony_ci<% continue %> 101bf215546Sopenharmony_ci% endif 102bf215546Sopenharmony_ci% if c.guard is not None: 103bf215546Sopenharmony_ci#ifdef ${c.guard} 104bf215546Sopenharmony_ci% endif 105bf215546Sopenharmony_cistruct ${to_struct_name(c.name)} { 106bf215546Sopenharmony_ci% for p in c.params[1:]: 107bf215546Sopenharmony_ci ${to_field_decl(p.decl)}; 108bf215546Sopenharmony_ci% endfor 109bf215546Sopenharmony_ci}; 110bf215546Sopenharmony_ci% if c.guard is not None: 111bf215546Sopenharmony_ci#endif // ${c.guard} 112bf215546Sopenharmony_ci% endif 113bf215546Sopenharmony_ci% endfor 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_cistruct vk_cmd_queue_entry { 116bf215546Sopenharmony_ci struct list_head cmd_link; 117bf215546Sopenharmony_ci enum vk_cmd_type type; 118bf215546Sopenharmony_ci union { 119bf215546Sopenharmony_ci% for c in commands: 120bf215546Sopenharmony_ci% if len(c.params) <= 1: 121bf215546Sopenharmony_ci<% continue %> 122bf215546Sopenharmony_ci% endif 123bf215546Sopenharmony_ci% if c.guard is not None: 124bf215546Sopenharmony_ci#ifdef ${c.guard} 125bf215546Sopenharmony_ci% endif 126bf215546Sopenharmony_ci struct ${to_struct_name(c.name)} ${to_struct_field_name(c.name)}; 127bf215546Sopenharmony_ci% if c.guard is not None: 128bf215546Sopenharmony_ci#endif // ${c.guard} 129bf215546Sopenharmony_ci% endif 130bf215546Sopenharmony_ci% endfor 131bf215546Sopenharmony_ci } u; 132bf215546Sopenharmony_ci void *driver_data; 133bf215546Sopenharmony_ci void (*driver_free_cb)(struct vk_cmd_queue *queue, 134bf215546Sopenharmony_ci struct vk_cmd_queue_entry *cmd); 135bf215546Sopenharmony_ci}; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci% for c in commands: 138bf215546Sopenharmony_ci% if c.name in manual_commands or c.name in no_enqueue_commands: 139bf215546Sopenharmony_ci<% continue %> 140bf215546Sopenharmony_ci% endif 141bf215546Sopenharmony_ci% if c.guard is not None: 142bf215546Sopenharmony_ci#ifdef ${c.guard} 143bf215546Sopenharmony_ci% endif 144bf215546Sopenharmony_ci void vk_enqueue_${to_underscore(c.name)}(struct vk_cmd_queue *queue 145bf215546Sopenharmony_ci% for p in c.params[1:]: 146bf215546Sopenharmony_ci , ${p.decl} 147bf215546Sopenharmony_ci% endfor 148bf215546Sopenharmony_ci ); 149bf215546Sopenharmony_ci% if c.guard is not None: 150bf215546Sopenharmony_ci#endif // ${c.guard} 151bf215546Sopenharmony_ci% endif 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci% endfor 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_civoid vk_free_queue(struct vk_cmd_queue *queue); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_cistatic inline void 158bf215546Sopenharmony_civk_cmd_queue_init(struct vk_cmd_queue *queue, VkAllocationCallbacks *alloc) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci queue->alloc = alloc; 161bf215546Sopenharmony_ci list_inithead(&queue->cmds); 162bf215546Sopenharmony_ci queue->error = VK_SUCCESS; 163bf215546Sopenharmony_ci} 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_cistatic inline void 166bf215546Sopenharmony_civk_cmd_queue_reset(struct vk_cmd_queue *queue) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci vk_free_queue(queue); 169bf215546Sopenharmony_ci list_inithead(&queue->cmds); 170bf215546Sopenharmony_ci queue->error = VK_SUCCESS; 171bf215546Sopenharmony_ci} 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_cistatic inline void 174bf215546Sopenharmony_civk_cmd_queue_finish(struct vk_cmd_queue *queue) 175bf215546Sopenharmony_ci{ 176bf215546Sopenharmony_ci vk_free_queue(queue); 177bf215546Sopenharmony_ci list_inithead(&queue->cmds); 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_civoid vk_cmd_queue_execute(struct vk_cmd_queue *queue, 181bf215546Sopenharmony_ci VkCommandBuffer commandBuffer, 182bf215546Sopenharmony_ci const struct vk_device_dispatch_table *disp); 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci#ifdef __cplusplus 185bf215546Sopenharmony_ci} 186bf215546Sopenharmony_ci#endif 187bf215546Sopenharmony_ci""", output_encoding='utf-8') 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ciTEMPLATE_C = Template(COPYRIGHT + """ 190bf215546Sopenharmony_ci/* This file generated from ${filename}, don't edit directly. */ 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_ci#include "${header}" 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci#define VK_PROTOTYPES 195bf215546Sopenharmony_ci#include <vulkan/vulkan.h> 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci#include "vk_alloc.h" 198bf215546Sopenharmony_ci#include "vk_cmd_enqueue_entrypoints.h" 199bf215546Sopenharmony_ci#include "vk_command_buffer.h" 200bf215546Sopenharmony_ci#include "vk_dispatch_table.h" 201bf215546Sopenharmony_ci#include "vk_device.h" 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ciconst char *vk_cmd_queue_type_names[] = { 204bf215546Sopenharmony_ci% for c in commands: 205bf215546Sopenharmony_ci% if c.guard is not None: 206bf215546Sopenharmony_ci#ifdef ${c.guard} 207bf215546Sopenharmony_ci% endif 208bf215546Sopenharmony_ci "${to_enum_name(c.name)}", 209bf215546Sopenharmony_ci% if c.guard is not None: 210bf215546Sopenharmony_ci#endif // ${c.guard} 211bf215546Sopenharmony_ci% endif 212bf215546Sopenharmony_ci% endfor 213bf215546Sopenharmony_ci}; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci% for c in commands: 216bf215546Sopenharmony_ci% if c.guard is not None: 217bf215546Sopenharmony_ci#ifdef ${c.guard} 218bf215546Sopenharmony_ci% endif 219bf215546Sopenharmony_cistatic void 220bf215546Sopenharmony_civk_free_${to_underscore(c.name)}(struct vk_cmd_queue *queue, 221bf215546Sopenharmony_ci${' ' * len('vk_free_' + to_underscore(c.name) + '(')}\\ 222bf215546Sopenharmony_cistruct vk_cmd_queue_entry *cmd) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci if (cmd->driver_free_cb) 225bf215546Sopenharmony_ci cmd->driver_free_cb(queue, cmd); 226bf215546Sopenharmony_ci else 227bf215546Sopenharmony_ci vk_free(queue->alloc, cmd->driver_data); 228bf215546Sopenharmony_ci% for p in c.params[1:]: 229bf215546Sopenharmony_ci% if p.len: 230bf215546Sopenharmony_ci vk_free(queue->alloc, (${remove_suffix(p.decl.replace("const", ""), p.name)})cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}); 231bf215546Sopenharmony_ci% elif '*' in p.decl: 232bf215546Sopenharmony_ci ${get_struct_free(c, p, types)} 233bf215546Sopenharmony_ci% endif 234bf215546Sopenharmony_ci% endfor 235bf215546Sopenharmony_ci vk_free(queue->alloc, cmd); 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci% if c.name not in manual_commands and c.name not in no_enqueue_commands: 239bf215546Sopenharmony_civoid vk_enqueue_${to_underscore(c.name)}(struct vk_cmd_queue *queue 240bf215546Sopenharmony_ci% for p in c.params[1:]: 241bf215546Sopenharmony_ci, ${p.decl} 242bf215546Sopenharmony_ci% endfor 243bf215546Sopenharmony_ci) 244bf215546Sopenharmony_ci{ 245bf215546Sopenharmony_ci if (queue->error) 246bf215546Sopenharmony_ci return; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci struct vk_cmd_queue_entry *cmd = vk_zalloc(queue->alloc, 249bf215546Sopenharmony_ci sizeof(*cmd), 8, 250bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 251bf215546Sopenharmony_ci if (!cmd) goto err; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci cmd->type = ${to_enum_name(c.name)}; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci% for p in c.params[1:]: 256bf215546Sopenharmony_ci% if p.len: 257bf215546Sopenharmony_ci if (${p.name}) { 258bf215546Sopenharmony_ci ${get_array_copy(c, p)} 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci% elif '[' in p.decl: 261bf215546Sopenharmony_ci memcpy(cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}, ${p.name}, 262bf215546Sopenharmony_ci sizeof(*${p.name}) * ${get_array_len(p)}); 263bf215546Sopenharmony_ci% elif p.type == "void": 264bf215546Sopenharmony_ci cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)} = (${remove_suffix(p.decl.replace("const", ""), p.name)}) ${p.name}; 265bf215546Sopenharmony_ci% elif '*' in p.decl: 266bf215546Sopenharmony_ci ${get_struct_copy("cmd->u.%s.%s" % (to_struct_field_name(c.name), to_field_name(p.name)), p.name, p.type, 'sizeof(%s)' % p.type, types)} 267bf215546Sopenharmony_ci% else: 268bf215546Sopenharmony_ci cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)} = ${p.name}; 269bf215546Sopenharmony_ci% endif 270bf215546Sopenharmony_ci% endfor 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci list_addtail(&cmd->cmd_link, &queue->cmds); 273bf215546Sopenharmony_ci return; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_cierr: 276bf215546Sopenharmony_ci queue->error = VK_ERROR_OUT_OF_HOST_MEMORY; 277bf215546Sopenharmony_ci if (cmd) 278bf215546Sopenharmony_ci vk_free_${to_underscore(c.name)}(queue, cmd); 279bf215546Sopenharmony_ci} 280bf215546Sopenharmony_ci% endif 281bf215546Sopenharmony_ci% if c.guard is not None: 282bf215546Sopenharmony_ci#endif // ${c.guard} 283bf215546Sopenharmony_ci% endif 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci% endfor 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_civoid 288bf215546Sopenharmony_civk_free_queue(struct vk_cmd_queue *queue) 289bf215546Sopenharmony_ci{ 290bf215546Sopenharmony_ci struct vk_cmd_queue_entry *tmp, *cmd; 291bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(cmd, tmp, &queue->cmds, cmd_link) { 292bf215546Sopenharmony_ci switch(cmd->type) { 293bf215546Sopenharmony_ci% for c in commands: 294bf215546Sopenharmony_ci% if c.guard is not None: 295bf215546Sopenharmony_ci#ifdef ${c.guard} 296bf215546Sopenharmony_ci% endif 297bf215546Sopenharmony_ci case ${to_enum_name(c.name)}: 298bf215546Sopenharmony_ci vk_free_${to_underscore(c.name)}(queue, cmd); 299bf215546Sopenharmony_ci break; 300bf215546Sopenharmony_ci% if c.guard is not None: 301bf215546Sopenharmony_ci#endif // ${c.guard} 302bf215546Sopenharmony_ci% endif 303bf215546Sopenharmony_ci% endfor 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci} 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_civoid 309bf215546Sopenharmony_civk_cmd_queue_execute(struct vk_cmd_queue *queue, 310bf215546Sopenharmony_ci VkCommandBuffer commandBuffer, 311bf215546Sopenharmony_ci const struct vk_device_dispatch_table *disp) 312bf215546Sopenharmony_ci{ 313bf215546Sopenharmony_ci list_for_each_entry(struct vk_cmd_queue_entry, cmd, &queue->cmds, cmd_link) { 314bf215546Sopenharmony_ci switch (cmd->type) { 315bf215546Sopenharmony_ci% for c in commands: 316bf215546Sopenharmony_ci% if c.guard is not None: 317bf215546Sopenharmony_ci#ifdef ${c.guard} 318bf215546Sopenharmony_ci% endif 319bf215546Sopenharmony_ci case ${to_enum_name(c.name)}: 320bf215546Sopenharmony_ci disp->${c.name}(commandBuffer 321bf215546Sopenharmony_ci% for p in c.params[1:]: 322bf215546Sopenharmony_ci , cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}\\ 323bf215546Sopenharmony_ci% endfor 324bf215546Sopenharmony_ci ); 325bf215546Sopenharmony_ci break; 326bf215546Sopenharmony_ci% if c.guard is not None: 327bf215546Sopenharmony_ci#endif // ${c.guard} 328bf215546Sopenharmony_ci% endif 329bf215546Sopenharmony_ci% endfor 330bf215546Sopenharmony_ci default: unreachable("Unsupported command"); 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci% for c in commands: 336bf215546Sopenharmony_ci% if c.name in no_enqueue_commands: 337bf215546Sopenharmony_ci/* TODO: Generate vk_cmd_enqueue_${c.name}() */ 338bf215546Sopenharmony_ci<% continue %> 339bf215546Sopenharmony_ci% endif 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci% if c.guard is not None: 342bf215546Sopenharmony_ci#ifdef ${c.guard} 343bf215546Sopenharmony_ci% endif 344bf215546Sopenharmony_ci<% assert c.return_type == 'void' %> 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci% if c.name in manual_commands: 347bf215546Sopenharmony_ci/* vk_cmd_enqueue_${c.name}() is hand-typed in vk_cmd_enqueue.c */ 348bf215546Sopenharmony_ci% else: 349bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 350bf215546Sopenharmony_civk_cmd_enqueue_${c.name}(${c.decl_params()}) 351bf215546Sopenharmony_ci{ 352bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci% if len(c.params) == 1: 355bf215546Sopenharmony_ci vk_enqueue_${to_underscore(c.name)}(&cmd_buffer->cmd_queue); 356bf215546Sopenharmony_ci% else: 357bf215546Sopenharmony_ci vk_enqueue_${to_underscore(c.name)}(&cmd_buffer->cmd_queue, 358bf215546Sopenharmony_ci ${c.call_params(1)}); 359bf215546Sopenharmony_ci% endif 360bf215546Sopenharmony_ci} 361bf215546Sopenharmony_ci% endif 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 364bf215546Sopenharmony_civk_cmd_enqueue_unless_primary_${c.name}(${c.decl_params()}) 365bf215546Sopenharmony_ci{ 366bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 369bf215546Sopenharmony_ci const struct vk_device_dispatch_table *disp = 370bf215546Sopenharmony_ci cmd_buffer->base.device->command_dispatch_table; 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci disp->${c.name}(${c.call_params()}); 373bf215546Sopenharmony_ci } else { 374bf215546Sopenharmony_ci vk_cmd_enqueue_${c.name}(${c.call_params()}); 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci} 377bf215546Sopenharmony_ci% if c.guard is not None: 378bf215546Sopenharmony_ci#endif // ${c.guard} 379bf215546Sopenharmony_ci% endif 380bf215546Sopenharmony_ci% endfor 381bf215546Sopenharmony_ci""", output_encoding='utf-8') 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_cidef remove_prefix(text, prefix): 384bf215546Sopenharmony_ci if text.startswith(prefix): 385bf215546Sopenharmony_ci return text[len(prefix):] 386bf215546Sopenharmony_ci return text 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_cidef remove_suffix(text, suffix): 389bf215546Sopenharmony_ci if text.endswith(suffix): 390bf215546Sopenharmony_ci return text[:-len(suffix)] 391bf215546Sopenharmony_ci return text 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_cidef to_underscore(name): 394bf215546Sopenharmony_ci return remove_prefix(re.sub('([A-Z]+)', r'_\1', name).lower(), '_') 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_cidef to_struct_field_name(name): 397bf215546Sopenharmony_ci return to_underscore(name).replace('cmd_', '') 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_cidef to_field_name(name): 400bf215546Sopenharmony_ci return remove_prefix(to_underscore(name).replace('cmd_', ''), 'p_') 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_cidef to_field_decl(decl): 403bf215546Sopenharmony_ci if 'const*' in decl: 404bf215546Sopenharmony_ci decl = decl.replace('const*', '*') 405bf215546Sopenharmony_ci else: 406bf215546Sopenharmony_ci decl = decl.replace('const ', '') 407bf215546Sopenharmony_ci [decl, name] = decl.rsplit(' ', 1) 408bf215546Sopenharmony_ci return decl + ' ' + to_field_name(name) 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_cidef to_enum_name(name): 411bf215546Sopenharmony_ci return "VK_%s" % to_underscore(name).upper() 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_cidef to_struct_name(name): 414bf215546Sopenharmony_ci return "vk_%s" % to_underscore(name) 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_cidef get_array_len(param): 417bf215546Sopenharmony_ci return param.decl[param.decl.find("[") + 1:param.decl.find("]")] 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_cidef get_array_copy(command, param): 420bf215546Sopenharmony_ci field_name = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name)) 421bf215546Sopenharmony_ci if param.type == "void": 422bf215546Sopenharmony_ci field_size = "1" 423bf215546Sopenharmony_ci else: 424bf215546Sopenharmony_ci field_size = "sizeof(*%s)" % field_name 425bf215546Sopenharmony_ci allocation = "%s = vk_zalloc(queue->alloc, %s * %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n if (%s == NULL) goto err;\n" % (field_name, field_size, param.len, field_name) 426bf215546Sopenharmony_ci const_cast = remove_suffix(param.decl.replace("const", ""), param.name) 427bf215546Sopenharmony_ci copy = "memcpy((%s)%s, %s, %s * %s);" % (const_cast, field_name, param.name, field_size, param.len) 428bf215546Sopenharmony_ci return "%s\n %s" % (allocation, copy) 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_cidef get_array_member_copy(struct, src_name, member): 431bf215546Sopenharmony_ci field_name = "%s->%s" % (struct, member.name) 432bf215546Sopenharmony_ci if member.len == "struct-ptr": 433bf215546Sopenharmony_ci field_size = "sizeof(*%s)" % (field_name) 434bf215546Sopenharmony_ci else: 435bf215546Sopenharmony_ci field_size = "sizeof(*%s) * %s->%s" % (field_name, struct, member.len) 436bf215546Sopenharmony_ci allocation = "%s = vk_zalloc(queue->alloc, %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n if (%s == NULL) goto err;\n" % (field_name, field_size, field_name) 437bf215546Sopenharmony_ci const_cast = remove_suffix(member.decl.replace("const", ""), member.name) 438bf215546Sopenharmony_ci copy = "memcpy((%s)%s, %s->%s, %s);" % (const_cast, field_name, src_name, member.name, field_size) 439bf215546Sopenharmony_ci return "if (%s->%s) {\n %s\n %s\n}\n" % (src_name, member.name, allocation, copy) 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_cidef get_pnext_member_copy(struct, src_type, member, types, level): 442bf215546Sopenharmony_ci if not types[src_type].extended_by: 443bf215546Sopenharmony_ci return "" 444bf215546Sopenharmony_ci field_name = "%s->%s" % (struct, member.name) 445bf215546Sopenharmony_ci pnext_decl = "const VkBaseInStructure *pnext = %s;" % field_name 446bf215546Sopenharmony_ci case_stmts = "" 447bf215546Sopenharmony_ci for type in types[src_type].extended_by: 448bf215546Sopenharmony_ci case_stmts += """ 449bf215546Sopenharmony_ci case %s: 450bf215546Sopenharmony_ci %s 451bf215546Sopenharmony_ci break; 452bf215546Sopenharmony_ci """ % (type.enum, get_struct_copy(field_name, "pnext", type.name, "sizeof(%s)" % type.name, types, level)) 453bf215546Sopenharmony_ci return """ 454bf215546Sopenharmony_ci %s 455bf215546Sopenharmony_ci if (pnext) { 456bf215546Sopenharmony_ci switch ((int32_t)pnext->sType) { 457bf215546Sopenharmony_ci %s 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci """ % (pnext_decl, case_stmts) 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_cidef get_struct_copy(dst, src_name, src_type, size, types, level=0): 463bf215546Sopenharmony_ci global tmp_dst_idx 464bf215546Sopenharmony_ci global tmp_src_idx 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci allocation = "%s = vk_zalloc(queue->alloc, %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n if (%s == NULL) goto err;\n" % (dst, size, dst) 467bf215546Sopenharmony_ci copy = "memcpy((void*)%s, %s, %s);" % (dst, src_name, size) 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci level += 1 470bf215546Sopenharmony_ci tmp_dst = "%s *tmp_dst%d = (void *) %s; (void) tmp_dst%d;" % (src_type, level, dst, level) 471bf215546Sopenharmony_ci tmp_src = "%s *tmp_src%d = (void *) %s; (void) tmp_src%d;" % (src_type, level, src_name, level) 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci member_copies = "" 474bf215546Sopenharmony_ci if src_type in types: 475bf215546Sopenharmony_ci for member in types[src_type].members: 476bf215546Sopenharmony_ci if member.len and member.len != 'null-terminated': 477bf215546Sopenharmony_ci member_copies += get_array_member_copy("tmp_dst%d" % level, "tmp_src%d" % level, member) 478bf215546Sopenharmony_ci elif member.name == 'pNext': 479bf215546Sopenharmony_ci member_copies += get_pnext_member_copy("tmp_dst%d" % level, src_type, member, types, level) 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci null_assignment = "%s = NULL;" % dst 482bf215546Sopenharmony_ci if_stmt = "if (%s) {" % src_name 483bf215546Sopenharmony_ci return "%s\n %s\n %s\n %s\n %s \n %s } else {\n %s\n }" % (if_stmt, allocation, copy, tmp_dst, tmp_src, member_copies, null_assignment) 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_cidef get_struct_free(command, param, types): 486bf215546Sopenharmony_ci field_name = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name)) 487bf215546Sopenharmony_ci const_cast = remove_suffix(param.decl.replace("const", ""), param.name) 488bf215546Sopenharmony_ci struct_free = "vk_free(queue->alloc, (%s)%s);" % (const_cast, field_name) 489bf215546Sopenharmony_ci member_frees = "" 490bf215546Sopenharmony_ci if (param.type in types): 491bf215546Sopenharmony_ci for member in types[param.type].members: 492bf215546Sopenharmony_ci if member.len and member.len != 'null-terminated': 493bf215546Sopenharmony_ci member_name = "cmd->u.%s.%s->%s" % (to_struct_field_name(command.name), to_field_name(param.name), member.name) 494bf215546Sopenharmony_ci const_cast = remove_suffix(member.decl.replace("const", ""), member.name) 495bf215546Sopenharmony_ci member_frees += "vk_free(queue->alloc, (%s)%s);\n" % (const_cast, member_name) 496bf215546Sopenharmony_ci return "%s %s\n" % (member_frees, struct_free) 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ciEntrypointType = namedtuple('EntrypointType', 'name enum members extended_by') 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_cidef get_types(doc): 501bf215546Sopenharmony_ci """Extract the types from the registry.""" 502bf215546Sopenharmony_ci types = {} 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci for _type in doc.findall('./types/type'): 505bf215546Sopenharmony_ci if _type.attrib.get('category') != 'struct': 506bf215546Sopenharmony_ci continue 507bf215546Sopenharmony_ci members = [] 508bf215546Sopenharmony_ci type_enum = None 509bf215546Sopenharmony_ci for p in _type.findall('./member'): 510bf215546Sopenharmony_ci mem_type = p.find('./type').text 511bf215546Sopenharmony_ci mem_name = p.find('./name').text 512bf215546Sopenharmony_ci mem_decl = ''.join(p.itertext()) 513bf215546Sopenharmony_ci mem_len = p.attrib.get('len', None) 514bf215546Sopenharmony_ci if mem_len is None and '*' in mem_decl and mem_name != 'pNext': 515bf215546Sopenharmony_ci mem_len = "struct-ptr" 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci member = EntrypointParam(type=mem_type, 518bf215546Sopenharmony_ci name=mem_name, 519bf215546Sopenharmony_ci decl=mem_decl, 520bf215546Sopenharmony_ci len=mem_len) 521bf215546Sopenharmony_ci members.append(member) 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci if mem_name == 'sType': 524bf215546Sopenharmony_ci type_enum = p.attrib.get('values') 525bf215546Sopenharmony_ci types[_type.attrib['name']] = EntrypointType(name=_type.attrib['name'], enum=type_enum, members=members, extended_by=[]) 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci for _type in doc.findall('./types/type'): 528bf215546Sopenharmony_ci if _type.attrib.get('category') != 'struct': 529bf215546Sopenharmony_ci continue 530bf215546Sopenharmony_ci if _type.attrib.get('structextends') is None: 531bf215546Sopenharmony_ci continue 532bf215546Sopenharmony_ci for extended in _type.attrib.get('structextends').split(','): 533bf215546Sopenharmony_ci types[extended].extended_by.append(types[_type.attrib['name']]) 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci return types 536bf215546Sopenharmony_ci 537bf215546Sopenharmony_cidef get_types_from_xml(xml_files): 538bf215546Sopenharmony_ci types = {} 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci for filename in xml_files: 541bf215546Sopenharmony_ci doc = et.parse(filename) 542bf215546Sopenharmony_ci types.update(get_types(doc)) 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci return types 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_cidef main(): 547bf215546Sopenharmony_ci parser = argparse.ArgumentParser() 548bf215546Sopenharmony_ci parser.add_argument('--out-c', required=True, help='Output C file.') 549bf215546Sopenharmony_ci parser.add_argument('--out-h', required=True, help='Output H file.') 550bf215546Sopenharmony_ci parser.add_argument('--xml', 551bf215546Sopenharmony_ci help='Vulkan API XML file.', 552bf215546Sopenharmony_ci required=True, action='append', dest='xml_files') 553bf215546Sopenharmony_ci args = parser.parse_args() 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci commands = [] 556bf215546Sopenharmony_ci for e in get_entrypoints_from_xml(args.xml_files): 557bf215546Sopenharmony_ci if e.name.startswith('Cmd') and \ 558bf215546Sopenharmony_ci not e.alias: 559bf215546Sopenharmony_ci commands.append(e) 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci types = get_types_from_xml(args.xml_files) 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h) 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci environment = { 566bf215546Sopenharmony_ci 'header': os.path.basename(args.out_h), 567bf215546Sopenharmony_ci 'commands': commands, 568bf215546Sopenharmony_ci 'filename': os.path.basename(__file__), 569bf215546Sopenharmony_ci 'to_underscore': to_underscore, 570bf215546Sopenharmony_ci 'get_array_len': get_array_len, 571bf215546Sopenharmony_ci 'to_struct_field_name': to_struct_field_name, 572bf215546Sopenharmony_ci 'to_field_name': to_field_name, 573bf215546Sopenharmony_ci 'to_field_decl': to_field_decl, 574bf215546Sopenharmony_ci 'to_enum_name': to_enum_name, 575bf215546Sopenharmony_ci 'to_struct_name': to_struct_name, 576bf215546Sopenharmony_ci 'get_array_copy': get_array_copy, 577bf215546Sopenharmony_ci 'get_struct_copy': get_struct_copy, 578bf215546Sopenharmony_ci 'get_struct_free': get_struct_free, 579bf215546Sopenharmony_ci 'types': types, 580bf215546Sopenharmony_ci 'manual_commands': MANUAL_COMMANDS, 581bf215546Sopenharmony_ci 'no_enqueue_commands': NO_ENQUEUE_COMMANDS, 582bf215546Sopenharmony_ci 'remove_suffix': remove_suffix, 583bf215546Sopenharmony_ci } 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci try: 586bf215546Sopenharmony_ci with open(args.out_h, 'wb') as f: 587bf215546Sopenharmony_ci guard = os.path.basename(args.out_h).replace('.', '_').upper() 588bf215546Sopenharmony_ci f.write(TEMPLATE_H.render(guard=guard, **environment)) 589bf215546Sopenharmony_ci with open(args.out_c, 'wb') as f: 590bf215546Sopenharmony_ci f.write(TEMPLATE_C.render(**environment)) 591bf215546Sopenharmony_ci except Exception: 592bf215546Sopenharmony_ci # In the event there's an error, this imports some helpers from mako 593bf215546Sopenharmony_ci # to print a useful stack trace and prints it, then exits with 594bf215546Sopenharmony_ci # status 1, if python is run with debug; otherwise it just raises 595bf215546Sopenharmony_ci # the exception 596bf215546Sopenharmony_ci import sys 597bf215546Sopenharmony_ci from mako import exceptions 598bf215546Sopenharmony_ci print(exceptions.text_error_template().render(), file=sys.stderr) 599bf215546Sopenharmony_ci sys.exit(1) 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ciif __name__ == '__main__': 602bf215546Sopenharmony_ci main() 603