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

Commit aa410941 authored by Jesse Hall's avatar Jesse Hall
Browse files

libvulkan: Enumerate device layers

Change-Id: I7623eab3d8bb958470437998ba603ac1171d764c
(cherry picked from commit eab7505b0741dc5c062df889a7ca5db1a9e619e8)
parent 715b86ac
Loading
Loading
Loading
Loading
+214 −81
Original line number Diff line number Diff line
@@ -28,6 +28,19 @@

using namespace vulkan;

// TODO(jessehall): This file currently builds up global data structures as it
// loads, and never cleans them up. This means we're doing heap allocations
// without going through an app-provided allocator, but worse, we'll leak those
// allocations if the loader is unloaded.
//
// We should allocate "enough" BSS space, and suballocate from there. Will
// probably want to intern strings, etc., and will need some custom/manual data
// structures.

// TODO(jessehall): Currently we have separate lists for instance and device
// layers. Most layers are both; we should use one entry for each layer name,
// with a mask saying what kind(s) it is.

namespace vulkan {
struct Layer {
    VkLayerProperties properties;
@@ -45,7 +58,8 @@ struct LayerLibrary {
    size_t refcount;
};
std::vector<LayerLibrary> g_layer_libraries;
std::vector<Layer> g_layers;
std::vector<Layer> g_instance_layers;
std::vector<Layer> g_device_layers;

void AddLayerLibrary(const std::string& path) {
    ALOGV("examining layer library '%s'", path.c_str());
@@ -56,81 +70,163 @@ void AddLayerLibrary(const std::string& path) {
        return;
    }

    PFN_vkEnumerateInstanceLayerProperties enumerate_layer_properties =
    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
            dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
    if (!enumerate_layer_properties) {
    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
            dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
            dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
    if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
          (enumerate_device_layers && enumerate_device_extensions))) {
        ALOGV(
            "layer library '%s' has neither instance nor device enumeraion "
            "functions",
            path.c_str());
        dlclose(dlhandle);
        return;
    }

    VkResult result;
    uint32_t num_instance_layers = 0;
    uint32_t num_device_layers = 0;
    if (enumerate_instance_layers) {
        result = enumerate_instance_layers(&num_instance_layers, nullptr);
        if (result != VK_SUCCESS) {
            ALOGW(
            "failed to find vkEnumerateInstanceLayerProperties in library "
            "'%s': %s",
            path.c_str(), dlerror());
                "vkEnumerateInstanceLayerProperties failed for library '%s': "
                "%d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
        }
    PFN_vkEnumerateInstanceExtensionProperties enumerate_extension_properties =
        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
    if (!enumerate_extension_properties) {
    }
    if (enumerate_device_layers) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
                                         nullptr);
        if (result != VK_SUCCESS) {
            ALOGW(
            "failed to find vkEnumerateInstanceExtensionProperties in library "
            "'%s': %s",
            path.c_str(), dlerror());
                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
        }

    uint32_t layer_count;
    VkResult result = enumerate_layer_properties(&layer_count, nullptr);
    }
    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
    if (num_instance_layers > 0) {
        result = enumerate_instance_layers(&num_instance_layers, properties);
        if (result != VK_SUCCESS) {
        ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
            ALOGW(
                "vkEnumerateInstanceLayerProperties failed for library '%s': "
                "%d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
        }
    VkLayerProperties* properties = static_cast<VkLayerProperties*>(
        alloca(layer_count * sizeof(VkLayerProperties)));
    result = enumerate_layer_properties(&layer_count, properties);
    }
    if (num_device_layers > 0) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
                                         properties + num_instance_layers);
        if (result != VK_SUCCESS) {
        ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
            ALOGW(
                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
        }
    }

    size_t library_idx = g_layer_libraries.size();
    g_layers.reserve(g_layers.size() + layer_count);
    for (size_t i = 0; i < layer_count; i++) {
    size_t prev_num_instance_layers = g_instance_layers.size();
    size_t prev_num_device_layers = g_device_layers.size();
    g_instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
    g_device_layers.reserve(prev_num_device_layers + num_device_layers);
    for (size_t i = 0; i < num_instance_layers; i++) {
        const VkLayerProperties& props = properties[i];

        Layer layer;
        layer.properties = properties[i];
        layer.properties = props;
        layer.library_idx = library_idx;

        uint32_t count;
        result = enumerate_extension_properties(properties[i].layerName, &count,
                                                nullptr);
        if (enumerate_instance_extensions) {
            uint32_t count = 0;
            result =
                enumerate_instance_extensions(props.layerName, &count, nullptr);
            if (result != VK_SUCCESS) {
                ALOGW(
                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
                    "library "
                    "'%s': %d",
                properties[i].layerName, path.c_str(), result);
            g_layers.resize(g_layers.size() - (i + 1));
                    props.layerName, path.c_str(), result);
                g_instance_layers.resize(prev_num_instance_layers);
                dlclose(dlhandle);
                return;
            }
            layer.extensions.resize(count);
        result = enumerate_extension_properties(properties[i].layerName, &count,
            result = enumerate_instance_extensions(props.layerName, &count,
                                                   layer.extensions.data());
            if (result != VK_SUCCESS) {
                ALOGW(
                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
                    "library "
                    "'%s': %d",
                properties[i].layerName, path.c_str(), result);
            g_layers.resize(g_layers.size() - (i + 1));
                    props.layerName, path.c_str(), result);
                g_instance_layers.resize(prev_num_instance_layers);
                dlclose(dlhandle);
                return;
            }
        }

        g_layers.push_back(layer);
        ALOGV("found layer '%s'", properties[i].layerName);
        g_instance_layers.push_back(layer);
        ALOGV("added instance layer '%s'", props.layerName);
    }
    for (size_t i = 0; i < num_device_layers; i++) {
        const VkLayerProperties& props = properties[num_instance_layers + i];

        Layer layer;
        layer.properties = props;
        layer.library_idx = library_idx;

        if (enumerate_device_extensions) {
            uint32_t count;
            result = enumerate_device_extensions(
                VK_NULL_HANDLE, props.layerName, &count, nullptr);
            if (result != VK_SUCCESS) {
                ALOGW(
                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
                    "library "
                    "'%s': %d",
                    props.layerName, path.c_str(), result);
                g_instance_layers.resize(prev_num_instance_layers);
                g_device_layers.resize(prev_num_device_layers);
                dlclose(dlhandle);
                return;
            }
            layer.extensions.resize(count);
            result =
                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
                                            &count, layer.extensions.data());
            if (result != VK_SUCCESS) {
                ALOGW(
                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
                    "library "
                    "'%s': %d",
                    props.layerName, path.c_str(), result);
                g_instance_layers.resize(prev_num_instance_layers);
                g_device_layers.resize(prev_num_device_layers);
                dlclose(dlhandle);
                return;
            }
        }

        g_device_layers.push_back(layer);
        ALOGV("added device layer '%s'", props.layerName);
    }

    dlclose(dlhandle);
@@ -185,40 +281,37 @@ void* GetLayerGetProcAddr(const Layer& layer,
    return gpa;
}

}  // anonymous namespace

namespace vulkan {

void DiscoverLayers() {
    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
        DiscoverLayersInDirectory("/data/local/debug/vulkan");
    if (!LoaderData::GetInstance().layer_path.empty())
        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
}

uint32_t EnumerateLayers(uint32_t count, VkLayerProperties* properties) {
    uint32_t n = std::min(count, static_cast<uint32_t>(g_layers.size()));
uint32_t EnumerateLayers(const std::vector<Layer>& layers,
                         uint32_t count,
                         VkLayerProperties* properties) {
    uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
    for (uint32_t i = 0; i < n; i++) {
        properties[i] = g_layers[i].properties;
        properties[i] = layers[i].properties;
    }
    return static_cast<uint32_t>(g_layers.size());
    return static_cast<uint32_t>(layers.size());
}

void GetLayerExtensions(const char* name,
void GetLayerExtensions(const std::vector<Layer>& layers,
                        const char* name,
                        const VkExtensionProperties** properties,
                        uint32_t* count) {
    for (const auto& layer : g_layers) {
        if (strcmp(name, layer.properties.layerName) != 0)
            continue;
        *properties = layer.extensions.data();
        *count = static_cast<uint32_t>(layer.extensions.size());
    auto layer =
        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
            return strcmp(entry.properties.layerName, name) == 0;
        });
    if (layer == layers.cend()) {
        *properties = nullptr;
        *count = 0;
    } else {
        *properties = layer->extensions.data();
        *count = static_cast<uint32_t>(layer->extensions.size());
    }
}

LayerRef GetLayerRef(const char* name) {
    for (uint32_t id = 0; id < g_layers.size(); id++) {
        if (strcmp(name, g_layers[id].properties.layerName) != 0) {
            LayerLibrary& library = g_layer_libraries[g_layers[id].library_idx];
LayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
    for (uint32_t id = 0; id < layers.size(); id++) {
        if (strcmp(name, layers[id].properties.layerName) != 0) {
            LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
            std::lock_guard<std::mutex> lock(g_library_mutex);
            if (library.refcount++ == 0) {
                library.dlhandle =
@@ -230,12 +323,52 @@ LayerRef GetLayerRef(const char* name) {
                    return LayerRef(nullptr);
                }
            }
            return LayerRef(&g_layers[id]);
            return LayerRef(&layers[id]);
        }
    }
    return LayerRef(nullptr);
}

}  // anonymous namespace

namespace vulkan {

void DiscoverLayers() {
    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
        DiscoverLayersInDirectory("/data/local/debug/vulkan");
    if (!LoaderData::GetInstance().layer_path.empty())
        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
}

uint32_t EnumerateInstanceLayers(uint32_t count,
                                 VkLayerProperties* properties) {
    return EnumerateLayers(g_instance_layers, count, properties);
}

uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
    return EnumerateLayers(g_device_layers, count, properties);
}

void GetInstanceLayerExtensions(const char* name,
                                const VkExtensionProperties** properties,
                                uint32_t* count) {
    GetLayerExtensions(g_instance_layers, name, properties, count);
}

void GetDeviceLayerExtensions(const char* name,
                              const VkExtensionProperties** properties,
                              uint32_t* count) {
    GetLayerExtensions(g_device_layers, name, properties, count);
}

LayerRef GetInstanceLayerRef(const char* name) {
    return GetLayerRef(g_instance_layers, name);
}

LayerRef GetDeviceLayerRef(const char* name) {
    return GetLayerRef(g_device_layers, name);
}

LayerRef::LayerRef(Layer* layer) : layer_(layer) {}

LayerRef::~LayerRef() {
+20 −7
Original line number Diff line number Diff line
@@ -343,9 +343,20 @@ void DestroyDevice(Device* device) {
    alloc->pfnFree(alloc->pUserData, device);
}

template <class TObject>
LayerRef GetLayerRef(const char* name);
template <>
LayerRef GetLayerRef<Instance>(const char* name) {
    return GetInstanceLayerRef(name);
}
template <>
LayerRef GetLayerRef<Device>(const char* name) {
    return GetDeviceLayerRef(name);
}

template <class TObject>
bool ActivateLayer(TObject* object, const char* name) {
    LayerRef layer(GetLayerRef(name));
    LayerRef layer(GetLayerRef<TObject>(name));
    if (!layer)
        return false;
    if (std::find(object->active_layers.begin(), object->active_layers.end(),
@@ -687,10 +698,12 @@ VkResult EnumerateDeviceExtensionProperties_Bottom(
VKAPI_ATTR
VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice /*pdev*/,
                                               uint32_t* properties_count,
                                               VkLayerProperties* /*properties*/) {
    // TODO(jessehall): Implement me...
    *properties_count = 0;
    return VK_SUCCESS;
                                               VkLayerProperties* properties) {
    uint32_t layer_count =
        EnumerateDeviceLayers(properties ? *properties_count : 0, properties);
    if (!properties || *properties_count > layer_count)
        *properties_count = layer_count;
    return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
}

VKAPI_ATTR
@@ -874,7 +887,7 @@ VkResult EnumerateInstanceExtensionProperties_Top(
    const VkExtensionProperties* extensions = nullptr;
    uint32_t num_extensions = 0;
    if (layer_name) {
        GetLayerExtensions(layer_name, &extensions, &num_extensions);
        GetInstanceLayerExtensions(layer_name, &extensions, &num_extensions);
    } else {
        VkExtensionProperties* available = static_cast<VkExtensionProperties*>(
            alloca(kInstanceExtensionCount * sizeof(VkExtensionProperties)));
@@ -907,7 +920,7 @@ VkResult EnumerateInstanceLayerProperties_Top(uint32_t* properties_count,
        return VK_ERROR_INITIALIZATION_FAILED;

    uint32_t layer_count =
        EnumerateLayers(properties ? *properties_count : 0, properties);
        EnumerateInstanceLayers(properties ? *properties_count : 0, properties);
    if (!properties || *properties_count > layer_count)
        *properties_count = layer_count;
    return *properties_count < layer_count ? VK_INCOMPLETE : VK_SUCCESS;
+10 −5
Original line number Diff line number Diff line
@@ -154,11 +154,16 @@ class LayerRef {
};

void DiscoverLayers();
uint32_t EnumerateLayers(uint32_t count, VkLayerProperties* properties);
void GetLayerExtensions(const char* name,
uint32_t EnumerateInstanceLayers(uint32_t count, VkLayerProperties* properties);
uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties);
void GetInstanceLayerExtensions(const char* name,
                                const VkExtensionProperties** properties,
                                uint32_t* count);
LayerRef GetLayerRef(const char* name);
void GetDeviceLayerExtensions(const char* name,
                              const VkExtensionProperties** properties,
                              uint32_t* count);
LayerRef GetInstanceLayerRef(const char* name);
LayerRef GetDeviceLayerRef(const char* name);

InstanceExtension InstanceExtensionFromName(const char* name);

+23 −24
Original line number Diff line number Diff line
@@ -255,6 +255,27 @@ void PrintExtensions(const std::vector<VkExtensionProperties>& extensions,
        printf("%s%s (v%u)\n", prefix, e.extensionName, e.specVersion);
}

void PrintLayers(
    const std::vector<VkLayerProperties>& layers,
    const std::vector<std::vector<VkExtensionProperties>> extensions,
    const char* prefix) {
    std::string ext_prefix(prefix);
    ext_prefix.append("    ");
    for (size_t i = 0; i < layers.size(); i++) {
        printf(
            "%s%s %u.%u.%u/%u\n"
            "%s  %s\n",
            prefix, layers[i].layerName,
            ExtractMajorVersion(layers[i].specVersion),
            ExtractMinorVersion(layers[i].specVersion),
            ExtractPatchVersion(layers[i].specVersion),
            layers[i].implementationVersion, prefix, layers[i].description);
        if (!extensions[i].empty())
            printf("%s  Extensions [%zu]:\n", prefix, extensions[i].size());
        PrintExtensions(extensions[i], ext_prefix.c_str());
    }
}

void PrintGpuInfo(const GpuInfo& info) {
    VkResult result;
    std::ostringstream strbuf;
@@ -321,19 +342,7 @@ void PrintGpuInfo(const GpuInfo& info) {
        }
        if (!info.layers.empty()) {
            printf("    Layers [%zu]:\n", info.layers.size());
            for (size_t i = 0; i < info.layers.size(); i++) {
                const auto& layer = info.layers[i];
                printf("    - %s %u.%u.%u/%u \"%s\"\n", layer.layerName,
                       ExtractMajorVersion(layer.specVersion),
                       ExtractMinorVersion(layer.specVersion),
                       ExtractPatchVersion(layer.specVersion),
                       layer.implementationVersion, layer.description);
                if (!info.layer_extensions[i].empty()) {
                    printf("       Extensions [%zu]:\n",
                           info.layer_extensions.size());
                    PrintExtensions(info.layer_extensions[i], "       ");
                }
            }
            PrintLayers(info.layers, info.layer_extensions, "      ");
        }
    }
}
@@ -345,17 +354,7 @@ void PrintInfo(const VulkanInfo& info) {
    PrintExtensions(info.extensions, "  ");
    if (!info.layers.empty()) {
        printf("Instance Layers [%zu]:\n", info.layers.size());
        for (size_t i = 0; i < info.layers.size(); i++) {
            const auto& layer = info.layers[i];
            printf("  %s %u.%u.%u/%u \"%s\"\n", layer.layerName,
                   ExtractMajorVersion(layer.specVersion),
                   ExtractMinorVersion(layer.specVersion),
                   ExtractPatchVersion(layer.specVersion),
                   layer.implementationVersion, layer.description);
            if (!info.layer_extensions[i].empty()) {
                PrintExtensions(info.layer_extensions[i], "    ");
            }
        }
        PrintLayers(info.layers, info.layer_extensions, "  ");
    }

    printf("PhysicalDevices [%zu]:\n", info.gpus.size());