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

Commit 1ca59c17 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

vulkan: clean up the framework generation script

1. Instead of mixing up all code formats, stick to pep8 and python style guide
2. Removed some redundant functions
3. Simplified seme code logic
4. Move constant codes back to main code gen blocks for readibility
5. Moved most of the hard-coded constants to the top
6. Removed a redundant clang format hint
7. Removed any mention of the legacy code gen stuff

Bug: 134185757
Test: ./scripts/code_generator.py && build
Change-Id: I1eca91fb0d181b7e8353c4c6a651d80ed1f2d1e0
parent dc792f55
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -562,5 +562,3 @@ bool InitDriverTable(VkDevice dev,

}  // namespace driver
}  // namespace vulkan

// clang-format on
+249 −217
Original line number Diff line number Diff line
@@ -20,21 +20,36 @@
import os
import generator_common as gencom

def isInstanceDispatchTableEntry(functionName):
  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
    return False
  if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
    return True
  return False
_INTERCEPTED_COMMANDS = [
    'vkCreateDevice',
    'vkDestroyDevice',
    'vkDestroyInstance',
    'vkEnumerateDeviceExtensionProperties',
    'vkEnumerateDeviceLayerProperties',
]

def isDeviceDispatchTableEntry(functionName):
  if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
    return True
  return False

def api_genh():
def gen_h():
  genfile = os.path.join(os.path.dirname(__file__),
                         '..', 'libvulkan', 'api_gen.h')

  header = """#ifndef LIBVULKAN_API_GEN_H
  with open(genfile, 'w') as f:
    instance_dispatch_table_entries = []
    device_dispatch_table_entries = []

    for cmd in gencom.command_list:
      if cmd not in gencom.alias_dict:
        if gencom.is_instance_dispatch_table_entry(cmd):
          instance_dispatch_table_entries.append(
              'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
        elif gencom.is_device_dispatch_table_entry(cmd):
          device_dispatch_table_entries.append(
              'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')

    f.write(gencom.copyright_and_warning(2016))

    f.write("""\
#ifndef LIBVULKAN_API_GEN_H
#define LIBVULKAN_API_GEN_H

#include <vulkan/vulkan.h>
@@ -46,9 +61,26 @@ def api_genh():
namespace vulkan {
namespace api {

"""
struct InstanceDispatchTable {
    // clang-format off\n""")

    for entry in instance_dispatch_table_entries:
      f.write(gencom.indent(1) + entry + '\n')

    f.write("""\
    // clang-format on
};

struct DeviceDispatchTable {
    // clang-format off\n""")

    for entry in device_dispatch_table_entries:
      f.write(gencom.indent(1) + entry + '\n')

    f.write("""\
    // clang-format on
};

  tail = """
bool InitDispatchTable(
    VkInstance instance,
    PFN_vkGetInstanceProcAddr get_proc,
@@ -61,105 +93,54 @@ bool InitDispatchTable(
}  // namespace api
}  // namespace vulkan

#endif  // LIBVULKAN_API_GEN_H
"""
  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h')
  with open(genfile, 'w') as f:
    instanceDispatchTableEntries = []
    deviceDispatchTableEntries = []
    for commands in gencom.allCommandsList:
      if commands not in gencom.aliasDict:
        if gencom.isInstanceDispatchTableEntry(commands):
          instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
        elif gencom.isDeviceDispatchTableEntry(commands):
          deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')

    f.write (gencom.copyright)
    f.write (gencom.warning)
    f.write (header)
    f.write ('struct InstanceDispatchTable {\n')
    gencom.clang_off(f,1)
    for functions in instanceDispatchTableEntries:
      f.write(gencom.clang_off_spaces + functions + '\n')
    gencom.clang_on(f,1)
    f.write ('};\n\n')

    f.write ('struct DeviceDispatchTable {\n')
    gencom.clang_off(f,1)
    for functions in deviceDispatchTableEntries:
      f.write(gencom.clang_off_spaces + functions + '\n')
    gencom.clang_on(f,1)
    f.write ('};\n')

    f.write (tail)
#endif  // LIBVULKAN_API_GEN_H\n""")

    f.close()
  gencom.runClangFormat(genfile)
  gencom.run_clang_format(genfile)

def defineInitProc(name, f):
  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
  f.write ('\n')
  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
    do {                                                               \\
        data.""" + name + """.proc =                                           \\
            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
        if (UNLIKELY(required && !data.""" + name + """.proc)) {               \\
            ALOGE("missing " #obj " proc: vk" #proc);                  \\
            success = false;                                           \\
        }                                                              \\
    } while (0)\n\n""")

def defineInitProcExt(f):
  f.write ('// Exported extension functions may be invoked even when their extensions\n')
  f.write ('// are disabled.  Dispatch to stubs when that happens.\n')
  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc)  \\
    do {                                         \\
        if (extensions[driver::ProcHook::ext])   \\
            INIT_PROC(required, obj, proc);      \\
        else                                     \\
            data.dispatch.proc = disabled##proc; \\
    } while (0)\n\n""")

def defineExtensionStub(functionName, f):
  if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
    extname = gencom.extensionsDict[functionName]
    base_name = functionName[2:]
    pList = gencom.paramDict[functionName]
    firstParam = pList[0][0] + pList[0][1]
    tailParams = [x[0][:-1] for x in pList[1:]]
    tailP = ', '.join(tailParams)
    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
    f.write (gencom.clang_off_spaces)
    f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
    if gencom.returnTypeDict[functionName] != 'void':
      f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
def _define_extension_stub(cmd, f):
  if (cmd in gencom.extension_dict and gencom.is_function_exported(cmd)):
    ext_name = gencom.extension_dict[cmd]
    ret = gencom.return_type_dict[cmd]
    params = gencom.param_dict[cmd]
    first_param = params[0][0] + params[0][1]
    tail_params = ', '.join([i[0][:-1] for i in params[1:]])

    f.write('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) +
            '(' + first_param + ', ' + tail_params + ') {\n')

    f.write(gencom.indent(1) + 'driver::Logger(' + params[0][1] +
            ').Err(' + params[0][1] + ', \"' + ext_name +
            ' not enabled. Exported ' + cmd + ' not executed.\");\n')

    if gencom.return_type_dict[cmd] != 'void':
      f.write(gencom.indent(1) + 'return VK_SUCCESS;\n')

    f.write('}\n\n')

def isIntercepted(functionName):
  if gencom.isFunctionSupported(functionName):
    if gencom.isGloballyDispatched(functionName):
      return True
    elif functionName == 'vkCreateDevice':
      return True
    elif functionName == 'vkEnumerateDeviceLayerProperties':
      return True
    elif functionName == 'vkEnumerateDeviceExtensionProperties':
      return True
    elif functionName == 'vkDestroyInstance':
      return True
    elif functionName == 'vkDestroyDevice':

def _is_intercepted(cmd):
  if gencom.is_function_supported(cmd):
    if gencom.is_globally_dispatched(cmd) or cmd in _INTERCEPTED_COMMANDS:
      return True
  return False

def interceptInstanceProcAddr(functionName, f):
  indent = 1
  f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
  indent = indent + 1
  for cmds in gencom.allCommandsList:
    if gencom.isGloballyDispatched(cmds):
      f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')

  f.write ('\n')
  f.write ("""        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
def _intercept_instance_proc_addr(f):
  f.write("""\
    // global functions
    if (instance == VK_NULL_HANDLE) {\n""")

  for cmd in gencom.command_list:
    if gencom.is_globally_dispatched(cmd):
      f.write(gencom.indent(2) +
              'if (strcmp(pName, \"' + cmd +
              '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
              gencom.base_name(cmd) + ');\n')

  f.write("""
        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
        return nullptr;
    }

@@ -167,14 +148,21 @@ def interceptInstanceProcAddr(functionName, f):
        const char* name;
        PFN_vkVoidFunction proc;
    } hooks[] = {\n""")
  sortedCommandsList = sorted(gencom.allCommandsList)
  for cmds in sortedCommandsList:
    if gencom.isFunctionExported(cmds):
      if gencom.isGloballyDispatched(cmds):
        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
      elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
  f.write (gencom.clang_off_spaces + """};

  sorted_command_list = sorted(gencom.command_list)
  for cmd in sorted_command_list:
    if gencom.is_function_exported(cmd):
      if gencom.is_globally_dispatched(cmd):
        f.write(gencom.indent(2) + '{ \"' + cmd + '\", nullptr },\n')
      elif (_is_intercepted(cmd) or
            cmd == 'vkGetInstanceProcAddr' or
            gencom.is_device_dispatched(cmd)):
        f.write(gencom.indent(2) + '{ \"' + cmd +
                '\", reinterpret_cast<PFN_vkVoidFunction>(' +
                gencom.base_name(cmd) + ') },\n')

  f.write("""\
    };
    // clang-format on
    constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
    auto hook = std::lower_bound(
@@ -190,19 +178,25 @@ def interceptInstanceProcAddr(functionName, f):
    }
    // clang-format off\n\n""")

def interceptDeviceProcAddr(functionName, f):
  f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {

def _intercept_device_proc_addr(f):
  f.write("""\
    if (device == VK_NULL_HANDLE) {
        ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
        return nullptr;
    }\n\n""")
  f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
  sortedCommandsList = sorted(gencom.allCommandsList)
  for cmds in sortedCommandsList:
    if gencom.isFunctionSupported(cmds):
      if not gencom.isDeviceDispatched(cmds):
        f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
  f.write(gencom.clang_off_spaces + '};\n')
  f.write(gencom.clang_off_spaces + """// clang-format on
    }

    static const char* const known_non_device_names[] = {\n""")

  sorted_command_list = sorted(gencom.command_list)
  for cmd in sorted_command_list:
    if gencom.is_function_supported(cmd):
      if not gencom.is_device_dispatched(cmd):
        f.write(gencom.indent(2) + '\"' + cmd + '\",\n')

  f.write("""\
    };
    // clang-format on
    constexpr size_t count =
        sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
    if (!pName ||
@@ -215,27 +209,38 @@ def interceptDeviceProcAddr(functionName, f):
        return nullptr;
    }
    // clang-format off\n\n""")
  for cmds in gencom.allCommandsList:
    if gencom.isDeviceDispatched(cmds):
      if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
        f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')

  for cmd in gencom.command_list:
    if gencom.is_device_dispatched(cmd):
      if _is_intercepted(cmd) or cmd == 'vkGetDeviceProcAddr':
        f.write(gencom.indent(1) + 'if (strcmp(pName, "' + cmd +
                '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
                gencom.base_name(cmd) + ');\n')
  f.write('\n')

def apiDispatch(functionName, f):
  assert not isIntercepted(functionName)

  f.write (gencom.clang_off_spaces)
  if gencom.returnTypeDict[functionName] != 'void':
def _api_dispatch(cmd, f):
  assert not _is_intercepted(cmd)

  f.write(gencom.indent(1))
  if gencom.return_type_dict[cmd] != 'void':
    f.write('return ')

  paramList = gencom.paramDict[functionName]
  p0 = paramList[0][1]
  f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
  param_list = gencom.param_dict[cmd]
  handle = param_list[0][1]
  f.write('GetData(' + handle + ').dispatch.' + gencom.base_name(cmd) +
          '(' + ', '.join(i[1] for i in param_list) + ');\n')


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

def api_gencpp():
  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp')
  header = """#include <log/log.h>
  with open(genfile, 'w') as f:
    f.write(gencom.copyright_and_warning(2016))

    f.write("""\
#include <log/log.h>
#include <string.h>

#include <algorithm>
@@ -247,80 +252,106 @@ def api_gencpp():
namespace vulkan {
namespace api {

"""
  with open(genfile, 'w') as f:
    f.write (gencom.copyright)
    f.write (gencom.warning)
    f.write ("""#include <log/log.h>
#include <string.h>
#define UNLIKELY(expr) __builtin_expect((expr), 0)

#include <algorithm>
#define INIT_PROC(required, obj, proc)                                 \\
    do {                                                               \\
        data.dispatch.proc =                                           \\
            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
        if (UNLIKELY(required && !data.dispatch.proc)) {               \\
            ALOGE("missing " #obj " proc: vk" #proc);                  \\
            success = false;                                           \\
        }                                                              \\
    } while (0)

// to catch mismatches between vulkan.h and this file
#undef VK_NO_PROTOTYPES
#include "api.h"
// Exported extension functions may be invoked even when their extensions
// are disabled.  Dispatch to stubs when that happens.
#define INIT_PROC_EXT(ext, required, obj, proc)  \\
    do {                                         \\
        if (extensions[driver::ProcHook::ext])   \\
            INIT_PROC(required, obj, proc);      \\
        else                                     \\
            data.dispatch.proc = disabled##proc; \\
    } while (0)

namespace vulkan {
namespace api {\n\n""")
    defineInitProc('dispatch',f)
    defineInitProcExt(f)
    f.write ('namespace {\n\n')
    gencom.clang_off(f,0)
    f.write ('\n')
    for cmds in gencom.allCommandsList:
      defineExtensionStub(cmds,f)
    gencom.clang_on(f,0)
    f.write ('\n}  // namespace\n\n')
    f.write ("""bool InitDispatchTable(
namespace {

// clang-format off\n\n""")

    for cmd in gencom.command_list:
      _define_extension_stub(cmd, f)

    f.write("""\
// clang-format on

}  // namespace

bool InitDispatchTable(
    VkInstance instance,
    PFN_vkGetInstanceProcAddr get_proc,
    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
    auto& data = GetData(instance);
    bool success = true;\n\n""")
    gencom.clang_off(f,1)
    for cmds in gencom.allCommandsList:
      if gencom.isInstanceDispatchTableEntry(cmds):
        gencom.initProc(cmds, f)
    gencom.clang_on(f,1)
    f.write ('\n')
    f.write ('    return success;\n}\n\n')
    f.write ("""bool InitDispatchTable(
    bool success = true;

    // clang-format off\n""")

    for cmd in gencom.command_list:
      if gencom.is_instance_dispatch_table_entry(cmd):
        gencom.init_proc(cmd, f)

    f.write("""\
    // clang-format on

    return success;
}

bool InitDispatchTable(
    VkDevice dev,
    PFN_vkGetDeviceProcAddr get_proc,
    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
    auto& data = GetData(dev);
    bool success = true;\n\n""")
    bool success = true;

    gencom.clang_off(f,1)
    for cmds in gencom.allCommandsList:
      if gencom.isDeviceDispatchTableEntry(cmds):
        gencom.initProc(cmds, f)
    gencom.clang_on(f,1)
    f.write ('\n')
    f.write ('    return success;\n}\n\n')
    // clang-format off\n""")

    for cmd in gencom.command_list:
      if gencom.is_device_dispatch_table_entry(cmd):
        gencom.init_proc(cmd, f)

    gencom.clang_off(f,0)
    f.write("""\
    // clang-format on

    f.write ('\nnamespace {\n\n')
    f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
    for cmds in gencom.allCommandsList:
      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
        f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
    return success;
}

    f.write ('\n')
// clang-format off

    for cmds in gencom.allCommandsList:
      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
        if cmds == 'vkGetInstanceProcAddr':
          interceptInstanceProcAddr(cmds, f)
        elif cmds == 'vkGetDeviceProcAddr':
          interceptDeviceProcAddr(cmds, f)
        apiDispatch(cmds, f)
namespace {

// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
""")

    for cmd in gencom.command_list:
      if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
                gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')

    f.write('\n')
    for cmd in gencom.command_list:
      if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
                gencom.base_name(cmd) + '(' + ', '.join(param_list) + ') {\n')
        if cmd == 'vkGetInstanceProcAddr':
          _intercept_instance_proc_addr(f)
        elif cmd == 'vkGetDeviceProcAddr':
          _intercept_device_proc_addr(f)
        _api_dispatch(cmd, f)
        f.write('}\n\n')
    f.write ("""\n}  // anonymous namespace

    f.write("""
}  // anonymous namespace

// clang-format on

@@ -329,18 +360,19 @@ namespace api {\n\n""")

// clang-format off\n\n""")

    for cmds in gencom.allCommandsList:
      if gencom.isFunctionExported(cmds):
        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
    for cmd in gencom.command_list:
      if gencom.is_function_exported(cmd):
        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
        f.write('__attribute__((visibility("default")))\n')
        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
        f.write (gencom.clang_off_spaces)
        if gencom.returnTypeDict[cmds] != 'void':
        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
                cmd + '(' + ', '.join(param_list) + ') {\n')
        f.write(gencom.indent(1))
        if gencom.return_type_dict[cmd] != 'void':
          f.write('return ')
        paramList = gencom.paramDict[cmds]
        f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
        f.write ('}\n\n')
        param_list = gencom.param_dict[cmd]
        f.write('vulkan::api::' + gencom.base_name(cmd) +
                '(' + ', '.join(i[1] for i in param_list) + ');\n}\n\n')

    gencom.clang_on(f, 0)
    f.write('// clang-format on\n')
    f.close()
  gencom.runClangFormat(genfile)
  gencom.run_clang_format(genfile)
+11 −11
Original line number Diff line number Diff line
@@ -17,16 +17,16 @@
# This script provides the main function for generating
# vulkan framework directly from the vulkan registry (vk.xml).

import generator_common as gencom
import api_generator as apigen
import driver_generator as drivergen
import null_generator as nullgen
import api_generator
import driver_generator
import generator_common
import null_generator

if __name__ == '__main__':
  gencom.parseVulkanRegistry()
  apigen.api_genh()
  apigen.api_gencpp()
  drivergen.driver_genh()
  drivergen.driver_gencpp()
  nullgen.null_driver_genh()
  nullgen.null_driver_gencpp()
  generator_common.parse_vulkan_registry()
  api_generator.gen_h()
  api_generator.gen_cpp()
  driver_generator.gen_h()
  driver_generator.gen_cpp()
  null_generator.gen_h()
  null_generator.gen_cpp()
+331 −277

File changed.

Preview size limit exceeded, changes collapsed.

+155 −146

File changed.

Preview size limit exceeded, changes collapsed.

Loading