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>
2280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <mutex>
2380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <sys/prctl.h>
2480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string>
2580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string.h>
2680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vector>
271a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
281a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall#include <android-base/strings.h>
2940c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall#include <android/dlext.h>
301a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall#include <cutils/properties.h>
3180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <log/log.h>
321a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall#include <ziparchive/zip_archive.h>
331a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
3480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vulkan/vulkan_loader_data.h>
3580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
36b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
37b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// not a good long-term solution. Having a hard-coded enum of extensions is
38b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// bad, of course. Representing sets of extensions (requested, supported, etc.)
39b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// as a bitset isn't necessarily bad, if the mapping from extension to bit were
40b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// dynamic. Need to rethink this completely when there's a little more time.
41b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
42aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// TODO(jessehall): This file currently builds up global data structures as it
43aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// loads, and never cleans them up. This means we're doing heap allocations
44aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// without going through an app-provided allocator, but worse, we'll leak those
45aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// allocations if the loader is unloaded.
46aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall//
47aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// We should allocate "enough" BSS space, and suballocate from there. Will
48aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// probably want to intern strings, etc., and will need some custom/manual data
49aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// structures.
50aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
5180523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace vulkan {
52c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wunamespace api {
53c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu
5480523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct Layer {
5580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    VkLayerProperties properties;
5680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t library_idx;
57bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
5825700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    // true if the layer intercepts vkCreateDevice and device commands
59bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    bool is_global;
60bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
61bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    std::vector<VkExtensionProperties> instance_extensions;
62bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    std::vector<VkExtensionProperties> device_extensions;
6380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
6480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
6580523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace {
6680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
671a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallconst char kSystemLayerLibraryDir[] = "/data/local/debug/vulkan";
681a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
696693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wuclass LayerLibrary {
706693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu   public:
716693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    LayerLibrary(const std::string& path)
726693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        : path_(path), dlhandle_(nullptr), refcount_(0) {}
73743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
7450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(LayerLibrary&& other)
756693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        : path_(std::move(other.path_)),
766693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu          dlhandle_(other.dlhandle_),
776693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu          refcount_(other.refcount_) {
786693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        other.dlhandle_ = nullptr;
796693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        other.refcount_ = 0;
8050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
8150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
8250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(const LayerLibrary&) = delete;
8350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary& operator=(const LayerLibrary&) = delete;
8450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
85a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    // these are thread-safe
86fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    bool Open();
87d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    void Close();
88fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
8950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    bool EnumerateLayers(size_t library_idx,
90bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                         std::vector<Layer>& instance_layers) const;
9150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
92ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    void* GetGPA(const Layer& layer,
93ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                 const char* gpa_name,
94ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                 size_t gpa_name_len) const;
95ba113275287a2293136d8737bf364651ea0b576dChia-I Wu
966693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu   private:
976693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    const std::string path_;
98a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu
99a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::mutex mutex_;
1006693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    void* dlhandle_;
1016693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    size_t refcount_;
10280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
103743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
104fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wubool LayerLibrary::Open() {
105a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::lock_guard<std::mutex> lock(mutex_);
1066693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (refcount_++ == 0) {
1071a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGV("opening layer library '%s'", path_.c_str());
10840c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // Libraries in the system layer library dir can't be loaded into
10940c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // the application namespace. That causes compatibility problems, since
11040c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // any symbol dependencies will be resolved by system libraries. They
11140c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // can't safely use libc++_shared, for example. Which is one reason
11240c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        // (among several) we only allow them in non-user builds.
11340c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        auto app_namespace = LoaderData::GetInstance().app_namespace;
11440c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        if (app_namespace &&
11540c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            !android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
11640c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            android_dlextinfo dlextinfo = {};
11740c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
11840c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlextinfo.library_namespace = app_namespace;
11940c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlhandle_ = android_dlopen_ext(path_.c_str(), RTLD_NOW | RTLD_LOCAL,
12040c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall                                           &dlextinfo);
12140c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        } else {
12240c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall            dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
12340c07a1d002561fc8db987ec30d890b041fb6336Jesse Hall        }
1246693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        if (!dlhandle_) {
1256693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
126fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu                  dlerror());
1276693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            refcount_ = 0;
128fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return false;
129fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        }
130fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    }
131fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    return true;
132fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu}
133fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
134d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wuvoid LayerLibrary::Close() {
135a6229749aeef225803c6a5411be9e8a40637454dChia-I Wu    std::lock_guard<std::mutex> lock(mutex_);
1366693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (--refcount_ == 0) {
1371a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGV("closing layer library '%s'", path_.c_str());
1386693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlclose(dlhandle_);
1396693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        dlhandle_ = nullptr;
140d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    }
141d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu}
142d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu
14350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wubool LayerLibrary::EnumerateLayers(size_t library_idx,
144bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                                   std::vector<Layer>& instance_layers) const {
145aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
14680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
1476693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
148aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
14980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
1506693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
1515f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
1521a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("layer library '%s' missing some instance enumeration functions",
1535f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu              path_.c_str());
1545f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
1555f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    }
1565f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu
1575f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // device functions are optional
158aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
159aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
1606693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
161aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
162aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
1636693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
16480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
1655f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // get layer counts
166aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_instance_layers = 0;
167aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_device_layers = 0;
1685f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
1695f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (result != VK_SUCCESS || !num_instance_layers) {
170aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
1711a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
172aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
173aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
1746693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
175aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
1765f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
17780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
178aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_device_layers) {
179aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
180aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         nullptr);
181aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
1821a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
183aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
1846693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
18550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
186aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
18780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
1885f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu
1895f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    // get layer properties
190aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
191aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
1925f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    result = enumerate_instance_layers(&num_instance_layers, properties);
1935f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu    if (result != VK_SUCCESS) {
1941a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
1955f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu              path_.c_str(), result);
1965f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        return false;
197aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
198aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_device_layers > 0) {
199aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
200aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         properties + num_instance_layers);
20180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
2021a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
203aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
2046693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                path_.c_str(), result);
20550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
20680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
207aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
208aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
209bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    // append layers to instance_layers
21050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    size_t prev_num_instance_layers = instance_layers.size();
21150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
212aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_instance_layers; i++) {
213aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[i];
214aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
215aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
216aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
217aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
218bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        layer.is_global = false;
219aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
2205f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        uint32_t count = 0;
2215f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        result =
2225f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            enumerate_instance_extensions(props.layerName, &count, nullptr);
2235f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        if (result != VK_SUCCESS) {
2241a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
2251a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "vkEnumerateInstanceExtensionProperties(\"%s\") failed for "
2261a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "library '%s': %d",
2275f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                props.layerName, path_.c_str(), result);
2285f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            instance_layers.resize(prev_num_instance_layers);
2295f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            return false;
2305f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        }
231bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        layer.instance_extensions.resize(count);
232bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        result = enumerate_instance_extensions(
233bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu            props.layerName, &count, layer.instance_extensions.data());
2345f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu        if (result != VK_SUCCESS) {
2351a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            ALOGE(
2361a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "vkEnumerateInstanceExtensionProperties(\"%s\") failed for "
2371a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                "library '%s': %d",
2385f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu                props.layerName, path_.c_str(), result);
2395f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            instance_layers.resize(prev_num_instance_layers);
2405f093bf18120a5cbf18d0f3e255b2178f524e438Chia-I Wu            return false;
241aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
24280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
243279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        for (size_t j = 0; j < num_device_layers; j++) {
244279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            const auto& dev_props = properties[num_instance_layers + j];
245279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
246bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                layer.is_global = true;
247279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu                break;
248279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu            }
249279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu        }
250279ccc0048d5bc7105af02538e33946814c68dc7Chia-I Wu
251bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        if (layer.is_global && enumerate_device_extensions) {
252aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_device_extensions(
253aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                VK_NULL_HANDLE, props.layerName, &count, nullptr);
254aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
2551a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                ALOGE(
2561a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                    "vkEnumerateDeviceExtensionProperties(\"%s\") failed for "
25750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
2586693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                    props.layerName, path_.c_str(), result);
25950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
26050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
261aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
262bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu            layer.device_extensions.resize(count);
263bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu            result = enumerate_device_extensions(
264bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                VK_NULL_HANDLE, props.layerName, &count,
265bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu                layer.device_extensions.data());
266aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
2671a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                ALOGE(
2681a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                    "vkEnumerateDeviceExtensionProperties(\"%s\") failed for "
26950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
2706693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu                    props.layerName, path_.c_str(), result);
27150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
27250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
273aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
274aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
275aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
276bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu        instance_layers.push_back(layer);
2771a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGD("added %s layer '%s' from library '%s'",
2781a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall              (layer.is_global) ? "global" : "instance", props.layerName,
2791a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall              path_.c_str());
28080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
28180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
28250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    return true;
28350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu}
28450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
285ba113275287a2293136d8737bf364651ea0b576dChia-I Wuvoid* LayerLibrary::GetGPA(const Layer& layer,
286ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                           const char* gpa_name,
287ba113275287a2293136d8737bf364651ea0b576dChia-I Wu                           size_t gpa_name_len) const {
288ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    void* gpa;
289ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    size_t layer_name_len =
290ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        std::max(size_t{2}, strlen(layer.properties.layerName));
291ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
292ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    strcpy(name, layer.properties.layerName);
293ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    strcpy(name + layer_name_len, gpa_name);
2946693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu    if (!(gpa = dlsym(dlhandle_, name))) {
295ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        strcpy(name, "vk");
296ba113275287a2293136d8737bf364651ea0b576dChia-I Wu        strcpy(name + 2, gpa_name);
2976693f5cd2238fe08b382bf762e33b701312c7038Chia-I Wu        gpa = dlsym(dlhandle_, name);
298ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    }
299ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    return gpa;
300ba113275287a2293136d8737bf364651ea0b576dChia-I Wu}
301ba113275287a2293136d8737bf364651ea0b576dChia-I Wu
3021a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall// ----------------------------------------------------------------------------
3031a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
30450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<LayerLibrary> g_layer_libraries;
30550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<Layer> g_instance_layers;
30650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
30750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wuvoid AddLayerLibrary(const std::string& path) {
30850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary library(path);
30950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    if (!library.Open())
31050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
31150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
312bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
31350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        library.Close();
31450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
31550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
31650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
31750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    library.Close();
31880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    g_layer_libraries.emplace_back(std::move(library));
32080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
32180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
3221a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Halltemplate <typename Functor>
3231a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid ForEachFileInDir(const std::string& dirname, Functor functor) {
3241a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    auto dir_deleter = [](DIR* handle) { closedir(handle); };
3251a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    std::unique_ptr<DIR, decltype(dir_deleter)> dir(opendir(dirname.c_str()),
3261a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                                                    dir_deleter);
3271a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if (!dir) {
3281a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        // It's normal for some search directories to not exist, especially
3291a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        // /data/local/debug/vulkan.
33080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        int err = errno;
3311a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGW_IF(err != ENOENT, "failed to open layer directory '%s': %s",
3321a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                 dirname.c_str(), strerror(err));
33380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
33480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
3351a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ALOGD("searching for layers in '%s'", dirname.c_str());
3361a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    dirent* entry;
3371a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    while ((entry = readdir(dir.get())) != nullptr)
3381a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        functor(entry->d_name);
3391a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall}
34080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
3411a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Halltemplate <typename Functor>
3421a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid ForEachFileInZip(const std::string& zipname,
3431a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                      const std::string& dir_in_zip,
3441a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                      Functor functor) {
3451a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    int32_t err;
3461a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ZipArchiveHandle zip = nullptr;
3471a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if ((err = OpenArchive(zipname.c_str(), &zip)) != 0) {
3481a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("failed to open apk '%s': %d", zipname.c_str(), err);
3491a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        return;
3501a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
3511a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    std::string prefix(dir_in_zip + "/");
3521a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    const ZipString prefix_str(prefix.c_str());
3531a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    void* iter_cookie = nullptr;
3541a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if ((err = StartIteration(zip, &iter_cookie, &prefix_str, nullptr)) != 0) {
3551a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ALOGE("failed to iterate entries in apk '%s': %d", zipname.c_str(),
3561a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall              err);
3571a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        CloseArchive(zip);
3581a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        return;
35980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
3601a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ALOGD("searching for layers in '%s!/%s'", zipname.c_str(),
3611a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall          dir_in_zip.c_str());
3621a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ZipEntry entry;
3631a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    ZipString name;
3641a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    while (Next(iter_cookie, &entry, &name) == 0) {
3651a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        std::string filename(
3661a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            reinterpret_cast<const char*>(name.name) + prefix.length(),
3671a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            name.name_length - prefix.length());
3681a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        // only enumerate direct entries of the directory, not subdirectories
3698c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        if (filename.find('/') != filename.npos)
3708c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall            continue;
3718c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // Check whether it *may* be possible to load the library directly from
3728c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // the APK. Loading still may fail for other reasons, but this at least
3738c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // lets us avoid failed-to-load log messages in the typical case of
3748c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        // compressed and/or unaligned libraries.
3758c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        if (entry.method != kCompressStored || entry.offset % PAGE_SIZE != 0)
3768c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall            continue;
3778c6c10e20d40066468bf4350b64703e11d5bff10Jesse Hall        functor(filename);
3781a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
3791a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    EndIteration(iter_cookie);
3801a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    CloseArchive(zip);
3811a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall}
38280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
3831a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Halltemplate <typename Functor>
3841a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid ForEachFileInPath(const std::string& path, Functor functor) {
3851a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    size_t zip_pos = path.find("!/");
3861a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if (zip_pos == std::string::npos) {
3871a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ForEachFileInDir(path, functor);
3881a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    } else {
3891a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ForEachFileInZip(path.substr(0, zip_pos), path.substr(zip_pos + 2),
3901a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                         functor);
3911a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
3921a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall}
3931a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall
3941a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hallvoid DiscoverLayersInPathList(const std::string& pathstr) {
3951a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    std::vector<std::string> paths = android::base::Split(pathstr, ":");
3961a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    for (const auto& path : paths) {
3971a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        ForEachFileInPath(path, [&](const std::string& filename) {
3981a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            if (android::base::StartsWith(filename, "libVkLayer") &&
3991a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                android::base::EndsWith(filename, ".so")) {
4001a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall                AddLayerLibrary(path + "/" + filename);
4011a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall            }
4021a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        });
4031a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
40480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
40580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
406dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wuconst VkExtensionProperties* FindExtension(
407dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    const std::vector<VkExtensionProperties>& extensions,
408dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    const char* name) {
409dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    auto it = std::find_if(extensions.cbegin(), extensions.cend(),
410dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                           [=](const VkExtensionProperties& ext) {
411dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                               return (strcmp(ext.extensionName, name) == 0);
412dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                           });
413dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return (it != extensions.cend()) ? &*it : nullptr;
414dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu}
415dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu
41680523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid* GetLayerGetProcAddr(const Layer& layer,
41780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          const char* gpa_name,
41880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          size_t gpa_name_len) {
41980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
420ba113275287a2293136d8737bf364651ea0b576dChia-I Wu    return library.GetGPA(layer, gpa_name, gpa_name_len);
42180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
42280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
423aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}  // anonymous namespace
424aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
425aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid DiscoverLayers() {
4261a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    if (property_get_bool("ro.debuggable", false) &&
4271a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
4281a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        DiscoverLayersInPathList(kSystemLayerLibraryDir);
4291a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall    }
430aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!LoaderData::GetInstance().layer_path.empty())
4311a7eb59c2a7907ea4c4925c6d13d66e53fb60339Jesse Hall        DiscoverLayersInPathList(LoaderData::GetInstance().layer_path);
432aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
433aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
43425700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wuuint32_t GetLayerCount() {
435bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu    return static_cast<uint32_t>(g_instance_layers.size());
436aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
437aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
43825700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wuconst Layer& GetLayer(uint32_t index) {
43925700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    return g_instance_layers[index];
44025700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu}
441bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
44204c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wuconst Layer* FindLayer(const char* name) {
44304c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    auto layer =
44404c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu        std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
44504c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                     [=](const Layer& entry) {
44604c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                         return strcmp(entry.properties.layerName, name) == 0;
44704c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                     });
44804c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
44904c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu}
45004c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu
45125700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wuconst VkLayerProperties& GetLayerProperties(const Layer& layer) {
45225700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    return layer.properties;
45325700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu}
454bea09db9c2165f06771f3a3da423f4f85ac6347eChia-I Wu
45525700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wubool IsLayerGlobal(const Layer& layer) {
45625700b452535ce7ae838bfe832392b46ed555ed2Chia-I Wu    return layer.is_global;
457aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
458aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
45904c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wuconst VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
46004c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                                                        uint32_t& count) {
46104c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    count = static_cast<uint32_t>(layer.instance_extensions.size());
46204c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    return layer.instance_extensions.data();
463aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
464aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
46504c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wuconst VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
46604c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu                                                      uint32_t& count) {
46704c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    count = static_cast<uint32_t>(layer.device_extensions.size());
46804c6551eb812a7efe38fa74e6ac67c17aab3df2dChia-I Wu    return layer.device_extensions.data();
469aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
470aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
471dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wuconst VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
472dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                                                        const char* name) {
473dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return FindExtension(layer.instance_extensions, name);
474aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
475aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
476dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wuconst VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
477dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu                                                      const char* name) {
478dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return FindExtension(layer.device_extensions, name);
479dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu}
480dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu
481dab25658fb17ec76569b8e91dfed801855027f08Chia-I WuLayerRef GetLayerRef(const Layer& layer) {
482d6e6f51426c566cd67ed765e5c4b206a063aaa30Chia-I Wu    LayerLibrary& library = g_layer_libraries[layer.library_idx];
483dab25658fb17ec76569b8e91dfed801855027f08Chia-I Wu    return LayerRef((library.Open()) ? &layer : nullptr);
484aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
485aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
486dab25658fb17ec76569b8e91dfed801855027f08Chia-I WuLayerRef::LayerRef(const Layer* layer) : layer_(layer) {}
48780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
48880523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::~LayerRef() {
48980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (layer_) {
49080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
491d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        library.Close();
49280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
49380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
49480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
495dab25658fb17ec76569b8e91dfed801855027f08Chia-I WuLayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
49654e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine    other.layer_ = nullptr;
49754e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine}
49880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
49980523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
50080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
50180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
50280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
50380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
50480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
50580523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
50680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
50780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
50880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
50980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
51080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
511c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu}  // namespace api
51280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
513