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

Commit 4901db70 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

vulkan: rework {Create,Destroy}Device_Bottom

The reworked driver::CreateDevice will

 - use the providied pAllocator,
 - call HAL's EnumerateDeviceExtensionProperties and filter out extensions
   unknown to HAL, if there is any extension enabled.

We do not expect or enumerate any HAL layer yet as that requires some
works to layers_extensions.cpp.

Change-Id: I3ba4019d18dfed994d7037d95825bf54096f2a5d
parent 6a58a8a7
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -792,6 +792,8 @@ VK_KHR_swapchain

      {{if eq $.Name "vkGetInstanceProcAddr"}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
      {{else if eq $.Name "vkCreateDevice"}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
      {{else}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
      {{end}}
@@ -831,12 +833,7 @@ VK_KHR_swapchain
      {{end}}
    {{else}}
      ProcHook::EXTENSION_CORE,

        {{if eq $.Name "vkDestroyDevice"}}
          reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
        {{else}}
      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
        {{end}}
      nullptr,
      nullptr,
    {{end}}
@@ -862,6 +859,8 @@ VK_KHR_swapchain
    {{else if eq $.Name "vkDestroyInstance"}}true
    {{else if eq $.Name "vkDestroyDevice"}}true

    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true

    {{/* Enumeration of extensions */}}
    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true

+352 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <new>
#include <malloc.h>
#include <sys/prctl.h>

@@ -44,6 +45,281 @@ namespace driver {

namespace {

class CreateInfoWrapper {
   public:
    CreateInfoWrapper(VkPhysicalDevice physical_dev,
                      const VkDeviceCreateInfo& create_info,
                      const VkAllocationCallbacks& allocator);
    ~CreateInfoWrapper();

    VkResult validate();

    const std::bitset<ProcHook::EXTENSION_COUNT>& get_hook_extensions() const;
    const std::bitset<ProcHook::EXTENSION_COUNT>& get_hal_extensions() const;

    explicit operator const VkDeviceCreateInfo*() const;

   private:
    struct ExtensionFilter {
        VkExtensionProperties* exts;
        uint32_t ext_count;

        const char** names;
        uint32_t name_count;
    };

    VkResult sanitize_pnext();

    VkResult sanitize_layers();
    VkResult sanitize_extensions();

    VkResult query_extension_count(uint32_t& count) const;
    VkResult enumerate_extensions(uint32_t& count,
                                  VkExtensionProperties* props) const;
    VkResult init_extension_filter();
    void filter_extension(const char* name);

    const bool is_instance_;
    const VkAllocationCallbacks& allocator_;

    union {
        hwvulkan_device_t* hw_dev_;
        VkPhysicalDevice physical_dev_;
    };

    union {
        VkInstanceCreateInfo instance_info_;
        VkDeviceCreateInfo dev_info_;
    };

    ExtensionFilter extension_filter_;

    std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
    std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
};

CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
                                     const VkDeviceCreateInfo& create_info,
                                     const VkAllocationCallbacks& allocator)
    : is_instance_(false),
      allocator_(allocator),
      physical_dev_(physical_dev),
      dev_info_(create_info),
      extension_filter_() {
    hook_extensions_.set(ProcHook::EXTENSION_CORE);
    hal_extensions_.set(ProcHook::EXTENSION_CORE);
}

CreateInfoWrapper::~CreateInfoWrapper() {
    allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
    allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
}

VkResult CreateInfoWrapper::validate() {
    VkResult result = sanitize_pnext();
    if (result == VK_SUCCESS)
        result = sanitize_layers();
    if (result == VK_SUCCESS)
        result = sanitize_extensions();

    return result;
}

const std::bitset<ProcHook::EXTENSION_COUNT>&
CreateInfoWrapper::get_hook_extensions() const {
    return hook_extensions_;
}

const std::bitset<ProcHook::EXTENSION_COUNT>&
CreateInfoWrapper::get_hal_extensions() const {
    return hal_extensions_;
}

CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
    return &dev_info_;
}

VkResult CreateInfoWrapper::sanitize_pnext() {
    const struct StructHeader {
        VkStructureType type;
        const void* next;
    } * header;

    if (is_instance_) {
        header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);

        // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
        while (header &&
               header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
            header = reinterpret_cast<const StructHeader*>(header->next);

        instance_info_.pNext = header;
    } else {
        header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);

        // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
        while (header &&
               header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
            header = reinterpret_cast<const StructHeader*>(header->next);

        dev_info_.pNext = header;
    }

    return VK_SUCCESS;
}

VkResult CreateInfoWrapper::sanitize_layers() {
    auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
                                       : dev_info_.ppEnabledLayerNames;
    auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
                                       : dev_info_.enabledLayerCount;

    // remove all layers
    layer_names = nullptr;
    layer_count = 0;

    return VK_SUCCESS;
}

VkResult CreateInfoWrapper::sanitize_extensions() {
    auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
                                     : dev_info_.ppEnabledExtensionNames;
    auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
                                     : dev_info_.enabledExtensionCount;
    if (!ext_count)
        return VK_SUCCESS;

    VkResult result = init_extension_filter();
    if (result != VK_SUCCESS)
        return result;

    for (uint32_t i = 0; i < ext_count; i++)
        filter_extension(ext_names[i]);

    ext_names = extension_filter_.names;
    ext_count = extension_filter_.name_count;

    return VK_SUCCESS;
}

VkResult CreateInfoWrapper::query_extension_count(uint32_t& count) const {
    if (is_instance_) {
        return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
                                                             nullptr);
    } else {
        const auto& driver = GetData(physical_dev_).driver;
        return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
                                                         &count, nullptr);
    }
}

VkResult CreateInfoWrapper::enumerate_extensions(
    uint32_t& count,
    VkExtensionProperties* props) const {
    if (is_instance_) {
        return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
                                                             props);
    } else {
        const auto& driver = GetData(physical_dev_).driver;
        return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
                                                         &count, props);
    }
}

VkResult CreateInfoWrapper::init_extension_filter() {
    // query extension count
    uint32_t count;
    VkResult result = query_extension_count(count);
    if (result != VK_SUCCESS || count == 0)
        return result;

    auto& filter = extension_filter_;
    filter.exts =
        reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
            allocator_.pUserData, sizeof(VkExtensionProperties) * count,
            alignof(VkExtensionProperties),
            VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
    if (!filter.exts)
        return VK_ERROR_OUT_OF_HOST_MEMORY;

    // enumerate extensions
    result = enumerate_extensions(count, filter.exts);
    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
        return result;

    if (!count)
        return VK_SUCCESS;

    filter.ext_count = count;

    // allocate name array
    uint32_t enabled_ext_count = (is_instance_)
                                     ? instance_info_.enabledExtensionCount
                                     : dev_info_.enabledExtensionCount;
    count = std::min(filter.ext_count, enabled_ext_count);
    filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
        allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
        VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
    if (!filter.names)
        return VK_ERROR_OUT_OF_HOST_MEMORY;

    return VK_SUCCESS;
}

void CreateInfoWrapper::filter_extension(const char* name) {
    auto& filter = extension_filter_;

    ProcHook::Extension ext_bit = GetProcHookExtension(name);
    if (is_instance_) {
        switch (ext_bit) {
            case ProcHook::KHR_android_surface:
            case ProcHook::KHR_surface:
                hook_extensions_.set(ext_bit);
                // return now as these extensions do not require HAL support
                return;
            case ProcHook::EXT_debug_report:
                // both we and HAL can take part in
                hook_extensions_.set(ext_bit);
                break;
            case ProcHook::EXTENSION_UNKNOWN:
                // HAL's extensions
                break;
            default:
                ALOGW("Ignored invalid instance extension %s", name);
                return;
        }
    } else {
        switch (ext_bit) {
            case ProcHook::KHR_swapchain:
                // map VK_KHR_swapchain to VK_ANDROID_native_buffer
                name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
                ext_bit = ProcHook::ANDROID_native_buffer;
                break;
            case ProcHook::EXTENSION_UNKNOWN:
                // HAL's extensions
                break;
            default:
                ALOGW("Ignored invalid device extension %s", name);
                return;
        }
    }

    for (uint32_t i = 0; i < filter.ext_count; i++) {
        const VkExtensionProperties& props = filter.exts[i];
        // ignore unknown extensions
        if (strcmp(name, props.extensionName) != 0)
            continue;

        if (ext_bit == ProcHook::ANDROID_native_buffer)
            hook_extensions_.set(ProcHook::KHR_swapchain);

        filter.names[filter.name_count++] = name;
        hal_extensions_.set(ext_bit);

        break;
    }
}

hwvulkan_device_t* g_hwdevice = nullptr;

VKAPI_ATTR void* DefaultAllocate(void*,
@@ -94,6 +370,21 @@ VKAPI_ATTR void DefaultFree(void*, void* ptr) {
    free(ptr);
}

DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
    void* data_mem = allocator.pfnAllocation(
        allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
    if (!data_mem)
        return nullptr;

    return new (data_mem) DeviceData(allocator);
}

void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
    data->~DeviceData();
    allocator.pfnFree(allocator.pUserData, data);
}

}  // anonymous namespace

bool Debuggable() {
@@ -205,6 +496,67 @@ PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
               : hook->disabled_proc;
}

VkResult CreateDevice(VkPhysicalDevice physicalDevice,
                      const VkDeviceCreateInfo* pCreateInfo,
                      const VkAllocationCallbacks* pAllocator,
                      VkDevice* pDevice) {
    const InstanceData& instance_data = GetData(physicalDevice);
    const VkAllocationCallbacks& data_allocator =
        (pAllocator) ? *pAllocator : instance_data.allocator;

    CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
    VkResult result = wrapper.validate();
    if (result != VK_SUCCESS)
        return result;

    DeviceData* data = AllocateDeviceData(data_allocator);
    if (!data)
        return VK_ERROR_OUT_OF_HOST_MEMORY;

    data->hook_extensions |= wrapper.get_hook_extensions();
    data->hal_extensions |= wrapper.get_hal_extensions();

    // call into the driver
    VkDevice dev;
    result = instance_data.driver.CreateDevice(
        physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
        pAllocator, &dev);
    if (result != VK_SUCCESS) {
        FreeDeviceData(data, data_allocator);
        return result;
    }

    // initialize DeviceDriverTable
    if (!SetData(dev, *data) ||
        !InitDriverTable(dev, instance_data.get_device_proc_addr)) {
        data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
            instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
        if (data->driver.DestroyDevice)
            data->driver.DestroyDevice(dev, pAllocator);

        FreeDeviceData(data, data_allocator);

        return VK_ERROR_INCOMPATIBLE_DRIVER;
    }

    *pDevice = dev;

    return VK_SUCCESS;
}

void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
    DeviceData& data = GetData(device);
    data.driver.DestroyDevice(device, pAllocator);

    VkAllocationCallbacks local_allocator;
    if (!pAllocator) {
        local_allocator = data.allocator;
        pAllocator = &local_allocator;
    }

    FreeDeviceData(&data, *pAllocator);
}

void GetDeviceQueue(VkDevice device,
                    uint32_t queueFamilyIndex,
                    uint32_t queueIndex,
+3 −0
Original line number Diff line number Diff line
@@ -109,6 +109,9 @@ VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const cha
VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);

VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);

VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
// clang-format on
+3 −2
Original line number Diff line number Diff line
@@ -164,7 +164,7 @@ const ProcHook g_proc_hooks[] = {
        "vkCreateDevice",
        ProcHook::INSTANCE,
        ProcHook::EXTENSION_CORE,
        reinterpret_cast<PFN_vkVoidFunction>(CreateDevice_Bottom),
        reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
        nullptr,
        nullptr,
    },
@@ -204,7 +204,7 @@ const ProcHook g_proc_hooks[] = {
        "vkDestroyDevice",
        ProcHook::DEVICE,
        ProcHook::EXTENSION_CORE,
        reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice_Bottom),
        reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
        nullptr,
        nullptr,
    },
@@ -397,6 +397,7 @@ bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
    INIT_PROC(instance, EnumeratePhysicalDevices);
    INIT_PROC(instance, GetInstanceProcAddr);
    INIT_PROC(instance, CreateDevice);
    INIT_PROC(instance, EnumerateDeviceLayerProperties);
    INIT_PROC(instance, EnumerateDeviceExtensionProperties);
    INIT_PROC_EXT(EXT_debug_report, instance, CreateDebugReportCallbackEXT);
    INIT_PROC_EXT(EXT_debug_report, instance, DestroyDebugReportCallbackEXT);
+1 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ struct InstanceDriverTable {
    PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
    PFN_vkCreateDevice CreateDevice;
    PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
    PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
    PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
    PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
Loading