blob: 38063df328abfb31d152d008ba644cef4af3a27c [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""code generator for Vulkan function pointers."""
import optparse
import os
import platform
import sys
from string import Template
from subprocess import call
VULKAN_UNASSOCIATED_FUNCTIONS = [
# vkGetInstanceProcAddr belongs here but is handled specially.
# vkEnumerateInstanceVersion belongs here but is handled specially.
{ 'name': 'vkCreateInstance' },
{ 'name': 'vkEnumerateInstanceExtensionProperties' },
{ 'name': 'vkEnumerateInstanceLayerProperties' },
]
VULKAN_INSTANCE_FUNCTIONS = [
{ 'name': 'vkDestroyInstance' },
# vkDestroySurfaceKHR belongs here but is handled specially.
{ 'name': 'vkEnumeratePhysicalDevices' },
{ 'name': 'vkGetDeviceProcAddr' },
]
VULKAN_PHYSICAL_DEVICE_FUNCTIONS = [
{ 'name': 'vkCreateDevice' },
{ 'name': 'vkEnumerateDeviceLayerProperties' },
{ 'name': 'vkGetPhysicalDeviceQueueFamilyProperties' },
# The following functions belong here but are handled specially:
# vkGetPhysicalDeviceSurfaceCapabilitiesKHR
# vkGetPhysicalDeviceSurfaceFormatsKHR
# vkGetPhysicalDeviceSurfaceSupportKHR
]
VULKAN_DEVICE_FUNCTIONS = [
{ 'name': 'vkAllocateCommandBuffers' },
{ 'name': 'vkAllocateDescriptorSets' },
{ 'name': 'vkAllocateMemory' },
{ 'name': 'vkBindImageMemory' },
{ 'name': 'vkCreateCommandPool' },
{ 'name': 'vkCreateDescriptorPool' },
{ 'name': 'vkCreateDescriptorSetLayout' },
{ 'name': 'vkCreateFence' },
{ 'name': 'vkCreateFramebuffer' },
{ 'name': 'vkCreateImage' },
{ 'name': 'vkCreateImageView' },
{ 'name': 'vkCreateRenderPass' },
{ 'name': 'vkCreateSampler' },
{ 'name': 'vkCreateSemaphore' },
{ 'name': 'vkCreateShaderModule' },
{ 'name': 'vkDestroyCommandPool' },
{ 'name': 'vkDestroyDescriptorPool' },
{ 'name': 'vkDestroyDescriptorSetLayout' },
{ 'name': 'vkDestroyDevice' },
{ 'name': 'vkDestroyFramebuffer' },
{ 'name': 'vkDestroyFence' },
{ 'name': 'vkDestroyImage' },
{ 'name': 'vkDestroyImageView' },
{ 'name': 'vkDestroyRenderPass' },
{ 'name': 'vkDestroySampler' },
{ 'name': 'vkDestroySemaphore' },
{ 'name': 'vkDestroyShaderModule' },
{ 'name': 'vkDeviceWaitIdle' },
{ 'name': 'vkFreeCommandBuffers' },
{ 'name': 'vkFreeDescriptorSets' },
{ 'name': 'vkFreeMemory' },
{ 'name': 'vkGetDeviceQueue' },
{ 'name': 'vkGetFenceStatus' },
{ 'name': 'vkGetImageMemoryRequirements' },
{ 'name': 'vkResetFences' },
{ 'name': 'vkUpdateDescriptorSets' },
{ 'name': 'vkWaitForFences' },
]
VULKAN_DEVICE_FUNCTIONS_ANDROID = [
{ 'name': 'vkGetAndroidHardwareBufferPropertiesANDROID' },
{ 'name': 'vkImportSemaphoreFdKHR' },
]
VULKAN_DEVICE_FUNCTIONS_LINUX_OR_ANDROID = [
{ 'name': 'vkGetSemaphoreFdKHR' },
]
VULKAN_DEVICE_FUNCTIONS_LINUX = [
{ 'name': 'vkGetMemoryFdKHR'},
]
VULKAN_QUEUE_FUNCTIONS = [
{ 'name': 'vkQueueSubmit' },
{ 'name': 'vkQueueWaitIdle' },
]
VULKAN_COMMAND_BUFFER_FUNCTIONS = [
{ 'name': 'vkBeginCommandBuffer' },
{ 'name': 'vkCmdBeginRenderPass' },
{ 'name': 'vkCmdEndRenderPass' },
{ 'name': 'vkCmdExecuteCommands' },
{ 'name': 'vkCmdNextSubpass' },
{ 'name': 'vkCmdPipelineBarrier' },
{ 'name': 'vkEndCommandBuffer' },
{ 'name': 'vkResetCommandBuffer' },
]
VULKAN_SWAPCHAIN_FUNCTIONS = [
{ 'name': 'vkAcquireNextImageKHR' },
{ 'name': 'vkCreateSwapchainKHR' },
{ 'name': 'vkDestroySwapchainKHR' },
{ 'name': 'vkGetSwapchainImagesKHR' },
{ 'name': 'vkQueuePresentKHR' },
]
SELF_LOCATION = os.path.dirname(os.path.abspath(__file__))
LICENSE_AND_HEADER = """\
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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 WriteFunctionDeclarations(file, functions):
template = Template(' PFN_${name} ${name}Fn = nullptr;\n')
for func in functions:
file.write(template.substitute(func))
def WriteMacros(file, functions):
template = Template(
'#define $name gpu::GetVulkanFunctionPointers()->${name}Fn\n')
for func in functions:
file.write(template.substitute(func))
def GenerateHeaderFile(file, unassociated_functions, instance_functions,
physical_device_functions, device_functions,
device_functions_android,
device_functions_linux_or_android,
device_functions_linux, queue_functions,
command_buffer_functions, swapchain_functions):
"""Generates gpu/vulkan/vulkan_function_pointers.h"""
file.write(LICENSE_AND_HEADER +
"""
#ifndef GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
#define GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
#include <vulkan/vulkan.h>
#if defined(OS_ANDROID)
#include <vulkan/vulkan_android.h>
#endif
#include "base/native_library.h"
#include "build/build_config.h"
#include "gpu/vulkan/vulkan_export.h"
namespace gpu {
struct VulkanFunctionPointers;
VULKAN_EXPORT VulkanFunctionPointers* GetVulkanFunctionPointers();
struct VulkanFunctionPointers {
VulkanFunctionPointers();
~VulkanFunctionPointers();
VULKAN_EXPORT bool BindUnassociatedFunctionPointers();
// These functions assume that vkGetInstanceProcAddr has been populated.
VULKAN_EXPORT bool BindInstanceFunctionPointers(VkInstance vk_instance);
VULKAN_EXPORT bool BindPhysicalDeviceFunctionPointers(VkInstance vk_instance);
// These functions assume that vkGetDeviceProcAddr has been populated.
VULKAN_EXPORT bool BindDeviceFunctionPointers(VkDevice vk_device);
bool BindSwapchainFunctionPointers(VkDevice vk_device);
base::NativeLibrary vulkan_loader_library_ = nullptr;
// Unassociated functions
PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersionFn = nullptr;
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddrFn = nullptr;
""")
WriteFunctionDeclarations(file, unassociated_functions)
file.write("""\
// Instance functions
""")
WriteFunctionDeclarations(file, instance_functions)
file.write("""\
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHRFn = nullptr;
// Physical Device functions
""")
WriteFunctionDeclarations(file, physical_device_functions)
file.write("""\
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
vkGetPhysicalDeviceSurfaceCapabilitiesKHRFn = nullptr;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
vkGetPhysicalDeviceSurfaceFormatsKHRFn = nullptr;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR
vkGetPhysicalDeviceSurfaceSupportKHRFn = nullptr;
// Device functions
""")
WriteFunctionDeclarations(file, device_functions)
file.write("""\
// Android only device functions.
#if defined(OS_ANDROID)
""")
WriteFunctionDeclarations(file, device_functions_android)
file.write("""\
#endif
""")
file.write("""\
// Device functions shared between Linux and Android.
#if defined(OS_LINUX) || defined(OS_ANDROID)
""")
WriteFunctionDeclarations(file, device_functions_linux_or_android)
file.write("""\
#endif
""")
file.write("""\
// Linux-only device functions.
#if defined(OS_LINUX)
""")
WriteFunctionDeclarations(file, device_functions_linux)
file.write("""\
#endif
""")
file.write("""\
// Queue functions
""")
WriteFunctionDeclarations(file, queue_functions)
file.write("""\
// Command Buffer functions
""")
WriteFunctionDeclarations(file, command_buffer_functions)
file.write("""\
// Swapchain functions
""")
WriteFunctionDeclarations(file, swapchain_functions)
file.write("""\
};
} // namespace gpu
// Unassociated functions
""")
WriteMacros(file, [ { 'name': 'vkGetInstanceProcAddr' } ])
WriteMacros(file, unassociated_functions)
file.write("""\
// Instance functions
""")
WriteMacros(file, instance_functions)
WriteMacros(file, [ { 'name': 'vkDestroySurfaceKHR' } ])
file.write("""\
// Physical Device functions
""")
WriteMacros(file, physical_device_functions)
WriteMacros(file, [
{ 'name': 'vkGetPhysicalDeviceSurfaceCapabilitiesKHR' },
{ 'name': 'vkGetPhysicalDeviceSurfaceFormatsKHR' },
{ 'name': 'vkGetPhysicalDeviceSurfaceSupportKHR' },
])
file.write("""\
// Device functions
""")
WriteMacros(file, device_functions)
file.write("""\
#if defined(OS_ANDROID)
""")
WriteMacros(file, device_functions_android)
file.write("""\
#endif
""")
file.write("""\
#if defined(OS_LINUX) || defined(OS_ANDROID)
""")
WriteMacros(file, device_functions_linux_or_android)
file.write("""\
#endif
""")
file.write("""\
#if defined(OS_LINUX)
""")
WriteMacros(file, device_functions_linux)
file.write("""\
#endif
""")
file.write("""\
// Queue functions
""")
WriteMacros(file, queue_functions)
file.write("""\
// Command buffer functions
""")
WriteMacros(file, command_buffer_functions)
file.write("""\
// Swapchain functions
""")
WriteMacros(file, swapchain_functions)
file.write("""\
#endif // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
""")
def WriteFunctionPointerInitialization(file, proc_addr_function, parent,
functions):
template = Template(""" ${name}Fn = reinterpret_cast<PFN_${name}>(
$get_proc_addr($parent, "$name"));
if (!${name}Fn)
return false;
""")
for func in functions:
file.write(template.substitute(name=func['name'], get_proc_addr =
proc_addr_function, parent=parent))
def WriteUnassociatedFunctionPointerInitialization(file, functions):
WriteFunctionPointerInitialization(file, 'vkGetInstanceProcAddrFn', 'nullptr',
functions)
def WriteInstanceFunctionPointerInitialization(file, functions):
WriteFunctionPointerInitialization(file, 'vkGetInstanceProcAddrFn',
'vk_instance', functions)
def WriteDeviceFunctionPointerInitialization(file, functions):
WriteFunctionPointerInitialization(file, 'vkGetDeviceProcAddrFn', 'vk_device',
functions)
def GenerateSourceFile(file, unassociated_functions, instance_functions,
physical_device_functions, device_functions,
device_functions_android,
device_functions_linux_or_android,
device_functions_linux, queue_functions,
command_buffer_functions, swapchain_functions):
"""Generates gpu/vulkan/vulkan_function_pointers.cc"""
file.write(LICENSE_AND_HEADER +
"""
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "base/no_destructor.h"
namespace gpu {
VulkanFunctionPointers* GetVulkanFunctionPointers() {
static base::NoDestructor<VulkanFunctionPointers> vulkan_function_pointers;
return vulkan_function_pointers.get();
}
VulkanFunctionPointers::VulkanFunctionPointers() = default;
VulkanFunctionPointers::~VulkanFunctionPointers() = default;
bool VulkanFunctionPointers::BindUnassociatedFunctionPointers() {
// vkGetInstanceProcAddr must be handled specially since it gets its function
// pointer through base::GetFunctionPOinterFromNativeLibrary(). Other Vulkan
// functions don't do this.
vkGetInstanceProcAddrFn = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
base::GetFunctionPointerFromNativeLibrary(vulkan_loader_library_,
"vkGetInstanceProcAddr"));
if (!vkGetInstanceProcAddrFn)
return false;
vkEnumerateInstanceVersionFn =
reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
vkGetInstanceProcAddrFn(nullptr, "vkEnumerateInstanceVersion"));
// vkEnumerateInstanceVersion didn't exist in Vulkan 1.0, so we should
// proceed even if we fail to get vkEnumerateInstanceVersion pointer.
""")
WriteUnassociatedFunctionPointerInitialization(file, unassociated_functions)
file.write("""\
return true;
}
bool VulkanFunctionPointers::BindInstanceFunctionPointers(
VkInstance vk_instance) {
""")
WriteInstanceFunctionPointerInitialization(file, instance_functions)
file.write("""\
return true;
}
bool VulkanFunctionPointers::BindPhysicalDeviceFunctionPointers(
VkInstance vk_instance) {
""")
WriteInstanceFunctionPointerInitialization(file, physical_device_functions)
file.write("""\
return true;
}
bool VulkanFunctionPointers::BindDeviceFunctionPointers(VkDevice vk_device) {
// Device functions
""")
WriteDeviceFunctionPointerInitialization(file, device_functions)
file.write("""\
#if defined(OS_ANDROID)
""")
WriteDeviceFunctionPointerInitialization(file, device_functions_android)
file.write("""\
#endif
""")
file.write("""\
#if defined(OS_LINUX) || defined(OS_ANDROID)
""")
WriteDeviceFunctionPointerInitialization(file,
device_functions_linux_or_android)
file.write("""\
#endif
""")
file.write("""\
#if defined(OS_LINUX)
""")
WriteDeviceFunctionPointerInitialization(file,
device_functions_linux)
file.write("""\
#endif
""")
file.write("""\
// Queue functions
""")
WriteDeviceFunctionPointerInitialization(file, queue_functions)
file.write("""\
// Command Buffer functions
""")
WriteDeviceFunctionPointerInitialization(file, command_buffer_functions)
file.write("""\
return true;
}
bool VulkanFunctionPointers::BindSwapchainFunctionPointers(VkDevice vk_device) {
""")
WriteDeviceFunctionPointerInitialization(file, swapchain_functions)
file.write("""\
return true;
}
} // namespace gpu
""")
def main(argv):
"""This is the main function."""
parser = optparse.OptionParser()
_, args = parser.parse_args(argv)
directory = SELF_LOCATION
if len(args) >= 1:
directory = args[0]
def ClangFormat(filename):
formatter = "clang-format"
if platform.system() == "Windows":
formatter += ".bat"
call([formatter, "-i", "-style=chromium", filename])
header_file = open(
os.path.join(directory, 'vulkan_function_pointers.h'), 'wb')
GenerateHeaderFile(header_file, VULKAN_UNASSOCIATED_FUNCTIONS,
VULKAN_INSTANCE_FUNCTIONS,
VULKAN_PHYSICAL_DEVICE_FUNCTIONS, VULKAN_DEVICE_FUNCTIONS,
VULKAN_DEVICE_FUNCTIONS_ANDROID,
VULKAN_DEVICE_FUNCTIONS_LINUX_OR_ANDROID,
VULKAN_DEVICE_FUNCTIONS_LINUX,
VULKAN_QUEUE_FUNCTIONS, VULKAN_COMMAND_BUFFER_FUNCTIONS,
VULKAN_SWAPCHAIN_FUNCTIONS)
header_file.close()
ClangFormat(header_file.name)
source_file = open(
os.path.join(directory, 'vulkan_function_pointers.cc'), 'wb')
GenerateSourceFile(source_file, VULKAN_UNASSOCIATED_FUNCTIONS,
VULKAN_INSTANCE_FUNCTIONS,
VULKAN_PHYSICAL_DEVICE_FUNCTIONS, VULKAN_DEVICE_FUNCTIONS,
VULKAN_DEVICE_FUNCTIONS_ANDROID,
VULKAN_DEVICE_FUNCTIONS_LINUX_OR_ANDROID,
VULKAN_DEVICE_FUNCTIONS_LINUX,
VULKAN_QUEUE_FUNCTIONS, VULKAN_COMMAND_BUFFER_FUNCTIONS,
VULKAN_SWAPCHAIN_FUNCTIONS)
source_file.close()
ClangFormat(source_file.name)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))