generate_bindings.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. #!/usr/bin/env python3
  2. # Copyright 2018 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Code generator for Vulkan function pointers."""
  6. import filecmp
  7. import optparse
  8. import os
  9. import platform
  10. import sys
  11. from os import path
  12. from string import Template
  13. from subprocess import call
  14. vulkan_reg_path = path.join(path.dirname(__file__), "..", "..", "third_party",
  15. "vulkan-deps", "vulkan-headers", "src", "registry")
  16. sys.path.append(vulkan_reg_path)
  17. from reg import Registry
  18. registry = Registry()
  19. registry.loadFile(open(path.join(vulkan_reg_path, "vk.xml")))
  20. VULKAN_REQUIRED_API_VERSION = 'VK_API_VERSION_1_1'
  21. VULKAN_UNASSOCIATED_FUNCTIONS = [
  22. {
  23. 'functions': [
  24. # vkGetInstanceProcAddr belongs here but is handled specially.
  25. 'vkEnumerateInstanceVersion',
  26. 'vkCreateInstance',
  27. 'vkEnumerateInstanceExtensionProperties',
  28. 'vkEnumerateInstanceLayerProperties',
  29. ]
  30. }
  31. ]
  32. VULKAN_INSTANCE_FUNCTIONS = [
  33. {
  34. 'functions': [
  35. 'vkCreateDevice',
  36. 'vkDestroyInstance',
  37. 'vkEnumerateDeviceExtensionProperties',
  38. 'vkEnumerateDeviceLayerProperties',
  39. 'vkEnumeratePhysicalDevices',
  40. 'vkGetDeviceProcAddr',
  41. 'vkGetPhysicalDeviceFeatures2',
  42. 'vkGetPhysicalDeviceFormatProperties',
  43. 'vkGetPhysicalDeviceFormatProperties2',
  44. 'vkGetPhysicalDeviceImageFormatProperties2',
  45. 'vkGetPhysicalDeviceMemoryProperties',
  46. 'vkGetPhysicalDeviceMemoryProperties2',
  47. 'vkGetPhysicalDeviceProperties',
  48. 'vkGetPhysicalDeviceProperties2',
  49. 'vkGetPhysicalDeviceQueueFamilyProperties',
  50. ]
  51. },
  52. {
  53. 'ifdef': 'DCHECK_IS_ON()',
  54. 'extension': 'VK_EXT_DEBUG_REPORT_EXTENSION_NAME',
  55. 'functions': [
  56. 'vkCreateDebugReportCallbackEXT',
  57. 'vkDestroyDebugReportCallbackEXT',
  58. ]
  59. },
  60. {
  61. 'extension': 'VK_KHR_SURFACE_EXTENSION_NAME',
  62. 'functions': [
  63. 'vkDestroySurfaceKHR',
  64. 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
  65. 'vkGetPhysicalDeviceSurfaceFormatsKHR',
  66. 'vkGetPhysicalDeviceSurfaceSupportKHR',
  67. ]
  68. },
  69. {
  70. 'extension': 'VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME',
  71. 'functions': [
  72. 'vkCreateHeadlessSurfaceEXT',
  73. ]
  74. },
  75. {
  76. 'ifdef': 'defined(USE_VULKAN_XCB)',
  77. 'extension': 'VK_KHR_XCB_SURFACE_EXTENSION_NAME',
  78. 'functions': [
  79. 'vkCreateXcbSurfaceKHR',
  80. 'vkGetPhysicalDeviceXcbPresentationSupportKHR',
  81. ]
  82. },
  83. {
  84. 'ifdef': 'BUILDFLAG(IS_WIN)',
  85. 'extension': 'VK_KHR_WIN32_SURFACE_EXTENSION_NAME',
  86. 'functions': [
  87. 'vkCreateWin32SurfaceKHR',
  88. 'vkGetPhysicalDeviceWin32PresentationSupportKHR',
  89. ]
  90. },
  91. {
  92. 'ifdef': 'BUILDFLAG(IS_ANDROID)',
  93. 'extension': 'VK_KHR_ANDROID_SURFACE_EXTENSION_NAME',
  94. 'functions': [
  95. 'vkCreateAndroidSurfaceKHR',
  96. ]
  97. },
  98. {
  99. 'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
  100. 'extension': 'VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME',
  101. 'functions': [
  102. 'vkCreateImagePipeSurfaceFUCHSIA',
  103. ]
  104. },
  105. ]
  106. VULKAN_DEVICE_FUNCTIONS = [
  107. {
  108. 'functions': [
  109. 'vkAllocateCommandBuffers',
  110. 'vkAllocateDescriptorSets',
  111. 'vkAllocateMemory',
  112. 'vkBeginCommandBuffer',
  113. 'vkBindBufferMemory',
  114. 'vkBindBufferMemory2',
  115. 'vkBindImageMemory',
  116. 'vkBindImageMemory2',
  117. 'vkCmdBeginRenderPass',
  118. 'vkCmdCopyBuffer',
  119. 'vkCmdCopyBufferToImage',
  120. 'vkCmdCopyImageToBuffer',
  121. 'vkCmdEndRenderPass',
  122. 'vkCmdExecuteCommands',
  123. 'vkCmdNextSubpass',
  124. 'vkCmdPipelineBarrier',
  125. 'vkCreateBuffer',
  126. 'vkCreateCommandPool',
  127. 'vkCreateDescriptorPool',
  128. 'vkCreateDescriptorSetLayout',
  129. 'vkCreateFence',
  130. 'vkCreateFramebuffer',
  131. 'vkCreateGraphicsPipelines',
  132. 'vkCreateImage',
  133. 'vkCreateImageView',
  134. 'vkCreateRenderPass',
  135. 'vkCreateSampler',
  136. 'vkCreateSemaphore',
  137. 'vkCreateShaderModule',
  138. 'vkDestroyBuffer',
  139. 'vkDestroyCommandPool',
  140. 'vkDestroyDescriptorPool',
  141. 'vkDestroyDescriptorSetLayout',
  142. 'vkDestroyDevice',
  143. 'vkDestroyFence',
  144. 'vkDestroyFramebuffer',
  145. 'vkDestroyImage',
  146. 'vkDestroyImageView',
  147. 'vkDestroyRenderPass',
  148. 'vkDestroySampler',
  149. 'vkDestroySemaphore',
  150. 'vkDestroyShaderModule',
  151. 'vkDeviceWaitIdle',
  152. 'vkFlushMappedMemoryRanges',
  153. 'vkEndCommandBuffer',
  154. 'vkFreeCommandBuffers',
  155. 'vkFreeDescriptorSets',
  156. 'vkFreeMemory',
  157. 'vkInvalidateMappedMemoryRanges',
  158. 'vkGetBufferMemoryRequirements',
  159. 'vkGetBufferMemoryRequirements2',
  160. 'vkGetDeviceQueue',
  161. 'vkGetDeviceQueue2',
  162. 'vkGetFenceStatus',
  163. 'vkGetImageMemoryRequirements',
  164. 'vkGetImageMemoryRequirements2',
  165. 'vkGetImageSubresourceLayout',
  166. 'vkMapMemory',
  167. 'vkQueueSubmit',
  168. 'vkQueueWaitIdle',
  169. 'vkResetCommandBuffer',
  170. 'vkResetFences',
  171. 'vkUnmapMemory',
  172. 'vkUpdateDescriptorSets',
  173. 'vkWaitForFences',
  174. ]
  175. },
  176. {
  177. 'ifdef': 'BUILDFLAG(IS_ANDROID)',
  178. 'extension':
  179. 'VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME',
  180. 'functions': [
  181. 'vkGetAndroidHardwareBufferPropertiesANDROID',
  182. ]
  183. },
  184. {
  185. 'ifdef':
  186. 'BUILDFLAG(IS_POSIX)',
  187. 'extension': 'VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME',
  188. 'functions': [
  189. 'vkGetSemaphoreFdKHR',
  190. 'vkImportSemaphoreFdKHR',
  191. ]
  192. },
  193. {
  194. 'ifdef': 'BUILDFLAG(IS_WIN)',
  195. 'extension': 'VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME',
  196. 'functions': [
  197. 'vkGetSemaphoreWin32HandleKHR',
  198. 'vkImportSemaphoreWin32HandleKHR',
  199. ]
  200. },
  201. {
  202. 'ifdef':
  203. 'BUILDFLAG(IS_POSIX)',
  204. 'extension': 'VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME',
  205. 'functions': [
  206. 'vkGetMemoryFdKHR',
  207. 'vkGetMemoryFdPropertiesKHR',
  208. ]
  209. },
  210. {
  211. 'ifdef': 'BUILDFLAG(IS_WIN)',
  212. 'extension': 'VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME',
  213. 'functions': [
  214. 'vkGetMemoryWin32HandleKHR',
  215. 'vkGetMemoryWin32HandlePropertiesKHR',
  216. ]
  217. },
  218. {
  219. 'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
  220. 'extension': 'VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME',
  221. 'functions': [
  222. 'vkImportSemaphoreZirconHandleFUCHSIA',
  223. 'vkGetSemaphoreZirconHandleFUCHSIA',
  224. ]
  225. },
  226. {
  227. 'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
  228. 'extension': 'VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME',
  229. 'functions': [
  230. 'vkGetMemoryZirconHandleFUCHSIA',
  231. ]
  232. },
  233. {
  234. 'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
  235. 'extension': 'VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME',
  236. 'functions': [
  237. 'vkCreateBufferCollectionFUCHSIA',
  238. 'vkSetBufferCollectionImageConstraintsFUCHSIA',
  239. 'vkGetBufferCollectionPropertiesFUCHSIA',
  240. 'vkDestroyBufferCollectionFUCHSIA',
  241. ]
  242. },
  243. {
  244. 'extension': 'VK_KHR_SWAPCHAIN_EXTENSION_NAME',
  245. 'functions': [
  246. 'vkAcquireNextImageKHR',
  247. 'vkCreateSwapchainKHR',
  248. 'vkDestroySwapchainKHR',
  249. 'vkGetSwapchainImagesKHR',
  250. 'vkQueuePresentKHR',
  251. ]
  252. },
  253. {
  254. 'ifdef': 'BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)',
  255. 'extension': 'VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME',
  256. 'functions': [
  257. 'vkGetImageDrmFormatModifierPropertiesEXT',
  258. ]
  259. }
  260. ]
  261. SELF_LOCATION = os.path.dirname(os.path.abspath(__file__))
  262. LICENSE_AND_HEADER = """\
  263. // Copyright 2018 The Chromium Authors. All rights reserved.
  264. // Use of this source code is governed by a BSD-style license that can be
  265. // found in the LICENSE file.
  266. //
  267. // This file is auto-generated from
  268. // gpu/vulkan/generate_bindings.py
  269. // It's formatted by clang-format using chromium coding style:
  270. // clang-format -i -style=chromium filename
  271. // DO NOT EDIT!
  272. """
  273. def WriteFunctionsInternal(out_file, functions, gen_content,
  274. check_extension=False):
  275. for group in functions:
  276. if 'ifdef' in group:
  277. out_file.write('#if %s\n' % group['ifdef'])
  278. extension = group['extension'] if 'extension' in group else ''
  279. min_api_version = \
  280. group['min_api_version'] if 'min_api_version' in group else ''
  281. if not check_extension:
  282. for func in group['functions']:
  283. out_file.write(gen_content(func))
  284. elif not extension and not min_api_version:
  285. for func in group['functions']:
  286. out_file.write(gen_content(func))
  287. else:
  288. if min_api_version:
  289. out_file.write(' if (api_version >= %s) {\n' % min_api_version)
  290. for func in group['functions']:
  291. out_file.write(
  292. gen_content(func))
  293. out_file.write('}\n')
  294. if extension:
  295. out_file.write('else ')
  296. if extension:
  297. out_file.write('if (gfx::HasExtension(enabled_extensions, %s)) {\n' %
  298. extension)
  299. extension_suffix = \
  300. group['extension_suffix'] if 'extension_suffix' in group \
  301. else ''
  302. for func in group['functions']:
  303. out_file.write(gen_content(func, extension_suffix))
  304. out_file.write('}\n')
  305. if 'ifdef' in group:
  306. out_file.write('#endif // %s\n' % group['ifdef'])
  307. out_file.write('\n')
  308. def WriteFunctions(out_file, functions, template, check_extension=False):
  309. def gen_content(func, suffix=''):
  310. return template.substitute({'name': func,'extension_suffix': suffix})
  311. WriteFunctionsInternal(out_file, functions, gen_content, check_extension)
  312. def WriteFunctionDeclarations(out_file, functions):
  313. template = Template(' VulkanFunction<PFN_${name}> ${name};\n')
  314. WriteFunctions(out_file, functions, template)
  315. def WriteMacros(out_file, functions):
  316. def gen_content(func, suffix=''):
  317. if func not in registry.cmddict:
  318. # Some fuchsia functions are not in the vulkan registry, so use macro for
  319. # them.
  320. template = Template(
  321. '#define $name gpu::GetVulkanFunctionPointers()->${name}\n')
  322. return template.substitute({'name': func, 'extension_suffix' : suffix})
  323. none_str = lambda s: s if s else ''
  324. cmd = registry.cmddict[func].elem
  325. proto = cmd.find('proto')
  326. params = cmd.findall('param')
  327. pdecl = none_str(proto.text)
  328. for elem in proto:
  329. text = none_str(elem.text)
  330. tail = none_str(elem.tail)
  331. pdecl += text + tail
  332. n = len(params)
  333. callstat = ''
  334. if func in ('vkQueueSubmit', 'vkQueueWaitIdle', 'vkQueuePresentKHR'):
  335. callstat = '''base::AutoLockMaybe auto_lock
  336. (gpu::GetVulkanFunctionPointers()->per_queue_lock_map[queue].get());
  337. \n'''
  338. callstat += 'return gpu::GetVulkanFunctionPointers()->%s(' % func
  339. paramdecl = '('
  340. if n > 0:
  341. paramnames = (''.join(t for t in p.itertext())
  342. for p in params)
  343. paramdecl += ', '.join(paramnames)
  344. paramnames = (''.join(p[1].text)
  345. for p in params)
  346. callstat += ', '.join(paramnames)
  347. else:
  348. paramdecl += 'void'
  349. paramdecl += ')'
  350. callstat += ')'
  351. pdecl += paramdecl
  352. return 'ALWAYS_INLINE %s { %s; }\n' % (pdecl, callstat)
  353. WriteFunctionsInternal(out_file, functions, gen_content)
  354. def GenerateHeaderFile(out_file):
  355. """Generates gpu/vulkan/vulkan_function_pointers.h"""
  356. out_file.write(LICENSE_AND_HEADER +
  357. """
  358. #ifndef GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
  359. #define GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
  360. #include <vulkan/vulkan.h>
  361. #include <memory>
  362. #include "base/compiler_specific.h"
  363. #include "base/component_export.h"
  364. #include "base/containers/flat_map.h"
  365. #include "base/native_library.h"
  366. #include "base/synchronization/lock.h"
  367. #include "build/build_config.h"
  368. #include "ui/gfx/extension_set.h"
  369. #if BUILDFLAG(IS_ANDROID)
  370. #include <vulkan/vulkan_android.h>
  371. #endif
  372. #if BUILDFLAG(IS_FUCHSIA)
  373. #include <zircon/types.h>
  374. // <vulkan/vulkan_fuchsia.h> must be included after <zircon/types.h>
  375. #include <vulkan/vulkan_fuchsia.h>
  376. #include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
  377. #endif
  378. #if defined(USE_VULKAN_XCB)
  379. #include <xcb/xcb.h>
  380. // <vulkan/vulkan_xcb.h> must be included after <xcb/xcb.h>
  381. #include <vulkan/vulkan_xcb.h>
  382. #endif
  383. #if BUILDFLAG(IS_WIN)
  384. #include <vulkan/vulkan_win32.h>
  385. #endif
  386. namespace gpu {
  387. struct VulkanFunctionPointers;
  388. constexpr uint32_t kVulkanRequiredApiVersion = %s;
  389. COMPONENT_EXPORT(VULKAN) VulkanFunctionPointers* GetVulkanFunctionPointers();
  390. struct COMPONENT_EXPORT(VULKAN) VulkanFunctionPointers {
  391. VulkanFunctionPointers();
  392. ~VulkanFunctionPointers();
  393. bool BindUnassociatedFunctionPointersFromLoaderLib(base::NativeLibrary lib);
  394. bool BindUnassociatedFunctionPointersFromGetProcAddr(
  395. PFN_vkGetInstanceProcAddr proc);
  396. // These functions assume that vkGetInstanceProcAddr has been populated.
  397. bool BindInstanceFunctionPointers(
  398. VkInstance vk_instance,
  399. uint32_t api_version,
  400. const gfx::ExtensionSet& enabled_extensions);
  401. // These functions assume that vkGetDeviceProcAddr has been populated.
  402. bool BindDeviceFunctionPointers(
  403. VkDevice vk_device,
  404. uint32_t api_version,
  405. const gfx::ExtensionSet& enabled_extensions);
  406. // This is used to allow thread safe access to a given vulkan queue when
  407. // multiple gpu threads are accessing it. Note that this map will be only
  408. // accessed by multiple gpu threads concurrently to read the data, so it
  409. // should be thread safe to use this map by multiple threads.
  410. base::flat_map<VkQueue, std::unique_ptr<base::Lock>> per_queue_lock_map;
  411. template<typename T>
  412. class VulkanFunction;
  413. template <typename R, typename ...Args>
  414. class VulkanFunction <R(VKAPI_PTR*)(Args...)> {
  415. public:
  416. using Fn = R(VKAPI_PTR*)(Args...);
  417. explicit operator bool() const {
  418. return !!fn_;
  419. }
  420. NO_SANITIZE("cfi-icall")
  421. R operator()(Args... args) const {
  422. return fn_(args...);
  423. }
  424. Fn get() const { return fn_; }
  425. private:
  426. friend VulkanFunctionPointers;
  427. Fn operator=(Fn fn) {
  428. fn_ = fn;
  429. return fn_;
  430. }
  431. Fn fn_ = nullptr;
  432. };
  433. // Unassociated functions
  434. VulkanFunction<PFN_vkGetInstanceProcAddr> vkGetInstanceProcAddr;
  435. """ % VULKAN_REQUIRED_API_VERSION)
  436. WriteFunctionDeclarations(out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
  437. out_file.write("""\
  438. // Instance functions
  439. """)
  440. WriteFunctionDeclarations(out_file, VULKAN_INSTANCE_FUNCTIONS);
  441. out_file.write("""\
  442. // Device functions
  443. """)
  444. WriteFunctionDeclarations(out_file, VULKAN_DEVICE_FUNCTIONS)
  445. out_file.write("""\
  446. private:
  447. bool BindUnassociatedFunctionPointersCommon();
  448. // The `Bind*` functions will acquires lock, so should not be called with
  449. // with this lock held. Code that writes to members directly should take this
  450. // lock as well.
  451. base::Lock write_lock_;
  452. base::NativeLibrary loader_library_ = nullptr;
  453. };
  454. } // namespace gpu
  455. // Unassociated functions
  456. """)
  457. WriteMacros(out_file, [{'functions': [ 'vkGetInstanceProcAddr']}])
  458. WriteMacros(out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
  459. out_file.write("""\
  460. // Instance functions
  461. """)
  462. WriteMacros(out_file, VULKAN_INSTANCE_FUNCTIONS);
  463. out_file.write("""\
  464. // Device functions
  465. """)
  466. WriteMacros(out_file, VULKAN_DEVICE_FUNCTIONS)
  467. out_file.write("""\
  468. #endif // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_""")
  469. def WriteFunctionPointerInitialization(out_file, proc_addr_function, parent,
  470. functions):
  471. template = Template(""" ${name} = reinterpret_cast<PFN_${name}>(
  472. ${get_proc_addr}(${parent}, "${name}${extension_suffix}"));
  473. if (!${name}) {
  474. DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
  475. << "${name}${extension_suffix}";
  476. return false;
  477. }
  478. """)
  479. # Substitute all values in the template, except name, which is processed in
  480. # WriteFunctions().
  481. template = Template(template.substitute({
  482. 'name': '${name}', 'extension_suffix': '${extension_suffix}',
  483. 'get_proc_addr': proc_addr_function, 'parent': parent}))
  484. WriteFunctions(out_file, functions, template, check_extension=True)
  485. def WriteUnassociatedFunctionPointerInitialization(out_file, functions):
  486. WriteFunctionPointerInitialization(out_file, 'vkGetInstanceProcAddr',
  487. 'nullptr', functions)
  488. def WriteInstanceFunctionPointerInitialization(out_file, functions):
  489. WriteFunctionPointerInitialization(out_file, 'vkGetInstanceProcAddr',
  490. 'vk_instance', functions)
  491. def WriteDeviceFunctionPointerInitialization(out_file, functions):
  492. WriteFunctionPointerInitialization(out_file, 'vkGetDeviceProcAddr',
  493. 'vk_device', functions)
  494. def GenerateSourceFile(out_file):
  495. """Generates gpu/vulkan/vulkan_function_pointers.cc"""
  496. out_file.write(LICENSE_AND_HEADER +
  497. """
  498. #include "gpu/vulkan/vulkan_function_pointers.h"
  499. #include "base/logging.h"
  500. #include "base/no_destructor.h"
  501. namespace gpu {
  502. VulkanFunctionPointers* GetVulkanFunctionPointers() {
  503. static base::NoDestructor<VulkanFunctionPointers> vulkan_function_pointers;
  504. return vulkan_function_pointers.get();
  505. }
  506. VulkanFunctionPointers::VulkanFunctionPointers() = default;
  507. VulkanFunctionPointers::~VulkanFunctionPointers() = default;
  508. bool VulkanFunctionPointers::BindUnassociatedFunctionPointersFromLoaderLib(
  509. base::NativeLibrary lib) {
  510. base::AutoLock lock(write_lock_);
  511. loader_library_ = lib;
  512. // vkGetInstanceProcAddr must be handled specially since it gets its
  513. // function pointer through base::GetFunctionPOinterFromNativeLibrary().
  514. // Other Vulkan functions don't do this.
  515. vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
  516. base::GetFunctionPointerFromNativeLibrary(loader_library_,
  517. "vkGetInstanceProcAddr"));
  518. if (!vkGetInstanceProcAddr)
  519. return false;
  520. return BindUnassociatedFunctionPointersCommon();
  521. }
  522. bool VulkanFunctionPointers::BindUnassociatedFunctionPointersFromGetProcAddr(
  523. PFN_vkGetInstanceProcAddr proc) {
  524. DCHECK(proc);
  525. DCHECK(!loader_library_);
  526. base::AutoLock lock(write_lock_);
  527. vkGetInstanceProcAddr = proc;
  528. return BindUnassociatedFunctionPointersCommon();
  529. }
  530. bool VulkanFunctionPointers::BindUnassociatedFunctionPointersCommon() {
  531. """)
  532. WriteUnassociatedFunctionPointerInitialization(
  533. out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
  534. out_file.write("""\
  535. return true;
  536. }
  537. bool VulkanFunctionPointers::BindInstanceFunctionPointers(
  538. VkInstance vk_instance,
  539. uint32_t api_version,
  540. const gfx::ExtensionSet& enabled_extensions) {
  541. DCHECK_GE(api_version, kVulkanRequiredApiVersion);
  542. base::AutoLock lock(write_lock_);
  543. """)
  544. WriteInstanceFunctionPointerInitialization(
  545. out_file, VULKAN_INSTANCE_FUNCTIONS);
  546. out_file.write("""\
  547. return true;
  548. }
  549. bool VulkanFunctionPointers::BindDeviceFunctionPointers(
  550. VkDevice vk_device,
  551. uint32_t api_version,
  552. const gfx::ExtensionSet& enabled_extensions) {
  553. DCHECK_GE(api_version, kVulkanRequiredApiVersion);
  554. base::AutoLock lock(write_lock_);
  555. // Device functions
  556. """)
  557. WriteDeviceFunctionPointerInitialization(out_file, VULKAN_DEVICE_FUNCTIONS)
  558. out_file.write("""\
  559. return true;
  560. }
  561. } // namespace gpu
  562. """)
  563. def main(argv):
  564. """This is the main function."""
  565. parser = optparse.OptionParser()
  566. parser.add_option(
  567. "--output-dir",
  568. help="Output directory for generated files. Defaults to this script's "
  569. "directory.")
  570. parser.add_option(
  571. "-c", "--check", action="store_true",
  572. help="Check if output files match generated files in chromium root "
  573. "directory. Use this in PRESUBMIT scripts with --output-dir.")
  574. (options, _) = parser.parse_args(args=argv)
  575. # Support generating files for PRESUBMIT.
  576. if options.output_dir:
  577. output_dir = options.output_dir
  578. else:
  579. output_dir = SELF_LOCATION
  580. def ClangFormat(filename):
  581. formatter = "clang-format"
  582. if platform.system() == "Windows":
  583. formatter += ".bat"
  584. call([formatter, "-i", "-style=chromium", filename])
  585. header_file_name = 'vulkan_function_pointers.h'
  586. header_file = open(
  587. os.path.join(output_dir, header_file_name), 'w', newline='\n')
  588. GenerateHeaderFile(header_file)
  589. header_file.close()
  590. ClangFormat(header_file.name)
  591. source_file_name = 'vulkan_function_pointers.cc'
  592. source_file = open(
  593. os.path.join(output_dir, source_file_name), 'w', newline='\n')
  594. GenerateSourceFile(source_file)
  595. source_file.close()
  596. ClangFormat(source_file.name)
  597. check_failed_filenames = []
  598. if options.check:
  599. for filename in [header_file_name, source_file_name]:
  600. if not filecmp.cmp(os.path.join(output_dir, filename),
  601. os.path.join(SELF_LOCATION, filename)):
  602. check_failed_filenames.append(filename)
  603. if len(check_failed_filenames) > 0:
  604. print('Please run gpu/vulkan/generate_bindings.py')
  605. print('Failed check on generated files:')
  606. for filename in check_failed_filenames:
  607. print(filename)
  608. return 1
  609. return 0
  610. if __name__ == '__main__':
  611. sys.exit(main(sys.argv[1:]))