layers_extensions.cpp revision b147127b06c1ce6443839e8102d1ed2631a57b07
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
1780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include "loader.h"
1880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <alloca.h>
1980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dirent.h>
2080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <dlfcn.h>
2180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <mutex>
2280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <sys/prctl.h>
2380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string>
2480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <string.h>
2580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vector>
2680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <log/log.h>
2780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall#include <vulkan/vulkan_loader_data.h>
2880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
2980523e2e39c29b06ab40573468dde43a9867f487Jesse Hallusing namespace vulkan;
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 {
5180523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct Layer {
5280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    VkLayerProperties properties;
5380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t library_idx;
5480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::vector<VkExtensionProperties> extensions;
5580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
5680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
5780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
5880523e2e39c29b06ab40573468dde43a9867f487Jesse Hallnamespace {
5980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
6080523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstd::mutex g_library_mutex;
6180523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstruct LayerLibrary {
6280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
6380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* dlhandle;
6480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    size_t refcount;
6580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall};
6680523e2e39c29b06ab40573468dde43a9867f487Jesse Hallstd::vector<LayerLibrary> g_layer_libraries;
67aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallstd::vector<Layer> g_instance_layers;
68aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallstd::vector<Layer> g_device_layers;
6980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
7080523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid AddLayerLibrary(const std::string& path) {
7180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    ALOGV("examining layer library '%s'", path.c_str());
7280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
7380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* dlhandle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
7480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!dlhandle) {
7580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        ALOGW("failed to load layer library '%s': %s", path.c_str(), dlerror());
7680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
7780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
7880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
79aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
8080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
8180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlsym(dlhandle, "vkEnumerateInstanceLayerProperties"));
82aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
8380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
8480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlsym(dlhandle, "vkEnumerateInstanceExtensionProperties"));
85aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
86aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
87aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlsym(dlhandle, "vkEnumerateDeviceLayerProperties"));
88aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
89aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
90aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlsym(dlhandle, "vkEnumerateDeviceExtensionProperties"));
91aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
92aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall          (enumerate_device_layers && enumerate_device_extensions))) {
93aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        ALOGV(
94aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "layer library '%s' has neither instance nor device enumeraion "
95aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "functions",
96aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            path.c_str());
9780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        dlclose(dlhandle);
9880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
9980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
10080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
101aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkResult result;
102aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_instance_layers = 0;
103aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t num_device_layers = 0;
104aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_instance_layers) {
105aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_instance_layers(&num_instance_layers, nullptr);
106aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
107aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
108aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
109aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
110aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
111aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlclose(dlhandle);
112aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return;
113aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
11480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
115aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (enumerate_device_layers) {
116aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
117aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         nullptr);
118aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (result != VK_SUCCESS) {
119aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ALOGW(
120aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
121aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
122aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            dlclose(dlhandle);
123aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return;
124aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
12580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
126aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
127aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
128aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_instance_layers > 0) {
129aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_instance_layers(&num_instance_layers, properties);
13080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
13180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            ALOGW(
132aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateInstanceLayerProperties failed for library '%s': "
133aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "%d",
134aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
13580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlclose(dlhandle);
13680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            return;
13780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
138aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
139aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (num_device_layers > 0) {
140aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
141aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                         properties + num_instance_layers);
14280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (result != VK_SUCCESS) {
14380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            ALOGW(
144aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
145aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                path.c_str(), result);
14680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlclose(dlhandle);
14780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            return;
14880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
149aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
150aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
151aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    size_t library_idx = g_layer_libraries.size();
152aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    size_t prev_num_instance_layers = g_instance_layers.size();
153aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    size_t prev_num_device_layers = g_device_layers.size();
154aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    g_instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
155aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    g_device_layers.reserve(prev_num_device_layers + num_device_layers);
156aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_instance_layers; i++) {
157aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[i];
158aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
159aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
160aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
161aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
162aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
163aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_instance_extensions) {
164aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            uint32_t count = 0;
165aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
166aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_instance_extensions(props.layerName, &count, nullptr);
167aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
168aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
169aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
170aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
171aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
172aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
173aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
174aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
175aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
176aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
177aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
178aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_instance_extensions(props.layerName, &count,
179aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                                   layer.extensions.data());
180aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
181aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
182aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateInstanceExtensionProperties(%s) failed for "
183aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
184aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
185aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
186aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
187aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
188aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
189aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
190aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
19180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
192aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        g_instance_layers.push_back(layer);
193b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added instance layer '%s'", props.layerName);
194aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
195aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < num_device_layers; i++) {
196aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        const VkLayerProperties& props = properties[num_instance_layers + i];
197aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
198aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        Layer layer;
199aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.properties = props;
200aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        layer.library_idx = library_idx;
201aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
202aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (enumerate_device_extensions) {
203aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            uint32_t count;
204aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result = enumerate_device_extensions(
205aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                VK_NULL_HANDLE, props.layerName, &count, nullptr);
206aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
207aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
208aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
209aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
210aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
211aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
212aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
213aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_device_layers.resize(prev_num_device_layers);
214aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
215aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
216aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
217aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layer.extensions.resize(count);
218aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            result =
219aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
220aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                            &count, layer.extensions.data());
221aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            if (result != VK_SUCCESS) {
222aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                ALOGW(
223aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
224aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "library "
225aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    "'%s': %d",
226aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                    props.layerName, path.c_str(), result);
227aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_instance_layers.resize(prev_num_instance_layers);
228aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                g_device_layers.resize(prev_num_device_layers);
229aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                dlclose(dlhandle);
230aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                return;
231aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            }
232aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        }
233aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
234aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        g_device_layers.push_back(layer);
235b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        ALOGV("  added device layer '%s'", props.layerName);
23680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
23780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
23880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    dlclose(dlhandle);
23980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
24080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    g_layer_libraries.push_back(LayerLibrary{path, nullptr, 0});
24180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
24280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
24380523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid DiscoverLayersInDirectory(const std::string& dir_path) {
24480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    ALOGV("looking for layers in '%s'", dir_path.c_str());
24580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
24680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    DIR* directory = opendir(dir_path.c_str());
24780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!directory) {
24880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        int err = errno;
24980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
25080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                 dir_path.c_str(), strerror(err), err);
25180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        return;
25280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
25380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
25480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    std::string path;
25580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.reserve(dir_path.size() + 20);
25680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append(dir_path);
25780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    path.append("/");
25880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
25980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    struct dirent* entry;
26080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    while ((entry = readdir(directory))) {
26180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        size_t libname_len = strlen(entry->d_name);
262a7ac76df54c30e771ecfd05cdd2b52209af71470Jesse Hall        if (strncmp(entry->d_name, "libVkLayer", 10) != 0 ||
26380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
26480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            continue;
26580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.append(entry->d_name);
26680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        AddLayerLibrary(path);
26780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        path.resize(dir_path.size() + 1);
26880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
26980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
27080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    closedir(directory);
27180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
27280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
27380523e2e39c29b06ab40573468dde43a9867f487Jesse Hallvoid* GetLayerGetProcAddr(const Layer& layer,
27480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          const char* gpa_name,
27580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          size_t gpa_name_len) {
27680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
27780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    void* gpa;
27830ac78b43ce408eb6d666c8667d184b8e44ed9e6Jesse Hall    size_t layer_name_len = std::max(size_t{2}, strlen(layer.properties.layerName));
27980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
28080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    strcpy(name, layer.properties.layerName);
28180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    strcpy(name + layer_name_len, gpa_name);
28280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (!(gpa = dlsym(library.dlhandle, name))) {
28380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        strcpy(name, "vk");
28480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        strcpy(name + 2, gpa_name);
28580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        gpa = dlsym(library.dlhandle, name);
28680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
28780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return gpa;
28880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
28980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
290aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateLayers(const std::vector<Layer>& layers,
291aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         uint32_t count,
292aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                         VkLayerProperties* properties) {
293aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
29480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    for (uint32_t i = 0; i < n; i++) {
295aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        properties[i] = layers[i].properties;
29680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
297aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return static_cast<uint32_t>(layers.size());
29880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
29980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
300aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetLayerExtensions(const std::vector<Layer>& layers,
301aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                        const char* name,
30280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        const VkExtensionProperties** properties,
30380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        uint32_t* count) {
304aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    auto layer =
305aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
306aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return strcmp(entry.properties.layerName, name) == 0;
307aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        });
308aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (layer == layers.cend()) {
309aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = nullptr;
310aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = 0;
311aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    } else {
312aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *properties = layer->extensions.data();
313aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        *count = static_cast<uint32_t>(layer->extensions.size());
31480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
31580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
31680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
317aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
318aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (uint32_t id = 0; id < layers.size(); id++) {
319aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (strcmp(name, layers[id].properties.layerName) != 0) {
320aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
32180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            std::lock_guard<std::mutex> lock(g_library_mutex);
32280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            if (library.refcount++ == 0) {
32380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                library.dlhandle =
32480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                    dlopen(library.path.c_str(), RTLD_NOW | RTLD_LOCAL);
32580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                if (!library.dlhandle) {
32680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                    ALOGE("failed to load layer library '%s': %s",
32780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                          library.path.c_str(), dlerror());
32880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                    library.refcount = 0;
32980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                    return LayerRef(nullptr);
33080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                }
33180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            }
332aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            return LayerRef(&layers[id]);
33380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
33480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
33580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return LayerRef(nullptr);
33680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
33780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
338aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}  // anonymous namespace
339aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
340aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallnamespace vulkan {
341aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
342aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid DiscoverLayers() {
343aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
344aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory("/data/local/debug/vulkan");
345aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    if (!LoaderData::GetInstance().layer_path.empty())
346aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
347aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
348aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
349aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateInstanceLayers(uint32_t count,
350aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                 VkLayerProperties* properties) {
351aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_instance_layers, count, properties);
352aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
353aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
354aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Halluint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
355aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return EnumerateLayers(g_device_layers, count, properties);
356aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
357aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
358aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetInstanceLayerExtensions(const char* name,
359aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                const VkExtensionProperties** properties,
360aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                                uint32_t* count) {
361aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_instance_layers, name, properties, count);
362aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
363aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
364aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid GetDeviceLayerExtensions(const char* name,
365aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              const VkExtensionProperties** properties,
366aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall                              uint32_t* count) {
367aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    GetLayerExtensions(g_device_layers, name, properties, count);
368aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
369aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
370aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetInstanceLayerRef(const char* name) {
371aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_instance_layers, name);
372aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
373aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
374aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse HallLayerRef GetDeviceLayerRef(const char* name) {
375aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    return GetLayerRef(g_device_layers, name);
376aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
377aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
37880523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::LayerRef(Layer* layer) : layer_(layer) {}
37980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
38080523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::~LayerRef() {
38180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    if (layer_) {
38280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
38380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        std::lock_guard<std::mutex> lock(g_library_mutex);
38480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        if (--library.refcount == 0) {
38580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            dlclose(library.dlhandle);
38680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall            library.dlhandle = nullptr;
38780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall        }
38880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    }
38980523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
39080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
39180523e2e39c29b06ab40573468dde43a9867f487Jesse HallLayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {}
39280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
39380523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
39480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
39580523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
39680523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
39780523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
39880523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
39980523e2e39c29b06ab40573468dde43a9867f487Jesse HallPFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
40080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
40180523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
40280523e2e39c29b06ab40573468dde43a9867f487Jesse Hall                  : nullptr;
40380523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}
40480523e2e39c29b06ab40573468dde43a9867f487Jesse Hall
405b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hallbool LayerRef::SupportsExtension(const char* name) const {
406b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
407b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        [=](const VkExtensionProperties& ext) {
408b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                            return strcmp(ext.extensionName, name) == 0;
409b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                        }) != layer_->extensions.cend();
410b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall}
411b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
4126bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse HallInstanceExtension InstanceExtensionFromName(const char* name) {
4136bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall    if (strcmp(name, VK_KHR_SURFACE_EXTENSION_NAME) == 0)
4146bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall        return kKHR_surface;
4156bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall    if (strcmp(name, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0)
4166bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall        return kKHR_android_surface;
4176bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall    if (strcmp(name, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0)
4186bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall        return kEXT_debug_report;
4196bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall    return kInstanceExtensionCount;
4206bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall}
4216bd5dfa9b94d1f1b2d9b6bae52979502c44c2847Jesse Hall
422b147127b06c1ce6443839e8102d1ed2631a57b07Jesse HallDeviceExtension DeviceExtensionFromName(const char* name) {
423b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (strcmp(name, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
424b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        return kKHR_swapchain;
425b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (strcmp(name, VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) == 0)
426b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        return kANDROID_native_buffer;
427b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    return kDeviceExtensionCount;
428b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall}
429b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
43080523e2e39c29b06ab40573468dde43a9867f487Jesse Hall}  // namespace vulkan
431