def _define_instance_proc_hook(cmd, f): """Emits definition of a instance ProcHook. Args: cmd: Vulkan function name. f: Output file handle. """ 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::' + gencom.base_ext_name(ext_name) + ',\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.indent(2) + _get_proc_hook_enum(cmd) + ',\n') f.write("""\ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), nullptr,\n""") f.write(gencom.indent(1) + '},\n')
def _define_proc_hook_stub(cmd, f): """Emits a stub for ProcHook::checked_proc. Args: cmd: Vulkan function name. f: Output file handle. """ if _need_proc_hook_stub(cmd): return_type = gencom.return_type_dict[cmd] ext_name = '' ext_hook = '' if cmd in gencom.extension_dict: ext_name = gencom.extension_dict[cmd] ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name) else: ext_name = gencom.version_dict[cmd] ext_hook = _get_proc_hook_enum(cmd) 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_device_proc_hook(cmd, f): """Emits definition of a device ProcHook. Args: cmd: Vulkan function name. f: Output file handle. """ f.write(gencom.indent(1) + '{\n') f.write(gencom.indent(2) + '\"' + cmd + '\",\n') f.write(gencom.indent(2) + 'ProcHook::DEVICE,\n') if (cmd in gencom.extension_dict or gencom.version_dict[cmd] != 'VK_VERSION_1_0'): ext_name = '' ext_hook = '' if cmd in gencom.extension_dict: ext_name = gencom.extension_dict[cmd] ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name) else: ext_name = gencom.version_dict[cmd] ext_hook = _get_proc_hook_enum(cmd) f.write(gencom.indent(2) + ext_hook + ',\n') if gencom.is_extension_internal(ext_name): f.write("""\ nullptr, nullptr,\n""") else: f.write("""\ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), reinterpret_cast<PFN_vkVoidFunction>(checked""" + gencom.base_name(cmd) + '),\n') else: f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n') f.write("""\ reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """), nullptr,\n""") f.write(gencom.indent(1) + '},\n')
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)