예제 #1
0
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 _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""")

    for cmd in gencom.command_list:
        # vkGetInstanceProcAddr(nullptr, "vkGetInstanceProcAddr") is effectively
        # globally dispatched
        if gencom.is_globally_dispatched(
                cmd) or cmd == 'vkGetInstanceProcAddr':
            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;
    }

    static const struct Hook {
        const char* name;
        PFN_vkVoidFunction proc;
    } hooks[] = {\n""")

    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(
        hooks, hooks + count, pName,
        [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
    if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
        if (!hook->proc) {
            vulkan::driver::Logger(instance).Err(
                instance, "invalid vkGetInstanceProcAddr(%p, \\\"%s\\\") call",
                instance, pName);
        }
        return hook->proc;
    }
    // clang-format off\n\n""")
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");
        return nullptr;
    }

    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 ||
        std::binary_search(
            known_non_device_names, known_non_device_names + count, pName,
            [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
        vulkan::driver::Logger(device).Err(
            device, "invalid vkGetDeviceProcAddr(%p, \\\"%s\\\") call", device,
            (pName) ? pName : "(null)");
        return nullptr;
    }
    // clang-format off\n\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')
예제 #4
0
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]):
                return True
        elif gencom.version_dict[cmd] != 'VK_VERSION_1_0':
            return True
    return False
예제 #5
0
def gen_cpp():
    """Generates the driver_gen.cpp file.
  """
    genfile = os.path.join(os.path.dirname(__file__), '..', 'libvulkan',
                           'driver_gen.cpp')

    with open(genfile, 'w') as f:
        f.write(gencom.copyright_and_warning(2016))
        f.write("""\
#include <log/log.h>
#include <string.h>

#include <algorithm>

#include "driver.h"

namespace vulkan {
namespace driver {

namespace {

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

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

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

const ProcHook g_proc_hooks[] = {
    // clang-format off\n""")

        sorted_command_list = sorted(gencom.command_list)
        for cmd in sorted_command_list:
            if _is_intercepted(cmd):
                if gencom.is_globally_dispatched(cmd):
                    _define_global_proc_hook(cmd, f)
                elif gencom.is_instance_dispatched(cmd):
                    _define_instance_proc_hook(cmd, f)
                elif gencom.is_device_dispatched(cmd):
                    _define_device_proc_hook(cmd, f)

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

}  // namespace

const ProcHook* GetProcHook(const char* name) {
    const auto& begin = g_proc_hooks;
    const auto& end =
        g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
    const auto hook = std::lower_bound(
        begin, end, name,
        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
    return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
}

ProcHook::Extension GetProcHookExtension(const char* name) {
    // clang-format off\n""")

        for ext in _KNOWN_EXTENSIONS:
            f.write(
                gencom.indent(1) + 'if (strcmp(name, \"' + ext +
                '\") == 0) return ProcHook::' + gencom.base_ext_name(ext) +
                ';\n')

        f.write("""\
    // clang-format on
    return ProcHook::EXTENSION_UNKNOWN;
}

#define UNLIKELY(expr) __builtin_expect((expr), 0)

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

#define INIT_PROC_EXT(ext, required, obj, proc) \\
    do {                                        \\
        if (extensions[ProcHook::ext])          \\
            INIT_PROC(required, obj, proc);     \\
    } while (0)

bool InitDriverTable(VkInstance instance,
                     PFN_vkGetInstanceProcAddr get_proc,
                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
    auto& data = GetData(instance);
    bool success = true;

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

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

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

    return success;
}

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

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

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

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

    return success;
}

}  // namespace driver
}  // namespace vulkan\n""")

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

    with open(genfile, 'w') as f:
        f.write(gencom.copyright_and_warning(2016))
        f.write("""\
#include <log/log.h>
#include <string.h>

#include <algorithm>

#include "driver.h"

namespace vulkan {
namespace driver {

namespace {

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

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

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

const ProcHook g_proc_hooks[] = {
    // clang-format off\n""")

        sorted_command_list = sorted(gencom.command_list)
        for cmd in sorted_command_list:
            if _is_intercepted(cmd):
                if gencom.is_globally_dispatched(cmd):
                    _define_global_proc_hook(cmd, f)
                elif gencom.is_instance_dispatched(cmd):
                    _define_instance_proc_hook(cmd, f)
                elif gencom.is_device_dispatched(cmd):
                    _define_device_proc_hook(cmd, f)

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

}  // namespace

const ProcHook* GetProcHook(const char* name) {
    auto begin = std::cbegin(g_proc_hooks);
    auto end = std::cend(g_proc_hooks);
    auto hook = std::lower_bound(
        begin, end, name,
        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
    return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
}

ProcHook::Extension GetProcHookExtension(const char* name) {
    // clang-format off\n""")

        for ext in _KNOWN_EXTENSIONS:
            f.write(
                gencom.indent(1) + 'if (strcmp(name, \"' + ext +
                '\") == 0) return ProcHook::' + gencom.base_ext_name(ext) +
                ';\n')

        f.write("""\
    // clang-format on
    return ProcHook::EXTENSION_UNKNOWN;
}

#define UNLIKELY(expr) __builtin_expect((expr), 0)

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

#define INIT_PROC_EXT(ext, required, obj, proc) \\
    do {                                        \\
        if (extensions[ProcHook::ext])          \\
            INIT_PROC(required, obj, proc);     \\
    } while (0)

bool InitDriverTable(VkInstance instance,
                     PFN_vkGetInstanceProcAddr get_proc,
                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
    auto& data = GetData(instance);
    bool success = true;

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

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

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

    return success;
}

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

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

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

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

    return success;
}

const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = {
    // clang-format off\n""")

        for key, value in sorted(gencom.promoted_inst_ext_dict.items()):
            f.write(
                gencom.indent(1) + 'std::make_pair("' + key + '", ' + value +
                '),\n')

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

std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    auto iter =
        std::lower_bound(begin, end, name,
                         [](const std::pair<const char*, uint32_t>& e,
                            const char* n) { return strcmp(e.first, n) < 0; });
    return (iter < end && strcmp(iter->first, name) == 0)
               ? std::optional<uint32_t>(iter->second)
               : std::nullopt;
}

uint32_t CountPromotedInstanceExtensions(uint32_t begin_version,
                                         uint32_t end_version) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    uint32_t count = 0;

    for (auto iter = begin; iter != end; iter++)
        if (iter->second > begin_version && iter->second <= end_version)
            count++;

    return count;
}

std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version,
                                                       uint32_t end_version) {
    auto begin = std::cbegin(g_promoted_instance_extensions);
    auto end = std::cend(g_promoted_instance_extensions);
    std::vector<const char*> extensions;

    for (auto iter = begin; iter != end; iter++)
        if (iter->second > begin_version && iter->second <= end_version)
            extensions.emplace_back(iter->first);

    return extensions;
}

}  // namespace driver
}  // namespace vulkan\n""")

        f.close()
    gencom.run_clang_format(genfile)