layers_extensions.cpp revision 279ccc0048d5bc7105af02538e33946814c68dc7
180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall/*
280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * Copyright 2016 The Android Open Source Project
380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *
480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * you may not use this file except in compliance with the License.
680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * You may obtain a copy of the License at
780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *
880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *
1080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * Unless required by applicable law or agreed to in writing, software
1180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
1280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * See the License for the specific language governing permissions and
1480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * limitations under the License.
1580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall */
1680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
17d0b7cb566288a4f6646e356a17188b7922ba5740Michael Lentine// #define LOG_NDEBUG 0
18d0b7cb566288a4f6646e356a17188b7922ba5740Michael Lentine
19c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu#include "layers_extensions.h"
2080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <alloca.h>
2180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dirent.h>
2280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dlfcn.h>
2380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <mutex>
2480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <sys/prctl.h>
2580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string>
2680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string.h>
2780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vector>
2880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <log/log.h>
2980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vulkan/vulkan_loader_data.h>
3080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
32b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// not a good long-term solution. Having a hard-coded enum of extensions is
33b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// bad, of course. Representing sets of extensions (requested, supported, etc.)
34b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// as a bitset isn't necessarily bad, if the mapping from extension to bit were
35b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// dynamic. Need to rethink this completely when there's a little more time.
36b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
37aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// TODO(jessehall): This file currently builds up global data structures as it
38aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// loads, and never cleans them up. This means we're doing heap allocations
39aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// without going through an app-provided allocator, but worse, we'll leak those
40aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// allocations if the loader is unloaded.
41aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall//
42aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// We should allocate "enough" BSS space, and suballocate from there. Will
43aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// probably want to intern strings, etc., and will need some custom/manual data
44aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// structures.
45aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
46aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// TODO(jessehall): Currently we have separate lists for instance and device
47aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// layers. Most layers are both; we should use one entry for each layer name,
48aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// with a mask saying what kind(s) it is.
49aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
5080523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace vulkan {
51c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wunamespace api {
52c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu
5380523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct Layer {
5480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    VkLayerProperties properties;
5580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t library_idx;
5680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::vector<VkExtensionProperties> extensions;
5780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
5880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
5980523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace {
6080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
616693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wuclass LayerLibrary {
626693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu   public:
636693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    LayerLibrary(const std::string& path)
646693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        : path_(path), dlhandle_(nullptr), refcount_(0) {}
65743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
6650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(LayerLibrary&& other)
676693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        : path_(std::move(other.path_)),
686693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu          dlhandle_(other.dlhandle_),
696693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu          refcount_(other.refcount_) {
706693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        other.dlhandle_ = nullptr;
716693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        other.refcount_ = 0;
7250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
7350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
7450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(const LayerLibrary&) = delete;
7550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary& operator=(const LayerLibrary&) = delete;
7650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
77a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    // these are thread-safe
78fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    bool Open();
79d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    void Close();
80fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
8150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    bool EnumerateLayers(size_t library_idx,
8250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                         std::vector<Layer>& instance_layers,
8350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                         std::vector<Layer>& device_layers) const;
8450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
85ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    void* GetGPA(const Layer& layer,
86ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                 const char* gpa_name,
87ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                 size_t gpa_name_len) const;
88ba113275287a2293136d8737bf364651ea0b576dChia-I Wu
896693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu   private:
906693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    const std::string path_;
91a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu
92a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::mutex mutex_;
936693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    void* dlhandle_;
946693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    size_t refcount_;
9580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
96743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
97fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wubool LayerLibrary::Open() {
98a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::lock_guard<std::mutex> lock(mutex_);
99a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu
1006693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (refcount_++ == 0) {
1016693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
1026693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        ALOGV("Opening library %s", path_.c_str());
1036693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        if (!dlhandle_) {
1046693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
105fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu                  dlerror());
1066693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            refcount_ = 0;
107fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return false;
108fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        }
109fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    }
1106693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    ALOGV("Refcount on activate is %zu", refcount_);
111fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    return true;
112fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu}
113fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
114d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wuvoid LayerLibrary::Close() {
115a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::lock_guard<std::mutex> lock(mutex_);
116a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu
1176693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (--refcount_ == 0) {
1186693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        ALOGV("Closing library %s", path_.c_str());
1196693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlclose(dlhandle_);
1206693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlhandle_ = nullptr;
121d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    }
1226693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    ALOGV("Refcount on destruction is %zu", refcount_);
123d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu}
124d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu
12550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wubool LayerLibrary::EnumerateLayers(size_t library_idx,
12650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                                   std::vector<Layer>& instance_layers,
12750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                                   std::vector<Layer>& device_layers) const {
128aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
12980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
1306693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
131aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
13280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
1336693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
1345f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
1355f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        ALOGV("layer library '%s' misses some instance enumeraion functions",
1365f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu              path_.c_str());
1375f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
1385f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    }
1395f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu
1405f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // device functions are optional
141aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
142aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
1436693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
144aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
145aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
1466693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
14780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
1485f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // get layer counts
149aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_instance_layers = 0;
150aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_device_layers = 0;
1515f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
1525f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (result != VK_SUCCESS || !num_instance_layers) {
153aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
154aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
155aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
156aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
1576693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
158aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
1595f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
16080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
161aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_device_layers) {
162aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
163aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         nullptr);
164aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
165aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
166aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
1676693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
16850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
169aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
17080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
1715f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu
1725f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // get layer properties
173aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
174aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
1755f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    result = enumerate_instance_layers(&num_instance_layers, properties);
1765f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (result != VK_SUCCESS) {
1775f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
1785f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu              path_.c_str(), result);
1795f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
180aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
181aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_device_layers > 0) {
182aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
183aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         properties + num_instance_layers);
18480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
18580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            ALOGW(
186aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
1876693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
18850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
18980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
190aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
191aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
1925f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // append layers to instance_layers/device_layers
19350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    size_t prev_num_instance_layers = instance_layers.size();
19450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    size_t prev_num_device_layers = device_layers.size();
19550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
19650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    device_layers.reserve(prev_num_device_layers + num_device_layers);
197aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_instance_layers; i++) {
198aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[i];
199aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
200aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
201aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
202aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
203aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
2045f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        uint32_t count = 0;
2055f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        result =
2065f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            enumerate_instance_extensions(props.layerName, &count, nullptr);
2075f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        if (result != VK_SUCCESS) {
2085f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            ALOGW(
2095f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
2105f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                "'%s': %d",
2115f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                props.layerName, path_.c_str(), result);
2125f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            instance_layers.resize(prev_num_instance_layers);
2135f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            return false;
2145f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        }
2155f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        layer.extensions.resize(count);
2165f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        result = enumerate_instance_extensions(props.layerName, &count,
2175f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                                               layer.extensions.data());
2185f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        if (result != VK_SUCCESS) {
2195f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            ALOGW(
2205f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
2215f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                "'%s': %d",
2225f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                props.layerName, path_.c_str(), result);
2235f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            instance_layers.resize(prev_num_instance_layers);
2245f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            return false;
225aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
22680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
22750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        instance_layers.push_back(layer);
228b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added instance layer '%s'", props.layerName);
229aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
230279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        bool is_global = false;
231279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        for (size_t j = 0; j < num_device_layers; j++) {
232279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            const auto& dev_props = properties[num_instance_layers + j];
233279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
234279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu                is_global = true;
235279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu                break;
236279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            }
237279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        }
238279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu
239279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        if (!is_global)
240279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            continue;
241aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
242279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        layer.extensions.clear();
243aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_device_extensions) {
244aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_device_extensions(
245aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                VK_NULL_HANDLE, props.layerName, &count, nullptr);
246aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
247aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
248aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
24950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
2506693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                    props.layerName, path_.c_str(), result);
25150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
25250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                device_layers.resize(prev_num_device_layers);
25350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
254aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
255aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
256aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
257aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
258aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                            &count, layer.extensions.data());
259aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
260aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
261aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
26250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
2636693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                    props.layerName, path_.c_str(), result);
26450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
26550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                device_layers.resize(prev_num_device_layers);
26650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
267aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
268aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
269aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
27050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        device_layers.push_back(layer);
271b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added device layer '%s'", props.layerName);
27280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
27380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
27450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    return true;
27550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu}
27650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
277ba113275287a2293136d8737bf364651ea0b576dChia-I Wuvoid* LayerLibrary::GetGPA(const Layer& layer,
278ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                           const char* gpa_name,
279ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                           size_t gpa_name_len) const {
280ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    void* gpa;
281ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    size_t layer_name_len =
282ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        std::max(size_t{2}, strlen(layer.properties.layerName));
283ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
284ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    strcpy(name, layer.properties.layerName);
285ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    strcpy(name + layer_name_len, gpa_name);
2866693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (!(gpa = dlsym(dlhandle_, name))) {
287ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        strcpy(name, "vk");
288ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        strcpy(name + 2, gpa_name);
2896693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        gpa = dlsym(dlhandle_, name);
290ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    }
291ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    return gpa;
292ba113275287a2293136d8737bf364651ea0b576dChia-I Wu}
293ba113275287a2293136d8737bf364651ea0b576dChia-I Wu
29450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<LayerLibrary> g_layer_libraries;
29550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<Layer> g_instance_layers;
29650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<Layer> g_device_layers;
29750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
29850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wuvoid AddLayerLibrary(const std::string& path) {
29950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    ALOGV("examining layer library '%s'", path.c_str());
30050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
30150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary library(path);
30250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    if (!library.Open())
30350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
30450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
30550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers,
30650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                                 g_device_layers)) {
30750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        library.Close();
30850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
30950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
31050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
31150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    library.Close();
31280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    g_layer_libraries.emplace_back(std::move(library));
31480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
31580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31680523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid DiscoverLayersInDirectory(const std::string& dir_path) {
31780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    ALOGV("looking for layers in '%s'", dir_path.c_str());
31880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    DIR* directory = opendir(dir_path.c_str());
32080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!directory) {
32180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        int err = errno;
32280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
32380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                 dir_path.c_str(), strerror(err), err);
32480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
32580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
32680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
32780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
32880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.reserve(dir_path.size() + 20);
32980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append(dir_path);
33080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append("/");
33180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
33280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    struct dirent* entry;
33380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    while ((entry = readdir(directory))) {
33480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        size_t libname_len = strlen(entry->d_name);
335a7ac76df54c30e771ecfd05cdd2b52209af71470Jesse Hall        if (strncmp(entry->d_name, "libVkLayer", 10) != 0 ||
33680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
33780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            continue;
33880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.append(entry->d_name);
33980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        AddLayerLibrary(path);
34080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.resize(dir_path.size() + 1);
34180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
34280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
34380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    closedir(directory);
34480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
34580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
34650db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wuconst Layer* FindLayer(const std::vector<Layer>& layers, const char* name) {
34750db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    auto layer =
34850db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
34950db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu            return strcmp(entry.properties.layerName, name) == 0;
35050db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu        });
35150db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    return (layer != layers.cend()) ? &*layer : nullptr;
35250db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu}
35350db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu
35480523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid* GetLayerGetProcAddr(const Layer& layer,
35580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          const char* gpa_name,
35680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          size_t gpa_name_len) {
35780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
358ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    return library.GetGPA(layer, gpa_name, gpa_name_len);
35980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
36080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
361aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateLayers(const std::vector<Layer>& layers,
362aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         uint32_t count,
363aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         VkLayerProperties* properties) {
364aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
36580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    for (uint32_t i = 0; i < n; i++) {
366aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        properties[i] = layers[i].properties;
36780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
368aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return static_cast<uint32_t>(layers.size());
36980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
37080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
371aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetLayerExtensions(const std::vector<Layer>& layers,
372aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                        const char* name,
37380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        const VkExtensionProperties** properties,
37480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        uint32_t* count) {
37550db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    const Layer* layer = FindLayer(layers, name);
37650db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    if (layer) {
377aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = layer->extensions.data();
378aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = static_cast<uint32_t>(layer->extensions.size());
37950db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    } else {
38050db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu        *properties = nullptr;
38150db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu        *count = 0;
38280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
38380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
38480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
385aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
38650db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    const Layer* layer = FindLayer(layers, name);
38750db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    if (layer) {
38850db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu        LayerLibrary& library = g_layer_libraries[layer->library_idx];
38950db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu        if (!library.Open())
39050db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu            layer = nullptr;
39180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
39250db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu
39350db9035b034385a27fb557e4da3c48b51a0e3ebChia-I Wu    return LayerRef(layer);
39480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
39580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
396aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}  // anonymous namespace
397aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
398aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid DiscoverLayers() {
399aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
400aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory("/data/local/debug/vulkan");
401aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!LoaderData::GetInstance().layer_path.empty())
402aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
403aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
404aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
405aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateInstanceLayers(uint32_t count,
406aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                 VkLayerProperties* properties) {
407aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_instance_layers, count, properties);
408aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
409aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
410aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
411aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_device_layers, count, properties);
412aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
413aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
414aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetInstanceLayerExtensions(const char* name,
415aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                const VkExtensionProperties** properties,
416aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                uint32_t* count) {
417aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_instance_layers, name, properties, count);
418aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
419aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
420aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetDeviceLayerExtensions(const char* name,
421aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              const VkExtensionProperties** properties,
422aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              uint32_t* count) {
423aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_device_layers, name, properties, count);
424aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
425aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
426aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetInstanceLayerRef(const char* name) {
427aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_instance_layers, name);
428aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
429aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
430aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetDeviceLayerRef(const char* name) {
431aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_device_layers, name);
432aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
433aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
43483506d84d00bbb35ecebb44261b2139bc40ef3e2Chia-I WuLayerRef::LayerRef(const Layer* layer) : layer_(layer) {}
43580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
43680523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::~LayerRef() {
43780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (layer_) {
43880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
439d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        library.Close();
44080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
44180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
44280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
4435703683fb645a7e31ac25aaf7136013a6a9b9fbcMichael Lentineconst char* LayerRef::GetName() const {
444eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter    return layer_->properties.layerName;
445eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter}
446eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter
44783506d84d00bbb35ecebb44261b2139bc40ef3e2Chia-I Wuuint32_t LayerRef::GetSpecVersion() const {
448eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter    return layer_->properties.specVersion;
449eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter}
450eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter
45154e6f086a6b373a0f496343451a76dde8aa86238Michael LentineLayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
45254e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine    other.layer_ = nullptr;
45354e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine}
45480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
45580523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
45680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
45780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
45880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
45980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
46080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
46180523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
46280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
46380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
46480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
46580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
46680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
467b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hallbool LayerRef::SupportsExtension(const char* name) const {
468b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
469b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        [=](const VkExtensionProperties& ext) {
470b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                            return strcmp(ext.extensionName, name) == 0;
471b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        }) != layer_->extensions.cend();
472b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall}
473b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
474c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu}  // namespace api
47580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
476