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