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
17c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu#include "layers_extensions.h"
181a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
1980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <alloca.h>
2080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dirent.h>
2180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dlfcn.h>
22a5e161b1207ef447a51e99856097d69d4a6111e1Mark Salyzyn#include <string.h>
2380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <sys/prctl.h>
24a5e161b1207ef447a51e99856097d69d4a6111e1Mark Salyzyn
25a5e161b1207ef447a51e99856097d69d4a6111e1Mark Salyzyn#include <mutex>
2680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string>
2780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vector>
281a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
2940c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall#include <android/dlext.h>
30a5e161b1207ef447a51e99856097d69d4a6111e1Mark Salyzyn#include <android-base/strings.h>
311a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall#include <cutils/properties.h>
327823e124e00576e20e47ec717cbe8bc89f0f2bf2Mark Salyzyn#include <log/log.h>
331a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall#include <ziparchive/zip_archive.h>
341a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
3580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vulkan/vulkan_loader_data.h>
3680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
37b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
38b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// not a good long-term solution. Having a hard-coded enum of extensions is
39b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// bad, of course. Representing sets of extensions (requested, supported, etc.)
40b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// as a bitset isn't necessarily bad, if the mapping from extension to bit were
41b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// dynamic. Need to rethink this completely when there's a little more time.
42b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
43aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// TODO(jessehall): This file currently builds up global data structures as it
44aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// loads, and never cleans them up. This means we're doing heap allocations
45aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// without going through an app-provided allocator, but worse, we'll leak those
46aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// allocations if the loader is unloaded.
47aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall//
48aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// We should allocate "enough" BSS space, and suballocate from there. Will
49aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// probably want to intern strings, etc., and will need some custom/manual data
50aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// structures.
51aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
5280523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace vulkan {
53c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wunamespace api {
54c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu
5580523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct Layer {
5680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    VkLayerProperties properties;
5780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t library_idx;
58bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
5925700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    // true if the layer intercepts vkCreateDevice and device commands
60bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    bool is_global;
61bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
62bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    std::vector<VkExtensionProperties> instance_extensions;
63bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    std::vector<VkExtensionProperties> device_extensions;
6480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
6580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
6680523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace {
6780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
681a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallconst char kSystemLayerLibraryDir[] = "/data/local/debug/vulkan";
691a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
706693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wuclass LayerLibrary {
716693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu   public:
72c406791ead6d864ec693ad01a80c5f471bdc2a7aChih-Hung Hsieh    explicit LayerLibrary(const std::string& path)
736693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        : path_(path), dlhandle_(nullptr), refcount_(0) {}
74743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
7550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(LayerLibrary&& other)
766693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        : path_(std::move(other.path_)),
776693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu          dlhandle_(other.dlhandle_),
786693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu          refcount_(other.refcount_) {
796693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        other.dlhandle_ = nullptr;
806693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        other.refcount_ = 0;
8150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
8250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
8350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(const LayerLibrary&) = delete;
8450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary& operator=(const LayerLibrary&) = delete;
8550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
86a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    // these are thread-safe
87fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    bool Open();
88d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    void Close();
89fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
9050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    bool EnumerateLayers(size_t library_idx,
91bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                         std::vector<Layer>& instance_layers) const;
9250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
93ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    void* GetGPA(const Layer& layer,
94ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                 const char* gpa_name,
95ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                 size_t gpa_name_len) const;
96ba113275287a2293136d8737bf364651ea0b576dChia-I Wu
976693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu   private:
986693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    const std::string path_;
99a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu
100a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::mutex mutex_;
1016693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    void* dlhandle_;
1026693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    size_t refcount_;
10380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
104743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
105fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wubool LayerLibrary::Open() {
106a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::lock_guard<std::mutex> lock(mutex_);
1076693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (refcount_++ == 0) {
1081a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGV("opening layer library '%s'", path_.c_str());
10940c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // Libraries in the system layer library dir can't be loaded into
11040c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // the application namespace. That causes compatibility problems, since
11140c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // any symbol dependencies will be resolved by system libraries. They
11240c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // can't safely use libc++_shared, for example. Which is one reason
11340c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // (among several) we only allow them in non-user builds.
11440c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        auto app_namespace = LoaderData::GetInstance().app_namespace;
11540c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        if (app_namespace &&
11640c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
11740c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            android_dlextinfo dlextinfo = {};
11840c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
11940c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlextinfo.library_namespace = app_namespace;
12040c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlhandle_ = android_dlopen_ext(path_.c_str(), RTLD_NOW | RTLD_LOCAL,
12140c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall                                           &dlextinfo);
12240c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        } else {
12340c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
12440c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        }
1256693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        if (!dlhandle_) {
1266693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
127fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu                  dlerror());
1286693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            refcount_ = 0;
129fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return false;
130fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        }
131fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    }
132fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    return true;
133fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu}
134fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
135d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wuvoid LayerLibrary::Close() {
136a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::lock_guard<std::mutex> lock(mutex_);
1376693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (--refcount_ == 0) {
1381a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGV("closing layer library '%s'", path_.c_str());
1396693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlclose(dlhandle_);
1406693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlhandle_ = nullptr;
141d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    }
142d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu}
143d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu
14450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wubool LayerLibrary::EnumerateLayers(size_t library_idx,
145bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                                   std::vector<Layer>& instance_layers) const {
146aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
14780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
1486693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
149aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
15080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
1516693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
1525f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
1531a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("layer library '%s' missing some instance enumeration functions",
1545f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu              path_.c_str());
1555f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
1565f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    }
1575f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu
1585f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // device functions are optional
159aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
160aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
1616693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
162aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
163aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
1646693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
16580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
1665f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // get layer counts
167aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_instance_layers = 0;
168aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_device_layers = 0;
1695f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
1705f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (result != VK_SUCCESS || !num_instance_layers) {
171aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
1721a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
173aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
174aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
1756693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
176aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
1775f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
17880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
179aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_device_layers) {
180aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
181aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         nullptr);
182aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
1831a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
184aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
1856693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
18650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
187aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
18880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
1895f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu
1905f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // get layer properties
191aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
192aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
1935f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    result = enumerate_instance_layers(&num_instance_layers, properties);
1945f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (result != VK_SUCCESS) {
1951a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
1965f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu              path_.c_str(), result);
1975f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
198aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
199aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_device_layers > 0) {
200aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
201aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         properties + num_instance_layers);
20280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
2031a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
204aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
2056693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
20650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
20780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
208aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
209aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
210bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    // append layers to instance_layers
21150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    size_t prev_num_instance_layers = instance_layers.size();
21250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
213aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_instance_layers; i++) {
214aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[i];
215aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
216aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
217aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
218aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
219bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        layer.is_global = false;
220aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
2215f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        uint32_t count = 0;
2225f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        result =
2235f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            enumerate_instance_extensions(props.layerName, &count, nullptr);
2245f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        if (result != VK_SUCCESS) {
2251a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
2261a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "vkEnumerateInstanceExtensionProperties(\"%s\") failed for "
2271a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "library '%s': %d",
2285f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                props.layerName, path_.c_str(), result);
2295f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            instance_layers.resize(prev_num_instance_layers);
2305f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            return false;
2315f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        }
232bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        layer.instance_extensions.resize(count);
233bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        result = enumerate_instance_extensions(
234bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu            props.layerName, &count, layer.instance_extensions.data());
2355f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        if (result != VK_SUCCESS) {
2361a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
2371a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "vkEnumerateInstanceExtensionProperties(\"%s\") failed for "
2381a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "library '%s': %d",
2395f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                props.layerName, path_.c_str(), result);
2405f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            instance_layers.resize(prev_num_instance_layers);
2415f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            return false;
242aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
24380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
244279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        for (size_t j = 0; j < num_device_layers; j++) {
245279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            const auto& dev_props = properties[num_instance_layers + j];
246279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
247bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                layer.is_global = true;
248279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu                break;
249279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            }
250279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        }
251279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu
252bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        if (layer.is_global && enumerate_device_extensions) {
253aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_device_extensions(
254aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                VK_NULL_HANDLE, props.layerName, &count, nullptr);
255aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
2561a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                ALOGE(
2571a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                    "vkEnumerateDeviceExtensionProperties(\"%s\") failed for "
25850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
2596693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                    props.layerName, path_.c_str(), result);
26050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
26150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
262aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
263bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu            layer.device_extensions.resize(count);
264bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu            result = enumerate_device_extensions(
265bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                VK_NULL_HANDLE, props.layerName, &count,
266bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                layer.device_extensions.data());
267aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
2681a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                ALOGE(
2691a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                    "vkEnumerateDeviceExtensionProperties(\"%s\") failed for "
27050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
2716693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                    props.layerName, path_.c_str(), result);
27250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
27350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
274aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
275aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
276aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
277bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        instance_layers.push_back(layer);
2781a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGD("added %s layer '%s' from library '%s'",
2791a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall              (layer.is_global) ? "global" : "instance", props.layerName,
2801a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall              path_.c_str());
28180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
28280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
28350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    return true;
28450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu}
28550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
286ba113275287a2293136d8737bf364651ea0b576dChia-I Wuvoid* LayerLibrary::GetGPA(const Layer& layer,
287ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                           const char* gpa_name,
288ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                           size_t gpa_name_len) const {
289ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    void* gpa;
290ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    size_t layer_name_len =
291ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        std::max(size_t{2}, strlen(layer.properties.layerName));
292ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
293ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    strcpy(name, layer.properties.layerName);
294ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    strcpy(name + layer_name_len, gpa_name);
2956693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (!(gpa = dlsym(dlhandle_, name))) {
296ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        strcpy(name, "vk");
297ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        strcpy(name + 2, gpa_name);
2986693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        gpa = dlsym(dlhandle_, name);
299ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    }
300ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    return gpa;
301ba113275287a2293136d8737bf364651ea0b576dChia-I Wu}
302ba113275287a2293136d8737bf364651ea0b576dChia-I Wu
3031a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall// ----------------------------------------------------------------------------
3041a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
30550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<LayerLibrary> g_layer_libraries;
30650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<Layer> g_instance_layers;
30750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
30850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wuvoid AddLayerLibrary(const std::string& path) {
30950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary library(path);
31050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    if (!library.Open())
31150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
31250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
313bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
31450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        library.Close();
31550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
31650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
31750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
31850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    library.Close();
31980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
32050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    g_layer_libraries.emplace_back(std::move(library));
32180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
32280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
3231a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Halltemplate <typename Functor>
3241a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid ForEachFileInDir(const std::string& dirname, Functor functor) {
3251a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    auto dir_deleter = [](DIR* handle) { closedir(handle); };
3261a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    std::unique_ptr<DIR, decltype(dir_deleter)> dir(opendir(dirname.c_str()),
3271a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                                                    dir_deleter);
3281a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if (!dir) {
3291a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        // It's normal for some search directories to not exist, especially
3301a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        // /data/local/debug/vulkan.
33180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        int err = errno;
3321a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGW_IF(err != ENOENT, "failed to open layer directory '%s': %s",
3331a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                 dirname.c_str(), strerror(err));
33480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
33580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
3361a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ALOGD("searching for layers in '%s'", dirname.c_str());
3371a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    dirent* entry;
3381a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    while ((entry = readdir(dir.get())) != nullptr)
3391a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        functor(entry->d_name);
3401a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall}
34180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
3421a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Halltemplate <typename Functor>
3431a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid ForEachFileInZip(const std::string& zipname,
3441a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                      const std::string& dir_in_zip,
3451a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                      Functor functor) {
3461a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    int32_t err;
3471a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ZipArchiveHandle zip = nullptr;
3481a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if ((err = OpenArchive(zipname.c_str(), &zip)) != 0) {
3491a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("failed to open apk '%s': %d", zipname.c_str(), err);
3501a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        return;
3511a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
3521a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    std::string prefix(dir_in_zip + "/");
3531a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    const ZipString prefix_str(prefix.c_str());
3541a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    void* iter_cookie = nullptr;
3551a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) {
3561a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(),
3571a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall              err);
3581a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        CloseArchive(zip);
3591a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        return;
36080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
3611a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ALOGD("searching for layers in '%s!/%s'", zipname.c_str(),
3621a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall          dir_in_zip.c_str());
3631a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ZipEntry entry;
3641a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ZipString name;
3651a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    while (Next(iter_cookie, &entry, &name) == 0) {
3661a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        std::string filename(
3671a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            reinterpret_cast<const char*>(name.name) + prefix.length(),
3681a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            name.name_length - prefix.length());
3691a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        // only enumerate direct entries of the directory, not subdirectories
3708c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        if (filename.find('/') != filename.npos)
3718c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall            continue;
3728c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // Check whether it *may* be possible to load the library directly from
3738c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // the APK. Loading still may fail for other reasons, but this at least
3748c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // lets us avoid failed-to-load log messages in the typical case of
3758c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // compressed and/or unaligned libraries.
3768c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        if (entry.method != kCompressStored || entry.offset % PAGE_SIZE != 0)
3778c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall            continue;
3788c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        functor(filename);
3791a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
3801a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    EndIteration(iter_cookie);
3811a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    CloseArchive(zip);
3821a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall}
38380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
3841a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Halltemplate <typename Functor>
3851a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid ForEachFileInPath(const std::string& path, Functor functor) {
3861a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    size_t zip_pos = path.find("!/");
3871a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if (zip_pos == std::string::npos) {
3881a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ForEachFileInDir(path, functor);
3891a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    } else {
3901a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ForEachFileInZip(path.substr(0, zip_pos), path.substr(zip_pos + 2),
3911a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                         functor);
3921a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
3931a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall}
3941a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
3951a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid DiscoverLayersInPathList(const std::string& pathstr) {
3961a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    std::vector<std::string> paths = android::base::Split(pathstr, ":");
3971a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    for (const auto& path : paths) {
3981a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ForEachFileInPath(path, [&](const std::string& filename) {
3991a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            if (android::base::StartsWith(filename, "libVkLayer") &&
4001a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                android::base::EndsWith(filename, ".so")) {
4011a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                AddLayerLibrary(path + "/" + filename);
4021a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            }
4031a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        });
4041a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
40580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
40680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
407dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wuconst VkExtensionProperties* FindExtension(
408dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    const std::vector<VkExtensionProperties>& extensions,
409dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    const char* name) {
410dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    auto it = std::find_if(extensions.cbegin(), extensions.cend(),
411dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                           [=](const VkExtensionProperties& ext) {
412dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                               return (strcmp(ext.extensionName, name) == 0);
413dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                           });
414dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return (it != extensions.cend()) ? &*it : nullptr;
415dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu}
416dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu
41780523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid* GetLayerGetProcAddr(const Layer& layer,
41880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          const char* gpa_name,
41980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          size_t gpa_name_len) {
42080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
421ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    return library.GetGPA(layer, gpa_name, gpa_name_len);
42280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
42380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
424aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}  // anonymous namespace
425aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
426aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid DiscoverLayers() {
4271a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if (property_get_bool("ro.debuggable", false) &&
4281a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
4291a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        DiscoverLayersInPathList(kSystemLayerLibraryDir);
4301a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
431aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!LoaderData::GetInstance().layer_path.empty())
4321a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        DiscoverLayersInPathList(LoaderData::GetInstance().layer_path);
433aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
434aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
43525700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wuuint32_t GetLayerCount() {
436bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    return static_cast<uint32_t>(g_instance_layers.size());
437aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
438aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
43925700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wuconst Layer& GetLayer(uint32_t index) {
44025700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    return g_instance_layers[index];
44125700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu}
442bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
44304c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wuconst Layer* FindLayer(const char* name) {
44404c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    auto layer =
44504c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu        std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
44604c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                     [=](const Layer& entry) {
44704c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                         return strcmp(entry.properties.layerName, name) == 0;
44804c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                     });
44904c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
45004c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu}
45104c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu
45225700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wuconst VkLayerProperties& GetLayerProperties(const Layer& layer) {
45325700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    return layer.properties;
45425700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu}
455bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
45625700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wubool IsLayerGlobal(const Layer& layer) {
45725700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    return layer.is_global;
458aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
459aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
46004c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wuconst VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
46104c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                                                        uint32_t& count) {
46204c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    count = static_cast<uint32_t>(layer.instance_extensions.size());
46304c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    return layer.instance_extensions.data();
464aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
465aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
46604c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wuconst VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
46704c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                                                      uint32_t& count) {
46804c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    count = static_cast<uint32_t>(layer.device_extensions.size());
46904c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    return layer.device_extensions.data();
470aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
471aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
472dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wuconst VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
473dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                                                        const char* name) {
474dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return FindExtension(layer.instance_extensions, name);
475aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
476aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
477dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wuconst VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
478dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                                                      const char* name) {
479dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return FindExtension(layer.device_extensions, name);
480dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu}
481dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu
482dab25658fb17ec76569b8e91dfed801855027f08Chia-I WuLayerRef GetLayerRef(const Layer& layer) {
483d6e6f51426c566cd67ed765e5c4b206a063aaa30Chia-I Wu    LayerLibrary& library = g_layer_libraries[layer.library_idx];
484dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return LayerRef((library.Open()) ? &layer : nullptr);
485aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
486aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
487dab25658fb17ec76569b8e91dfed801855027f08Chia-I WuLayerRef::LayerRef(const Layer* layer) : layer_(layer) {}
48880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
48980523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::~LayerRef() {
49080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (layer_) {
49180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
492d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        library.Close();
49380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
49480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
49580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
496dab25658fb17ec76569b8e91dfed801855027f08Chia-I WuLayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
49754e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine    other.layer_ = nullptr;
49854e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine}
49980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
50080523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
50180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
50280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
50380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
50480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
50580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
50680523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
50780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
50880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
50980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
51080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
51180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
512c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu}  // namespace api
51380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
514