vk/util: Generate defines to help casting structs with vk_find_struct
authorDanylo Piliaiev <dpiliaiev@igalia.com>
Tue, 14 Mar 2023 13:44:17 +0000 (14:44 +0100)
committerMarge Bot <emma+marge@anholt.net>
Fri, 24 Mar 2023 15:49:25 +0000 (15:49 +0000)
C++ doesn't like implicit casts from void *.

Signed-off-by: Danylo Piliaiev <dpiliaiev@igalia.com>
Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21931>

src/vulkan/runtime/vk_render_pass.h
src/vulkan/util/meson.build
src/vulkan/util/vk_struct_type_cast_gen.py [new file with mode: 0644]
src/vulkan/util/vk_util.h
src/vulkan/wsi/wsi_common.h

index e041f44..36e5d02 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 typedef struct VkRenderingSelfDependencyInfoMESA {
     VkStructureType    sType;
 #define VK_STRUCTURE_TYPE_RENDERING_SELF_DEPENDENCY_INFO_MESA (VkStructureType)1000044900
+#define VK_STRUCTURE_TYPE_RENDERING_SELF_DEPENDENCY_INFO_MESA_cast VkRenderingSelfDependencyInfoMESA
     const void*        pNext;
 
     /** Bitset of which color attachments have self-dependencies */
@@ -73,6 +74,7 @@ typedef struct VkRenderingSelfDependencyInfoMESA {
 typedef struct VkRenderingAttachmentInitialLayoutInfoMESA {
     VkStructureType    sType;
 #define VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA (VkStructureType)1000044901
+#define VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INITIAL_LAYOUT_INFO_MESA_cast VkRenderingAttachmentInitialLayoutInfoMESA
     const void*        pNext;
 
     /** Initial layout of the attachment */
index 589b4f9..9d12380 100644 (file)
@@ -86,6 +86,16 @@ vk_enum_to_str = custom_target(
   ],
 )
 
+vk_struct_type_cast = custom_target(
+  'vk_struct_type_cast',
+  input : ['vk_struct_type_cast_gen.py', vk_api_xml],
+  output : ['vk_struct_type_cast.h'],
+  command : [
+    prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+    '--outdir', meson.current_build_dir()
+  ],
+)
+
 vk_extensions = custom_target(
   'vk_extensions',
   input : ['vk_extensions_gen.py', vk_api_xml],
@@ -99,7 +109,8 @@ vk_extensions = custom_target(
 
 libvulkan_util = static_library(
   'vulkan_util',
-  [files_vulkan_util, vk_dispatch_table, vk_enum_to_str, vk_extensions],
+  [files_vulkan_util, vk_dispatch_table, vk_enum_to_str,
+   vk_struct_type_cast, vk_extensions],
   include_directories : [inc_include, inc_src, inc_gallium],
   dependencies : [vulkan_wsi_deps, idep_mesautil, idep_nir_headers],
   c_args : [c_msvc_compat_args],
@@ -108,7 +119,8 @@ libvulkan_util = static_library(
 )
 
 idep_vulkan_util_headers = declare_dependency(
-  sources : [vk_dispatch_table[1], vk_enum_to_str[1], vk_extensions[1]],
+  sources : [vk_dispatch_table[1], vk_enum_to_str[1],
+             vk_struct_type_cast[0], vk_extensions[1]],
   include_directories : include_directories('.')
 )
 
diff --git a/src/vulkan/util/vk_struct_type_cast_gen.py b/src/vulkan/util/vk_struct_type_cast_gen.py
new file mode 100644 (file)
index 0000000..b5df181
--- /dev/null
@@ -0,0 +1,115 @@
+# Copyright © 2023 Igalia S.L.
+# SPDX-License-Identifier: MIT
+
+"""Create shortcuts for casting Vulkan structs when knowing their stype."""
+
+import argparse
+import functools
+import os
+import re
+import textwrap
+import xml.etree.ElementTree as et
+
+from mako.template import Template
+from vk_extensions import Extension, filter_api, get_all_required
+
+COPYRIGHT = textwrap.dedent(u"""\
+     * Copyright © 2023 Igalia S.L.
+     * SPDX-License-Identifier: MIT
+     """)
+
+H_TEMPLATE = Template(textwrap.dedent(u"""\
+    /* Autogenerated file -- do not edit
+     * generated by ${file}
+     *
+     ${copyright}
+     */
+
+    #ifndef MESA_VK_STRUCT_CASTS_H
+    #define MESA_VK_STRUCT_CASTS_H
+
+    #include <vulkan/vulkan.h>
+
+    #ifdef __cplusplus
+    extern "C" {
+    #endif
+
+    % for s in structs:
+    #define ${s.stype}_cast ${s.name}
+    % endfor
+
+    #ifdef __cplusplus
+    } /* extern "C" */
+    #endif
+
+    #endif"""))
+
+
+class VkStruct(object):
+    """Simple struct-like class representing a single Vulkan struct identified with a VkStructureType"""
+    def __init__(self, name, stype):
+        self.name = name
+        self.stype = stype
+
+
+def struct_get_stype(xml_node):
+    for member in xml_node.findall('./member'):
+        name = member.findall('./name')
+        if len(name) > 0 and name[0].text == "sType":
+            return member.get('values')
+    return None
+
+
+def parse_xml(filename, structs):
+    xml = et.parse(filename)
+    api = 'vulkan'
+
+    required_types = get_all_required(xml, 'type', api)
+
+    for struct_type in xml.findall('./types/type[@category="struct"]'):
+        if not filter_api(struct_type, api):
+            continue
+
+        name = struct_type.attrib['name']
+        if name not in required_types:
+            continue
+
+        stype = struct_get_stype(struct_type)
+        if stype is not None:
+            structs.append(VkStruct(name, stype))
+
+    for struct_type in xml.findall('.//enum[@alias][@extends=\'VkStructureType\']'):
+        name = struct_type.attrib['name']
+        alias = struct_type.attrib['alias']
+        structs.append(VkStruct(alias + "_cast", name))
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--xml', required=True,
+                        help='Vulkan API XML files',
+                        action='append',
+                        dest='xml_files')
+    parser.add_argument('--outdir',
+                        help='Directory to put the generated files in',
+                        required=True)
+
+    args = parser.parse_args()
+
+    structs = []
+
+    for filename in args.xml_files:
+        parse_xml(filename, structs)
+
+    structs = sorted(structs, key=lambda s: s.name)
+
+    for template, file_ in [(H_TEMPLATE, os.path.join(args.outdir, 'vk_struct_type_cast.h'))]:
+        with open(file_, 'w', encoding='utf-8') as f:
+            f.write(template.render(
+                file=os.path.basename(__file__),
+                structs=structs,
+                copyright=COPYRIGHT))
+
+
+if __name__ == '__main__':
+    main()
index 77dfa29..b1a65c1 100644 (file)
@@ -29,6 +29,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "vk_struct_type_cast.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -269,11 +271,13 @@ __vk_find_struct(void *start, VkStructureType sType)
    return NULL;
 }
 
-#define vk_find_struct(__start, __sType) \
-   __vk_find_struct((__start), VK_STRUCTURE_TYPE_##__sType)
+#define vk_find_struct(__start, __sType)                                       \
+  (VK_STRUCTURE_TYPE_##__sType##_cast *)__vk_find_struct(                      \
+      (__start), VK_STRUCTURE_TYPE_##__sType)
 
-#define vk_find_struct_const(__start, __sType) \
-   (const void *)__vk_find_struct((void *)(__start), VK_STRUCTURE_TYPE_##__sType)
+#define vk_find_struct_const(__start, __sType)                                 \
+  (const VK_STRUCTURE_TYPE_##__sType##_cast *)__vk_find_struct(                \
+      (void *)(__start), VK_STRUCTURE_TYPE_##__sType)
 
 static inline void
 __vk_append_struct(void *start, void *element)
index 8a8138e..3460256 100644 (file)
@@ -51,6 +51,11 @@ extern const struct vk_device_entrypoint_table wsi_device_entrypoints;
 #define VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA (VkStructureType)1000001005
 #define VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA (VkStructureType)1000001006
 
+#define VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA_cast struct wsi_image_create_info
+#define VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA_cast struct wsi_memory_allocate_info
+#define VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA_cast struct wsi_surface_supported_counters
+#define VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA_cast struct wsi_memory_signal_submit_info
+
 /* This is always chained to VkImageCreateInfo when a wsi image is created.
  * It indicates that the image can be transitioned to/from
  * VK_IMAGE_LAYOUT_PRESENT_SRC_KHR.