blob: d8ea2daf47c1fdd734741f098399f59514619748 [file] [log] [blame]
Jesse Hall80523e22016-01-06 16:47:54 -08001/*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Michael Lentined0b7cb52016-01-19 13:57:26 -060017// #define LOG_NDEBUG 0
18
Chia-I Wuc96880f2016-03-26 06:56:45 +080019#include "layers_extensions.h"
Jesse Hall80523e22016-01-06 16:47:54 -080020#include <alloca.h>
21#include <dirent.h>
22#include <dlfcn.h>
23#include <mutex>
24#include <sys/prctl.h>
25#include <string>
26#include <string.h>
27#include <vector>
28#include <log/log.h>
29#include <vulkan/vulkan_loader_data.h>
30
Jesse Hallb1471272016-01-17 21:36:58 -080031// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
32// not a good long-term solution. Having a hard-coded enum of extensions is
33// bad, of course. Representing sets of extensions (requested, supported, etc.)
34// as a bitset isn't necessarily bad, if the mapping from extension to bit were
35// dynamic. Need to rethink this completely when there's a little more time.
36
Jesse Hallaa410942016-01-17 13:07:10 -080037// TODO(jessehall): This file currently builds up global data structures as it
38// loads, and never cleans them up. This means we're doing heap allocations
39// without going through an app-provided allocator, but worse, we'll leak those
40// allocations if the loader is unloaded.
41//
42// We should allocate "enough" BSS space, and suballocate from there. Will
43// probably want to intern strings, etc., and will need some custom/manual data
44// structures.
45
46// TODO(jessehall): Currently we have separate lists for instance and device
47// layers. Most layers are both; we should use one entry for each layer name,
48// with a mask saying what kind(s) it is.
49
Jesse Hall80523e22016-01-06 16:47:54 -080050namespace vulkan {
Chia-I Wuc96880f2016-03-26 06:56:45 +080051namespace api {
52
Jesse Hall80523e22016-01-06 16:47:54 -080053struct Layer {
54 VkLayerProperties properties;
55 size_t library_idx;
56 std::vector<VkExtensionProperties> extensions;
57};
Jesse Hall80523e22016-01-06 16:47:54 -080058
59namespace {
60
Chia-I Wu6693f5c2016-04-18 12:20:02 +080061class LayerLibrary {
62 public:
63 LayerLibrary(const std::string& path)
64 : path_(path), dlhandle_(nullptr), refcount_(0) {}
Chia-I Wu74349592016-04-18 12:08:39 +080065
Chia-I Wu50174ee2016-04-18 16:33:20 +080066 LayerLibrary(LayerLibrary&& other)
Chia-I Wu6693f5c2016-04-18 12:20:02 +080067 : path_(std::move(other.path_)),
68 dlhandle_(other.dlhandle_),
69 refcount_(other.refcount_) {
70 other.dlhandle_ = nullptr;
71 other.refcount_ = 0;
Chia-I Wu50174ee2016-04-18 16:33:20 +080072 }
73
74 LayerLibrary(const LayerLibrary&) = delete;
75 LayerLibrary& operator=(const LayerLibrary&) = delete;
76
Chia-I Wufd0389f2016-04-18 12:11:00 +080077 bool Open();
Chia-I Wud91c74f2016-04-18 12:12:36 +080078 void Close();
Chia-I Wufd0389f2016-04-18 12:11:00 +080079
Chia-I Wu50174ee2016-04-18 16:33:20 +080080 bool EnumerateLayers(size_t library_idx,
81 std::vector<Layer>& instance_layers,
82 std::vector<Layer>& device_layers) const;
83
Chia-I Wuba113272016-04-18 16:38:39 +080084 void* GetGPA(const Layer& layer,
85 const char* gpa_name,
86 size_t gpa_name_len) const;
87
Chia-I Wu6693f5c2016-04-18 12:20:02 +080088 private:
89 const std::string path_;
90 void* dlhandle_;
91 size_t refcount_;
Jesse Hall80523e22016-01-06 16:47:54 -080092};
Chia-I Wu74349592016-04-18 12:08:39 +080093
Chia-I Wufd0389f2016-04-18 12:11:00 +080094bool LayerLibrary::Open() {
Chia-I Wu6693f5c2016-04-18 12:20:02 +080095 if (refcount_++ == 0) {
96 dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
97 ALOGV("Opening library %s", path_.c_str());
98 if (!dlhandle_) {
99 ALOGE("failed to load layer library '%s': %s", path_.c_str(),
Chia-I Wufd0389f2016-04-18 12:11:00 +0800100 dlerror());
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800101 refcount_ = 0;
Chia-I Wufd0389f2016-04-18 12:11:00 +0800102 return false;
103 }
104 }
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800105 ALOGV("Refcount on activate is %zu", refcount_);
Chia-I Wufd0389f2016-04-18 12:11:00 +0800106 return true;
107}
108
Chia-I Wud91c74f2016-04-18 12:12:36 +0800109void LayerLibrary::Close() {
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800110 if (--refcount_ == 0) {
111 ALOGV("Closing library %s", path_.c_str());
112 dlclose(dlhandle_);
113 dlhandle_ = nullptr;
Chia-I Wud91c74f2016-04-18 12:12:36 +0800114 }
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800115 ALOGV("Refcount on destruction is %zu", refcount_);
Chia-I Wud91c74f2016-04-18 12:12:36 +0800116}
117
Chia-I Wu50174ee2016-04-18 16:33:20 +0800118bool LayerLibrary::EnumerateLayers(size_t library_idx,
119 std::vector<Layer>& instance_layers,
120 std::vector<Layer>& device_layers) const {
Jesse Hallaa410942016-01-17 13:07:10 -0800121 PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
Jesse Hall80523e22016-01-06 16:47:54 -0800122 reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800123 dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
Jesse Hallaa410942016-01-17 13:07:10 -0800124 PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
Jesse Hall80523e22016-01-06 16:47:54 -0800125 reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800126 dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
Jesse Hallaa410942016-01-17 13:07:10 -0800127 PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
128 reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800129 dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
Jesse Hallaa410942016-01-17 13:07:10 -0800130 PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
131 reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800132 dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
Jesse Hallaa410942016-01-17 13:07:10 -0800133 if (!((enumerate_instance_layers && enumerate_instance_extensions) ||
134 (enumerate_device_layers && enumerate_device_extensions))) {
135 ALOGV(
136 "layer library '%s' has neither instance nor device enumeraion "
137 "functions",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800138 path_.c_str());
Chia-I Wu50174ee2016-04-18 16:33:20 +0800139 return false;
Jesse Hall80523e22016-01-06 16:47:54 -0800140 }
141
Jesse Hallaa410942016-01-17 13:07:10 -0800142 VkResult result;
143 uint32_t num_instance_layers = 0;
144 uint32_t num_device_layers = 0;
145 if (enumerate_instance_layers) {
146 result = enumerate_instance_layers(&num_instance_layers, nullptr);
147 if (result != VK_SUCCESS) {
148 ALOGW(
149 "vkEnumerateInstanceLayerProperties failed for library '%s': "
150 "%d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800151 path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800152 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800153 }
Jesse Hall80523e22016-01-06 16:47:54 -0800154 }
Jesse Hallaa410942016-01-17 13:07:10 -0800155 if (enumerate_device_layers) {
156 result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
157 nullptr);
158 if (result != VK_SUCCESS) {
159 ALOGW(
160 "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800161 path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800162 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800163 }
164 }
165 VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
166 (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
167 if (num_instance_layers > 0) {
168 result = enumerate_instance_layers(&num_instance_layers, properties);
169 if (result != VK_SUCCESS) {
170 ALOGW(
171 "vkEnumerateInstanceLayerProperties failed for library '%s': "
172 "%d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800173 path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800174 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800175 }
176 }
177 if (num_device_layers > 0) {
178 result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
179 properties + num_instance_layers);
180 if (result != VK_SUCCESS) {
181 ALOGW(
182 "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800183 path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800184 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800185 }
Jesse Hall80523e22016-01-06 16:47:54 -0800186 }
187
Chia-I Wu50174ee2016-04-18 16:33:20 +0800188 size_t prev_num_instance_layers = instance_layers.size();
189 size_t prev_num_device_layers = device_layers.size();
190 instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
191 device_layers.reserve(prev_num_device_layers + num_device_layers);
Jesse Hallaa410942016-01-17 13:07:10 -0800192 for (size_t i = 0; i < num_instance_layers; i++) {
193 const VkLayerProperties& props = properties[i];
194
Jesse Hall80523e22016-01-06 16:47:54 -0800195 Layer layer;
Jesse Hallaa410942016-01-17 13:07:10 -0800196 layer.properties = props;
Jesse Hall80523e22016-01-06 16:47:54 -0800197 layer.library_idx = library_idx;
198
Jesse Hallaa410942016-01-17 13:07:10 -0800199 if (enumerate_instance_extensions) {
200 uint32_t count = 0;
201 result =
202 enumerate_instance_extensions(props.layerName, &count, nullptr);
203 if (result != VK_SUCCESS) {
204 ALOGW(
205 "vkEnumerateInstanceExtensionProperties(%s) failed for "
Chia-I Wu50174ee2016-04-18 16:33:20 +0800206 "library '%s': %d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800207 props.layerName, path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800208 instance_layers.resize(prev_num_instance_layers);
209 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800210 }
211 layer.extensions.resize(count);
212 result = enumerate_instance_extensions(props.layerName, &count,
213 layer.extensions.data());
214 if (result != VK_SUCCESS) {
215 ALOGW(
216 "vkEnumerateInstanceExtensionProperties(%s) failed for "
Chia-I Wu50174ee2016-04-18 16:33:20 +0800217 "library '%s': %d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800218 props.layerName, path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800219 instance_layers.resize(prev_num_instance_layers);
220 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800221 }
Jesse Hall80523e22016-01-06 16:47:54 -0800222 }
223
Chia-I Wu50174ee2016-04-18 16:33:20 +0800224 instance_layers.push_back(layer);
Jesse Hallb1471272016-01-17 21:36:58 -0800225 ALOGV(" added instance layer '%s'", props.layerName);
Jesse Hallaa410942016-01-17 13:07:10 -0800226 }
227 for (size_t i = 0; i < num_device_layers; i++) {
228 const VkLayerProperties& props = properties[num_instance_layers + i];
229
230 Layer layer;
231 layer.properties = props;
232 layer.library_idx = library_idx;
233
234 if (enumerate_device_extensions) {
235 uint32_t count;
236 result = enumerate_device_extensions(
237 VK_NULL_HANDLE, props.layerName, &count, nullptr);
238 if (result != VK_SUCCESS) {
239 ALOGW(
240 "vkEnumerateDeviceExtensionProperties(%s) failed for "
Chia-I Wu50174ee2016-04-18 16:33:20 +0800241 "library '%s': %d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800242 props.layerName, path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800243 instance_layers.resize(prev_num_instance_layers);
244 device_layers.resize(prev_num_device_layers);
245 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800246 }
247 layer.extensions.resize(count);
248 result =
249 enumerate_device_extensions(VK_NULL_HANDLE, props.layerName,
250 &count, layer.extensions.data());
251 if (result != VK_SUCCESS) {
252 ALOGW(
253 "vkEnumerateDeviceExtensionProperties(%s) failed for "
Chia-I Wu50174ee2016-04-18 16:33:20 +0800254 "library '%s': %d",
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800255 props.layerName, path_.c_str(), result);
Chia-I Wu50174ee2016-04-18 16:33:20 +0800256 instance_layers.resize(prev_num_instance_layers);
257 device_layers.resize(prev_num_device_layers);
258 return false;
Jesse Hallaa410942016-01-17 13:07:10 -0800259 }
260 }
261
Chia-I Wu50174ee2016-04-18 16:33:20 +0800262 device_layers.push_back(layer);
Jesse Hallb1471272016-01-17 21:36:58 -0800263 ALOGV(" added device layer '%s'", props.layerName);
Jesse Hall80523e22016-01-06 16:47:54 -0800264 }
265
Chia-I Wu50174ee2016-04-18 16:33:20 +0800266 return true;
267}
Jesse Hall80523e22016-01-06 16:47:54 -0800268
Chia-I Wuba113272016-04-18 16:38:39 +0800269void* LayerLibrary::GetGPA(const Layer& layer,
270 const char* gpa_name,
271 size_t gpa_name_len) const {
272 void* gpa;
273 size_t layer_name_len =
274 std::max(size_t{2}, strlen(layer.properties.layerName));
275 char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
276 strcpy(name, layer.properties.layerName);
277 strcpy(name + layer_name_len, gpa_name);
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800278 if (!(gpa = dlsym(dlhandle_, name))) {
Chia-I Wuba113272016-04-18 16:38:39 +0800279 strcpy(name, "vk");
280 strcpy(name + 2, gpa_name);
Chia-I Wu6693f5c2016-04-18 12:20:02 +0800281 gpa = dlsym(dlhandle_, name);
Chia-I Wuba113272016-04-18 16:38:39 +0800282 }
283 return gpa;
284}
285
Chia-I Wu50174ee2016-04-18 16:33:20 +0800286std::mutex g_library_mutex;
287std::vector<LayerLibrary> g_layer_libraries;
288std::vector<Layer> g_instance_layers;
289std::vector<Layer> g_device_layers;
290
291void AddLayerLibrary(const std::string& path) {
292 ALOGV("examining layer library '%s'", path.c_str());
293
294 LayerLibrary library(path);
295 if (!library.Open())
296 return;
297
298 if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers,
299 g_device_layers)) {
300 library.Close();
301 return;
302 }
303
304 library.Close();
305
306 g_layer_libraries.emplace_back(std::move(library));
Jesse Hall80523e22016-01-06 16:47:54 -0800307}
308
309void DiscoverLayersInDirectory(const std::string& dir_path) {
310 ALOGV("looking for layers in '%s'", dir_path.c_str());
311
312 DIR* directory = opendir(dir_path.c_str());
313 if (!directory) {
314 int err = errno;
315 ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
316 dir_path.c_str(), strerror(err), err);
317 return;
318 }
319
320 std::string path;
321 path.reserve(dir_path.size() + 20);
322 path.append(dir_path);
323 path.append("/");
324
325 struct dirent* entry;
326 while ((entry = readdir(directory))) {
327 size_t libname_len = strlen(entry->d_name);
Jesse Halla7ac76d2016-01-08 22:29:42 -0800328 if (strncmp(entry->d_name, "libVkLayer", 10) != 0 ||
Jesse Hall80523e22016-01-06 16:47:54 -0800329 strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
330 continue;
331 path.append(entry->d_name);
332 AddLayerLibrary(path);
333 path.resize(dir_path.size() + 1);
334 }
335
336 closedir(directory);
337}
338
339void* GetLayerGetProcAddr(const Layer& layer,
340 const char* gpa_name,
341 size_t gpa_name_len) {
342 const LayerLibrary& library = g_layer_libraries[layer.library_idx];
Chia-I Wuba113272016-04-18 16:38:39 +0800343 return library.GetGPA(layer, gpa_name, gpa_name_len);
Jesse Hall80523e22016-01-06 16:47:54 -0800344}
345
Jesse Hallaa410942016-01-17 13:07:10 -0800346uint32_t EnumerateLayers(const std::vector<Layer>& layers,
347 uint32_t count,
348 VkLayerProperties* properties) {
349 uint32_t n = std::min(count, static_cast<uint32_t>(layers.size()));
Jesse Hall80523e22016-01-06 16:47:54 -0800350 for (uint32_t i = 0; i < n; i++) {
Jesse Hallaa410942016-01-17 13:07:10 -0800351 properties[i] = layers[i].properties;
Jesse Hall80523e22016-01-06 16:47:54 -0800352 }
Jesse Hallaa410942016-01-17 13:07:10 -0800353 return static_cast<uint32_t>(layers.size());
Jesse Hall80523e22016-01-06 16:47:54 -0800354}
355
Jesse Hallaa410942016-01-17 13:07:10 -0800356void GetLayerExtensions(const std::vector<Layer>& layers,
357 const char* name,
Jesse Hall80523e22016-01-06 16:47:54 -0800358 const VkExtensionProperties** properties,
359 uint32_t* count) {
Jesse Hallaa410942016-01-17 13:07:10 -0800360 auto layer =
361 std::find_if(layers.cbegin(), layers.cend(), [=](const Layer& entry) {
362 return strcmp(entry.properties.layerName, name) == 0;
363 });
364 if (layer == layers.cend()) {
365 *properties = nullptr;
366 *count = 0;
367 } else {
368 *properties = layer->extensions.data();
369 *count = static_cast<uint32_t>(layer->extensions.size());
Jesse Hall80523e22016-01-06 16:47:54 -0800370 }
371}
372
Jesse Hallaa410942016-01-17 13:07:10 -0800373LayerRef GetLayerRef(std::vector<Layer>& layers, const char* name) {
374 for (uint32_t id = 0; id < layers.size(); id++) {
Michael Lentined0b7cb52016-01-19 13:57:26 -0600375 if (strcmp(name, layers[id].properties.layerName) == 0) {
Jesse Hallaa410942016-01-17 13:07:10 -0800376 LayerLibrary& library = g_layer_libraries[layers[id].library_idx];
Jesse Hall80523e22016-01-06 16:47:54 -0800377 std::lock_guard<std::mutex> lock(g_library_mutex);
Chia-I Wufd0389f2016-04-18 12:11:00 +0800378 return LayerRef((library.Open()) ? &layers[id] : nullptr);
Jesse Hall80523e22016-01-06 16:47:54 -0800379 }
380 }
381 return LayerRef(nullptr);
382}
383
Jesse Hallaa410942016-01-17 13:07:10 -0800384} // anonymous namespace
385
Jesse Hallaa410942016-01-17 13:07:10 -0800386void DiscoverLayers() {
387 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
388 DiscoverLayersInDirectory("/data/local/debug/vulkan");
389 if (!LoaderData::GetInstance().layer_path.empty())
390 DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
391}
392
393uint32_t EnumerateInstanceLayers(uint32_t count,
394 VkLayerProperties* properties) {
395 return EnumerateLayers(g_instance_layers, count, properties);
396}
397
398uint32_t EnumerateDeviceLayers(uint32_t count, VkLayerProperties* properties) {
399 return EnumerateLayers(g_device_layers, count, properties);
400}
401
402void GetInstanceLayerExtensions(const char* name,
403 const VkExtensionProperties** properties,
404 uint32_t* count) {
405 GetLayerExtensions(g_instance_layers, name, properties, count);
406}
407
408void GetDeviceLayerExtensions(const char* name,
409 const VkExtensionProperties** properties,
410 uint32_t* count) {
411 GetLayerExtensions(g_device_layers, name, properties, count);
412}
413
414LayerRef GetInstanceLayerRef(const char* name) {
415 return GetLayerRef(g_instance_layers, name);
416}
417
418LayerRef GetDeviceLayerRef(const char* name) {
419 return GetLayerRef(g_device_layers, name);
420}
421
Jesse Hall80523e22016-01-06 16:47:54 -0800422LayerRef::LayerRef(Layer* layer) : layer_(layer) {}
423
424LayerRef::~LayerRef() {
425 if (layer_) {
426 LayerLibrary& library = g_layer_libraries[layer_->library_idx];
427 std::lock_guard<std::mutex> lock(g_library_mutex);
Chia-I Wud91c74f2016-04-18 12:12:36 +0800428 library.Close();
Jesse Hall80523e22016-01-06 16:47:54 -0800429 }
430}
431
Michael Lentine57036832016-03-04 11:03:35 -0600432const char* LayerRef::GetName() const {
Courtney Goeltzenleuchtereff63112016-02-08 20:12:59 -0700433 return layer_->properties.layerName;
434}
435
436uint32_t LayerRef::GetSpecVersion() {
437 return layer_->properties.specVersion;
438}
439
Michael Lentine54e6f082016-01-20 11:25:28 -0600440LayerRef::LayerRef(LayerRef&& other) : layer_(std::move(other.layer_)) {
441 other.layer_ = nullptr;
442}
Jesse Hall80523e22016-01-06 16:47:54 -0800443
444PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
445 return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
446 GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
447 : nullptr;
448}
449
450PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
451 return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
452 GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
453 : nullptr;
454}
455
Jesse Hallb1471272016-01-17 21:36:58 -0800456bool LayerRef::SupportsExtension(const char* name) const {
457 return std::find_if(layer_->extensions.cbegin(), layer_->extensions.cend(),
458 [=](const VkExtensionProperties& ext) {
459 return strcmp(ext.extensionName, name) == 0;
460 }) != layer_->extensions.cend();
461}
462
Chia-I Wuc96880f2016-03-26 06:56:45 +0800463} // namespace api
Jesse Hall80523e22016-01-06 16:47:54 -0800464} // namespace vulkan