layers_extensions.cpp revision d91c74f917b603d8d1dec7d27da03e580919e0a6
180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall/*
280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * Copyright 2016 The Android Open Source Project
380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *
480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * you may not use this file except in compliance with the License.
680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * You may obtain a copy of the License at
780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *
880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall *
1080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * Unless required by applicable law or agreed to in writing, software
1180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
1280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * See the License for the specific language governing permissions and
1480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall * limitations under the License.
1580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall */
1680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
17d0b7cb566288a4f6646e356a17188b7922ba5740Michael Lentine// #define LOG_NDEBUG 0
18d0b7cb566288a4f6646e356a17188b7922ba5740Michael Lentine
19c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu#include "layers_extensions.h"
2080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <alloca.h>
2180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dirent.h>
2280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dlfcn.h>
2380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <mutex>
2480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <sys/prctl.h>
2580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string>
2680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string.h>
2780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vector>
2880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <log/log.h>
2980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vulkan/vulkan_loader_data.h>
3080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
32b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// not a good long-term solution. Having a hard-coded enum of extensions is
33b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// bad, of course. Representing sets of extensions (requested, supported, etc.)
34b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// as a bitset isn't necessarily bad, if the mapping from extension to bit were
35b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall// dynamic. Need to rethink this completely when there's a little more time.
36b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
37aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// TODO(jessehall): This file currently builds up global data structures as it
38aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// loads, and never cleans them up. This means we're doing heap allocations
39aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// without going through an app-provided allocator, but worse, we'll leak those
40aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// allocations if the loader is unloaded.
41aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall//
42aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// We should allocate "enough" BSS space, and suballocate from there. Will
43aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// probably want to intern strings, etc., and will need some custom/manual data
44aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// structures.
45aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
46aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// TODO(jessehall): Currently we have separate lists for instance and device
47aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// layers. Most layers are both; we should use one entry for each layer name,
48aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall// with a mask saying what kind(s) it is.
49aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
5080523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace vulkan {
51c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wunamespace api {
52c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu
5380523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct Layer {
5480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    VkLayerProperties properties;
5580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t library_idx;
5680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::vector<VkExtensionProperties> extensions;
5780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
5880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
5980523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace {
6080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
6180523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct LayerLibrary {
62743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu    LayerLibrary(const std::string& path_)
63743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu        : path(path_), dlhandle(nullptr), refcount(0) {}
64743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
65fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    bool Open();
66d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    void Close();
67fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
6880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
6980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* dlhandle;
7080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t refcount;
7180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
72743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
73fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wubool LayerLibrary::Open() {
74fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    if (refcount++ == 0) {
75fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
76fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        ALOGV("Opening library %s", path.c_str());
77fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        if (!dlhandle) {
78fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            ALOGE("failed to load layer library '%s': %s", path.c_str(),
79fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu                  dlerror());
80fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            refcount = 0;
81fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return false;
82fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        }
83fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    }
84fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    ALOGV("Refcount on activate is %zu", refcount);
85fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    return true;
86fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu}
87fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
88d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wuvoid LayerLibrary::Close() {
89d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    if (--refcount == 0) {
90d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        ALOGV("Closing library %s", path.c_str());
91d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        dlclose(dlhandle);
92d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        dlhandle = nullptr;
93d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    }
94d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    ALOGV("Refcount on destruction is %zu", refcount);
95d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu}
96d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu
97743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wustd::mutex g_library_mutex;
9880523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstd::vector<LayerLibrary> g_layer_libraries;
99aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallstd::vector<Layer> g_instance_layers;
100aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallstd::vector<Layer> g_device_layers;
10180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
10280523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid AddLayerLibrary(const std::string& path) {
10380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    ALOGV("examining layer library '%s'", path.c_str());
10480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
10580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
10680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!dlhandle) {
10780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        ALOGW("failed to load layer library '%s': %s", path.c_str(), dlerror());
10880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
10980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
11080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
111aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
11280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
11380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
114aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
11580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
11680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
117aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
118aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
119aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
120aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
121aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
122aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
123aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
124aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall          (enumerate_device_layers && enumerate_device_extensions))) {
125aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        ALOGV(
126aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "layer library '%s' has neither instance nor device enumeraion "
127aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "functions",
128aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            path.c_str());
12980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        dlclose(dlhandle);
13080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
13180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
13280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
133aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkResult result;
134aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_instance_layers = 0;
135aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_device_layers = 0;
136aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_instance_layers) {
137aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_instance_layers(&num_instance_layers, nullptr);
138aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
139aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
140aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
141aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
142aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
143aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlclose(dlhandle);
144aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return;
145aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
14680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
147aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_device_layers) {
148aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
149aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         nullptr);
150aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
151aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
152aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
153aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
154aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlclose(dlhandle);
155aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return;
156aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
15780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
158aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
159aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
160aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_instance_layers > 0) {
161aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_instance_layers(&num_instance_layers, properties);
16280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
16380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            ALOGW(
164aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
165aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
166aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
16780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlclose(dlhandle);
16880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            return;
16980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
170aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
171aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_device_layers > 0) {
172aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
173aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         properties + num_instance_layers);
17480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
17580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            ALOGW(
176aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
177aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
17880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlclose(dlhandle);
17980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            return;
18080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
181aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
182aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
183aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    size_t library_idx = g_layer_libraries.size();
184aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    size_t prev_num_instance_layers = g_instance_layers.size();
185aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    size_t prev_num_device_layers = g_device_layers.size();
186aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    g_instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
187aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    g_device_layers.reserve(prev_num_device_layers + num_device_layers);
188aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_instance_layers; i++) {
189aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[i];
190aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
191aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
192aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
193aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
194aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
195aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_instance_extensions) {
196aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            uint32_t count = 0;
197aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
198aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_instance_extensions(props.layerName, &count, nullptr);
199aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
200aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
201aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
202aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
203aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
204aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
205aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
206aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
207aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
208aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
209aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
210aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_instance_extensions(props.layerName, &count,
211aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                                   layer.extensions.data());
212aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
213aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
214aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
215aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
216aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
217aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
218aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
219aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
220aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
221aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
222aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
22380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
224aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        g_instance_layers.push_back(layer);
225b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added instance layer '%s'", props.layerName);
226aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
227aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_device_layers; i++) {
228aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[num_instance_layers + i];
229aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
230aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
231aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
232aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
233aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
234aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_device_extensions) {
235aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            uint32_t count;
236aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_device_extensions(
237aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                VK_NULL_HANDLE, props.layerName, &count, nullptr);
238aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
239aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
240aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
241aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
242aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
243aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
244aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
245aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_device_layers.resize(prev_num_device_layers);
246aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
247aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
248aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
249aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
250aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
251aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
252aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                            &count, layer.extensions.data());
253aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
254aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
255aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
256aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
257aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
258aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
259aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
260aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_device_layers.resize(prev_num_device_layers);
261aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
262aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
263aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
264aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
265aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
266aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        g_device_layers.push_back(layer);
267b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added device layer '%s'", props.layerName);
26880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
26980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
27080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    dlclose(dlhandle);
27180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
272743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu    g_layer_libraries.emplace_back(path);
27380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
27480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
27580523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid DiscoverLayersInDirectory(const std::string& dir_path) {
27680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    ALOGV("looking for layers in '%s'", dir_path.c_str());
27780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
27880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    DIR* directory = opendir(dir_path.c_str());
27980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!directory) {
28080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        int err = errno;
28180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
28280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                 dir_path.c_str(), strerror(err), err);
28380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
28480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
28580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
28680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
28780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.reserve(dir_path.size() + 20);
28880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append(dir_path);
28980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append("/");
29080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
29180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    struct dirent* entry;
29280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    while ((entry = readdir(directory))) {
29380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        size_t libname_len = strlen(entry->d_name);
294a7ac76df54c30e771ecfd05cdd2b52209af71470Jesse Hall        if (strncmp(entry->d_name, "libVkLayer", 10) != 0 ||
29580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
29680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            continue;
29780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.append(entry->d_name);
29880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        AddLayerLibrary(path);
29980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.resize(dir_path.size() + 1);
30080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
30180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
30280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    closedir(directory);
30380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
30480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
30580523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid* GetLayerGetProcAddr(const Layer& layer,
30680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          const char* gpa_name,
30780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          size_t gpa_name_len) {
30880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
30980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* gpa;
31030ac78b43ce408eb6d666c8667d184b8e44ed9e6Jesse Hall    size_t layer_name_len = std::max(size_t{2}, strlen(layer.properties.layerName));
31180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
31280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    strcpy(name, layer.properties.layerName);
31380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    strcpy(name + layer_name_len, gpa_name);
31480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!(gpa = dlsym(library.dlhandle, name))) {
31580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        strcpy(name, "vk");
31680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        strcpy(name + 2, gpa_name);
31780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        gpa = dlsym(library.dlhandle, name);
31880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
31980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return gpa;
32080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
32180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
322aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateLayers(const std::vector<Layer>& layers,
323aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         uint32_t count,
324aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         VkLayerProperties* properties) {
325aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
32680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    for (uint32_t i = 0; i < n; i++) {
327aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        properties[i] = layers[i].properties;
32880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
329aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return static_cast<uint32_t>(layers.size());
33080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
33180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
332aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetLayerExtensions(const std::vector<Layer>& layers,
333aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                        const char* name,
33480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        const VkExtensionProperties** properties,
33580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        uint32_t* count) {
336aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    auto layer =
337aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
338aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return strcmp(entry.properties.layerName, name) == 0;
339aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        });
340aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (layer == layers.cend()) {
341aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = nullptr;
342aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = 0;
343aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    } else {
344aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = layer->extensions.data();
345aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = static_cast<uint32_t>(layer->extensions.size());
34680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
34780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
34880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
349aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
350aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (uint32_t id = 0; id < layers.size(); id++) {
351d0b7cb566288a4f6646e356a17188b7922ba5740Michael Lentine        if (strcmp(name, layers[id].properties.layerName) == 0) {
352aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
35380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            std::lock_guard<std::mutex> lock(g_library_mutex);
354fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return LayerRef((library.Open()) ? &layers[id] : nullptr);
35580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
35680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
35780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return LayerRef(nullptr);
35880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
35980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
360aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}  // anonymous namespace
361aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
362aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid DiscoverLayers() {
363aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
364aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory("/data/local/debug/vulkan");
365aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!LoaderData::GetInstance().layer_path.empty())
366aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
367aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
368aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
369aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateInstanceLayers(uint32_t count,
370aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                 VkLayerProperties* properties) {
371aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_instance_layers, count, properties);
372aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
373aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
374aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
375aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_device_layers, count, properties);
376aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
377aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
378aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetInstanceLayerExtensions(const char* name,
379aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                const VkExtensionProperties** properties,
380aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                uint32_t* count) {
381aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_instance_layers, name, properties, count);
382aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
383aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
384aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetDeviceLayerExtensions(const char* name,
385aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              const VkExtensionProperties** properties,
386aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              uint32_t* count) {
387aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_device_layers, name, properties, count);
388aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
389aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
390aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetInstanceLayerRef(const char* name) {
391aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_instance_layers, name);
392aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
393aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
394aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetDeviceLayerRef(const char* name) {
395aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_device_layers, name);
396aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
397aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
39880523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::LayerRef(Layer* layer) : layer_(layer) {}
39980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
40080523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::~LayerRef() {
40180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (layer_) {
40280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
40380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        std::lock_guard<std::mutex> lock(g_library_mutex);
404d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        library.Close();
40580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
40680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
40780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
4085703683fb645a7e31ac25aaf7136013a6a9b9fbcMichael Lentineconst char* LayerRef::GetName() const {
409eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter    return layer_->properties.layerName;
410eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter}
411eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter
412eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchteruint32_t LayerRef::GetSpecVersion() {
413eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter    return layer_->properties.specVersion;
414eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter}
415eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter
41654e6f086a6b373a0f496343451a76dde8aa86238Michael LentineLayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
41754e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine    other.layer_ = nullptr;
41854e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine}
41980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
42080523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
42180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
42280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
42380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
42480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
42580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
42680523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
42780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
42880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
42980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
43080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
43180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
432b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hallbool LayerRef::SupportsExtension(const char* name) const {
433b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
434b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        [=](const VkExtensionProperties& ext) {
435b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                            return strcmp(ext.extensionName, name) == 0;
436b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        }) != layer_->extensions.cend();
437b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall}
438b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
439c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu}  // namespace api
44080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
441