vk/entry_points: Add option to generate template entrypoints
authorDanylo Piliaiev <dpiliaiev@igalia.com>
Thu, 9 Mar 2023 18:56:43 +0000 (19:56 +0100)
committerMarge Bot <emma+marge@anholt.net>
Fri, 24 Mar 2023 15:49:26 +0000 (15:49 +0000)
As a C++ alternative to genX macros.

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/util/vk_entrypoints_gen.py

index 6763f1c..2ec13a0 100644 (file)
@@ -36,12 +36,25 @@ TEMPLATE_H = Template(COPYRIGHT + """\
 
 #include "vk_dispatch_table.h"
 
+% for i in includes:
+#include "${i}"
+% endfor
+
 #ifndef ${guard}
 #define ${guard}
 
+% if not tmpl_prefix:
 #ifdef __cplusplus
 extern "C" {
 #endif
+% endif
+
+/* clang wants function declarations in the header to have weak attribute */
+#ifndef _MSC_VER
+#define ATTR_WEAK __attribute__ ((weak))
+#else
+#define ATTR_WEAK
+#endif
 
 % for p in instance_prefixes:
 extern const struct vk_instance_entrypoint_table ${p}_instance_entrypoints;
@@ -55,6 +68,10 @@ extern const struct vk_physical_device_entrypoint_table ${p}_physical_device_ent
 extern const struct vk_device_entrypoint_table ${p}_device_entrypoints;
 % endfor
 
+% for v in tmpl_variants_sanitized:
+extern const struct vk_device_entrypoint_table ${tmpl_prefix}_device_entrypoints_${v};
+% endfor
+
 % if gen_proto:
 % for e in instance_entrypoints:
   % if e.guard is not None:
@@ -85,17 +102,28 @@ extern const struct vk_device_entrypoint_table ${p}_device_entrypoints;
 #ifdef ${e.guard}
   % endif
   % for p in device_prefixes:
-  VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()});
+  VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) ATTR_WEAK;
   % endfor
+
+  % if tmpl_prefix:
+  template <${tmpl_param}>
+  VKAPI_ATTR ${e.return_type} VKAPI_CALL ${tmpl_prefix}_${e.name}(${e.decl_params()});
+
+  #define ${tmpl_prefix}_${e.name}_GENS(X) \
+  template VKAPI_ATTR ${e.return_type} VKAPI_CALL ${tmpl_prefix}_${e.name}<X>(${e.decl_params()});
+  % endif
+
   % if e.guard is not None:
 #endif // ${e.guard}
   % endif
 % endfor
 % endif
 
+% if not tmpl_prefix:
 #ifdef __cplusplus
 }
 #endif
+% endif
 
 #endif /* ${guard} */
 """)
@@ -134,8 +162,16 @@ TEMPLATE_C = Template(COPYRIGHT + """
 #endif
 #else
     VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) __attribute__ ((weak));
+
+    % if entrypoints == device_entrypoints:
+      % for v in tmpl_variants:
+    extern template
+    VKAPI_ATTR __attribute__ ((weak)) ${e.return_type} VKAPI_CALL ${tmpl_prefix}_${e.name}${v}(${e.decl_params()});
+      % endfor
+    % endif
 #endif
     % endfor
+
     % if e.guard is not None:
 #endif // ${e.guard}
     % endif
@@ -157,6 +193,24 @@ const struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = {
   % endfor
 };
 % endfor
+
+% if entrypoints == device_entrypoints:
+% for v, entrypoint_v in zip(tmpl_variants, tmpl_variants_sanitized):
+const struct vk_${type}_entrypoint_table ${tmpl_prefix}_${type}_entrypoints_${entrypoint_v} = {
+  % for e in entrypoints:
+    % if e.guard is not None:
+#ifdef ${e.guard}
+    % endif
+    .${e.name} = ${tmpl_prefix}_${e.name}${v},
+    % if e.guard is not None:
+#elif defined(_MSC_VER)
+    .${e.name} = (PFN_vkVoidFunction)vk_entrypoint_stub,
+#endif // ${e.guard}
+    % endif
+  % endfor
+};
+% endfor
+% endif
 </%def>
 
 ${entrypoint_table('instance', instance_entrypoints, instance_prefixes)}
@@ -182,12 +236,27 @@ def main():
     parser.add_argument('--device-prefix',
                         help='Prefix to use for device dispatch tables.',
                         action='append', default=[], dest='device_prefixes')
+    parser.add_argument('--include',
+                        help='Includes to add to the H file.',
+                        action='append', default=[], dest='includes')
+    parser.add_argument('--tmpl-prefix',
+                        help='Prefix to use for templated device dispatch tables.',
+                        dest='tmpl_prefix')
+    parser.add_argument('--tmpl-param',
+                        help='Param to use for templated device dispatch tables.',
+                        dest='tmpl_param')
+    parser.add_argument('--tmpl-variants',
+                      help='All template specializations.',
+                      nargs='+', default=[], dest='tmpl_variants')
     args = parser.parse_args()
 
     instance_prefixes = args.prefixes
     physical_device_prefixes = args.prefixes
     device_prefixes = args.prefixes + args.device_prefixes
 
+    tmpl_variants_sanitized = [
+        ''.join(filter(str.isalnum, v)).lower() for v in args.tmpl_variants]
+
     entrypoints = get_entrypoints_from_xml(args.xml_files)
 
     device_entrypoints = []
@@ -213,6 +282,11 @@ def main():
         'physical_device_prefixes': physical_device_prefixes,
         'device_entrypoints': device_entrypoints,
         'device_prefixes': device_prefixes,
+        'includes': args.includes,
+        'tmpl_prefix': args.tmpl_prefix,
+        'tmpl_param': args.tmpl_param,
+        'tmpl_variants': args.tmpl_variants,
+        'tmpl_variants_sanitized': tmpl_variants_sanitized,
         'filename': os.path.basename(__file__),
     }