layers_extensions.cpp revision 50174ee4ff2f6537c4aa4e8aa475f0dc8d910870
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
6550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(LayerLibrary&& other)
6650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        : path(std::move(other.path)),
6750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu          dlhandle(other.dlhandle),
6850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu          refcount(other.refcount) {
6950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        other.dlhandle = nullptr;
7050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        other.refcount = 0;
7150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
7250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
7350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary(const LayerLibrary&) = delete;
7450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary& operator=(const LayerLibrary&) = delete;
7550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
76fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    bool Open();
77d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    void Close();
78fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
7950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    bool EnumerateLayers(size_t library_idx,
8050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                         std::vector<Layer>& instance_layers,
8150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                         std::vector<Layer>& device_layers) const;
8250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
8380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
8480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* dlhandle;
8580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t refcount;
8680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
87743495943b1a0b6d81ac70df524f67041f116ba6Chia-I Wu
88fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wubool LayerLibrary::Open() {
89fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    if (refcount++ == 0) {
90fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
91fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        ALOGV("Opening library %s", path.c_str());
92fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        if (!dlhandle) {
93fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            ALOGE("failed to load layer library '%s': %s", path.c_str(),
94fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu                  dlerror());
95fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            refcount = 0;
96fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return false;
97fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu        }
98fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    }
99fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    ALOGV("Refcount on activate is %zu", refcount);
100fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu    return true;
101fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu}
102fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu
103d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wuvoid LayerLibrary::Close() {
104d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    if (--refcount == 0) {
105d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        ALOGV("Closing library %s", path.c_str());
106d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        dlclose(dlhandle);
107d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        dlhandle = nullptr;
108d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    }
109d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu    ALOGV("Refcount on destruction is %zu", refcount);
110d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu}
111d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu
11250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wubool LayerLibrary::EnumerateLayers(size_t library_idx,
11350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                                   std::vector<Layer>& instance_layers,
11450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                                   std::vector<Layer>& device_layers) const {
115aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
11680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
11780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
118aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
11980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
12080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
121aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
122aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
123aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
124aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
125aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
126aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
127aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
128aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall          (enumerate_device_layers && enumerate_device_extensions))) {
129aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        ALOGV(
130aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "layer library '%s' has neither instance nor device enumeraion "
131aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "functions",
132aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            path.c_str());
13350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return false;
13480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
13580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
136aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkResult result;
137aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_instance_layers = 0;
138aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_device_layers = 0;
139aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_instance_layers) {
140aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_instance_layers(&num_instance_layers, nullptr);
141aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
142aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
143aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
144aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
145aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
14650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
147aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
14880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
149aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_device_layers) {
150aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
151aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         nullptr);
152aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
153aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
154aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
155aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
15650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
157aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
15880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
159aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
160aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
161aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_instance_layers > 0) {
162aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_instance_layers(&num_instance_layers, properties);
16380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
16480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            ALOGW(
165aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
166aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
167aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
16850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
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);
17850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu            return false;
17980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
180aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
181aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
18250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    size_t prev_num_instance_layers = instance_layers.size();
18350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    size_t prev_num_device_layers = device_layers.size();
18450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
18550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    device_layers.reserve(prev_num_device_layers + num_device_layers);
186aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_instance_layers; i++) {
187aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[i];
188aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
189aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
190aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
191aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
192aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
193aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_instance_extensions) {
194aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            uint32_t count = 0;
195aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
196aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_instance_extensions(props.layerName, &count, nullptr);
197aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
198aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
199aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
20050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
201aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
20250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
20350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
204aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
205aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
206aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_instance_extensions(props.layerName, &count,
207aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                                   layer.extensions.data());
208aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
209aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
210aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
21150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
212aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
21350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
21450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
215aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
216aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
21780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
21850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        instance_layers.push_back(layer);
219b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added instance layer '%s'", props.layerName);
220aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
221aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_device_layers; i++) {
222aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[num_instance_layers + i];
223aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
224aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
225aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
226aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
227aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
228aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_device_extensions) {
229aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            uint32_t count;
230aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_device_extensions(
231aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                VK_NULL_HANDLE, props.layerName, &count, nullptr);
232aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
233aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
234aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
23550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
236aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
23750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
23850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                device_layers.resize(prev_num_device_layers);
23950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
240aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
241aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
242aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
243aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
244aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                            &count, layer.extensions.data());
245aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
246aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
247aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
24850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                    "library '%s': %d",
249aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
25050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                instance_layers.resize(prev_num_instance_layers);
25150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                device_layers.resize(prev_num_device_layers);
25250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                return false;
253aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
254aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
255aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
25650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        device_layers.push_back(layer);
257b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added device layer '%s'", props.layerName);
25880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
25980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
26050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    return true;
26150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu}
26250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
26350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::mutex g_library_mutex;
26450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<LayerLibrary> g_layer_libraries;
26550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<Layer> g_instance_layers;
26650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wustd::vector<Layer> g_device_layers;
26750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
26850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wuvoid AddLayerLibrary(const std::string& path) {
26950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    ALOGV("examining layer library '%s'", path.c_str());
27050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
27150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    LayerLibrary library(path);
27250174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    if (!library.Open())
27350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
27450174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
27550174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers,
27650174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu                                 g_device_layers)) {
27750174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        library.Close();
27850174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu        return;
27950174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    }
28050174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu
28150174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    library.Close();
28280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
28350174ee4ff2f6537c4aa4e8aa475f0dc8d910870Chia-I Wu    g_layer_libraries.emplace_back(std::move(library));
28480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
28580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
28680523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid DiscoverLayersInDirectory(const std::string& dir_path) {
28780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    ALOGV("looking for layers in '%s'", dir_path.c_str());
28880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
28980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    DIR* directory = opendir(dir_path.c_str());
29080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!directory) {
29180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        int err = errno;
29280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
29380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                 dir_path.c_str(), strerror(err), err);
29480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
29580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
29680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
29780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
29880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.reserve(dir_path.size() + 20);
29980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append(dir_path);
30080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append("/");
30180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
30280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    struct dirent* entry;
30380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    while ((entry = readdir(directory))) {
30480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        size_t libname_len = strlen(entry->d_name);
305a7ac76df54c30e771ecfd05cdd2b52209af71470Jesse Hall        if (strncmp(entry->d_name, "libVkLayer", 10) != 0 ||
30680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
30780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            continue;
30880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.append(entry->d_name);
30980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        AddLayerLibrary(path);
31080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.resize(dir_path.size() + 1);
31180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
31280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    closedir(directory);
31480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
31580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
31680523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid* GetLayerGetProcAddr(const Layer& layer,
31780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          const char* gpa_name,
31880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          size_t gpa_name_len) {
31980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
32080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* gpa;
32130ac78b43ce408eb6d666c8667d184b8e44ed9e6Jesse Hall    size_t layer_name_len = std::max(size_t{2}, strlen(layer.properties.layerName));
32280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
32380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    strcpy(name, layer.properties.layerName);
32480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    strcpy(name + layer_name_len, gpa_name);
32580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!(gpa = dlsym(library.dlhandle, name))) {
32680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        strcpy(name, "vk");
32780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        strcpy(name + 2, gpa_name);
32880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        gpa = dlsym(library.dlhandle, name);
32980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
33080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return gpa;
33180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
33280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
333aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateLayers(const std::vector<Layer>& layers,
334aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         uint32_t count,
335aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         VkLayerProperties* properties) {
336aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
33780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    for (uint32_t i = 0; i < n; i++) {
338aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        properties[i] = layers[i].properties;
33980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
340aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return static_cast<uint32_t>(layers.size());
34180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
34280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
343aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetLayerExtensions(const std::vector<Layer>& layers,
344aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                        const char* name,
34580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        const VkExtensionProperties** properties,
34680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        uint32_t* count) {
347aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    auto layer =
348aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
349aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return strcmp(entry.properties.layerName, name) == 0;
350aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        });
351aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (layer == layers.cend()) {
352aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = nullptr;
353aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = 0;
354aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    } else {
355aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = layer->extensions.data();
356aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = static_cast<uint32_t>(layer->extensions.size());
35780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
35880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
35980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
360aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
361aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (uint32_t id = 0; id < layers.size(); id++) {
362d0b7cb566288a4f6646e356a17188b7922ba5740Michael Lentine        if (strcmp(name, layers[id].properties.layerName) == 0) {
363aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
36480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            std::lock_guard<std::mutex> lock(g_library_mutex);
365fd0389fb67298e530142566e7a5f6fb16741cabaChia-I Wu            return LayerRef((library.Open()) ? &layers[id] : nullptr);
36680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
36780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
36880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return LayerRef(nullptr);
36980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
37080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
371aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}  // anonymous namespace
372aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
373aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid DiscoverLayers() {
374aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
375aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory("/data/local/debug/vulkan");
376aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!LoaderData::GetInstance().layer_path.empty())
377aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
378aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
379aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
380aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateInstanceLayers(uint32_t count,
381aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                 VkLayerProperties* properties) {
382aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_instance_layers, count, properties);
383aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
384aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
385aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
386aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_device_layers, count, properties);
387aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
388aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
389aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetInstanceLayerExtensions(const char* name,
390aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                const VkExtensionProperties** properties,
391aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                uint32_t* count) {
392aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_instance_layers, name, properties, count);
393aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
394aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
395aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetDeviceLayerExtensions(const char* name,
396aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              const VkExtensionProperties** properties,
397aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              uint32_t* count) {
398aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_device_layers, name, properties, count);
399aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
400aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
401aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetInstanceLayerRef(const char* name) {
402aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_instance_layers, name);
403aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
404aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
405aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetDeviceLayerRef(const char* name) {
406aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_device_layers, name);
407aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
408aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
40980523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::LayerRef(Layer* layer) : layer_(layer) {}
41080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
41180523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::~LayerRef() {
41280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (layer_) {
41380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
41480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        std::lock_guard<std::mutex> lock(g_library_mutex);
415d91c74f917b603d8d1dec7d27da03e580919e0a6Chia-I Wu        library.Close();
41680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
41780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
41880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
4195703683fb645a7e31ac25aaf7136013a6a9b9fbcMichael Lentineconst char* LayerRef::GetName() const {
420eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter    return layer_->properties.layerName;
421eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter}
422eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter
423eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchteruint32_t LayerRef::GetSpecVersion() {
424eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter    return layer_->properties.specVersion;
425eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter}
426eff631189b135a9579a7f8510f9b1ccadd6fb4f9Courtney Goeltzenleuchter
42754e6f086a6b373a0f496343451a76dde8aa86238Michael LentineLayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
42854e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine    other.layer_ = nullptr;
42954e6f086a6b373a0f496343451a76dde8aa86238Michael Lentine}
43080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
43180523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
43280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
43380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
43480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
43580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
43680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
43780523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
43880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
43980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
44080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
44180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
44280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
443b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hallbool LayerRef::SupportsExtension(const char* name) const {
444b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
445b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        [=](const VkExtensionProperties& ext) {
446b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                            return strcmp(ext.extensionName, name) == 0;
447b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        }) != layer_->extensions.cend();
448b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall}
449b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
450c96880f2cd1d34ffb9e3d10d80f0a3ddcc5579a8Chia-I Wu}  // namespace api
45180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
452