"""Code generator for Vulkan function pointers."""
import filecmp
import optparse
import os
import platform
import sys
from os import path
from string import Template
from subprocess import call
vulkan_reg_path = path.join(path.dirname(__file__), "..", "..", "third_party",
"vulkan-headers", "src", "registry")
sys.path.append(vulkan_reg_path)
from reg import Registry
registry = Registry()
registry.loadFile(open(path.join(vulkan_reg_path, "vk.xml")))
VULKAN_REQUIRED_API_VERSION = 'VK_API_VERSION_1_1'
VULKAN_UNASSOCIATED_FUNCTIONS = [
{
'functions': [
'vkEnumerateInstanceVersion',
'vkCreateInstance',
'vkEnumerateInstanceExtensionProperties',
'vkEnumerateInstanceLayerProperties',
]
}
]
VULKAN_INSTANCE_FUNCTIONS = [
{
'functions': [
'vkCreateDevice',
'vkDestroyInstance',
'vkEnumerateDeviceExtensionProperties',
'vkEnumerateDeviceLayerProperties',
'vkEnumeratePhysicalDevices',
'vkGetDeviceProcAddr',
'vkGetPhysicalDeviceExternalSemaphoreProperties',
'vkGetPhysicalDeviceFeatures2',
'vkGetPhysicalDeviceFormatProperties',
'vkGetPhysicalDeviceFormatProperties2',
'vkGetPhysicalDeviceImageFormatProperties2',
'vkGetPhysicalDeviceMemoryProperties',
'vkGetPhysicalDeviceMemoryProperties2',
'vkGetPhysicalDeviceProperties',
'vkGetPhysicalDeviceProperties2',
'vkGetPhysicalDeviceQueueFamilyProperties',
]
},
{
'ifdef': 'DCHECK_IS_ON()',
'extension': 'VK_EXT_DEBUG_REPORT_EXTENSION_NAME',
'functions': [
'vkCreateDebugReportCallbackEXT',
'vkDestroyDebugReportCallbackEXT',
]
},
{
'extension': 'VK_KHR_SURFACE_EXTENSION_NAME',
'functions': [
'vkDestroySurfaceKHR',
'vkGetPhysicalDeviceSurfaceCapabilitiesKHR',
'vkGetPhysicalDeviceSurfaceFormatsKHR',
'vkGetPhysicalDeviceSurfaceSupportKHR',
]
},
{
'extension': 'VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME',
'functions': [
'vkCreateHeadlessSurfaceEXT',
]
},
{
'ifdef': 'defined(USE_VULKAN_XCB)',
'extension': 'VK_KHR_XCB_SURFACE_EXTENSION_NAME',
'functions': [
'vkCreateXcbSurfaceKHR',
'vkGetPhysicalDeviceXcbPresentationSupportKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_WIN)',
'extension': 'VK_KHR_WIN32_SURFACE_EXTENSION_NAME',
'functions': [
'vkCreateWin32SurfaceKHR',
'vkGetPhysicalDeviceWin32PresentationSupportKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_ANDROID)',
'extension': 'VK_KHR_ANDROID_SURFACE_EXTENSION_NAME',
'functions': [
'vkCreateAndroidSurfaceKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
'extension': 'VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME',
'functions': [
'vkCreateImagePipeSurfaceFUCHSIA',
]
},
]
VULKAN_DEVICE_FUNCTIONS = [
{
'functions': [
'vkAllocateCommandBuffers',
'vkAllocateDescriptorSets',
'vkAllocateMemory',
'vkBeginCommandBuffer',
'vkBindBufferMemory',
'vkBindBufferMemory2',
'vkBindImageMemory',
'vkBindImageMemory2',
'vkCmdBeginRenderPass',
'vkCmdBindDescriptorSets',
'vkCmdBindPipeline',
'vkCmdBindVertexBuffers',
'vkCmdCopyBuffer',
'vkCmdCopyBufferToImage',
'vkCmdCopyImage',
'vkCmdCopyImageToBuffer',
'vkCmdDraw',
'vkCmdEndRenderPass',
'vkCmdExecuteCommands',
'vkCmdNextSubpass',
'vkCmdPipelineBarrier',
'vkCmdPushConstants',
'vkCmdSetScissor',
'vkCmdSetViewport',
'vkCreateBuffer',
'vkCreateCommandPool',
'vkCreateDescriptorPool',
'vkCreateDescriptorSetLayout',
'vkCreateFence',
'vkCreateFramebuffer',
'vkCreateGraphicsPipelines',
'vkCreateImage',
'vkCreateImageView',
'vkCreatePipelineLayout',
'vkCreateRenderPass',
'vkCreateSampler',
'vkCreateSemaphore',
'vkCreateShaderModule',
'vkDestroyBuffer',
'vkDestroyCommandPool',
'vkDestroyDescriptorPool',
'vkDestroyDescriptorSetLayout',
'vkDestroyDevice',
'vkDestroyFence',
'vkDestroyFramebuffer',
'vkDestroyImage',
'vkDestroyImageView',
'vkDestroyPipeline',
'vkDestroyPipelineLayout',
'vkDestroyRenderPass',
'vkDestroySampler',
'vkDestroySemaphore',
'vkDestroyShaderModule',
'vkDeviceWaitIdle',
'vkFlushMappedMemoryRanges',
'vkEndCommandBuffer',
'vkFreeCommandBuffers',
'vkFreeDescriptorSets',
'vkFreeMemory',
'vkInvalidateMappedMemoryRanges',
'vkGetBufferMemoryRequirements',
'vkGetBufferMemoryRequirements2',
'vkGetDeviceQueue',
'vkGetDeviceQueue2',
'vkGetFenceStatus',
'vkGetImageMemoryRequirements',
'vkGetImageMemoryRequirements2',
'vkGetImageSubresourceLayout',
'vkMapMemory',
'vkQueueSubmit',
'vkQueueWaitIdle',
'vkResetCommandBuffer',
'vkResetFences',
'vkUnmapMemory',
'vkUpdateDescriptorSets',
'vkWaitForFences',
]
},
{
'ifdef': 'BUILDFLAG(IS_ANDROID)',
'extension':
'VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME',
'functions': [
'vkGetAndroidHardwareBufferPropertiesANDROID',
]
},
{
'ifdef':
'BUILDFLAG(IS_POSIX)',
'extension': 'VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME',
'functions': [
'vkGetSemaphoreFdKHR',
'vkImportSemaphoreFdKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_WIN)',
'extension': 'VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME',
'functions': [
'vkGetSemaphoreWin32HandleKHR',
'vkImportSemaphoreWin32HandleKHR',
]
},
{
'ifdef':
'BUILDFLAG(IS_POSIX)',
'extension': 'VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME',
'functions': [
'vkGetMemoryFdKHR',
'vkGetMemoryFdPropertiesKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_WIN)',
'extension': 'VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME',
'functions': [
'vkGetMemoryWin32HandleKHR',
'vkGetMemoryWin32HandlePropertiesKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
'extension': 'VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME',
'functions': [
'vkImportSemaphoreZirconHandleFUCHSIA',
'vkGetSemaphoreZirconHandleFUCHSIA',
]
},
{
'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
'extension': 'VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME',
'functions': [
'vkGetMemoryZirconHandleFUCHSIA',
]
},
{
'ifdef': 'BUILDFLAG(IS_FUCHSIA)',
'extension': 'VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME',
'functions': [
'vkCreateBufferCollectionFUCHSIA',
'vkSetBufferCollectionImageConstraintsFUCHSIA',
'vkGetBufferCollectionPropertiesFUCHSIA',
'vkDestroyBufferCollectionFUCHSIA',
]
},
{
'extension': 'VK_KHR_SWAPCHAIN_EXTENSION_NAME',
'functions': [
'vkAcquireNextImageKHR',
'vkCreateSwapchainKHR',
'vkDestroySwapchainKHR',
'vkGetSwapchainImagesKHR',
'vkQueuePresentKHR',
]
},
{
'ifdef': 'BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)',
'extension': 'VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME',
'functions': [
'vkGetImageDrmFormatModifierPropertiesEXT',
]
}
]
SELF_LOCATION = os.path.dirname(os.path.abspath(__file__))
LICENSE_AND_HEADER = """\
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file is auto-generated from
// gpu/vulkan/generate_bindings.py
// It's formatted by clang-format using chromium coding style:
// clang-format -i -style=chromium filename
// DO NOT EDIT!
"""
def WriteReset(out_file, functions):
for group in functions:
if 'ifdef' in group:
out_file.write('#if %s\n' % group['ifdef'])
for func in group['functions']:
out_file.write('%s = nullptr;\n' % func)
if 'ifdef' in group:
out_file.write('#endif // %s\n' % group['ifdef'])
out_file.write('\n')
def WriteFunctionsInternal(out_file, functions, gen_content,
check_extension=False):
for group in functions:
if 'ifdef' in group:
out_file.write('#if %s\n' % group['ifdef'])
extension = group['extension'] if 'extension' in group else ''
min_api_version = \
group['min_api_version'] if 'min_api_version' in group else ''
if not check_extension:
for func in group['functions']:
out_file.write(gen_content(func))
elif not extension and not min_api_version:
for func in group['functions']:
out_file.write(gen_content(func))
else:
if min_api_version:
out_file.write(' if (api_version >= %s) {\n' % min_api_version)
for func in group['functions']:
out_file.write(
gen_content(func))
out_file.write('}\n')
if extension:
out_file.write('else ')
if extension:
out_file.write('if (gfx::HasExtension(enabled_extensions, %s)) {\n' %
extension)
extension_suffix = \
group['extension_suffix'] if 'extension_suffix' in group \
else ''
for func in group['functions']:
out_file.write(gen_content(func, extension_suffix))
out_file.write('}\n')
if 'ifdef' in group:
out_file.write('#endif // %s\n' % group['ifdef'])
out_file.write('\n')
def WriteFunctions(out_file, functions, template, check_extension=False):
def gen_content(func, suffix=''):
return template.substitute({'name': func,'extension_suffix': suffix})
WriteFunctionsInternal(out_file, functions, gen_content, check_extension)
def WriteFunctionDeclarations(out_file, functions):
template = Template(' VulkanFunction<PFN_${name}> ${name};\n')
WriteFunctions(out_file, functions, template)
def WriteMacros(out_file, functions):
def gen_content(func, suffix=''):
if func not in registry.cmddict:
template = Template(
'#define $name gpu::GetVulkanFunctionPointers()->${name}\n')
return template.substitute({'name': func, 'extension_suffix' : suffix})
none_str = lambda s: s if s else ''
cmd = registry.cmddict[func].elem
proto = cmd.find('proto')
params = cmd.findall('param')
pdecl = none_str(proto.text)
for elem in proto:
text = none_str(elem.text)
tail = none_str(elem.tail)
pdecl += text + tail
n = len(params)
callstat = ''
if func in ('vkQueueSubmit', 'vkQueueWaitIdle', 'vkQueuePresentKHR'):
callstat = 'gpu::VulkanQueueLock* lock = nullptr;\n'
callstat += '''auto it = gpu::GetVulkanFunctionPointers()->
per_queue_lock_map.find(queue);\n'''
callstat += '''if (it != gpu::GetVulkanFunctionPointers()->
per_queue_lock_map.end()) {\n'''
callstat += '\tlock = it->second.get();\n'
callstat += '}\n'
callstat += 'gpu::VulkanQueueAutoLockMaybe auto_lock(lock);\n'
callstat += 'return gpu::GetVulkanFunctionPointers()->%s(' % func
paramdecl = '('
if n > 0:
paramnames = (''.join(t for t in p.itertext())
for p in params)
paramdecl += ', '.join(paramnames)
paramnames = (''.join(p[1].text)
for p in params)
callstat += ', '.join(paramnames)
else:
paramdecl += 'void'
paramdecl += ')'
callstat += ')'
pdecl += paramdecl
return 'ALWAYS_INLINE %s { %s; }\n' % (pdecl, callstat)
WriteFunctionsInternal(out_file, functions, gen_content)
def GenerateHeaderFile(out_file):
"""Generates gpu/vulkan/vulkan_function_pointers.h"""
out_file.write(LICENSE_AND_HEADER +
"""
#ifndef GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
#define GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
#include <vulkan/vulkan.h>
// vulkan.h includes <X11/Xlib.h> when VK_USE_PLATFORM_XLIB_KHR is defined
// after https://github.com/KhronosGroup/Vulkan-Headers/pull/534.
// This defines some macros which break build, so undefine them here.
#undef Above
#undef AllTemporary
#undef AlreadyGrabbed
#undef Always
#undef AsyncBoth
#undef AsyncKeyboard
#undef AsyncPointer
#undef Below
#undef Bool
#undef BottomIf
#undef Button1
#undef Button2
#undef Button3
#undef Button4
#undef Button5
#undef ButtonPress
#undef ButtonRelease
#undef ClipByChildren
#undef Complex
#undef Convex
#undef CopyFromParent
#undef CurrentTime
#undef DestroyAll
#undef DirectColor
#undef DisplayString
#undef EnterNotify
#undef GrayScale
#undef IncludeInferiors
#undef InputFocus
#undef InputOnly
#undef InputOutput
#undef KeyPress
#undef KeyRelease
#undef LSBFirst
#undef LeaveNotify
#undef LowerHighest
#undef MSBFirst
#undef Nonconvex
#undef None
#undef NotUseful
#undef Opposite
#undef ParentRelative
#undef PointerRoot
#undef PointerWindow
#undef PseudoColor
#undef RaiseLowest
#undef ReplayKeyboard
#undef ReplayPointer
#undef RetainPermanent
#undef RetainTemporary
#undef StaticColor
#undef StaticGray
#undef Success
#undef SyncBoth
#undef SyncKeyboard
#undef SyncPointer
#undef TopIf
#undef TrueColor
#undef Unsorted
#undef WhenMapped
#undef XYBitmap
#undef XYPixmap
#undef YSorted
#undef YXBanded
#undef YXSorted
#undef ZPixmap
#include <memory>
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/native_library.h"
#include "build/build_config.h"
#include "gpu/vulkan/vulkan_queue_lock.h"
#include "ui/gfx/extension_set.h"
#if BUILDFLAG(IS_ANDROID)
#include <vulkan/vulkan_android.h>
#endif
#if BUILDFLAG(IS_FUCHSIA)
#include <zircon/types.h>
// <vulkan/vulkan_fuchsia.h> must be included after <zircon/types.h>
#include <vulkan/vulkan_fuchsia.h>
#include "gpu/vulkan/fuchsia/vulkan_fuchsia_ext.h"
#endif
#if defined(USE_VULKAN_XCB)
#include <xcb/xcb.h>
// <vulkan/vulkan_xcb.h> must be included after <xcb/xcb.h>
#include <vulkan/vulkan_xcb.h>
#endif
#if BUILDFLAG(IS_WIN)
#include <vulkan/vulkan_win32.h>
#endif
namespace gpu {
struct VulkanFunctionPointers;
constexpr uint32_t kVulkanRequiredApiVersion = %s;
COMPONENT_EXPORT(VULKAN) VulkanFunctionPointers* GetVulkanFunctionPointers();
struct COMPONENT_EXPORT(VULKAN) VulkanFunctionPointers {
VulkanFunctionPointers();
~VulkanFunctionPointers();
bool BindUnassociatedFunctionPointersFromLoaderLib(base::NativeLibrary lib);
bool BindUnassociatedFunctionPointersFromGetProcAddr(
PFN_vkGetInstanceProcAddr proc);
// These functions assume that vkGetInstanceProcAddr has been populated.
bool BindInstanceFunctionPointers(
VkInstance vk_instance,
uint32_t api_version,
const gfx::ExtensionSet& enabled_extensions);
// These functions assume that vkGetDeviceProcAddr has been populated.
bool BindDeviceFunctionPointers(
VkDevice vk_device,
uint32_t api_version,
const gfx::ExtensionSet& enabled_extensions);
void ResetForTesting();
// This is used to allow thread safe access to a given vulkan queue when
// multiple gpu threads are accessing it. Note that this map will be only
// accessed by multiple gpu threads concurrently to read the data, so it
// should be thread safe to use this map by multiple threads.
base::flat_map<VkQueue, std::unique_ptr<VulkanQueueLock>> per_queue_lock_map;
template<typename T>
class VulkanFunction;
template <typename R, typename ...Args>
class VulkanFunction <R(VKAPI_PTR*)(Args...)> {
public:
using Fn = R(VKAPI_PTR*)(Args...);
explicit operator bool() const {
return !!fn_;
}
NO_SANITIZE("cfi-icall")
R operator()(Args... args) const {
return fn_(args...);
}
Fn get() const { return fn_; }
void OverrideForTesting(Fn fn) { fn_ = fn; }
private:
friend VulkanFunctionPointers;
Fn operator=(Fn fn) {
fn_ = fn;
return fn_;
}
Fn fn_ = nullptr;
};
// Unassociated functions
VulkanFunction<PFN_vkGetInstanceProcAddr> vkGetInstanceProcAddr;
""" % VULKAN_REQUIRED_API_VERSION)
WriteFunctionDeclarations(out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
out_file.write("""\
// Instance functions
""")
WriteFunctionDeclarations(out_file, VULKAN_INSTANCE_FUNCTIONS);
out_file.write("""\
// Device functions
""")
WriteFunctionDeclarations(out_file, VULKAN_DEVICE_FUNCTIONS)
out_file.write("""\
private:
bool BindUnassociatedFunctionPointersCommon();
// The `Bind*` functions will acquires lock, so should not be called with
// with this lock held. Code that writes to members directly should take this
// lock as well.
base::Lock write_lock_;
base::NativeLibrary loader_library_ = nullptr;
};
} // namespace gpu
// Unassociated functions
""")
WriteMacros(out_file, [{'functions': [ 'vkGetInstanceProcAddr']}])
WriteMacros(out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
out_file.write("""\
// Instance functions
""")
WriteMacros(out_file, VULKAN_INSTANCE_FUNCTIONS);
out_file.write("""\
// Device functions
""")
WriteMacros(out_file, VULKAN_DEVICE_FUNCTIONS)
out_file.write("""\
#endif // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_""")
def WriteFunctionPointerInitialization(out_file, proc_addr_function, parent,
functions):
template = Template(""" constexpr char k${name}${extension_suffix}[] =
"${name}${extension_suffix}";
${name} = reinterpret_cast<PFN_${name}>(
${get_proc_addr}(${parent}, k${name}${extension_suffix}));
if (!${name}) {
LogGetProcError(k${name}${extension_suffix});
return false;
}
""")
template = Template(template.substitute({
'name': '${name}', 'extension_suffix': '${extension_suffix}',
'get_proc_addr': proc_addr_function, 'parent': parent}))
WriteFunctions(out_file, functions, template, check_extension=True)
def WriteUnassociatedFunctionPointerInitialization(out_file, functions):
WriteFunctionPointerInitialization(out_file, 'vkGetInstanceProcAddr',
'nullptr', functions)
def WriteInstanceFunctionPointerInitialization(out_file, functions):
WriteFunctionPointerInitialization(out_file, 'vkGetInstanceProcAddr',
'vk_instance', functions)
def WriteDeviceFunctionPointerInitialization(out_file, functions):
WriteFunctionPointerInitialization(out_file, 'vkGetDeviceProcAddr',
'vk_device', functions)
def GenerateSourceFile(out_file):
"""Generates gpu/vulkan/vulkan_function_pointers.cc"""
out_file.write(LICENSE_AND_HEADER +
"""
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/no_destructor.h"
namespace gpu {
namespace {
NOINLINE void LogGetProcError(const char* funcName) {
LOG(WARNING) << "Failed to bind vulkan entrypoint: " << funcName;
}
}
VulkanFunctionPointers* GetVulkanFunctionPointers() {
static base::NoDestructor<VulkanFunctionPointers> vulkan_function_pointers;
return vulkan_function_pointers.get();
}
VulkanFunctionPointers::VulkanFunctionPointers() = default;
VulkanFunctionPointers::~VulkanFunctionPointers() = default;
bool VulkanFunctionPointers::BindUnassociatedFunctionPointersFromLoaderLib(
base::NativeLibrary lib) {
base::AutoLock lock(write_lock_);
loader_library_ = lib;
// vkGetInstanceProcAddr must be handled specially since it gets its
// function pointer through base::GetFunctionPointerFromNativeLibrary().
// Other Vulkan functions don't do this.
vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
base::GetFunctionPointerFromNativeLibrary(loader_library_,
"vkGetInstanceProcAddr"));
if (!vkGetInstanceProcAddr) {
LOG(WARNING) << "Failed to find vkGetInstanceProcAddr";
return false;
}
return BindUnassociatedFunctionPointersCommon();
}
bool VulkanFunctionPointers::BindUnassociatedFunctionPointersFromGetProcAddr(
PFN_vkGetInstanceProcAddr proc) {
DCHECK(proc);
DCHECK(!loader_library_);
base::AutoLock lock(write_lock_);
vkGetInstanceProcAddr = proc;
return BindUnassociatedFunctionPointersCommon();
}
bool VulkanFunctionPointers::BindUnassociatedFunctionPointersCommon() {
""")
WriteUnassociatedFunctionPointerInitialization(
out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
out_file.write("""\
return true;
}
bool VulkanFunctionPointers::BindInstanceFunctionPointers(
VkInstance vk_instance,
uint32_t api_version,
const gfx::ExtensionSet& enabled_extensions) {
DCHECK_GE(api_version, kVulkanRequiredApiVersion);
base::AutoLock lock(write_lock_);
""")
WriteInstanceFunctionPointerInitialization(
out_file, VULKAN_INSTANCE_FUNCTIONS);
out_file.write("""\
return true;
}
bool VulkanFunctionPointers::BindDeviceFunctionPointers(
VkDevice vk_device,
uint32_t api_version,
const gfx::ExtensionSet& enabled_extensions) {
DCHECK_GE(api_version, kVulkanRequiredApiVersion);
base::AutoLock lock(write_lock_);
// Device functions
""")
WriteDeviceFunctionPointerInitialization(out_file, VULKAN_DEVICE_FUNCTIONS)
out_file.write("""\
return true;
}
void VulkanFunctionPointers::ResetForTesting() {
base::AutoLock lock(write_lock_);
per_queue_lock_map.clear();
loader_library_ = nullptr;
vkGetInstanceProcAddr = nullptr;
""")
WriteReset(
out_file, VULKAN_UNASSOCIATED_FUNCTIONS)
WriteReset(
out_file, VULKAN_INSTANCE_FUNCTIONS)
WriteReset(
out_file, VULKAN_DEVICE_FUNCTIONS)
out_file.write("""\
}
} // namespace gpu
""")
def main(argv):
"""This is the main function."""
parser = optparse.OptionParser()
parser.add_option(
"--output-dir",
help="Output directory for generated files. Defaults to this script's "
"directory.")
parser.add_option(
"-c", "--check", action="store_true",
help="Check if output files match generated files in chromium root "
"directory. Use this in PRESUBMIT scripts with --output-dir.")
(options, _) = parser.parse_args(args=argv)
if options.output_dir:
output_dir = options.output_dir
else:
output_dir = SELF_LOCATION
def ClangFormat(filename):
formatter = "clang-format"
if platform.system() == "Windows":
formatter += ".bat"
call([formatter, "-i", "-style=chromium", filename])
header_file_name = 'vulkan_function_pointers.h'
header_file = open(
os.path.join(output_dir, header_file_name), 'w', newline='\n')
GenerateHeaderFile(header_file)
header_file.close()
ClangFormat(header_file.name)
source_file_name = 'vulkan_function_pointers.cc'
source_file = open(
os.path.join(output_dir, source_file_name), 'w', newline='\n')
GenerateSourceFile(source_file)
source_file.close()
ClangFormat(source_file.name)
check_failed_filenames = []
if options.check:
for filename in [header_file_name, source_file_name]:
if not filecmp.cmp(os.path.join(output_dir, filename),
os.path.join(SELF_LOCATION, filename)):
check_failed_filenames.append(filename)
if len(check_failed_filenames) > 0:
print('Please run gpu/vulkan/generate_bindings.py')
print('Failed check on generated files:')
for filename in check_failed_filenames:
print(filename)
return 1
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))