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

Commit 6cfb89c0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I97efd6c9,I6460f8f0,Ic67e4290,I16214514,Ieaa4e463, ... into nyc-dev

* changes:
  vulkan: remove g_device_layers
  vulkan: ignore device-only layers
  vulkan: ignore layer libraries without instance layers
  vulkan: add FindLayer helper
  vulkan: constify LayerRef members
  vulkan: make g_library_mutex per-LayerLibrary
  vulkan: make LayerLibrary a class
  vulkan: refactor GetLayerGetProcAddr
  vulkan: refactor AddLayerLibrary
  vulkan: refactor LayerRef::~LayerRef
  vulkan: refactor GetLayerRef
  vulkan: add a constructor for LayerLibrary
parents 5882a267 bea09db9
Loading
Loading
Loading
Loading
+252 −198
Original line number Diff line number Diff line
@@ -43,75 +43,118 @@
// 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 {
namespace api {

struct Layer {
    VkLayerProperties properties;
    size_t library_idx;
    std::vector<VkExtensionProperties> extensions;

    bool is_global;

    std::vector<VkExtensionProperties> instance_extensions;
    std::vector<VkExtensionProperties> device_extensions;
};

namespace {

std::mutex g_library_mutex;
struct LayerLibrary {
    std::string path;
    void* dlhandle;
    size_t refcount;
class LayerLibrary {
   public:
    LayerLibrary(const std::string& path)
        : path_(path), dlhandle_(nullptr), refcount_(0) {}

    LayerLibrary(LayerLibrary&& other)
        : path_(std::move(other.path_)),
          dlhandle_(other.dlhandle_),
          refcount_(other.refcount_) {
        other.dlhandle_ = nullptr;
        other.refcount_ = 0;
    }

    LayerLibrary(const LayerLibrary&) = delete;
    LayerLibrary& operator=(const LayerLibrary&) = delete;

    // these are thread-safe
    bool Open();
    void Close();

    bool EnumerateLayers(size_t library_idx,
                         std::vector<Layer>& instance_layers) const;

    void* GetGPA(const Layer& layer,
                 const char* gpa_name,
                 size_t gpa_name_len) const;

   private:
    const std::string path_;

    std::mutex mutex_;
    void* dlhandle_;
    size_t refcount_;
};
std::vector<LayerLibrary> g_layer_libraries;
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());
bool LayerLibrary::Open() {
    std::lock_guard<std::mutex> lock(mutex_);

    void* dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
    if (!dlhandle) {
        ALOGW("failed to load layer library '%s': %s", path.c_str(), dlerror());
        return;
    if (refcount_++ == 0) {
        dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
        ALOGV("Opening library %s", path_.c_str());
        if (!dlhandle_) {
            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
                  dlerror());
            refcount_ = 0;
            return false;
        }
    }
    ALOGV("Refcount on activate is %zu", refcount_);
    return true;
}

void LayerLibrary::Close() {
    std::lock_guard<std::mutex> lock(mutex_);

    if (--refcount_ == 0) {
        ALOGV("Closing library %s", path_.c_str());
        dlclose(dlhandle_);
        dlhandle_ = nullptr;
    }
    ALOGV("Refcount on destruction is %zu", refcount_);
}

bool LayerLibrary::EnumerateLayers(size_t library_idx,
                                   std::vector<Layer>& instance_layers) const {
    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
            dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
        ALOGV("layer library '%s' misses some instance enumeraion functions",
              path_.c_str());
        return false;
    }

    // device functions are optional
    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
            dlsym(dlhandle, "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;
    }
            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));

    VkResult result;
    // get layer counts
    uint32_t num_instance_layers = 0;
    uint32_t num_device_layers = 0;
    if (enumerate_instance_layers) {
        result = enumerate_instance_layers(&num_instance_layers, nullptr);
    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
    if (result != VK_SUCCESS || !num_instance_layers) {
        if (result != VK_SUCCESS) {
            ALOGW(
                "vkEnumerateInstanceLayerProperties failed for library '%s': "
                "%d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
                path_.c_str(), result);
        }
        return false;
    }
    if (enumerate_device_layers) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -119,23 +162,19 @@ void AddLayerLibrary(const std::string& path) {
        if (result != VK_SUCCESS) {
            ALOGW(
                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
                path_.c_str(), result);
            return false;
        }
    }

    // get layer properties
    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",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
        }
        ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
              path_.c_str(), result);
        return false;
    }
    if (num_device_layers > 0) {
        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
@@ -143,102 +182,121 @@ void AddLayerLibrary(const std::string& path) {
        if (result != VK_SUCCESS) {
            ALOGW(
                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
                path.c_str(), result);
            dlclose(dlhandle);
            return;
                path_.c_str(), result);
            return false;
        }
    }

    size_t library_idx = g_layer_libraries.size();
    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);
    // append layers to instance_layers
    size_t prev_num_instance_layers = instance_layers.size();
    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
    for (size_t i = 0; i < num_instance_layers; i++) {
        const VkLayerProperties& props = properties[i];

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

        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",
                    props.layerName, path.c_str(), result);
                g_instance_layers.resize(prev_num_instance_layers);
                dlclose(dlhandle);
                return;
                props.layerName, path_.c_str(), result);
            instance_layers.resize(prev_num_instance_layers);
            return false;
        }
            layer.extensions.resize(count);
            result = enumerate_instance_extensions(props.layerName, &count,
                                                   layer.extensions.data());
        layer.instance_extensions.resize(count);
        result = enumerate_instance_extensions(
            props.layerName, &count, layer.instance_extensions.data());
        if (result != VK_SUCCESS) {
            ALOGW(
                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
                    "library "
                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
                "'%s': %d",
                    props.layerName, path.c_str(), result);
                g_instance_layers.resize(prev_num_instance_layers);
                dlclose(dlhandle);
                return;
            }
                props.layerName, path_.c_str(), result);
            instance_layers.resize(prev_num_instance_layers);
            return false;
        }

        g_instance_layers.push_back(layer);
        ALOGV("  added instance layer '%s'", props.layerName);
        for (size_t j = 0; j < num_device_layers; j++) {
            const auto& dev_props = properties[num_instance_layers + j];
            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
                layer.is_global = true;
                break;
            }
        }
    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;
        if (layer.is_global && enumerate_device_extensions) {
            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;
                    "library '%s': %d",
                    props.layerName, path_.c_str(), result);
                instance_layers.resize(prev_num_instance_layers);
                return false;
            }
            layer.extensions.resize(count);
            result =
                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
                                            &count, layer.extensions.data());
            layer.device_extensions.resize(count);
            result = enumerate_device_extensions(
                VK_NULL_HANDLE, props.layerName, &count,
                layer.device_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;
                    "library '%s': %d",
                    props.layerName, path_.c_str(), result);
                instance_layers.resize(prev_num_instance_layers);
                return false;
            }
        }

        g_device_layers.push_back(layer);
        ALOGV("  added device layer '%s'", props.layerName);
        instance_layers.push_back(layer);
        ALOGV("  added %s layer '%s'",
              (layer.is_global) ? "global" : "instance", props.layerName);
    }

    dlclose(dlhandle);
    return true;
}

    g_layer_libraries.push_back(LayerLibrary{path, nullptr, 0});
void* LayerLibrary::GetGPA(const Layer& layer,
                           const char* gpa_name,
                           size_t gpa_name_len) const {
    void* gpa;
    size_t layer_name_len =
        std::max(size_t{2}, strlen(layer.properties.layerName));
    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
    strcpy(name, layer.properties.layerName);
    strcpy(name + layer_name_len, gpa_name);
    if (!(gpa = dlsym(dlhandle_, name))) {
        strcpy(name, "vk");
        strcpy(name + 2, gpa_name);
        gpa = dlsym(dlhandle_, name);
    }
    return gpa;
}

std::vector<LayerLibrary> g_layer_libraries;
std::vector<Layer> g_instance_layers;

void AddLayerLibrary(const std::string& path) {
    ALOGV("examining layer library '%s'", path.c_str());

    LayerLibrary library(path);
    if (!library.Open())
        return;

    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
        library.Close();
        return;
    }

    library.Close();

    g_layer_libraries.emplace_back(std::move(library));
}

void DiscoverLayersInDirectory(const std::string& dir_path) {
@@ -271,71 +329,25 @@ void DiscoverLayersInDirectory(const std::string& dir_path) {
    closedir(directory);
}

void* GetLayerGetProcAddr(const Layer& layer,
                          const char* gpa_name,
                          size_t gpa_name_len) {
    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
    void* gpa;
    size_t layer_name_len = std::max(size_t{2}, strlen(layer.properties.layerName));
    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
    strcpy(name, layer.properties.layerName);
    strcpy(name + layer_name_len, gpa_name);
    if (!(gpa = dlsym(library.dlhandle, name))) {
        strcpy(name, "vk");
        strcpy(name + 2, gpa_name);
        gpa = dlsym(library.dlhandle, name);
    }
    return gpa;
}

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] = layers[i].properties;
    }
    return static_cast<uint32_t>(layers.size());
}

void GetLayerExtensions(const std::vector<Layer>& layers,
                        const char* name,
                        const VkExtensionProperties** properties,
                        uint32_t* count) {
const Layer* FindInstanceLayer(const char* name) {
    auto layer =
        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
        std::find_if(g_instance_layers.cbegin(), g_instance_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());
    }
    return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
}

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 =
                    dlopen(library.path.c_str(), RTLD_NOW | RTLD_LOCAL);
                ALOGV("Opening library %s", library.path.c_str());
                if (!library.dlhandle) {
                    ALOGE("failed to load layer library '%s': %s",
                          library.path.c_str(), dlerror());
                    library.refcount = 0;
                    return LayerRef(nullptr);
                }
            }
            ALOGV("Refcount on activate is %zu", library.refcount);
            return LayerRef(&layers[id]);
        }
const Layer* FindDeviceLayer(const char* name) {
    const Layer* layer = FindInstanceLayer(name);
    return (layer && layer->is_global) ? layer : nullptr;
}
    return LayerRef(nullptr);

void* GetLayerGetProcAddr(const Layer& layer,
                          const char* gpa_name,
                          size_t gpa_name_len) {
    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
    return library.GetGPA(layer, gpa_name, gpa_name_len);
}

}  // anonymous namespace
@@ -349,45 +361,84 @@ void DiscoverLayers() {

uint32_t EnumerateInstanceLayers(uint32_t count,
                                 VkLayerProperties* properties) {
    return EnumerateLayers(g_instance_layers, count, properties);
    uint32_t n =
        std::min(count, static_cast<uint32_t>(g_instance_layers.size()));
    for (uint32_t i = 0; i < n; i++)
        properties[i] = g_instance_layers[i].properties;

    return static_cast<uint32_t>(g_instance_layers.size());
}

uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
    return EnumerateLayers(g_device_layers, count, properties);
    uint32_t n = 0;
    for (const auto& layer : g_instance_layers) {
        // ignore non-global layers
        if (!layer.is_global)
            continue;

        if (n < count)
            properties[n] = layer.properties;
        n++;
    }

    return n;
}

void GetInstanceLayerExtensions(const char* name,
                                const VkExtensionProperties** properties,
                                uint32_t* count) {
    GetLayerExtensions(g_instance_layers, name, properties, count);
    const Layer* layer = FindInstanceLayer(name);
    if (layer) {
        *properties = layer->instance_extensions.data();
        *count = static_cast<uint32_t>(layer->instance_extensions.size());
    } else {
        *properties = nullptr;
        *count = 0;
    }
}

void GetDeviceLayerExtensions(const char* name,
                              const VkExtensionProperties** properties,
                              uint32_t* count) {
    GetLayerExtensions(g_device_layers, name, properties, count);
    const Layer* layer = FindDeviceLayer(name);
    if (layer) {
        *properties = layer->device_extensions.data();
        *count = static_cast<uint32_t>(layer->device_extensions.size());
    } else {
        *properties = nullptr;
        *count = 0;
    }
}

LayerRef GetInstanceLayerRef(const char* name) {
    return GetLayerRef(g_instance_layers, name);
    const Layer* layer = FindInstanceLayer(name);
    if (layer) {
        LayerLibrary& library = g_layer_libraries[layer->library_idx];
        if (!library.Open())
            layer = nullptr;
    }

    return LayerRef(layer, true);
}

LayerRef GetDeviceLayerRef(const char* name) {
    return GetLayerRef(g_device_layers, name);
    const Layer* layer = FindDeviceLayer(name);
    if (layer) {
        LayerLibrary& library = g_layer_libraries[layer->library_idx];
        if (!library.Open())
            layer = nullptr;
    }

LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
    return LayerRef(layer, false);
}

LayerRef::LayerRef(const Layer* layer, bool is_instance)
    : layer_(layer), is_instance_(is_instance) {}

LayerRef::~LayerRef() {
    if (layer_) {
        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
        std::lock_guard<std::mutex> lock(g_library_mutex);
        if (--library.refcount == 0) {
            ALOGV("Closing library %s", library.path.c_str());
            dlclose(library.dlhandle);
            library.dlhandle = nullptr;
        }
        ALOGV("Refcount on destruction is %zu", library.refcount);
        library.Close();
    }
}

@@ -395,11 +446,12 @@ const char* LayerRef::GetName() const {
    return layer_->properties.layerName;
}

uint32_t LayerRef::GetSpecVersion() {
uint32_t LayerRef::GetSpecVersion() const {
    return layer_->properties.specVersion;
}

LayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
LayerRef::LayerRef(LayerRef&& other)
    : layer_(other.layer_), is_instance_(other.is_instance_) {
    other.layer_ = nullptr;
}

@@ -416,10 +468,12 @@ PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
}

bool LayerRef::SupportsExtension(const char* name) const {
    return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
    const auto& extensions = (is_instance_) ? layer_->instance_extensions
                                            : layer_->device_extensions;
    return std::find_if(extensions.cbegin(), extensions.cend(),
                        [=](const VkExtensionProperties& ext) {
                            return strcmp(ext.extensionName, name) == 0;
                        }) != layer_->extensions.cend();
                        }) != extensions.cend();
}

}  // namespace api
+4 −3
Original line number Diff line number Diff line
@@ -25,14 +25,14 @@ namespace api {
struct Layer;
class LayerRef {
   public:
    LayerRef(Layer* layer);
    LayerRef(const Layer* layer, bool is_instance);
    LayerRef(LayerRef&& other);
    ~LayerRef();
    LayerRef(const LayerRef&) = delete;
    LayerRef& operator=(const LayerRef&) = delete;

    const char* GetName() const;
    uint32_t GetSpecVersion();
    uint32_t GetSpecVersion() const;

    // provides bool-like behavior
    operator const Layer*() const { return layer_; }
@@ -43,7 +43,8 @@ class LayerRef {
    bool SupportsExtension(const char* name) const;

   private:
    Layer* layer_;
    const Layer* layer_;
    bool is_instance_;
};

void DiscoverLayers();