def gen_h(): """Generates the null_driver_gen.h file. """ 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> #include <vulkan/vulkan.h> namespace null_driver { PFN_vkVoidFunction GetGlobalProcAddr(const char* name); PFN_vkVoidFunction GetInstanceProcAddr(const char* name); // 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.run_clang_format(genfile)
def gen_cpp(): """Generates the driver_gen.cpp file. """ 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> #include "driver.h" namespace vulkan { namespace driver { namespace { // clang-format off\n\n""") for cmd in gencom.command_list: _define_proc_hook_stub(cmd, f) 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]); const auto hook = std::lower_bound( 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; } ProcHook::Extension GetProcHookExtension(const char* name) { // clang-format off\n""") for ext in _KNOWN_EXTENSIONS: f.write( gencom.indent(1) + 'if (strcmp(name, \"' + ext + '\") == 0) return ProcHook::' + gencom.base_ext_name(ext) + ';\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) #define INIT_PROC_EXT(ext, required, obj, proc) \\ do { \\ if (extensions[ProcHook::ext]) \\ INIT_PROC(required, obj, proc); \\ } while (0) bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) { auto& data = GetData(instance); 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; // 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.run_clang_format(genfile)
def gen_h(): """Generates the driver_gen.h file. """ 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> #include <vulkan/vulkan.h> #include <bitset> namespace vulkan { namespace driver { struct ProcHook { enum Type { GLOBAL, INSTANCE, DEVICE, }; enum Extension {\n""") for ext in _KNOWN_EXTENSIONS: f.write(gencom.indent(2) + gencom.base_ext_name(ext) + ',\n') f.write('\n') for version in gencom.version_code_list: f.write(gencom.indent(2) + 'EXTENSION_CORE_' + version + ',\n') # EXTENSION_COUNT must be the next enum after the highest API version. f.write("""\ 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, PFN_vkGetInstanceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions); bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions); } // namespace driver } // namespace vulkan #endif // LIBVULKAN_DRIVER_TABLE_H\n""") f.close() gencom.run_clang_format(genfile)
def gen_cpp(): """Generates the driver_gen.cpp file. """ 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> #include "driver.h" namespace vulkan { namespace driver { namespace { // clang-format off\n\n""") for cmd in gencom.command_list: _define_proc_hook_stub(cmd, f) 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) { auto begin = std::cbegin(g_proc_hooks); auto end = std::cend(g_proc_hooks); auto hook = std::lower_bound( 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; } ProcHook::Extension GetProcHookExtension(const char* name) { // clang-format off\n""") for ext in _KNOWN_EXTENSIONS: f.write( gencom.indent(1) + 'if (strcmp(name, \"' + ext + '\") == 0) return ProcHook::' + gencom.base_ext_name(ext) + ';\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) #define INIT_PROC_EXT(ext, required, obj, proc) \\ do { \\ if (extensions[ProcHook::ext]) \\ INIT_PROC(required, obj, proc); \\ } while (0) bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) { auto& data = GetData(instance); 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; // 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; } const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = { // clang-format off\n""") for key, value in sorted(gencom.promoted_inst_ext_dict.items()): f.write( gencom.indent(1) + 'std::make_pair("' + key + '", ' + value + '),\n') f.write("""\ // clang-format on }; std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) { auto begin = std::cbegin(g_promoted_instance_extensions); auto end = std::cend(g_promoted_instance_extensions); auto iter = std::lower_bound(begin, end, name, [](const std::pair<const char*, uint32_t>& e, const char* n) { return strcmp(e.first, n) < 0; }); return (iter < end && strcmp(iter->first, name) == 0) ? std::optional<uint32_t>(iter->second) : std::nullopt; } uint32_t CountPromotedInstanceExtensions(uint32_t begin_version, uint32_t end_version) { auto begin = std::cbegin(g_promoted_instance_extensions); auto end = std::cend(g_promoted_instance_extensions); uint32_t count = 0; for (auto iter = begin; iter != end; iter++) if (iter->second > begin_version && iter->second <= end_version) count++; return count; } std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version, uint32_t end_version) { auto begin = std::cbegin(g_promoted_instance_extensions); auto end = std::cend(g_promoted_instance_extensions); std::vector<const char*> extensions; for (auto iter = begin; iter != end; iter++) if (iter->second > begin_version && iter->second <= end_version) extensions.emplace_back(iter->first); return extensions; } } // namespace driver } // namespace vulkan\n""") f.close() gencom.run_clang_format(genfile)
def gen_cpp(): """Generates the null_driver_gen.cpp file. """ 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" using namespace null_driver; namespace { struct NameProc { const char* name; PFN_vkVoidFunction proc; }; PFN_vkVoidFunction Lookup(const char* name, const NameProc* begin, const NameProc* end) { const auto& entry = std::lower_bound( begin, end, name, [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; }); if (entry == end || strcmp(entry->name, name) != 0) return nullptr; return entry->proc; } template <size_t N> PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) { return Lookup(name, procs, procs + N); } const NameProc kGlobalProcs[] = { // 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); } PFN_vkVoidFunction GetInstanceProcAddr(const char* name) { return Lookup(name, kInstanceProcs); } } // namespace null_driver\n""") f.close() gencom.run_clang_format(genfile)
def gen_h(): """Generates the api_gen.h file. """ genfile = os.path.join(os.path.dirname(__file__), '..', '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> #include <bitset> #include "driver_gen.h" 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 }; bool InitDispatchTable( VkInstance instance, PFN_vkGetInstanceProcAddr get_proc, const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions); bool InitDispatchTable( VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions); } // namespace api } // namespace vulkan #endif // LIBVULKAN_API_GEN_H\n""") f.close() gencom.run_clang_format(genfile)
def gen_cpp(): """Generates the api_gen.cpp file. """ 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> // to catch mismatches between vulkan.h and this file #undef VK_NO_PROTOTYPES #include "api.h" namespace vulkan { namespace api { #define UNLIKELY(expr) __builtin_expect((expr), 0) #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) // 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 { // 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; // 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; // 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(""" } // anonymous namespace // clang-format on } // namespace api } // namespace vulkan // clang-format off\n\n""") 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.run_clang_format(genfile)