diff options
author | 2019-10-10 12:54:42 -0700 | |
---|---|---|
committer | 2019-10-11 15:16:16 -0700 | |
commit | 1ca59c17a05359a08f072bc10c54ea0ad67554f1 (patch) | |
tree | 2f2062243a8a9fc4d1221f61e9fa188cc325c96b | |
parent | dc792f55e03081d4356996d700dacda90eda8817 (diff) |
vulkan: clean up the framework generation script
1. Instead of mixing up all code formats, stick to pep8 and python style guide
2. Removed some redundant functions
3. Simplified seme code logic
4. Move constant codes back to main code gen blocks for readibility
5. Moved most of the hard-coded constants to the top
6. Removed a redundant clang format hint
7. Removed any mention of the legacy code gen stuff
Bug: 134185757
Test: ./scripts/code_generator.py && build
Change-Id: I1eca91fb0d181b7e8353c4c6a651d80ed1f2d1e0
-rw-r--r-- | vulkan/libvulkan/driver_gen.cpp | 2 | ||||
-rw-r--r-- | vulkan/scripts/api_generator.py | 466 | ||||
-rwxr-xr-x | vulkan/scripts/code_generator.py | 22 | ||||
-rw-r--r-- | vulkan/scripts/driver_generator.py | 608 | ||||
-rw-r--r-- | vulkan/scripts/generator_common.py | 301 | ||||
-rw-r--r-- | vulkan/scripts/null_generator.py | 159 |
6 files changed, 825 insertions, 733 deletions
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 272f2d1873..f676573de9 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -562,5 +562,3 @@ bool InitDriverTable(VkDevice dev, } // namespace driver } // namespace vulkan - -// clang-format on diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py index a0c648cc90..d1fff42125 100644 --- a/vulkan/scripts/api_generator.py +++ b/vulkan/scripts/api_generator.py @@ -20,21 +20,36 @@ import os import generator_common as gencom -def isInstanceDispatchTableEntry(functionName): - if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc - return False - if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName): - return True - return False +_INTERCEPTED_COMMANDS = [ + 'vkCreateDevice', + 'vkDestroyDevice', + 'vkDestroyInstance', + 'vkEnumerateDeviceExtensionProperties', + 'vkEnumerateDeviceLayerProperties', +] -def isDeviceDispatchTableEntry(functionName): - if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName): - return True - return False -def api_genh(): +def gen_h(): + genfile = os.path.join(os.path.dirname(__file__), + '..', 'libvulkan', 'api_gen.h') - header = """#ifndef LIBVULKAN_API_GEN_H + with open(genfile, 'w') as f: + instance_dispatch_table_entries = [] + device_dispatch_table_entries = [] + + for cmd in gencom.command_list: + if cmd not in gencom.alias_dict: + if gencom.is_instance_dispatch_table_entry(cmd): + instance_dispatch_table_entries.append( + 'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';') + elif gencom.is_device_dispatch_table_entry(cmd): + device_dispatch_table_entries.append( + 'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';') + + f.write(gencom.copyright_and_warning(2016)) + + f.write("""\ +#ifndef LIBVULKAN_API_GEN_H #define LIBVULKAN_API_GEN_H #include <vulkan/vulkan.h> @@ -46,9 +61,26 @@ def api_genh(): namespace vulkan { namespace api { -""" +struct InstanceDispatchTable { + // clang-format off\n""") + + for entry in instance_dispatch_table_entries: + f.write(gencom.indent(1) + entry + '\n') + + f.write("""\ + // clang-format on +}; + +struct DeviceDispatchTable { + // clang-format off\n""") + + for entry in device_dispatch_table_entries: + f.write(gencom.indent(1) + entry + '\n') + + f.write("""\ + // clang-format on +}; - tail = """ bool InitDispatchTable( VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, @@ -61,105 +93,54 @@ bool InitDispatchTable( } // namespace api } // namespace vulkan -#endif // LIBVULKAN_API_GEN_H -""" - genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h') - with open(genfile, 'w') as f: - instanceDispatchTableEntries = [] - deviceDispatchTableEntries = [] - for commands in gencom.allCommandsList: - if commands not in gencom.aliasDict: - if gencom.isInstanceDispatchTableEntry(commands): - instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';') - elif gencom.isDeviceDispatchTableEntry(commands): - deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';') - - f.write (gencom.copyright) - f.write (gencom.warning) - f.write (header) - f.write ('struct InstanceDispatchTable {\n') - gencom.clang_off(f,1) - for functions in instanceDispatchTableEntries: - f.write(gencom.clang_off_spaces + functions + '\n') - gencom.clang_on(f,1) - f.write ('};\n\n') - - f.write ('struct DeviceDispatchTable {\n') - gencom.clang_off(f,1) - for functions in deviceDispatchTableEntries: - f.write(gencom.clang_off_spaces + functions + '\n') - gencom.clang_on(f,1) - f.write ('};\n') - - f.write (tail) +#endif // LIBVULKAN_API_GEN_H\n""") + f.close() - gencom.runClangFormat(genfile) + gencom.run_clang_format(genfile) -def defineInitProc(name, f): - f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n') - f.write ('\n') - f.write ("""#define INIT_PROC(required, obj, proc) \\ - do { \\ - data.""" + name + """.proc = \\ - reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\ - if (UNLIKELY(required && !data.""" + name + """.proc)) { \\ - ALOGE("missing " #obj " proc: vk" #proc); \\ - success = false; \\ - } \\ - } while (0)\n\n""") -def defineInitProcExt(f): - f.write ('// Exported extension functions may be invoked even when their extensions\n') - f.write ('// are disabled. Dispatch to stubs when that happens.\n') - f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\ - do { \\ - if (extensions[driver::ProcHook::ext]) \\ - INIT_PROC(required, obj, proc); \\ - else \\ - data.dispatch.proc = disabled##proc; \\ - } while (0)\n\n""") - -def defineExtensionStub(functionName, f): - if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName): - extname = gencom.extensionsDict[functionName] - base_name = functionName[2:] - pList = gencom.paramDict[functionName] - firstParam = pList[0][0] + pList[0][1] - tailParams = [x[0][:-1] for x in pList[1:]] - tailP = ', '.join(tailParams) - f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n') - f.write (gencom.clang_off_spaces) - f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n') - if gencom.returnTypeDict[functionName] != 'void': - f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n') - f.write ('}\n\n') - -def isIntercepted(functionName): - if gencom.isFunctionSupported(functionName): - if gencom.isGloballyDispatched(functionName): - return True - elif functionName == 'vkCreateDevice': - return True - elif functionName == 'vkEnumerateDeviceLayerProperties': - return True - elif functionName == 'vkEnumerateDeviceExtensionProperties': - return True - elif functionName == 'vkDestroyInstance': - return True - elif functionName == 'vkDestroyDevice': +def _define_extension_stub(cmd, f): + if (cmd in gencom.extension_dict and gencom.is_function_exported(cmd)): + ext_name = gencom.extension_dict[cmd] + ret = gencom.return_type_dict[cmd] + params = gencom.param_dict[cmd] + first_param = params[0][0] + params[0][1] + tail_params = ', '.join([i[0][:-1] for i in params[1:]]) + + f.write('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) + + '(' + first_param + ', ' + tail_params + ') {\n') + + f.write(gencom.indent(1) + 'driver::Logger(' + params[0][1] + + ').Err(' + params[0][1] + ', \"' + ext_name + + ' not enabled. Exported ' + cmd + ' not executed.\");\n') + + if gencom.return_type_dict[cmd] != 'void': + f.write(gencom.indent(1) + 'return VK_SUCCESS;\n') + + f.write('}\n\n') + + +def _is_intercepted(cmd): + if gencom.is_function_supported(cmd): + if gencom.is_globally_dispatched(cmd) or cmd in _INTERCEPTED_COMMANDS: return True return False -def interceptInstanceProcAddr(functionName, f): - indent = 1 - f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n') - indent = indent + 1 - for cmds in gencom.allCommandsList: - if gencom.isGloballyDispatched(cmds): - f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n') - f.write ('\n') - f.write (""" ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName); +def _intercept_instance_proc_addr(f): + f.write("""\ + // global functions + if (instance == VK_NULL_HANDLE) {\n""") + + for cmd in gencom.command_list: + if gencom.is_globally_dispatched(cmd): + f.write(gencom.indent(2) + + 'if (strcmp(pName, \"' + cmd + + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + + gencom.base_name(cmd) + ');\n') + + f.write(""" + ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName); return nullptr; } @@ -167,14 +148,21 @@ def interceptInstanceProcAddr(functionName, f): const char* name; PFN_vkVoidFunction proc; } hooks[] = {\n""") - sortedCommandsList = sorted(gencom.allCommandsList) - for cmds in sortedCommandsList: - if gencom.isFunctionExported(cmds): - if gencom.isGloballyDispatched(cmds): - f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n') - elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds): - f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n') - f.write (gencom.clang_off_spaces + """}; + + sorted_command_list = sorted(gencom.command_list) + for cmd in sorted_command_list: + if gencom.is_function_exported(cmd): + if gencom.is_globally_dispatched(cmd): + f.write(gencom.indent(2) + '{ \"' + cmd + '\", nullptr },\n') + elif (_is_intercepted(cmd) or + cmd == 'vkGetInstanceProcAddr' or + gencom.is_device_dispatched(cmd)): + f.write(gencom.indent(2) + '{ \"' + cmd + + '\", reinterpret_cast<PFN_vkVoidFunction>(' + + gencom.base_name(cmd) + ') },\n') + + f.write("""\ + }; // clang-format on constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]); auto hook = std::lower_bound( @@ -190,19 +178,25 @@ def interceptInstanceProcAddr(functionName, f): } // clang-format off\n\n""") -def interceptDeviceProcAddr(functionName, f): - f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) { + +def _intercept_device_proc_addr(f): + f.write("""\ + if (device == VK_NULL_HANDLE) { ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call"); return nullptr; - }\n\n""") - f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n') - sortedCommandsList = sorted(gencom.allCommandsList) - for cmds in sortedCommandsList: - if gencom.isFunctionSupported(cmds): - if not gencom.isDeviceDispatched(cmds): - f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n') - f.write(gencom.clang_off_spaces + '};\n') - f.write(gencom.clang_off_spaces + """// clang-format on + } + + static const char* const known_non_device_names[] = {\n""") + + sorted_command_list = sorted(gencom.command_list) + for cmd in sorted_command_list: + if gencom.is_function_supported(cmd): + if not gencom.is_device_dispatched(cmd): + f.write(gencom.indent(2) + '\"' + cmd + '\",\n') + + f.write("""\ + }; + // clang-format on constexpr size_t count = sizeof(known_non_device_names) / sizeof(known_non_device_names[0]); if (!pName || @@ -215,27 +209,38 @@ def interceptDeviceProcAddr(functionName, f): return nullptr; } // clang-format off\n\n""") - for cmds in gencom.allCommandsList: - if gencom.isDeviceDispatched(cmds): - if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr': - f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n') - f.write ('\n') -def apiDispatch(functionName, f): - assert not isIntercepted(functionName) + for cmd in gencom.command_list: + if gencom.is_device_dispatched(cmd): + if _is_intercepted(cmd) or cmd == 'vkGetDeviceProcAddr': + f.write(gencom.indent(1) + 'if (strcmp(pName, "' + cmd + + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + + gencom.base_name(cmd) + ');\n') + f.write('\n') + - f.write (gencom.clang_off_spaces) - if gencom.returnTypeDict[functionName] != 'void': - f.write ('return ') +def _api_dispatch(cmd, f): + assert not _is_intercepted(cmd) - paramList = gencom.paramDict[functionName] - p0 = paramList[0][1] - f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n') + f.write(gencom.indent(1)) + if gencom.return_type_dict[cmd] != 'void': + f.write('return ') + param_list = gencom.param_dict[cmd] + handle = param_list[0][1] + f.write('GetData(' + handle + ').dispatch.' + gencom.base_name(cmd) + + '(' + ', '.join(i[1] for i in param_list) + ');\n') -def api_gencpp(): - genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp') - header = """#include <log/log.h> + +def gen_cpp(): + genfile = os.path.join(os.path.dirname(__file__), + '..', 'libvulkan', 'api_gen.cpp') + + with open(genfile, 'w') as f: + f.write(gencom.copyright_and_warning(2016)) + + f.write("""\ +#include <log/log.h> #include <string.h> #include <algorithm> @@ -247,80 +252,106 @@ def api_gencpp(): namespace vulkan { namespace api { -""" - with open(genfile, 'w') as f: - f.write (gencom.copyright) - f.write (gencom.warning) - f.write ("""#include <log/log.h> -#include <string.h> +#define UNLIKELY(expr) __builtin_expect((expr), 0) -#include <algorithm> +#define INIT_PROC(required, obj, proc) \\ + do { \\ + data.dispatch.proc = \\ + reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\ + if (UNLIKELY(required && !data.dispatch.proc)) { \\ + ALOGE("missing " #obj " proc: vk" #proc); \\ + success = false; \\ + } \\ + } while (0) -// to catch mismatches between vulkan.h and this file -#undef VK_NO_PROTOTYPES -#include "api.h" +// Exported extension functions may be invoked even when their extensions +// are disabled. Dispatch to stubs when that happens. +#define INIT_PROC_EXT(ext, required, obj, proc) \\ + do { \\ + if (extensions[driver::ProcHook::ext]) \\ + INIT_PROC(required, obj, proc); \\ + else \\ + data.dispatch.proc = disabled##proc; \\ + } while (0) -namespace vulkan { -namespace api {\n\n""") - defineInitProc('dispatch',f) - defineInitProcExt(f) - f.write ('namespace {\n\n') - gencom.clang_off(f,0) - f.write ('\n') - for cmds in gencom.allCommandsList: - defineExtensionStub(cmds,f) - gencom.clang_on(f,0) - f.write ('\n} // namespace\n\n') - f.write ("""bool InitDispatchTable( +namespace { + +// clang-format off\n\n""") + + for cmd in gencom.command_list: + _define_extension_stub(cmd, f) + + f.write("""\ +// clang-format on + +} // namespace + +bool InitDispatchTable( VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) { auto& data = GetData(instance); - bool success = true;\n\n""") - gencom.clang_off(f,1) - for cmds in gencom.allCommandsList: - if gencom.isInstanceDispatchTableEntry(cmds): - gencom.initProc(cmds, f) - gencom.clang_on(f,1) - f.write ('\n') - f.write (' return success;\n}\n\n') - f.write ("""bool InitDispatchTable( + bool success = true; + + // clang-format off\n""") + + for cmd in gencom.command_list: + if gencom.is_instance_dispatch_table_entry(cmd): + gencom.init_proc(cmd, f) + + f.write("""\ + // clang-format on + + return success; +} + +bool InitDispatchTable( VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) { auto& data = GetData(dev); - bool success = true;\n\n""") - - gencom.clang_off(f,1) - for cmds in gencom.allCommandsList: - if gencom.isDeviceDispatchTableEntry(cmds): - gencom.initProc(cmds, f) - gencom.clang_on(f,1) - f.write ('\n') - f.write (' return success;\n}\n\n') - - gencom.clang_off(f,0) - - f.write ('\nnamespace {\n\n') - f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n') - for cmds in gencom.allCommandsList: - if gencom.isFunctionExported(cmds) and not isIntercepted(cmds): - paramList = [''.join(i) for i in gencom.paramDict[cmds]] - f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n') - - f.write ('\n') - - for cmds in gencom.allCommandsList: - if gencom.isFunctionExported(cmds) and not isIntercepted(cmds): - paramList = [''.join(i) for i in gencom.paramDict[cmds]] - f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n') - if cmds == 'vkGetInstanceProcAddr': - interceptInstanceProcAddr(cmds, f) - elif cmds == 'vkGetDeviceProcAddr': - interceptDeviceProcAddr(cmds, f) - apiDispatch(cmds, f) + bool success = true; + + // clang-format off\n""") + + for cmd in gencom.command_list: + if gencom.is_device_dispatch_table_entry(cmd): + gencom.init_proc(cmd, f) + + f.write("""\ + // clang-format on + + return success; +} + +// clang-format off + +namespace { + +// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr +""") + + for cmd in gencom.command_list: + if gencom.is_function_exported(cmd) and not _is_intercepted(cmd): + param_list = [''.join(i) for i in gencom.param_dict[cmd]] + f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' + + gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n') + + f.write('\n') + for cmd in gencom.command_list: + if gencom.is_function_exported(cmd) and not _is_intercepted(cmd): + param_list = [''.join(i) for i in gencom.param_dict[cmd]] + f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' + + gencom.base_name(cmd) + '(' + ', '.join(param_list) + ') {\n') + if cmd == 'vkGetInstanceProcAddr': + _intercept_instance_proc_addr(f) + elif cmd == 'vkGetDeviceProcAddr': + _intercept_device_proc_addr(f) + _api_dispatch(cmd, f) f.write('}\n\n') - f.write ("""\n} // anonymous namespace + + f.write(""" +} // anonymous namespace // clang-format on @@ -329,18 +360,19 @@ namespace api {\n\n""") // clang-format off\n\n""") - for cmds in gencom.allCommandsList: - if gencom.isFunctionExported(cmds): - paramList = [''.join(i) for i in gencom.paramDict[cmds]] - f.write ('__attribute__((visibility("default")))\n') - f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n') - f.write (gencom.clang_off_spaces) - if gencom.returnTypeDict[cmds] != 'void': - f.write ('return ') - paramList = gencom.paramDict[cmds] - f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n') - f.write ('}\n\n') - - gencom.clang_on(f, 0) + for cmd in gencom.command_list: + if gencom.is_function_exported(cmd): + param_list = [''.join(i) for i in gencom.param_dict[cmd]] + f.write('__attribute__((visibility("default")))\n') + f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' + + cmd + '(' + ', '.join(param_list) + ') {\n') + f.write(gencom.indent(1)) + if gencom.return_type_dict[cmd] != 'void': + f.write('return ') + param_list = gencom.param_dict[cmd] + f.write('vulkan::api::' + gencom.base_name(cmd) + + '(' + ', '.join(i[1] for i in param_list) + ');\n}\n\n') + + f.write('// clang-format on\n') f.close() - gencom.runClangFormat(genfile) + gencom.run_clang_format(genfile) diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py index 39fedf4777..378a9c0e10 100755 --- a/vulkan/scripts/code_generator.py +++ b/vulkan/scripts/code_generator.py @@ -17,16 +17,16 @@ # This script provides the main function for generating # vulkan framework directly from the vulkan registry (vk.xml). -import generator_common as gencom -import api_generator as apigen -import driver_generator as drivergen -import null_generator as nullgen +import api_generator +import driver_generator +import generator_common +import null_generator if __name__ == '__main__': - gencom.parseVulkanRegistry() - apigen.api_genh() - apigen.api_gencpp() - drivergen.driver_genh() - drivergen.driver_gencpp() - nullgen.null_driver_genh() - nullgen.null_driver_gencpp() + generator_common.parse_vulkan_registry() + api_generator.gen_h() + api_generator.gen_cpp() + driver_generator.gen_h() + driver_generator.gen_cpp() + null_generator.gen_h() + null_generator.gen_cpp() diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py index 4868ac0bc9..5fff83efca 100644 --- a/vulkan/scripts/driver_generator.py +++ b/vulkan/scripts/driver_generator.py @@ -17,114 +17,124 @@ # This script provides the functions for generating the # vulkan driver framework directly from the vulkan registry (vk.xml). -import generator_common as gencom import os +import generator_common as gencom -interceptedExtensions = [ - 'VK_ANDROID_native_buffer', - 'VK_EXT_debug_report', - 'VK_EXT_hdr_metadata', - 'VK_EXT_swapchain_colorspace', - 'VK_GOOGLE_display_timing', - 'VK_KHR_android_surface', - 'VK_KHR_get_surface_capabilities2', - 'VK_KHR_incremental_present', - 'VK_KHR_shared_presentable_image', - 'VK_KHR_surface', - 'VK_KHR_swapchain', +_INTERCEPTED_EXTENSIONS = [ + 'VK_ANDROID_native_buffer', + 'VK_EXT_debug_report', + 'VK_EXT_hdr_metadata', + 'VK_EXT_swapchain_colorspace', + 'VK_GOOGLE_display_timing', + 'VK_KHR_android_surface', + 'VK_KHR_get_surface_capabilities2', + 'VK_KHR_incremental_present', + 'VK_KHR_shared_presentable_image', + 'VK_KHR_surface', + 'VK_KHR_swapchain', ] -knownExtensions = interceptedExtensions + [ - 'VK_ANDROID_external_memory_android_hardware_buffer', - 'VK_KHR_bind_memory2', - 'VK_KHR_get_physical_device_properties2', +_KNOWN_EXTENSIONS = _INTERCEPTED_EXTENSIONS + [ + 'VK_ANDROID_external_memory_android_hardware_buffer', + 'VK_KHR_bind_memory2', + 'VK_KHR_get_physical_device_properties2', ] -def defineProcHookType(f): - f.write ("""struct ProcHook { - enum Type { - GLOBAL, - INSTANCE, - DEVICE, - }; - enum Extension {\n""") - for exts in knownExtensions: - f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n') - f.write ('\n') - f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE, // valid bit - EXTENSION_COUNT, - EXTENSION_UNKNOWN, - }; - - const char* name; - Type type; - Extension extension; - - PFN_vkVoidFunction proc; - PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks -};\n\n""") - -def isExtensionIntercepted(extensionName): - if extensionName in interceptedExtensions: - return True - return False - -def isDriverTableEntry(functionName): - switchCase = { +_NEEDED_COMMANDS = [ # Create functions of dispatchable objects - 'vkCreateDevice' : True, - 'vkGetDeviceQueue' : True, - 'vkGetDeviceQueue2' : True, - 'vkAllocateCommandBuffers' : True, + 'vkCreateDevice', + 'vkGetDeviceQueue', + 'vkGetDeviceQueue2', + 'vkAllocateCommandBuffers', # Destroy functions of dispatchable objects - 'vkDestroyInstance' : True, - 'vkDestroyDevice' : True, + 'vkDestroyInstance', + 'vkDestroyDevice', # Enumeration of extensions - 'vkEnumerateDeviceExtensionProperties' : True, + 'vkEnumerateDeviceExtensionProperties', # We cache physical devices in loader.cpp - 'vkEnumeratePhysicalDevices' : True, - 'vkEnumeratePhysicalDeviceGroups' : True, + 'vkEnumeratePhysicalDevices', + 'vkEnumeratePhysicalDeviceGroups', - 'vkGetInstanceProcAddr' : True, - 'vkGetDeviceProcAddr' : True, + 'vkGetInstanceProcAddr', + 'vkGetDeviceProcAddr', - 'vkQueueSubmit' : True, + 'vkQueueSubmit', # VK_KHR_swapchain->VK_ANDROID_native_buffer translation - 'vkCreateImage' : True, - 'vkDestroyImage' : True, + 'vkCreateImage', + 'vkDestroyImage', - 'vkGetPhysicalDeviceProperties' : True, - 'vkGetPhysicalDeviceProperties2' : True, - 'vkGetPhysicalDeviceProperties2KHR' : True, + 'vkGetPhysicalDeviceProperties', + 'vkGetPhysicalDeviceProperties2', + 'vkGetPhysicalDeviceProperties2KHR', # VK_KHR_swapchain v69 requirement - 'vkBindImageMemory2' : True, - 'vkBindImageMemory2KHR' : True - } - if gencom.isFunctionSupported(functionName): - if functionName in switchCase: + 'vkBindImageMemory2', + 'vkBindImageMemory2KHR', +] + +_INTERCEPTED_COMMANDS = [ + # Create functions of dispatchable objects + 'vkCreateInstance', + 'vkCreateDevice', + 'vkEnumeratePhysicalDevices', + 'vkEnumeratePhysicalDeviceGroups', + 'vkGetDeviceQueue', + 'vkGetDeviceQueue2', + 'vkAllocateCommandBuffers', + + # Destroy functions of dispatchable objects + 'vkDestroyInstance', + 'vkDestroyDevice', + + # Enumeration of extensions + 'vkEnumerateInstanceExtensionProperties', + 'vkEnumerateDeviceExtensionProperties', + + 'vkGetInstanceProcAddr', + 'vkGetDeviceProcAddr', + + 'vkQueueSubmit', + + # VK_KHR_swapchain v69 requirement + 'vkBindImageMemory2', + 'vkBindImageMemory2KHR', +] + + +def _is_driver_table_entry(cmd): + if gencom.is_function_supported(cmd): + if cmd in _NEEDED_COMMANDS: return True - if functionName in gencom.extensionsDict: - if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report': + if cmd in gencom.extension_dict: + if (gencom.extension_dict[cmd] == 'VK_ANDROID_native_buffer' or + gencom.extension_dict[cmd] == 'VK_EXT_debug_report'): return True return False -def isInstanceDriverTableEntry(functionName): - if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName): - return True - return False -def isDeviceDriverTableEntry(functionName): - if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName): - return True - return False +def _is_instance_driver_table_entry(cmd): + return (_is_driver_table_entry(cmd) and + gencom.is_instance_dispatched(cmd)) + + +def _is_device_driver_table_entry(cmd): + return (_is_driver_table_entry(cmd) and + gencom.is_device_dispatched(cmd)) + -def driver_genh(): - header = """#ifndef LIBVULKAN_DRIVER_GEN_H +def gen_h(): + genfile = os.path.join(os.path.dirname(__file__), + '..', 'libvulkan', 'driver_gen.h') + + with open(genfile, 'w') as f: + f.write(gencom.copyright_and_warning(2016)) + + f.write("""\ +#ifndef LIBVULKAN_DRIVER_GEN_H #define LIBVULKAN_DRIVER_GEN_H #include <vulkan/vk_android_native_buffer.h> @@ -133,28 +143,58 @@ def driver_genh(): #include <bitset> namespace vulkan { -namespace driver {\n\n""" - genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h') - with open(genfile, 'w') as f: - f.write (gencom.copyright) - f.write (gencom.warning) - f.write (header) - defineProcHookType(f) - f.write ('struct InstanceDriverTable {\n') - gencom.clang_off(f, 1) - for cmds in gencom.allCommandsList: - if isInstanceDriverTableEntry(cmds): - f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n') - gencom.clang_on(f, 1) - f.write ('};\n\n') - f.write ('struct DeviceDriverTable {\n') - gencom.clang_off(f,1) - for cmds in gencom.allCommandsList: - if isDeviceDriverTableEntry(cmds): - f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n') - gencom.clang_on(f,1) - f.write ('};\n\n') - f.write ("""const ProcHook* GetProcHook(const char* name); +namespace driver { + +struct ProcHook { + enum Type { + GLOBAL, + INSTANCE, + DEVICE, + }; + enum Extension {\n""") + + for exts in _KNOWN_EXTENSIONS: + f.write(gencom.indent(2) + exts[3:] + ',\n') + + f.write(""" + EXTENSION_CORE, // valid bit + EXTENSION_COUNT, + EXTENSION_UNKNOWN, + }; + + const char* name; + Type type; + Extension extension; + + PFN_vkVoidFunction proc; + PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks +}; + +struct InstanceDriverTable { + // clang-format off\n""") + + for cmd in gencom.command_list: + if _is_instance_driver_table_entry(cmd): + f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' + + gencom.base_name(cmd) + ';\n') + + f.write("""\ + // clang-format on +}; + +struct DeviceDriverTable { + // clang-format off\n""") + + for cmd in gencom.command_list: + if _is_device_driver_table_entry(cmd): + f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' + + gencom.base_name(cmd) + ';\n') + + f.write("""\ + // clang-format on +}; + +const ProcHook* GetProcHook(const char* name); ProcHook::Extension GetProcHookExtension(const char* name); bool InitDriverTable(VkInstance instance, @@ -168,148 +208,131 @@ bool InitDriverTable(VkDevice dev, } // namespace vulkan #endif // LIBVULKAN_DRIVER_TABLE_H\n""") - f.close() - gencom.runClangFormat(genfile) - -def isIntercepted(functionName): - switchCase = { - # Create functions of dispatchable objects - 'vkCreateInstance' : True, - 'vkCreateDevice' : True, - 'vkEnumeratePhysicalDevices' : True, - 'vkEnumeratePhysicalDeviceGroups' : True, - 'vkGetDeviceQueue' : True, - 'vkGetDeviceQueue2' : True, - 'vkAllocateCommandBuffers' : True, - # Destroy functions of dispatchable objects - 'vkDestroyInstance' : True, - 'vkDestroyDevice' : True, - - # Enumeration of extensions - 'vkEnumerateInstanceExtensionProperties' : True, - 'vkEnumerateDeviceExtensionProperties' : True, + f.close() + gencom.run_clang_format(genfile) - 'vkGetInstanceProcAddr' : True, - 'vkGetDeviceProcAddr' : True, - 'vkQueueSubmit' : True, +def _is_intercepted(cmd): + if gencom.is_function_supported(cmd): + if cmd in _INTERCEPTED_COMMANDS: + return True - # VK_KHR_swapchain v69 requirement - 'vkBindImageMemory2' : True, - 'vkBindImageMemory2KHR' : True - } - if gencom.isFunctionSupported(functionName): - if functionName in switchCase: - return switchCase[functionName] - - if functionName in gencom.extensionsDict: - return isExtensionIntercepted(gencom.extensionsDict[functionName]) + if cmd in gencom.extension_dict: + return gencom.extension_dict[cmd] in _INTERCEPTED_EXTENSIONS return False -def needProcHookStub(functionName): - if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName): - if functionName in gencom.extensionsDict: - if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]): + +def _need_proc_hook_stub(cmd): + if _is_intercepted(cmd) and gencom.is_device_dispatched(cmd): + if cmd in gencom.extension_dict: + if not gencom.is_extension_internal(gencom.extension_dict[cmd]): return True return False -def defineInitProc(name, f): - f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n') - f.write ('\n') - f.write ("""#define INIT_PROC(required, obj, proc) \\ - do { \\ - data.""" + name + """.proc = \\ - reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\ - if (UNLIKELY(required && !data.""" + name + """.proc)) { \\ - ALOGE("missing " #obj " proc: vk" #proc); \\ - success = false; \\ - } \\ - } while (0)\n\n""") -def defineInitProcExt(f): - f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\ - do { \\ - if (extensions[ProcHook::ext]) \\ - INIT_PROC(required, obj, proc); \\ - } while (0)\n\n""") - -def defineProcHookStub(functionName, f): - if needProcHookStub(functionName): - ext_name = gencom.extensionsDict[functionName] - base_name = functionName[2:] - paramList = [''.join(i) for i in gencom.paramDict[functionName]] - p0 = gencom.paramDict[functionName][0][1] - f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n') +def _define_proc_hook_stub(cmd, f): + if _need_proc_hook_stub(cmd): + return_type = gencom.return_type_dict[cmd] + ext_name = gencom.extension_dict[cmd] ext_hook = 'ProcHook::' + ext_name[3:] - - f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n') - f.write (gencom.clang_off_spaces *2) - if gencom.returnTypeDict[functionName] != 'void': - f.write ('return ') - paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]] - f.write (base_name + '(' + ', '.join(paramNames) + ');\n') - f.write (gencom.clang_off_spaces + '} else {\n') - f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n') - if gencom.returnTypeDict[functionName] != 'void': - f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n') - f.write (gencom.clang_off_spaces + '}\n') - f.write ('}\n\n') - -def defineGlobalProcHook(functionName, f): - base_name = functionName[2:] - assert (functionName not in gencom.extensionsDict) - f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2) - f.write ("""ProcHook::GLOBAL, + handle = gencom.param_dict[cmd][0][1] + param_types = ', '.join([''.join(i) for i in gencom.param_dict[cmd]]) + param_names = ', '.join([''.join(i[1]) for i in gencom.param_dict[cmd]]) + + f.write('VKAPI_ATTR ' + return_type + ' checked' + gencom.base_name(cmd) + + '(' + param_types + ') {\n') + f.write(gencom.indent(1) + 'if (GetData(' + handle + ').hook_extensions[' + + ext_hook + ']) {\n') + + f.write(gencom.indent(2)) + if gencom.return_type_dict[cmd] != 'void': + f.write('return ') + f.write(gencom.base_name(cmd) + '(' + param_names + ');\n') + + f.write(gencom.indent(1) + '} else {\n') + f.write(gencom.indent(2) + 'Logger(' + handle + ').Err(' + handle + ', \"' + + ext_name + ' not enabled. ' + cmd + ' not executed.\");\n') + if gencom.return_type_dict[cmd] != 'void': + f.write(gencom.indent(2) + 'return VK_SUCCESS;\n') + f.write(gencom.indent(1) + '}\n}\n\n') + + +def _define_global_proc_hook(cmd, f): + assert cmd not in gencom.extension_dict + + f.write(gencom.indent(1) + '{\n') + f.write(gencom.indent(2) + '\"' + cmd + '\",\n') + f.write("""\ + ProcHook::GLOBAL, ProcHook::EXTENSION_CORE, - reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """), + reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), nullptr, },\n""") -def defineInstanceProcHook(functionName, f): - base_name = functionName[2:] - f.write (gencom.clang_off_spaces + '{\n') - f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n') - f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n') - - if functionName in gencom.extensionsDict: - ext_name = gencom.extensionsDict[functionName] - f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n') - if gencom.isExtensionInternal(ext_name): - f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n') - else: - f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n') +def _define_instance_proc_hook(cmd, f): + f.write(gencom.indent(1) + '{\n') + f.write(gencom.indent(2) + '\"' + cmd + '\",\n') + f.write(gencom.indent(2) + 'ProcHook::INSTANCE,\n') + + if cmd in gencom.extension_dict: + ext_name = gencom.extension_dict[cmd] + f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n') + + if gencom.is_extension_internal(ext_name): + f.write("""\ + nullptr, + nullptr,\n""") + else: + f.write("""\ + reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), + nullptr,\n""") else: - f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE, - reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """), + f.write("""\ + ProcHook::EXTENSION_CORE, + reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), nullptr,\n""") - f.write (gencom.clang_off_spaces + '},\n') + f.write(gencom.indent(1) + '},\n') + + +def _define_device_proc_hook(cmd, f): + f.write(gencom.indent(1) + '{\n') + f.write(gencom.indent(2) + '\"' + cmd + '\",\n') + f.write(gencom.indent(2) + 'ProcHook::DEVICE,\n') -def defineDeviceProcHook(functionName, f): - base_name = functionName[2:] - f.write (gencom.clang_off_spaces + '{\n') - f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n') - f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n') + if cmd in gencom.extension_dict: + ext_name = gencom.extension_dict[cmd] + f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n') - if functionName in gencom.extensionsDict: - ext_name = gencom.extensionsDict[functionName] - f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n') - if gencom.isExtensionInternal(ext_name): - f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n') + if gencom.is_extension_internal(ext_name): + f.write("""\ + nullptr, + nullptr,\n""") else: - f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n') + f.write("""\ + reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), + reinterpret_cast<PFN_vkVoidFunction>(checked""" + + gencom.base_name(cmd) + '),\n') else: - f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE, - reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """), + f.write("""\ + ProcHook::EXTENSION_CORE, + reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), nullptr,\n""") - f.write (gencom.clang_off_spaces + '},\n') + f.write(gencom.indent(1) + '},\n') + -def driver_gencpp(): - header = """#include <log/log.h> +def gen_cpp(): + genfile = os.path.join(os.path.dirname(__file__), + '..', 'libvulkan', 'driver_gen.cpp') + + with open(genfile, 'w') as f: + f.write(gencom.copyright_and_warning(2016)) + f.write("""\ +#include <log/log.h> #include <string.h> #include <algorithm> @@ -321,35 +344,34 @@ namespace driver { namespace { -// clang-format off\n\n""" +// clang-format off\n\n""") - genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp') + for cmd in gencom.command_list: + _define_proc_hook_stub(cmd, f) - with open(genfile, 'w') as f: - f.write (gencom.copyright) - f.write (gencom.warning) - f.write (header) - - for cmds in gencom.allCommandsList: - defineProcHookStub(cmds, f) - gencom.clang_on(f, 0) - f.write ('\n') - - f.write ('const ProcHook g_proc_hooks[] = {\n') - gencom.clang_off(f, 1) - sortedCommandsList = sorted(gencom.allCommandsList) - for cmds in sortedCommandsList: - if isIntercepted(cmds): - if gencom.isGloballyDispatched(cmds): - defineGlobalProcHook(cmds, f) - elif gencom.isInstanceDispatched(cmds): - defineInstanceProcHook(cmds, f) - elif gencom.isDeviceDispatched(cmds): - defineDeviceProcHook(cmds, f) - gencom.clang_on(f, 1) - f.write ('};\n\n} // namespace\n\n') - - f.write ("""const ProcHook* GetProcHook(const char* name) { + f.write("""\ +// clang-format on + +const ProcHook g_proc_hooks[] = { + // clang-format off\n""") + + sorted_command_list = sorted(gencom.command_list) + for cmd in sorted_command_list: + if _is_intercepted(cmd): + if gencom.is_globally_dispatched(cmd): + _define_global_proc_hook(cmd, f) + elif gencom.is_instance_dispatched(cmd): + _define_instance_proc_hook(cmd, f) + elif gencom.is_device_dispatched(cmd): + _define_device_proc_hook(cmd, f) + + f.write("""\ + // clang-format on +}; + +} // namespace + +const ProcHook* GetProcHook(const char* name) { const auto& begin = g_proc_hooks; const auto& end = g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]); @@ -357,44 +379,76 @@ namespace { begin, end, name, [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; }); return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr; -}\n\n""") +} + +ProcHook::Extension GetProcHookExtension(const char* name) { + // clang-format off\n""") - f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n') - gencom.clang_off(f, 1) - for exts in knownExtensions: - f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n') - gencom.clang_on(f, 1) - f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n') - f.write ('}\n\n') + for exts in _KNOWN_EXTENSIONS: + f.write(gencom.indent(1) + 'if (strcmp(name, \"' + exts + + '\") == 0) return ProcHook::' + exts[3:] + ';\n') + + f.write("""\ + // clang-format on + return ProcHook::EXTENSION_UNKNOWN; +} + +#define UNLIKELY(expr) __builtin_expect((expr), 0) + +#define INIT_PROC(required, obj, proc) \\ + do { \\ + data.driver.proc = \\ + reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\ + if (UNLIKELY(required && !data.driver.proc)) { \\ + ALOGE("missing " #obj " proc: vk" #proc); \\ + success = false; \\ + } \\ + } while (0) - defineInitProc('driver', f) - defineInitProcExt(f) +#define INIT_PROC_EXT(ext, required, obj, proc) \\ + do { \\ + if (extensions[ProcHook::ext]) \\ + INIT_PROC(required, obj, proc); \\ + } while (0) - f.write ("""bool InitDriverTable(VkInstance instance, +bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) { auto& data = GetData(instance); - bool success = true;\n\n""") - gencom.clang_off(f, 1) - for cmds in gencom.allCommandsList: - if isInstanceDriverTableEntry(cmds): - gencom.initProc(cmds, f) - gencom.clang_on(f, 1) - f.write ('\n' + gencom.clang_off_spaces + 'return success;\n') - f.write ('}\n\n') - - f.write ("""bool InitDriverTable(VkDevice dev, + bool success = true; + + // clang-format off\n""") + + for cmd in gencom.command_list: + if _is_instance_driver_table_entry(cmd): + gencom.init_proc(cmd, f) + + f.write("""\ + // clang-format on + + return success; +} + +bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) { auto& data = GetData(dev); - bool success = true;\n\n""") - gencom.clang_off(f, 1) - for cmds in gencom.allCommandsList: - if isDeviceDriverTableEntry(cmds): - gencom.initProc(cmds, f) - gencom.clang_on(f, 1) - f.write ('\n' + gencom.clang_off_spaces + 'return success;\n') - f.write ('}\n\n} // namespace driver\n} // namespace vulkan\n\n') - gencom.clang_on(f, 0) + bool success = true; + + // clang-format off\n""") + + for cmd in gencom.command_list: + if _is_device_driver_table_entry(cmd): + gencom.init_proc(cmd, f) + + f.write("""\ + // clang-format on + + return success; +} + +} // namespace driver +} // namespace vulkan\n""") + f.close() - gencom.runClangFormat(genfile) + gencom.run_clang_format(genfile) diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py index f1f09d59e5..03993e21d7 100644 --- a/vulkan/scripts/generator_common.py +++ b/vulkan/scripts/generator_common.py @@ -17,29 +17,11 @@ # This script provides the common functions for generating the # vulkan framework directly from the vulkan registry (vk.xml). -from subprocess import check_call +import os +import subprocess +import xml.etree.ElementTree as element_tree -copyright = """/* - * Copyright 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -""" - -warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n' - -blacklistedExtensions = [ +_BLACKLISTED_EXTENSIONS = [ 'VK_EXT_acquire_xlib_display', 'VK_EXT_direct_mode_display', 'VK_EXT_display_control', @@ -70,191 +52,218 @@ blacklistedExtensions = [ 'VK_NVX_image_view_handle', ] -exportedExtensions = [ +_EXPORTED_EXTENSIONS = [ 'VK_ANDROID_external_memory_android_hardware_buffer', 'VK_KHR_android_surface', 'VK_KHR_surface', 'VK_KHR_swapchain', ] -optionalCommands = [ +_OPTIONAL_COMMANDS = [ 'vkGetSwapchainGrallocUsageANDROID', 'vkGetSwapchainGrallocUsage2ANDROID', ] -def runClangFormat(args): - clang_call = ["clang-format", "--style", "file", "-i", args] - check_call (clang_call) +_DISPATCH_TYPE_DICT = { + 'VkInstance ': 'Instance', + 'VkPhysicalDevice ': 'Instance', + 'VkDevice ': 'Device', + 'VkQueue ': 'Device', + 'VkCommandBuffer ': 'Device' +} + +alias_dict = {} +command_list = [] +extension_dict = {} +param_dict = {} +return_type_dict = {} +version_dict = {} + + +def indent(num): + return ' ' * num + + +def copyright_and_warning(year): + return """\ +/* + * Copyright """ + str(year) + """ The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// WARNING: This file is generated. See ../README.md for instructions. + +""" + + +def run_clang_format(args): + clang_call = ['clang-format', '--style', 'file', '-i', args] + subprocess.check_call(clang_call) + + +def is_extension_internal(extension_name): + return extension_name == 'VK_ANDROID_native_buffer' -def isExtensionInternal(extensionName): - if extensionName == 'VK_ANDROID_native_buffer': - return True - return False -def isFunctionSupported(functionName): - if functionName not in extensionsDict: +def base_name(cmd): + return cmd[2:] + + +def is_function_supported(cmd): + if cmd not in extension_dict: return True else: - if extensionsDict[functionName] not in blacklistedExtensions: + if extension_dict[cmd] not in _BLACKLISTED_EXTENSIONS: return True return False -def isInstanceDispatched(functionName): - return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance' -def isDeviceDispatched(functionName): - return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device' +def get_dispatch_table_type(cmd): + if cmd not in param_dict: + return None -def isGloballyDispatched(functionName): - return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global' + if param_dict[cmd]: + return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global') + return 'Global' -def isExtensionExported(extensionName): - if extensionName in exportedExtensions: - return True - return False -def isFunctionExported(functionName): - if isFunctionSupported(functionName): - if functionName in extensionsDict: - return isExtensionExported(extensionsDict[functionName]) - return True - return False +def is_globally_dispatched(cmd): + return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global' -def getDispatchTableType(functionName): - if functionName not in paramDict: - return None - switchCase = { - 'VkInstance ' : 'Instance', - 'VkPhysicalDevice ' : 'Instance', - 'VkDevice ' : 'Device', - 'VkQueue ' : 'Device', - 'VkCommandBuffer ' : 'Device' - } +def is_instance_dispatched(cmd): + return (is_function_supported(cmd) and + get_dispatch_table_type(cmd) == 'Instance') - if len(paramDict[functionName]) > 0: - return switchCase.get(paramDict[functionName][0][0], 'Global') - return 'Global' -def isInstanceDispatchTableEntry(functionName): - if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc - return False - if isFunctionExported(functionName) and isInstanceDispatched(functionName): - return True - return False +def is_device_dispatched(cmd): + return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device' + -def isDeviceDispatchTableEntry(functionName): - if isFunctionExported(functionName) and isDeviceDispatched(functionName): +def is_extension_exported(extension_name): + return extension_name in _EXPORTED_EXTENSIONS + + +def is_function_exported(cmd): + if is_function_supported(cmd): + if cmd in extension_dict: + return is_extension_exported(extension_dict[cmd]) return True return False -def clang_on(f, indent): - f.write (clang_off_spaces * indent + '// clang-format on\n') +def is_instance_dispatch_table_entry(cmd): + if cmd == 'vkEnumerateDeviceLayerProperties': + # deprecated, unused internally - @dbd33bc + return False + return is_function_exported(cmd) and is_instance_dispatched(cmd) + + +def is_device_dispatch_table_entry(cmd): + return is_function_exported(cmd) and is_device_dispatched(cmd) + + +def init_proc(name, f): + f.write(indent(1)) + if name in extension_dict: + f.write('INIT_PROC_EXT(' + extension_dict[name][3:] + ', ') + else: + f.write('INIT_PROC(') + + if name in version_dict and version_dict[name] == 'VK_VERSION_1_1': + f.write('false, ') + elif name in _OPTIONAL_COMMANDS: + f.write('false, ') + else: + f.write('true, ') -def clang_off(f, indent): - f.write (clang_off_spaces * indent + '// clang-format off\n') + if is_instance_dispatched(name): + f.write('instance, ') + else: + f.write('dev, ') -clang_off_spaces = ' ' * 4 + f.write(base_name(name) + ');\n') -parametersList = [] -paramDict = {} -allCommandsList = [] -extensionsDict = {} -returnTypeDict = {} -versionDict = {} -aliasDict = {} -def parseVulkanRegistry(): - import xml.etree.ElementTree as ET - import os - vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml') - tree = ET.parse(vulkan_registry) +def parse_vulkan_registry(): + registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', + 'external', 'vulkan-headers', 'registry', 'vk.xml') + tree = element_tree.parse(registry) root = tree.getroot() for commands in root.iter('commands'): for command in commands: if command.tag == 'command': - parametersList.clear() + parameter_list = [] protoset = False - fnName = "" - fnType = "" - if command.get('alias') != None: + cmd_name = '' + cmd_type = '' + if command.get('alias') is not None: alias = command.get('alias') - fnName = command.get('name') - aliasDict[fnName] = alias - allCommandsList.append(fnName) - paramDict[fnName] = paramDict[alias].copy() - returnTypeDict[fnName] = returnTypeDict[alias] + cmd_name = command.get('name') + alias_dict[cmd_name] = alias + command_list.append(cmd_name) + param_dict[cmd_name] = param_dict[alias].copy() + return_type_dict[cmd_name] = return_type_dict[alias] for params in command: if params.tag == 'param': - paramtype = "" - if params.text != None and params.text.strip() != '': - paramtype = params.text.strip() + ' ' - typeval = params.find('type') - paramtype = paramtype + typeval.text - if typeval.tail != None: - paramtype += typeval.tail.strip() + ' ' + param_type = '' + if params.text is not None and params.text.strip(): + param_type = params.text.strip() + ' ' + type_val = params.find('type') + param_type = param_type + type_val.text + if type_val.tail is not None: + param_type += type_val.tail.strip() + ' ' pname = params.find('name') - paramname = pname.text - if pname.tail != None and pname.tail.strip() != '': - parametersList.append((paramtype, paramname, pname.tail.strip())) + param_name = pname.text + if pname.tail is not None and pname.tail.strip(): + parameter_list.append( + (param_type, param_name, pname.tail.strip())) else: - parametersList.append((paramtype, paramname)) + parameter_list.append((param_type, param_name)) if params.tag == 'proto': for c in params: if c.tag == 'type': - fnType = c.text + cmd_type = c.text if c.tag == 'name': - fnName = c.text + cmd_name = c.text protoset = True - allCommandsList.append(fnName) - returnTypeDict[fnName] = fnType - if protoset == True: - paramDict[fnName] = parametersList.copy() + command_list.append(cmd_name) + return_type_dict[cmd_name] = cmd_type + if protoset: + param_dict[cmd_name] = parameter_list.copy() for exts in root.iter('extensions'): for extension in exts: - apiversion = "" + apiversion = '' if extension.tag == 'extension': extname = extension.get('name') for req in extension: - if req.get('feature') != None: + if req.get('feature') is not None: apiversion = req.get('feature') for commands in req: if commands.tag == 'command': - commandname = commands.get('name') - if commandname not in extensionsDict: - extensionsDict[commandname] = extname - if apiversion != "": - versionDict[commandname] = apiversion + cmd_name = commands.get('name') + if cmd_name not in extension_dict: + extension_dict[cmd_name] = extname + if apiversion: + version_dict[cmd_name] = apiversion for feature in root.iter('feature'): apiversion = feature.get('name') for req in feature: for command in req: if command.tag == 'command': - cmdName = command.get('name') - if cmdName in allCommandsList: - versionDict[cmdName] = apiversion - - -def initProc(name, f): - if name in extensionsDict: - f.write (' INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ') - else: - f.write (' INIT_PROC(') - - if name in versionDict and versionDict[name] == 'VK_VERSION_1_1': - f.write('false, ') - elif name in optionalCommands: - f.write('false, ') - else: - f.write('true, ') - - if isInstanceDispatched(name): - f.write('instance, ') - else: - f.write('dev, ') - - f.write(name[2:] + ');\n') - + cmd_name = command.get('name') + if cmd_name in command_list: + version_dict[cmd_name] = apiversion diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py index 3a761ceb8b..2a99a1dda4 100644 --- a/vulkan/scripts/null_generator.py +++ b/vulkan/scripts/null_generator.py @@ -17,45 +17,31 @@ # This script provides the functions for generating the null driver # framework directly from the vulkan registry (vk.xml). -import generator_common as gencom import os +import generator_common as gencom + +_DRIVER_EXTENSION_DICT = { + 'VK_ANDROID_native_buffer', + 'VK_EXT_debug_report', + 'VK_KHR_get_physical_device_properties2' +} -copyright = """/* - * Copyright 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -""" - -def isDriverExtension(extensionName): - switchCase = { - 'VK_ANDROID_native_buffer' : True, - 'VK_EXT_debug_report' : True, - 'VK_KHR_get_physical_device_properties2' : True - } - - if extensionName in switchCase: - return switchCase[extensionName] - return False - -def isDriverFunction(functionName): - if functionName in gencom.extensionsDict: - return isDriverExtension(gencom.extensionsDict[functionName]) + +def _is_driver_function(cmd): + if cmd in gencom.extension_dict: + return gencom.extension_dict[cmd] in _DRIVER_EXTENSION_DICT return True -def null_driver_genh(): - header = """#ifndef NULLDRV_NULL_DRIVER_H + +def gen_h(): + genfile = os.path.join(os.path.dirname(__file__), + '..', 'nulldrv', 'null_driver_gen.h') + + with open(genfile, 'w') as f: + f.write(gencom.copyright_and_warning(2015)) + + f.write("""\ +#ifndef NULLDRV_NULL_DRIVER_H #define NULLDRV_NULL_DRIVER_H 1 #include <vulkan/vk_android_native_buffer.h> @@ -66,27 +52,34 @@ namespace null_driver { PFN_vkVoidFunction GetGlobalProcAddr(const char* name); PFN_vkVoidFunction GetInstanceProcAddr(const char* name); -""" - genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.h') - with open(genfile, 'w') as f: - f.write (copyright) - f.write (gencom.warning) - f.write (header) - gencom.clang_off(f,0) - - for cmds in gencom.allCommandsList: - if isDriverFunction(cmds): - paramList = [''.join(i) for i in gencom.paramDict[cmds]] - f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' +', '.join(paramList) + ');\n') - gencom.clang_on(f,0) - - f.write ('\n} // namespace null_driver\n') - f.write ('\n#endif // NULLDRV_NULL_DRIVER_H\n') +// clang-format off\n""") + + for cmd in gencom.command_list: + if _is_driver_function(cmd): + param_list = [''.join(i) for i in gencom.param_dict[cmd]] + f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' + + gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n') + + f.write("""\ +// clang-format on + +} // namespace null_driver + +#endif // NULLDRV_NULL_DRIVER_H\n""") + f.close() - gencom.runClangFormat(genfile) + gencom.run_clang_format(genfile) -def null_driver_gencpp(): - header = """#include <algorithm> + +def gen_cpp(): + genfile = os.path.join(os.path.dirname(__file__), + '..', 'nulldrv', 'null_driver_gen.cpp') + + with open(genfile, 'w') as f: + f.write(gencom.copyright_and_warning(2015)) + + f.write("""\ +#include <algorithm> #include "null_driver_gen.h" @@ -116,30 +109,36 @@ PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) { } const NameProc kGlobalProcs[] = { -""" - genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.cpp') - with open(genfile, 'w') as f: - f.write (copyright) - f.write (gencom.warning) - f.write (header) - gencom.clang_off(f,1) - - sortedCommandsList = sorted(gencom.allCommandsList) - for cmds in sortedCommandsList: - if isDriverFunction(cmds) and gencom.getDispatchTableType(cmds) == 'Global': - f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n') - gencom.clang_on(f,1) - f.write ('};\n\n') - - f.write ('const NameProc kInstanceProcs[] = {\n') - gencom.clang_off(f,1) - for cmds in sortedCommandsList: - if isDriverFunction(cmds): - f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n') - gencom.clang_on(f,1) - f.write ('};\n\n} // namespace\n\n') - - f.write ("""namespace null_driver { + // clang-format off\n""") + + sorted_command_list = sorted(gencom.command_list) + for cmd in sorted_command_list: + if (_is_driver_function(cmd) and + gencom.get_dispatch_table_type(cmd) == 'Global'): + f.write(gencom.indent(1) + '{\"' + cmd + + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + + cmd + '>(' + gencom.base_name(cmd) + '))},\n') + + f.write("""\ + // clang-format on +}; + +const NameProc kInstanceProcs[] = { + // clang-format off\n""") + + for cmd in sorted_command_list: + if _is_driver_function(cmd): + f.write(gencom.indent(1) + '{\"' + cmd + + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + + cmd + '>(' + gencom.base_name(cmd) + '))},\n') + + f.write("""\ + // clang-format on +}; + +} // namespace + +namespace null_driver { PFN_vkVoidFunction GetGlobalProcAddr(const char* name) { return Lookup(name, kGlobalProcs); @@ -150,6 +149,6 @@ PFN_vkVoidFunction GetInstanceProcAddr(const char* name) { } } // namespace null_driver\n""") - f.close() - gencom.runClangFormat(genfile) + f.close() + gencom.run_clang_format(genfile) |