Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ca5d0c5 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

Vulkan: add docs for the framework generation scripts

Bug: 134185757
Test: ./scripts/code_generator.py && build
Change-Id: I108412fdc672c5513f570ddac9221074a0027cd0
parent 1ca59c17
Loading
Loading
Loading
Loading
+35 −3
Original line number Diff line number Diff line
@@ -13,13 +13,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script provides the functions required for generating the
# vulkan api framework directly from the vulkan registry (vk.xml)

"""Generates the api_gen.h and api_gen.cpp.
"""

import os
import generator_common as gencom

# Functions intercepted at vulkan::api level.
_INTERCEPTED_COMMANDS = [
    'vkCreateDevice',
    'vkDestroyDevice',
@@ -30,6 +31,8 @@ _INTERCEPTED_COMMANDS = [


def gen_h():
  """Generates the api_gen.h file.
  """
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'libvulkan', 'api_gen.h')

@@ -100,6 +103,12 @@ bool InitDispatchTable(


def _define_extension_stub(cmd, f):
  """Emits a stub for an exported extension function.

  Args:
    cmd: Vulkan function name.
    f: Output file handle.
  """
  if (cmd in gencom.extension_dict and gencom.is_function_exported(cmd)):
    ext_name = gencom.extension_dict[cmd]
    ret = gencom.return_type_dict[cmd]
@@ -121,6 +130,11 @@ def _define_extension_stub(cmd, f):


def _is_intercepted(cmd):
  """Returns true if a function is intercepted by vulkan::api.

  Args:
    cmd: Vulkan function name.
  """
  if gencom.is_function_supported(cmd):
    if gencom.is_globally_dispatched(cmd) or cmd in _INTERCEPTED_COMMANDS:
      return True
@@ -128,6 +142,11 @@ def _is_intercepted(cmd):


def _intercept_instance_proc_addr(f):
  """Emits code for vkGetInstanceProcAddr for function interception.

  Args:
    f: Output file handle.
  """
  f.write("""\
    // global functions
    if (instance == VK_NULL_HANDLE) {\n""")
@@ -180,6 +199,11 @@ def _intercept_instance_proc_addr(f):


def _intercept_device_proc_addr(f):
  """Emits code for vkGetDeviceProcAddr for function interception.

  Args:
    f: Output file handle.
  """
  f.write("""\
    if (device == VK_NULL_HANDLE) {
        ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
@@ -220,6 +244,12 @@ def _intercept_device_proc_addr(f):


def _api_dispatch(cmd, f):
  """Emits code to dispatch a function.

  Args:
    cmd: Vulkan function name.
    f: Output file handle.
  """
  assert not _is_intercepted(cmd)

  f.write(gencom.indent(1))
@@ -233,6 +263,8 @@ def _api_dispatch(cmd, f):


def gen_cpp():
  """Generates the api_gen.cpp file.
  """
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'libvulkan', 'api_gen.cpp')

+3 −3
Original line number Diff line number Diff line
@@ -13,9 +13,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script provides the main function for generating
# vulkan framework directly from the vulkan registry (vk.xml).

"""Generates vulkan framework directly from the vulkan registry (vk.xml).
"""

import api_generator
import driver_generator
+60 −3
Original line number Diff line number Diff line
@@ -13,13 +13,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script provides the functions for generating the
# vulkan driver framework directly from the vulkan registry (vk.xml).

"""Generates the driver_gen.h and driver_gen.cpp.
"""

import os
import generator_common as gencom

# Extensions intercepted at vulkan::driver level.
_INTERCEPTED_EXTENSIONS = [
    'VK_ANDROID_native_buffer',
    'VK_EXT_debug_report',
@@ -34,12 +35,14 @@ _INTERCEPTED_EXTENSIONS = [
    'VK_KHR_swapchain',
]

# Extensions known to vulkan::driver level.
_KNOWN_EXTENSIONS = _INTERCEPTED_EXTENSIONS + [
    'VK_ANDROID_external_memory_android_hardware_buffer',
    'VK_KHR_bind_memory2',
    'VK_KHR_get_physical_device_properties2',
]

# Functions needed at vulkan::driver level.
_NEEDED_COMMANDS = [
    # Create functions of dispatchable objects
    'vkCreateDevice',
@@ -76,6 +79,7 @@ _NEEDED_COMMANDS = [
    'vkBindImageMemory2KHR',
]

# Functions intercepted at vulkan::driver level.
_INTERCEPTED_COMMANDS = [
    # Create functions of dispatchable objects
    'vkCreateInstance',
@@ -106,6 +110,11 @@ _INTERCEPTED_COMMANDS = [


def _is_driver_table_entry(cmd):
  """Returns true if a function is needed by vulkan::driver.

  Args:
    cmd: Vulkan function name.
  """
  if gencom.is_function_supported(cmd):
    if cmd in _NEEDED_COMMANDS:
      return True
@@ -117,16 +126,28 @@ def _is_driver_table_entry(cmd):


def _is_instance_driver_table_entry(cmd):
  """Returns true if a instance-dispatched function is needed by vulkan::driver.

  Args:
    cmd: Vulkan function name.
  """
  return (_is_driver_table_entry(cmd) and
          gencom.is_instance_dispatched(cmd))


def _is_device_driver_table_entry(cmd):
  """Returns true if a device-dispatched function is needed by vulkan::driver.

  Args:
    cmd: Vulkan function name.
  """
  return (_is_driver_table_entry(cmd) and
          gencom.is_device_dispatched(cmd))


def gen_h():
  """Generates the driver_gen.h file.
  """
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'libvulkan', 'driver_gen.h')

@@ -214,6 +235,11 @@ bool InitDriverTable(VkDevice dev,


def _is_intercepted(cmd):
  """Returns true if a function is intercepted by vulkan::driver.

  Args:
    cmd: Vulkan function name.
  """
  if gencom.is_function_supported(cmd):
    if cmd in _INTERCEPTED_COMMANDS:
      return True
@@ -224,6 +250,11 @@ def _is_intercepted(cmd):


def _need_proc_hook_stub(cmd):
  """Returns true if a function needs a ProcHook stub.

  Args:
    cmd: Vulkan function name.
  """
  if _is_intercepted(cmd) and gencom.is_device_dispatched(cmd):
    if cmd in gencom.extension_dict:
      if not gencom.is_extension_internal(gencom.extension_dict[cmd]):
@@ -232,6 +263,12 @@ def _need_proc_hook_stub(cmd):


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 = gencom.extension_dict[cmd]
@@ -259,6 +296,12 @@ def _define_proc_hook_stub(cmd, f):


def _define_global_proc_hook(cmd, f):
  """Emits definition of a global ProcHook.

  Args:
    cmd: Vulkan function name.
    f: Output file handle.
  """
  assert cmd not in gencom.extension_dict

  f.write(gencom.indent(1) + '{\n')
@@ -272,6 +315,12 @@ def _define_global_proc_hook(cmd, f):


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')
@@ -298,6 +347,12 @@ def _define_instance_proc_hook(cmd, f):


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')
@@ -326,6 +381,8 @@ def _define_device_proc_hook(cmd, f):


def gen_cpp():
  """Generates the driver_gen.cpp file.
  """
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'libvulkan', 'driver_gen.cpp')

+112 −3
Original line number Diff line number Diff line
@@ -13,14 +13,15 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script provides the common functions for generating the
# vulkan framework directly from the vulkan registry (vk.xml).

"""Provide the utilities for framework generation.
"""

import os
import subprocess
import xml.etree.ElementTree as element_tree

# Extensions unsupported on Android.
_BLACKLISTED_EXTENSIONS = [
    'VK_EXT_acquire_xlib_display',
    'VK_EXT_direct_mode_display',
@@ -52,6 +53,7 @@ _BLACKLISTED_EXTENSIONS = [
    'VK_NVX_image_view_handle',
]

# Extensions having functions exported by the loader.
_EXPORTED_EXTENSIONS = [
    'VK_ANDROID_external_memory_android_hardware_buffer',
    'VK_KHR_android_surface',
@@ -59,11 +61,13 @@ _EXPORTED_EXTENSIONS = [
    'VK_KHR_swapchain',
]

# Functions optional on Android even if extension is advertised.
_OPTIONAL_COMMANDS = [
    'vkGetSwapchainGrallocUsageANDROID',
    'vkGetSwapchainGrallocUsage2ANDROID',
]

# Dict for mapping dispatch table to a type.
_DISPATCH_TYPE_DICT = {
    'VkInstance ': 'Instance',
    'VkPhysicalDevice ': 'Instance',
@@ -72,19 +76,40 @@ _DISPATCH_TYPE_DICT = {
    'VkCommandBuffer ': 'Device'
}

# Dict for mapping a function to its alias.
alias_dict = {}

# List of all the Vulkan functions.
command_list = []

# Dict for mapping a function to an extension.
extension_dict = {}

# Dict for mapping a function to all its parameters.
param_dict = {}

# Dict for mapping a function to its return type.
return_type_dict = {}

# Dict for mapping a function to the core Vulkan API version.
version_dict = {}


def indent(num):
  """Returns the requested indents.

  Args:
    num: Number of the 4-space indents.
  """
  return '    ' * num


def copyright_and_warning(year):
  """Returns the standard copyright and warning codes.

  Args:
    year: An integer year for the copyright.
  """
  return """\
/*
 * Copyright """ + str(year) + """ The Android Open Source Project
@@ -108,19 +133,41 @@ def copyright_and_warning(year):


def run_clang_format(args):
  """Run clang format on the file.

  Args:
    args: The file to be formatted.
  """
  clang_call = ['clang-format', '--style', 'file', '-i', args]
  subprocess.check_call(clang_call)


def is_extension_internal(extension_name):
  """Returns true if an extension is internal to the loader and drivers.

  The loader should not enumerate this extension.

  Args:
    extension_name: Vulkan extension name.
  """
  return extension_name == 'VK_ANDROID_native_buffer'


def base_name(cmd):
  """Returns a function name without the 'vk' prefix.

  Args:
    cmd: Vulkan function name.
  """
  return cmd[2:]


def is_function_supported(cmd):
  """Returns true if a function is core or from a supportable extension.

  Args:
    cmd: Vulkan function name.
  """
  if cmd not in extension_dict:
    return True
  else:
@@ -130,6 +177,11 @@ def is_function_supported(cmd):


def get_dispatch_table_type(cmd):
  """Returns the dispatch table type for a function.

  Args:
    cmd: Vulkan function name.
  """
  if cmd not in param_dict:
    return None

@@ -139,23 +191,55 @@ def get_dispatch_table_type(cmd):


def is_globally_dispatched(cmd):
  """Returns true if the function is global, which is not dispatched.

  Only global functions and functions handled in the loader top without calling
  into lower layers are not dispatched.

  Args:
    cmd: Vulkan function name.
  """
  return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'


def is_instance_dispatched(cmd):
  """Returns true for functions that can have instance-specific dispatch.

  Args:
    cmd: Vulkan function name.
  """
  return (is_function_supported(cmd) and
          get_dispatch_table_type(cmd) == 'Instance')


def is_device_dispatched(cmd):
  """Returns true for functions that can have device-specific dispatch.

  Args:
    cmd: Vulkan function name.
  """
  return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'


def is_extension_exported(extension_name):
  """Returns true if an extension has functions exported by the loader.

  E.g. applications can directly link to an extension function.

  Args:
    extension_name: Vulkan extension name.
  """
  return extension_name in _EXPORTED_EXTENSIONS


def is_function_exported(cmd):
  """Returns true if a function is exported from the Android Vulkan library.

  Functions in the core API and in loader extensions are exported.

  Args:
    cmd: Vulkan function name.
  """
  if is_function_supported(cmd):
    if cmd in extension_dict:
      return is_extension_exported(extension_dict[cmd])
@@ -164,6 +248,11 @@ def is_function_exported(cmd):


def is_instance_dispatch_table_entry(cmd):
  """Returns true if a function is exported and instance-dispatched.

  Args:
    cmd: Vulkan function name.
  """
  if cmd == 'vkEnumerateDeviceLayerProperties':
    # deprecated, unused internally - @dbd33bc
    return False
@@ -171,10 +260,21 @@ def is_instance_dispatch_table_entry(cmd):


def is_device_dispatch_table_entry(cmd):
  """Returns true if a function is exported and device-dispatched.

  Args:
    cmd: Vulkan function name.
  """
  return is_function_exported(cmd) and is_device_dispatched(cmd)


def init_proc(name, f):
  """Emits code to invoke INIT_PROC or INIT_PROC_EXT.

  Args:
    name: Vulkan function name.
    f: Output file handle.
  """
  f.write(indent(1))
  if name in extension_dict:
    f.write('INIT_PROC_EXT(' + extension_dict[name][3:] + ', ')
@@ -197,6 +297,15 @@ def init_proc(name, f):


def parse_vulkan_registry():
  """Parses Vulkan registry into the below global variables.

  alias_dict
  command_list
  extension_dict
  param_dict
  return_type_dict
  version_dict
  """
  registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
                          'external', 'vulkan-headers', 'registry', 'vk.xml')
  tree = element_tree.parse(registry)
+13 −3
Original line number Diff line number Diff line
@@ -13,13 +13,14 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script provides the functions for generating the null driver
# framework directly from the vulkan registry (vk.xml).

"""Generates the null_driver_gen.h and null_driver_gen.cpp.
"""

import os
import generator_common as gencom

# Extensions implemented by the driver.
_DRIVER_EXTENSION_DICT = {
    'VK_ANDROID_native_buffer',
    'VK_EXT_debug_report',
@@ -28,12 +29,19 @@ _DRIVER_EXTENSION_DICT = {


def _is_driver_function(cmd):
  """Returns true if the function is implemented by the driver.

  Args:
    cmd: Vulkan function name.
  """
  if cmd in gencom.extension_dict:
    return gencom.extension_dict[cmd] in _DRIVER_EXTENSION_DICT
  return True


def gen_h():
  """Generates the null_driver_gen.h file.
  """
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'nulldrv', 'null_driver_gen.h')

@@ -72,6 +80,8 @@ PFN_vkVoidFunction GetInstanceProcAddr(const char* name);


def gen_cpp():
  """Generates the null_driver_gen.cpp file.
  """
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'nulldrv', 'null_driver_gen.cpp')