RetroArch/tools/vulkan_loader_generator.py
Hans-Kristian Arntzen 54c1759f45 Vulkan: Make a more general purpose symbol loader.
Avoids painful manual loading and wrapping function pointers everywhere
...

Reusable for cores, so move to libretro-common.
Also update built-in Vulkan headers.
2016-06-26 13:10:58 +02:00

175 lines
6.7 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import re
def entry_is_device(entry):
first_arg_type = entry[1][1:].split(' ')[0]
device_types = ['VkDevice', 'VkCommandBuffer', 'VkQueue']
return (first_arg_type in device_types) and (entry[0] != 'vkGetDeviceProcAddr')
def main():
pure_entrypoints = []
entrypoints = []
extensions = []
pure_list = ['vkCreateInstance', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateInstanceLayerProperties']
with open(sys.argv[1], 'r') as f:
header = f.readlines()
for line in header:
m = re.search('typedef \S+.*PFN_([^\)]+)\)(.*);$', line)
if m and m.group(1)[-3:] != 'KHR' and m.group(1)[-3:] != 'EXT' and m.group(2) != '(void)':
entry = m.group(1)
if entry == 'vkGetInstanceProcAddr':
continue
if entry in pure_list:
pure_entrypoints.append((m.group(1), m.group(2)))
else:
entrypoints.append((m.group(1), m.group(2)))
elif m and (m.group(1)[-3:] == 'KHR' or m.group(1)[-3:] == 'EXT') and m.group(2) != '(void)':
entry = m.group(1)
if 'Android' in entry:
continue
if 'Xlib' in entry:
continue
if 'Xcb' in entry:
continue
if 'Win32' in entry:
continue
if 'Wayland' in entry:
continue
if 'Mir' in entry:
continue
extensions.append((m.group(1), m.group(2)))
with open(sys.argv[2], 'w') as f:
print('''
/* This header is autogenerated by vulkan_loader_generator.py */
#ifndef VULKAN_SYMBOL_WRAPPER_H
#define VULKAN_SYMBOL_WRAPPER_H
#define VK_NO_PROTOTYPES
#include <vulkan/vulkan.h>
#ifdef __cplusplus
extern "C" {
#endif
''', file = f)
for entry in pure_entrypoints:
s = entry[0]
print('extern PFN_{} vulkan_symbol_wrapper_{};'.format(s, s), file = f)
print('#define {} vulkan_symbol_wrapper_{}'.format(s, s), file = f)
for entry in entrypoints:
s = entry[0]
print('extern PFN_{} vulkan_symbol_wrapper_{};'.format(s, s), file = f)
print('#define {} vulkan_symbol_wrapper_{}'.format(s, s), file = f)
for entry in extensions:
s = entry[0]
print('extern PFN_{} vulkan_symbol_wrapper_{};'.format(s, s), file = f)
print('#define {} vulkan_symbol_wrapper_{}'.format(s, s), file = f)
print('''
void vulkan_symbol_wrapper_init(PFN_vkGetInstanceProcAddr get_instance_proc_addr);
PFN_vkGetInstanceProcAddr vulkan_symbol_wrapper_instance_proc_addr(void);
VkBool32 vulkan_symbol_wrapper_load_global_symbols(void);
VkBool32 vulkan_symbol_wrapper_load_core_instance_symbols(VkInstance instance);
VkBool32 vulkan_symbol_wrapper_load_core_symbols(VkInstance instance);
VkBool32 vulkan_symbol_wrapper_load_core_device_symbols(VkDevice device);
VkBool32 vulkan_symbol_wrapper_load_instance_symbol(VkInstance instance, const char *name, PFN_vkVoidFunction *ppSymbol);
VkBool32 vulkan_symbol_wrapper_load_device_symbol(VkDevice device, const char *name, PFN_vkVoidFunction *ppSymbol);
#define VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, name, pfn) vulkan_symbol_wrapper_load_instance_symbol(instance, name, (PFN_vkVoidFunction*) &(pfn))
#define VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_EXTENSION_SYMBOL(instance, name) vulkan_symbol_wrapper_load_instance_symbol(instance, #name, (PFN_vkVoidFunction*) & name)
#define VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, name, pfn) vulkan_symbol_wrapper_load_device_symbol(device, name, (PFN_vkVoidFunction*) &(pfn))
#define VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_EXTENSION_SYMBOL(device, name) vulkan_symbol_wrapper_load_device_symbol(device, #name, (PFN_vkVoidFunction*) & name)
''', file = f)
print('''
#ifdef __cplusplus
}
#endif
#endif
''', file = f)
with open(sys.argv[3], 'w') as f:
print('''
/* This header is autogenerated by vulkan_loader_generator.py */
#include "vulkan_symbol_wrapper.h"
''', file = f)
for entry in pure_entrypoints:
s = entry[0]
print('PFN_{} vulkan_symbol_wrapper_{};'.format(s, s), file = f)
for entry in entrypoints:
s = entry[0]
print('PFN_{} vulkan_symbol_wrapper_{};'.format(s, s), file = f)
for entry in extensions:
s = entry[0]
print('PFN_{} vulkan_symbol_wrapper_{};'.format(s, s), file = f)
print('''
static PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
void vulkan_symbol_wrapper_init(PFN_vkGetInstanceProcAddr get_instance_proc_addr)
{
GetInstanceProcAddr = get_instance_proc_addr;
}
PFN_vkGetInstanceProcAddr vulkan_symbol_wrapper_instance_proc_addr(void)
{
return GetInstanceProcAddr;
}
''', file = f)
print('''
VkBool32 vulkan_symbol_wrapper_load_instance_symbol(VkInstance instance, const char *name, PFN_vkVoidFunction *ppSymbol)
{
*ppSymbol = GetInstanceProcAddr(instance, name);
return *ppSymbol != NULL;
}''', file = f)
print('''
VkBool32 vulkan_symbol_wrapper_load_device_symbol(VkDevice device, const char *name, PFN_vkVoidFunction *ppSymbol)
{
*ppSymbol = vkGetDeviceProcAddr(device, name);
return *ppSymbol != NULL;
}''', file = f)
print('''
VkBool32 vulkan_symbol_wrapper_load_global_symbols(void)
{''', file = f)
for pure in pure_entrypoints:
print(' if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(NULL, "{}", {})) return VK_FALSE;'.format(pure[0], pure[0]), file = f)
print(' return VK_TRUE;', file = f)
print('}', file = f)
print('''
VkBool32 vulkan_symbol_wrapper_load_core_symbols(VkInstance instance)
{''', file = f)
for entry in entrypoints:
print(' if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "{}", {})) return VK_FALSE;'.format(entry[0], entry[0]), file = f)
print(' return VK_TRUE;', file = f)
print('}', file = f)
print('''
VkBool32 vulkan_symbol_wrapper_load_core_instance_symbols(VkInstance instance)
{''', file = f)
for entry in entrypoints:
if not entry_is_device(entry):
print(' if (!VULKAN_SYMBOL_WRAPPER_LOAD_INSTANCE_SYMBOL(instance, "{}", {})) return VK_FALSE;'.format(entry[0], entry[0]), file = f)
print(' return VK_TRUE;', file = f)
print('}', file = f)
print('''
VkBool32 vulkan_symbol_wrapper_load_core_device_symbols(VkDevice device)
{''', file = f)
for entry in entrypoints:
if entry_is_device(entry):
print(' if (!VULKAN_SYMBOL_WRAPPER_LOAD_DEVICE_SYMBOL(device, "{}", {})) return VK_FALSE;'.format(entry[0], entry[0]), file = f)
print(' return VK_TRUE;', file = f)
print('}', file = f)
if __name__ == '__main__':
main()