blob: ee9af85b5dc49f7b6f9f5dd4190530a38fac3067 [file] [log] [blame]
Jesse Halld02edcb2015-09-08 07:44:48 -07001/*
2 * Copyright 2015 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 Lentine9dbe67f2015-09-16 15:53:50 -050017//#define LOG_NDEBUG 0
18
Jesse Hall04f4f472015-08-16 19:51:04 -070019// module header
20#include "loader.h"
21// standard C headers
Michael Lentine03c64b02015-08-26 18:27:26 -050022#include <dirent.h>
23#include <dlfcn.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070024#include <inttypes.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070025#include <pthread.h>
Jesse Hall03b6fe12015-11-24 12:44:21 -080026#include <stdlib.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070027#include <string.h>
28// standard C++ headers
29#include <algorithm>
30#include <mutex>
Michael Lentine03c64b02015-08-26 18:27:26 -050031#include <sstream>
32#include <string>
33#include <unordered_map>
34#include <vector>
Jesse Hall04f4f472015-08-16 19:51:04 -070035// platform/library headers
Michael Lentine03c64b02015-08-26 18:27:26 -050036#include <cutils/properties.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070037#include <hardware/hwvulkan.h>
38#include <log/log.h>
Michael Lentinecd6cabf2015-09-14 17:32:59 -050039#include <vulkan/vk_debug_report_lunarg.h>
Michael Lentine1c69b9e2015-09-14 13:26:59 -050040#include <vulkan/vulkan_loader_data.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070041
42using namespace vulkan;
43
44static const uint32_t kMaxPhysicalDevices = 4;
45
Michael Lentine03c64b02015-08-26 18:27:26 -050046namespace {
47
48// These definitions are taken from the LunarG Vulkan Loader. They are used to
49// enforce compatability between the Loader and Layers.
50typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
51
52typedef struct VkLayerLinkedListElem_ {
53 PFN_vkGetProcAddr get_proc_addr;
54 void* next_element;
55 void* base_object;
56} VkLayerLinkedListElem;
57
58// Define Handle typedef to be void* as returned from dlopen.
59typedef void* SharedLibraryHandle;
60
Jesse Hall3fbc8562015-11-29 22:10:52 -080061// Standard-library allocator that delegates to VkAllocationCallbacks.
Jesse Hall03b6fe12015-11-24 12:44:21 -080062//
63// TODO(jessehall): This class currently always uses
Jesse Hall3fbc8562015-11-29 22:10:52 -080064// VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE. The scope to use could be a template
Jesse Hall03b6fe12015-11-24 12:44:21 -080065// parameter or a constructor parameter. The former would help catch bugs
66// where we use the wrong scope, e.g. adding a command-scope string to an
67// instance-scope vector. But that might also be pretty annoying to deal with.
Michael Lentine03c64b02015-08-26 18:27:26 -050068template <class T>
69class CallbackAllocator {
70 public:
71 typedef T value_type;
72
Jesse Hall3fbc8562015-11-29 22:10:52 -080073 CallbackAllocator(const VkAllocationCallbacks* alloc_input)
Michael Lentine03c64b02015-08-26 18:27:26 -050074 : alloc(alloc_input) {}
75
76 template <class T2>
77 CallbackAllocator(const CallbackAllocator<T2>& other)
78 : alloc(other.alloc) {}
79
80 T* allocate(std::size_t n) {
Jesse Hall3fbc8562015-11-29 22:10:52 -080081 void* mem =
82 alloc->pfnAllocation(alloc->pUserData, n * sizeof(T), alignof(T),
83 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Michael Lentine03c64b02015-08-26 18:27:26 -050084 return static_cast<T*>(mem);
85 }
86
87 void deallocate(T* array, std::size_t /*n*/) {
88 alloc->pfnFree(alloc->pUserData, array);
89 }
90
Jesse Hall3fbc8562015-11-29 22:10:52 -080091 const VkAllocationCallbacks* alloc;
Michael Lentine03c64b02015-08-26 18:27:26 -050092};
93// These are needed in order to move Strings
94template <class T>
95bool operator==(const CallbackAllocator<T>& alloc1,
96 const CallbackAllocator<T>& alloc2) {
97 return alloc1.alloc == alloc2.alloc;
98}
99template <class T>
100bool operator!=(const CallbackAllocator<T>& alloc1,
101 const CallbackAllocator<T>& alloc2) {
102 return !(alloc1 == alloc2);
103}
104
105template <class Key,
106 class T,
107 class Hash = std::hash<Key>,
108 class Pred = std::equal_to<Key> >
109using UnorderedMap =
110 std::unordered_map<Key,
111 T,
112 Hash,
113 Pred,
114 CallbackAllocator<std::pair<const Key, T> > >;
115
116template <class T>
117using Vector = std::vector<T, CallbackAllocator<T> >;
118
119typedef std::basic_string<char,
120 std::char_traits<char>,
121 CallbackAllocator<char> > String;
122
123} // namespace
124
125// -----------------------------------------------------------------------------
126
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500127namespace {
128
129struct LayerData {
130 String path;
131 SharedLibraryHandle handle;
132 uint32_t ref_count;
133};
134
135typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
136
137} // namespace
138
Jesse Hall04f4f472015-08-16 19:51:04 -0700139struct VkInstance_T {
Jesse Hall3fbc8562015-11-29 22:10:52 -0800140 VkInstance_T(const VkAllocationCallbacks* alloc_callbacks)
Michael Lentine03c64b02015-08-26 18:27:26 -0500141 : vtbl(&vtbl_storage),
142 alloc(alloc_callbacks),
143 num_physical_devices(0),
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500144 layers(CallbackAllocator<std::pair<String, LayerData> >(alloc)),
145 active_layers(CallbackAllocator<String>(alloc)) {
146 pthread_mutex_init(&layer_lock, 0);
Jesse Hall04f4f472015-08-16 19:51:04 -0700147 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
148 memset(physical_devices, 0, sizeof(physical_devices));
149 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
150 drv.GetDeviceProcAddr = nullptr;
151 drv.num_physical_devices = 0;
152 }
153
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500154 ~VkInstance_T() { pthread_mutex_destroy(&layer_lock); }
155
Jesse Hall04f4f472015-08-16 19:51:04 -0700156 InstanceVtbl* vtbl;
157 InstanceVtbl vtbl_storage;
158
Jesse Hall3fbc8562015-11-29 22:10:52 -0800159 const VkAllocationCallbacks* alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700160 uint32_t num_physical_devices;
161 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
162
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500163 pthread_mutex_t layer_lock;
164 // Map of layer names to layer data
165 UnorderedMap<String, LayerData> layers;
166 // Vector of layers active for this instance
167 Vector<LayerMapIterator> active_layers;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500168 VkDbgMsgCallback message;
Michael Lentine03c64b02015-08-26 18:27:26 -0500169
Jesse Hall04f4f472015-08-16 19:51:04 -0700170 struct Driver {
171 // Pointers to driver entry points. Used explicitly by the loader; not
172 // set as the dispatch table for any objects.
173 InstanceVtbl vtbl;
174
175 // Pointer to the driver's get_device_proc_addr, must be valid for any
176 // of the driver's physical devices. Not part of the InstanceVtbl since
177 // it's not an Instance/PhysicalDevice function.
178 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
179
180 // Number of physical devices owned by this driver.
181 uint32_t num_physical_devices;
182 } drv; // may eventually be an array
183};
184
185// -----------------------------------------------------------------------------
186
187namespace {
188
189typedef VkInstance_T Instance;
190
191struct Device {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500192 Device(Instance* instance_input)
193 : instance(instance_input),
194 active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700195 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
196 vtbl_storage.device = this;
197 }
198 DeviceVtbl vtbl_storage;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500199 Instance* instance;
200 // Vector of layers active for this device
201 Vector<LayerMapIterator> active_layers;
Jesse Hall04f4f472015-08-16 19:51:04 -0700202};
203
204// -----------------------------------------------------------------------------
205// Utility Code
206
207inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
208 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
209}
210
211inline const DeviceVtbl* GetVtbl(VkDevice device) {
212 return *reinterpret_cast<DeviceVtbl**>(device);
213}
Jesse Halld7b994a2015-09-07 14:17:37 -0700214inline const DeviceVtbl* GetVtbl(VkQueue queue) {
215 return *reinterpret_cast<DeviceVtbl**>(queue);
216}
Jesse Hall04f4f472015-08-16 19:51:04 -0700217
Jesse Halle1b12782015-11-30 11:27:32 -0800218VKAPI_ATTR void* DefaultAllocate(void*,
219 size_t size,
220 size_t alignment,
221 VkSystemAllocationScope) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800222 void* ptr = nullptr;
223 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
224 // additionally requires that it be at least sizeof(void*).
225 return posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0
226 ? ptr
227 : nullptr;
228}
229
Jesse Halle1b12782015-11-30 11:27:32 -0800230VKAPI_ATTR void* DefaultReallocate(void*,
231 void* ptr,
232 size_t size,
233 size_t alignment,
234 VkSystemAllocationScope) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800235 if (size == 0) {
236 free(ptr);
237 return nullptr;
238 }
239
240 // TODO(jessehall): Right now we never shrink allocations; if the new
241 // request is smaller than the existing chunk, we just continue using it.
242 // Right now the loader never reallocs, so this doesn't matter. If that
243 // changes, or if this code is copied into some other project, this should
244 // probably have a heuristic to allocate-copy-free when doing so will save
245 // "enough" space.
246 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
247 if (size <= old_size)
248 return ptr;
249
250 void* new_ptr = nullptr;
251 if (posix_memalign(&new_ptr, alignment, size) != 0)
252 return nullptr;
253 if (ptr) {
254 memcpy(new_ptr, ptr, std::min(old_size, size));
255 free(ptr);
256 }
257 return new_ptr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700258}
259
Jesse Halle1b12782015-11-30 11:27:32 -0800260VKAPI_ATTR void DefaultFree(void*, void* pMem) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700261 free(pMem);
262}
263
Jesse Hall3fbc8562015-11-29 22:10:52 -0800264const VkAllocationCallbacks kDefaultAllocCallbacks = {
Jesse Hall04f4f472015-08-16 19:51:04 -0700265 .pUserData = nullptr,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800266 .pfnAllocation = DefaultAllocate,
267 .pfnReallocation = DefaultReallocate,
Jesse Hall04f4f472015-08-16 19:51:04 -0700268 .pfnFree = DefaultFree,
269};
270
271hwvulkan_device_t* g_hwdevice;
272bool EnsureInitialized() {
273 static std::once_flag once_flag;
274 static const hwvulkan_module_t* module;
275
276 std::call_once(once_flag, []() {
277 int result;
278 result = hw_get_module("vulkan",
279 reinterpret_cast<const hw_module_t**>(&module));
280 if (result != 0) {
281 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
282 result);
283 return;
284 }
285 result = module->common.methods->open(
286 &module->common, HWVULKAN_DEVICE_0,
287 reinterpret_cast<hw_device_t**>(&g_hwdevice));
288 if (result != 0) {
289 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
290 result);
291 module = nullptr;
292 return;
293 }
294 });
295
296 return module != nullptr && g_hwdevice != nullptr;
297}
298
299void DestroyDevice(Device* device) {
Jesse Hall3fbc8562015-11-29 22:10:52 -0800300 const VkAllocationCallbacks* alloc = device->instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700301 device->~Device();
302 alloc->pfnFree(alloc->pUserData, device);
303}
304
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500305void FindLayersInDirectory(Instance& instance, const String& dir_name) {
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700306 DIR* directory = opendir(dir_name.c_str());
307 if (!directory) {
308 android_LogPriority log_priority =
309 (errno == ENOENT) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_ERROR;
310 LOG_PRI(log_priority, LOG_TAG,
311 "failed to open layer directory '%s': %s (%d)",
312 dir_name.c_str(), strerror(errno), errno);
313 return;
Michael Lentine03c64b02015-08-26 18:27:26 -0500314 }
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700315
316 Vector<VkLayerProperties> properties(
317 CallbackAllocator<VkLayerProperties>(instance.alloc));
318 struct dirent* entry;
319 while ((entry = readdir(directory))) {
320 size_t length = strlen(entry->d_name);
321 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
322 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
323 continue;
324 // Open so
325 SharedLibraryHandle layer_handle =
326 dlopen((dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
327 if (!layer_handle) {
328 ALOGE("%s failed to load with error %s; Skipping", entry->d_name,
329 dlerror());
330 continue;
331 }
332
333 // Get Layers in so
334 PFN_vkEnumerateInstanceLayerProperties get_layer_properties =
335 reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
336 dlsym(layer_handle, "vkEnumerateInstanceLayerProperties"));
337 if (!get_layer_properties) {
338 ALOGE(
339 "%s failed to find vkEnumerateInstanceLayerProperties with "
340 "error %s; Skipping",
341 entry->d_name, dlerror());
342 dlclose(layer_handle);
343 continue;
344 }
345 uint32_t count;
346 get_layer_properties(&count, nullptr);
347
348 properties.resize(count);
349 get_layer_properties(&count, &properties[0]);
350
351 // Add Layers to potential list
352 for (uint32_t i = 0; i < count; ++i) {
353 String layer_name(properties[i].layerName,
354 CallbackAllocator<char>(instance.alloc));
355 LayerData layer_data = {dir_name + entry->d_name, 0, 0};
356 instance.layers.insert(std::make_pair(layer_name, layer_data));
357 ALOGV("Found layer %s", properties[i].layerName);
358 }
359 dlclose(layer_handle);
360 }
361
362 closedir(directory);
Michael Lentine03c64b02015-08-26 18:27:26 -0500363}
364
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500365template <class TObject>
366void ActivateLayer(TObject* object, Instance* instance, const String& name) {
367 // If object has layer, do nothing
368 auto element = instance->layers.find(name);
Michael Lentine233ac732015-11-18 18:28:07 -0800369 if (element == instance->layers.end()) {
370 return;
371 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500372 if (std::find(object->active_layers.begin(), object->active_layers.end(),
373 element) != object->active_layers.end()) {
374 ALOGW("Layer %s already activated; skipping", name.c_str());
375 return;
376 }
377 // If layer is not open, open it
378 LayerData& layer_data = element->second;
379 pthread_mutex_lock(&instance->layer_lock);
380 if (layer_data.ref_count == 0) {
381 SharedLibraryHandle layer_handle =
382 dlopen(layer_data.path.c_str(), RTLD_NOW | RTLD_LOCAL);
383 if (!layer_handle) {
384 pthread_mutex_unlock(&instance->layer_lock);
385 ALOGE("%s failed to load with error %s; Skipping",
386 layer_data.path.c_str(), dlerror());
387 return;
388 }
389 layer_data.handle = layer_handle;
390 }
391 layer_data.ref_count++;
392 pthread_mutex_unlock(&instance->layer_lock);
393 ALOGV("Activating layer %s", name.c_str());
394 object->active_layers.push_back(element);
395}
396
Michael Lentine1d1e65f2015-11-19 14:23:06 -0800397void DeactivateLayer(Instance* instance,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500398 Vector<LayerMapIterator>::iterator& element) {
399 LayerMapIterator& layer_map_data = *element;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500400 LayerData& layer_data = layer_map_data->second;
401 pthread_mutex_lock(&instance->layer_lock);
402 layer_data.ref_count--;
403 if (!layer_data.ref_count) {
404 dlclose(layer_data.handle);
405 }
406 pthread_mutex_unlock(&instance->layer_lock);
407}
408
Michael Lentine9da191b2015-10-13 11:08:45 -0500409struct InstanceNamesPair {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500410 Instance* instance;
Michael Lentine9da191b2015-10-13 11:08:45 -0500411 Vector<String>* layer_names;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500412};
413
Michael Lentine9da191b2015-10-13 11:08:45 -0500414void SetLayerNamesFromProperty(const char* name,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500415 const char* value,
416 void* data) {
417 const char prefix[] = "debug.vulkan.layer.";
418 const size_t prefixlen = sizeof(prefix) - 1;
419 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
420 return;
Michael Lentine9da191b2015-10-13 11:08:45 -0500421 const char* number_str = name + prefixlen;
422 long layer_number = strtol(number_str, nullptr, 10);
423 if (layer_number <= 0 || layer_number == LONG_MAX) {
424 ALOGW("Cannot use a layer at number %ld from string %s", layer_number,
425 number_str);
426 return;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500427 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500428 auto instance_names_pair = static_cast<InstanceNamesPair*>(data);
429 Vector<String>* layer_names = instance_names_pair->layer_names;
430 Instance* instance = instance_names_pair->instance;
431 size_t layer_size = static_cast<size_t>(layer_number);
432 if (layer_size > layer_names->size()) {
433 layer_names->resize(layer_size,
434 String(CallbackAllocator<char>(instance->alloc)));
435 }
436 (*layer_names)[layer_size - 1] = value;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500437}
438
439template <class TInfo, class TObject>
Jesse Hall9a16f972015-10-28 15:59:53 -0700440VkResult ActivateAllLayers(TInfo create_info, Instance* instance, TObject* object) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500441 ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
442 create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
443 "Cannot activate layers for unknown object %p", object);
444 CallbackAllocator<char> string_allocator(instance->alloc);
445 // Load system layers
446 {
447 char layer_prop[PROPERTY_VALUE_MAX];
448 property_get("debug.vulkan.layers", layer_prop, "");
449 String layer_name(string_allocator);
450 String layer_prop_str(layer_prop, string_allocator);
451 size_t end, start = 0;
452 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
453 layer_name = layer_prop_str.substr(start, end - start);
Michael Lentine233ac732015-11-18 18:28:07 -0800454 ActivateLayer(object, instance, layer_name);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500455 start = end + 1;
456 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500457 Vector<String> layer_names(CallbackAllocator<String>(instance->alloc));
458 InstanceNamesPair instance_names_pair = {.instance = instance,
459 .layer_names = &layer_names};
460 property_list(SetLayerNamesFromProperty,
461 static_cast<void*>(&instance_names_pair));
462 for (auto layer_name_element : layer_names) {
463 ActivateLayer(object, instance, layer_name_element);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500464 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500465 }
466 // Load app layers
Jesse Hall03b6fe12015-11-24 12:44:21 -0800467 for (uint32_t i = 0; i < create_info->enabledLayerNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500468 String layer_name(create_info->ppEnabledLayerNames[i],
469 string_allocator);
470 auto element = instance->layers.find(layer_name);
471 if (element == instance->layers.end()) {
Jesse Hall9a16f972015-10-28 15:59:53 -0700472 ALOGE("requested %s layer '%s' not present",
473 create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ?
474 "instance" : "device",
475 layer_name.c_str());
476 return VK_ERROR_LAYER_NOT_PRESENT;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500477 } else {
478 ActivateLayer(object, instance, layer_name);
479 }
480 }
Jesse Hall9a16f972015-10-28 15:59:53 -0700481 return VK_SUCCESS;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500482}
483
484template <class TCreateInfo>
485bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
486 const char* extension_name,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800487 const VkAllocationCallbacks* alloc) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800488 for (uint32_t i = 0; i < local_create_info.enabledExtensionNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500489 if (!strcmp(extension_name,
490 local_create_info.ppEnabledExtensionNames[i])) {
491 return false;
492 }
493 }
Jesse Hall03b6fe12015-11-24 12:44:21 -0800494 uint32_t extension_count = local_create_info.enabledExtensionNameCount;
495 local_create_info.enabledExtensionNameCount++;
Jesse Hall3fbc8562015-11-29 22:10:52 -0800496 void* mem = alloc->pfnAllocation(
Jesse Hall03b6fe12015-11-24 12:44:21 -0800497 alloc->pUserData,
498 local_create_info.enabledExtensionNameCount * sizeof(char*),
Jesse Hall3fbc8562015-11-29 22:10:52 -0800499 alignof(char*), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500500 if (mem) {
501 const char** enabled_extensions = static_cast<const char**>(mem);
502 for (uint32_t i = 0; i < extension_count; ++i) {
503 enabled_extensions[i] =
504 local_create_info.ppEnabledExtensionNames[i];
505 }
506 enabled_extensions[extension_count] = extension_name;
507 local_create_info.ppEnabledExtensionNames = enabled_extensions;
508 } else {
509 ALOGW("%s extension cannot be enabled: memory allocation failed",
510 extension_name);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800511 local_create_info.enabledExtensionNameCount--;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500512 return false;
513 }
514 return true;
515}
516
517template <class T>
518void FreeAllocatedCreateInfo(T& local_create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800519 const VkAllocationCallbacks* alloc) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500520 alloc->pfnFree(
521 alloc->pUserData,
522 const_cast<char**>(local_create_info.ppEnabledExtensionNames));
523}
524
Jesse Halle1b12782015-11-30 11:27:32 -0800525VKAPI_ATTR
Michael Lentineeb970862015-10-15 12:42:22 -0500526VkBool32 LogDebugMessageCallback(VkFlags message_flags,
527 VkDbgObjectType /*obj_type*/,
528 uint64_t /*src_object*/,
529 size_t /*location*/,
530 int32_t message_code,
531 const char* layer_prefix,
532 const char* message,
533 void* /*user_data*/) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500534 if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
535 ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
536 } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
537 ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
538 }
Michael Lentineeb970862015-10-15 12:42:22 -0500539 return false;
Michael Lentine03c64b02015-08-26 18:27:26 -0500540}
541
Jesse Hall06193802015-12-03 16:12:51 -0800542VkResult Noop() {
Michael Lentine03c64b02015-08-26 18:27:26 -0500543 return VK_SUCCESS;
544}
545
Jesse Halle1b12782015-11-30 11:27:32 -0800546VKAPI_ATTR PFN_vkVoidFunction
547GetLayerDeviceProcAddr(VkDevice device, const char* name) {
Jesse Hall06193802015-12-03 16:12:51 -0800548 // The static_casts are used to ensure that our function actually
549 // matches the API function prototype. Otherwise, if the API function
550 // prototype changes (only a problem during API development), the compiler
551 // has no way of knowing that the function is supposed to match the
552 // prototype, so won't warn us if they don't.
Michael Lentine03c64b02015-08-26 18:27:26 -0500553 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800554 return reinterpret_cast<PFN_vkVoidFunction>(
555 static_cast<PFN_vkGetDeviceProcAddr>(GetLayerDeviceProcAddr));
Michael Lentine03c64b02015-08-26 18:27:26 -0500556 }
557 if (strcmp(name, "vkCreateDevice") == 0) {
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800558 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
Michael Lentine03c64b02015-08-26 18:27:26 -0500559 }
Michael Lentine88594d72015-11-12 12:49:45 -0800560 // WSI extensions are not in the driver so return the loader functions
Michael Lentine88594d72015-11-12 12:49:45 -0800561 if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800562 return reinterpret_cast<PFN_vkVoidFunction>(
563 static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800564 }
565 if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800566 return reinterpret_cast<PFN_vkVoidFunction>(
567 static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800568 }
569 if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800570 return reinterpret_cast<PFN_vkVoidFunction>(
571 static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800572 }
573 if (strcmp(name, "vkAcquireNextImageKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800574 return reinterpret_cast<PFN_vkVoidFunction>(
575 static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800576 }
577 if (strcmp(name, "vkQueuePresentKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800578 return reinterpret_cast<PFN_vkVoidFunction>(
579 static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800580 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500581 if (!device)
582 return GetGlobalDeviceProcAddr(name);
583 Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500584 return loader_device->instance->drv.GetDeviceProcAddr(device, name);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500585}
586
Jesse Hall04f4f472015-08-16 19:51:04 -0700587// -----------------------------------------------------------------------------
588// "Bottom" functions. These are called at the end of the instance dispatch
589// chain.
590
Jesse Halle1b12782015-11-30 11:27:32 -0800591VKAPI_ATTR
Jesse Hall03b6fe12015-11-24 12:44:21 -0800592void DestroyInstanceBottom(VkInstance instance,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800593 const VkAllocationCallbacks* allocator) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700594 // These checks allow us to call DestroyInstanceBottom from any error path
595 // in CreateInstanceBottom, before the driver instance is fully initialized.
596 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
597 instance->drv.vtbl.DestroyInstance) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800598 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance,
599 allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700600 }
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500601 if (instance->message) {
602 PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500603 DebugDestroyMessageCallback =
604 reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
605 vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500606 DebugDestroyMessageCallback(instance, instance->message);
607 }
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800608 for (auto it = instance->active_layers.begin();
609 it != instance->active_layers.end(); ++it) {
Michael Lentine1d1e65f2015-11-19 14:23:06 -0800610 DeactivateLayer(instance, it);
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800611 }
Jesse Hall3fbc8562015-11-29 22:10:52 -0800612 const VkAllocationCallbacks* alloc = instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700613 instance->~VkInstance_T();
614 alloc->pfnFree(alloc->pUserData, instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700615}
616
Jesse Halle1b12782015-11-30 11:27:32 -0800617VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700618VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800619 const VkAllocationCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700620 VkInstance* instance_ptr) {
621 Instance* instance = *instance_ptr;
622 VkResult result;
623
Jesse Hall03b6fe12015-11-24 12:44:21 -0800624 result = g_hwdevice->CreateInstance(create_info, instance->alloc,
625 &instance->drv.vtbl.instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700626 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800627 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700628 return result;
629 }
630
Michael Lentine03c64b02015-08-26 18:27:26 -0500631 if (!LoadInstanceVtbl(
632 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
633 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800634 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700635 return VK_ERROR_INITIALIZATION_FAILED;
636 }
637
638 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
639 // queryable from the Instance, and that the resulting function work for any
640 // VkDevice created from the instance.
641 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
642 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
643 "vkGetDeviceProcAddr"));
644 if (!instance->drv.GetDeviceProcAddr) {
645 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
Jesse Hall03b6fe12015-11-24 12:44:21 -0800646 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700647 return VK_ERROR_INITIALIZATION_FAILED;
648 }
649
650 hwvulkan_dispatch_t* dispatch =
651 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
652 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
653 // Skip setting dispatch->vtbl on the driver instance handle, since we
654 // never intentionally call through it; we go through Instance::drv.vtbl
655 // instead.
656 } else {
657 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
658 dispatch->magic);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800659 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700660 return VK_ERROR_INITIALIZATION_FAILED;
661 }
662
663 uint32_t num_physical_devices = 0;
664 result = instance->drv.vtbl.EnumeratePhysicalDevices(
665 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
666 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800667 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700668 return VK_ERROR_INITIALIZATION_FAILED;
669 }
670 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
671 result = instance->drv.vtbl.EnumeratePhysicalDevices(
672 instance->drv.vtbl.instance, &num_physical_devices,
673 instance->physical_devices);
674 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800675 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700676 return VK_ERROR_INITIALIZATION_FAILED;
677 }
678 for (uint32_t i = 0; i < num_physical_devices; i++) {
679 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
680 instance->physical_devices[i]);
681 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
682 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
683 dispatch->magic);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800684 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700685 return VK_ERROR_INITIALIZATION_FAILED;
686 }
687 dispatch->vtbl = instance->vtbl;
688 }
689 instance->drv.num_physical_devices = num_physical_devices;
690
691 instance->num_physical_devices = instance->drv.num_physical_devices;
692 return VK_SUCCESS;
693}
694
Jesse Halle1b12782015-11-30 11:27:32 -0800695VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700696VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
697 uint32_t* pdev_count,
698 VkPhysicalDevice* pdevs) {
699 uint32_t count = instance->num_physical_devices;
700 if (pdevs) {
701 count = std::min(count, *pdev_count);
702 std::copy(instance->physical_devices,
703 instance->physical_devices + count, pdevs);
704 }
705 *pdev_count = count;
706 return VK_SUCCESS;
707}
708
Jesse Halle1b12782015-11-30 11:27:32 -0800709VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800710void GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
711 VkPhysicalDeviceFeatures* features) {
712 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
Jesse Hall04f4f472015-08-16 19:51:04 -0700713}
714
Jesse Halle1b12782015-11-30 11:27:32 -0800715VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800716void GetPhysicalDeviceFormatPropertiesBottom(VkPhysicalDevice pdev,
717 VkFormat format,
718 VkFormatProperties* properties) {
719 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700720 pdev, format, properties);
721}
722
Jesse Halle1b12782015-11-30 11:27:32 -0800723VKAPI_ATTR
Jesse Halla9e57032015-11-30 01:03:10 -0800724VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700725 VkPhysicalDevice pdev,
726 VkFormat format,
727 VkImageType type,
728 VkImageTiling tiling,
729 VkImageUsageFlags usage,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700730 VkImageCreateFlags flags,
Jesse Hall04f4f472015-08-16 19:51:04 -0700731 VkImageFormatProperties* properties) {
Jesse Halla9e57032015-11-30 01:03:10 -0800732 return GetVtbl(pdev)
733 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
734 pdev, format, type, tiling, usage, flags, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700735}
736
Jesse Halle1b12782015-11-30 11:27:32 -0800737VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800738void GetPhysicalDevicePropertiesBottom(VkPhysicalDevice pdev,
739 VkPhysicalDeviceProperties* properties) {
740 GetVtbl(pdev)
Jesse Hall04f4f472015-08-16 19:51:04 -0700741 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
742}
743
Jesse Halle1b12782015-11-30 11:27:32 -0800744VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800745void GetPhysicalDeviceQueueFamilyPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700746 VkPhysicalDevice pdev,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700747 uint32_t* pCount,
748 VkQueueFamilyProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800749 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueFamilyProperties(
750 pdev, pCount, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700751}
752
Jesse Halle1b12782015-11-30 11:27:32 -0800753VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800754void GetPhysicalDeviceMemoryPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700755 VkPhysicalDevice pdev,
756 VkPhysicalDeviceMemoryProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800757 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700758 pdev, properties);
759}
760
Jesse Halle1b12782015-11-30 11:27:32 -0800761VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700762VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
763 const VkDeviceCreateInfo* create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800764 const VkAllocationCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700765 VkDevice* out_device) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500766 Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700767 VkResult result;
768
Jesse Hall03b6fe12015-11-24 12:44:21 -0800769 if (!allocator) {
770 if (instance.alloc)
771 allocator = instance.alloc;
772 else
773 allocator = &kDefaultAllocCallbacks;
774 }
775
Jesse Hall3fbc8562015-11-29 22:10:52 -0800776 void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Device),
777 alignof(Device),
778 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700779 if (!mem)
780 return VK_ERROR_OUT_OF_HOST_MEMORY;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500781 Device* device = new (mem) Device(&instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700782
Jesse Hall9a16f972015-10-28 15:59:53 -0700783 result = ActivateAllLayers(create_info, &instance, device);
784 if (result != VK_SUCCESS) {
785 DestroyDevice(device);
786 return result;
787 }
788
Jesse Hall04f4f472015-08-16 19:51:04 -0700789 VkDevice drv_device;
Jesse Hall03b6fe12015-11-24 12:44:21 -0800790 result = instance.drv.vtbl.CreateDevice(pdev, create_info, allocator,
791 &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700792 if (result != VK_SUCCESS) {
793 DestroyDevice(device);
794 return result;
795 }
796
Jesse Hall04f4f472015-08-16 19:51:04 -0700797 hwvulkan_dispatch_t* dispatch =
798 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
799 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
800 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500801 PFN_vkDestroyDevice destroy_device =
802 reinterpret_cast<PFN_vkDestroyDevice>(
803 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800804 destroy_device(drv_device, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700805 DestroyDevice(device);
806 return VK_ERROR_INITIALIZATION_FAILED;
807 }
808 dispatch->vtbl = &device->vtbl_storage;
809
Michael Lentine03c64b02015-08-26 18:27:26 -0500810 void* base_object = static_cast<void*>(drv_device);
811 void* next_object = base_object;
812 VkLayerLinkedListElem* next_element;
813 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
814 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500815 device->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500816 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
817
818 for (size_t i = elem_list.size(); i > 0; i--) {
819 size_t idx = i - 1;
820 next_element = &elem_list[idx];
821 next_element->get_proc_addr =
822 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
823 next_element->base_object = base_object;
824 next_element->next_element = next_object;
825 next_object = static_cast<void*>(next_element);
826
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500827 auto& name = device->active_layers[idx]->first;
828 auto& handle = device->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -0500829 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500830 dlsym(handle, (name + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500831 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500832 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500833 dlsym(handle, "vkGetDeviceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -0700834 if (!next_get_proc_addr) {
835 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500836 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700837 next_object = next_element->next_element;
838 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
839 next_element->get_proc_addr);
840 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500841 }
842 }
843
844 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
845 static_cast<VkDevice>(next_object), next_get_proc_addr,
846 device->vtbl_storage)) {
847 DestroyDevice(device);
848 return VK_ERROR_INITIALIZATION_FAILED;
849 }
850
851 PFN_vkCreateDevice layer_createDevice =
852 reinterpret_cast<PFN_vkCreateDevice>(
853 device->vtbl_storage.GetDeviceProcAddr(drv_device,
854 "vkCreateDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800855 layer_createDevice(pdev, create_info, allocator, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700856
Michael Lentine88594d72015-11-12 12:49:45 -0800857 // TODO(mlentine) : This is needed to use WSI layer validation. Remove this
858 // when new version of layer initialization exits.
859 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
860 static_cast<VkDevice>(next_object), next_get_proc_addr,
861 device->vtbl_storage)) {
862 DestroyDevice(device);
863 return VK_ERROR_INITIALIZATION_FAILED;
864 }
865
Jesse Hall04f4f472015-08-16 19:51:04 -0700866 *out_device = drv_device;
867 return VK_SUCCESS;
868}
869
Jesse Halle1b12782015-11-30 11:27:32 -0800870VKAPI_ATTR
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700871VkResult EnumerateDeviceExtensionPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700872 VkPhysicalDevice pdev,
873 const char* layer_name,
874 uint32_t* properties_count,
875 VkExtensionProperties* properties) {
876 // TODO: what are we supposed to do with layer_name here?
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700877 return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceExtensionProperties(
878 pdev, layer_name, properties_count, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700879}
880
Jesse Halle1b12782015-11-30 11:27:32 -0800881VKAPI_ATTR
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700882VkResult EnumerateDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
883 uint32_t* properties_count,
884 VkLayerProperties* properties) {
885 return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceLayerProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700886 pdev, properties_count, properties);
887}
888
Jesse Halle1b12782015-11-30 11:27:32 -0800889VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800890void GetPhysicalDeviceSparseImageFormatPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700891 VkPhysicalDevice pdev,
892 VkFormat format,
893 VkImageType type,
Jesse Hall091ed9e2015-11-30 00:55:29 -0800894 VkSampleCountFlagBits samples,
Jesse Hall04f4f472015-08-16 19:51:04 -0700895 VkImageUsageFlags usage,
896 VkImageTiling tiling,
897 uint32_t* properties_count,
898 VkSparseImageFormatProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800899 GetVtbl(pdev)
Jesse Hall04f4f472015-08-16 19:51:04 -0700900 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
901 pdev, format, type, samples, usage, tiling, properties_count,
902 properties);
903}
904
Jesse Halle1b12782015-11-30 11:27:32 -0800905VKAPI_ATTR PFN_vkVoidFunction
906GetInstanceProcAddrBottom(VkInstance, const char*);
Jesse Hall04f4f472015-08-16 19:51:04 -0700907
908const InstanceVtbl kBottomInstanceFunctions = {
909 // clang-format off
910 .instance = nullptr,
911 .CreateInstance = CreateInstanceBottom,
912 .DestroyInstance = DestroyInstanceBottom,
913 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
914 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
915 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
916 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
917 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700918 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700919 .GetPhysicalDeviceQueueFamilyProperties = GetPhysicalDeviceQueueFamilyPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700920 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
921 .CreateDevice = CreateDeviceBottom,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700922 .EnumerateDeviceExtensionProperties = EnumerateDeviceExtensionPropertiesBottom,
923 .EnumerateDeviceLayerProperties = EnumerateDeviceLayerPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700924 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700925 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hallb00daad2015-11-29 19:46:20 -0800926 .GetPhysicalDeviceSurfaceCapabilitiesKHR = GetPhysicalDeviceSurfaceCapabilitiesKHR,
927 .GetPhysicalDeviceSurfaceFormatsKHR = GetPhysicalDeviceSurfaceFormatsKHR,
928 .GetPhysicalDeviceSurfacePresentModesKHR = GetPhysicalDeviceSurfacePresentModesKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700929 // clang-format on
930};
931
Jesse Halle1b12782015-11-30 11:27:32 -0800932VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700933PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500934 // TODO: Possibly move this into the instance table
935 // TODO: Possibly register the callbacks in the loader
936 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
937 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
938 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
939 }
940 if (strcmp(name, "vkCreateInstance") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800941 return reinterpret_cast<PFN_vkVoidFunction>(
942 static_cast<PFN_vkCreateInstance>(CreateInstanceBottom));
Michael Lentine03c64b02015-08-26 18:27:26 -0500943 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700944 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
945}
946
947} // namespace
948
949// -----------------------------------------------------------------------------
950// Global functions. These are called directly from the loader entry points,
951// without going through a dispatch table.
952
953namespace vulkan {
954
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700955VkResult EnumerateInstanceExtensionProperties(
956 const char* /*layer_name*/,
957 uint32_t* count,
958 VkExtensionProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700959 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700960 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700961
962 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700963 ALOGW("vkEnumerateInstanceExtensionProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700964
965 *count = 0;
966 return VK_SUCCESS;
967}
968
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700969VkResult EnumerateInstanceLayerProperties(uint32_t* count,
970 VkLayerProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700971 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700972 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700973
974 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700975 ALOGW("vkEnumerateInstanceLayerProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700976
977 *count = 0;
978 return VK_SUCCESS;
979}
980
981VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800982 const VkAllocationCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700983 VkInstance* out_instance) {
984 VkResult result;
985
986 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700987 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700988
Jesse Hall03b6fe12015-11-24 12:44:21 -0800989 if (!allocator)
990 allocator = &kDefaultAllocCallbacks;
991
Jesse Hall04f4f472015-08-16 19:51:04 -0700992 VkInstanceCreateInfo local_create_info = *create_info;
Jesse Hall04f4f472015-08-16 19:51:04 -0700993 create_info = &local_create_info;
994
Jesse Hall3fbc8562015-11-29 22:10:52 -0800995 void* instance_mem = allocator->pfnAllocation(
996 allocator->pUserData, sizeof(Instance), alignof(Instance),
997 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700998 if (!instance_mem)
999 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001000 Instance* instance = new (instance_mem) Instance(allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -07001001
1002 instance->vtbl_storage = kBottomInstanceFunctions;
1003 instance->vtbl_storage.instance = instance;
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001004 instance->message = VK_NULL_HANDLE;
Jesse Hall04f4f472015-08-16 19:51:04 -07001005
Michael Lentine03c64b02015-08-26 18:27:26 -05001006 // Scan layers
Michael Lentine03c64b02015-08-26 18:27:26 -05001007 CallbackAllocator<char> string_allocator(instance->alloc);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001008
Michael Lentine03c64b02015-08-26 18:27:26 -05001009 String dir_name("/data/local/tmp/vulkan/", string_allocator);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001010 FindLayersInDirectory(*instance, dir_name);
Michael Lentine1c69b9e2015-09-14 13:26:59 -05001011 const std::string& path = LoaderData::GetInstance().layer_path;
1012 dir_name.assign(path.c_str(), path.size());
1013 dir_name.append("/");
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001014 FindLayersInDirectory(*instance, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -07001015
Jesse Hall9a16f972015-10-28 15:59:53 -07001016 result = ActivateAllLayers(create_info, instance, instance);
1017 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -08001018 DestroyInstanceBottom(instance, allocator);
Jesse Hall9a16f972015-10-28 15:59:53 -07001019 return result;
1020 }
Michael Lentine03c64b02015-08-26 18:27:26 -05001021
1022 void* base_object = static_cast<void*>(instance);
1023 void* next_object = base_object;
1024 VkLayerLinkedListElem* next_element;
1025 PFN_vkGetInstanceProcAddr next_get_proc_addr =
1026 kBottomInstanceFunctions.GetInstanceProcAddr;
1027 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -07001028 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -05001029 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
1030
1031 for (size_t i = elem_list.size(); i > 0; i--) {
1032 size_t idx = i - 1;
1033 next_element = &elem_list[idx];
1034 next_element->get_proc_addr =
1035 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
1036 next_element->base_object = base_object;
1037 next_element->next_element = next_object;
1038 next_object = static_cast<void*>(next_element);
1039
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001040 auto& name = instance->active_layers[idx]->first;
1041 auto& handle = instance->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -05001042 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001043 dlsym(handle, (name + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -05001044 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -05001045 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001046 dlsym(handle, "vkGetInstanceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -07001047 if (!next_get_proc_addr) {
1048 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001049 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -07001050 next_object = next_element->next_element;
1051 next_get_proc_addr =
1052 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
1053 next_element->get_proc_addr);
1054 }
Michael Lentine03c64b02015-08-26 18:27:26 -05001055 }
1056 }
1057
1058 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
1059 static_cast<VkInstance>(next_object),
1060 next_get_proc_addr, instance->vtbl_storage)) {
Jesse Hall03b6fe12015-11-24 12:44:21 -08001061 DestroyInstanceBottom(instance, allocator);
Michael Lentine03c64b02015-08-26 18:27:26 -05001062 return VK_ERROR_INITIALIZATION_FAILED;
1063 }
1064
Michael Lentine950bb4f2015-09-14 13:26:30 -05001065 // Force enable callback extension if required
1066 bool enable_callback =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001067 property_get_bool("debug.vulkan.enable_callback", false);
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001068 bool enable_logging = enable_callback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001069 const char* extension_name = "DEBUG_REPORT";
Michael Lentine950bb4f2015-09-14 13:26:30 -05001070 if (enable_callback) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001071 enable_callback = AddExtensionToCreateInfo(
1072 local_create_info, extension_name, instance->alloc);
Michael Lentine950bb4f2015-09-14 13:26:30 -05001073 }
1074
Jesse Hall04f4f472015-08-16 19:51:04 -07001075 *out_instance = instance;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001076 result = instance->vtbl_storage.CreateInstance(create_info, allocator,
1077 out_instance);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001078 if (enable_callback)
1079 FreeAllocatedCreateInfo(local_create_info, instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001080 if (result <= 0) {
1081 // For every layer, including the loader top and bottom layers:
1082 // - If a call to the next CreateInstance fails, the layer must clean
1083 // up anything it has successfully done so far, and propagate the
1084 // error upwards.
1085 // - If a layer successfully calls the next layer's CreateInstance, and
1086 // afterwards must fail for some reason, it must call the next layer's
1087 // DestroyInstance before returning.
1088 // - The layer must not call the next layer's DestroyInstance if that
1089 // layer's CreateInstance wasn't called, or returned failure.
1090
1091 // On failure, CreateInstanceBottom frees the instance struct, so it's
1092 // already gone at this point. Nothing to do.
1093 }
1094
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001095 if (enable_logging) {
1096 PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001097 DebugCreateMessageCallback =
1098 reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
1099 vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
1100 DebugCreateMessageCallback(
1101 instance, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
1102 LogDebugMessageCallback, NULL, &instance->message);
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001103 }
1104
Jesse Hall04f4f472015-08-16 19:51:04 -07001105 return result;
1106}
1107
1108PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
1109 if (!instance)
1110 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001111 // TODO: Possibly move this into the instance table
1112 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
1113 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
1114 if (!instance->vtbl)
1115 return NULL;
1116 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
1117 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
1118 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001119 // For special-case functions we always return the loader entry
1120 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
1121 strcmp(name, "vkGetDeviceProcAddr") == 0) {
1122 return GetGlobalInstanceProcAddr(name);
1123 }
1124 return GetSpecificInstanceProcAddr(instance->vtbl, name);
1125}
1126
1127PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
1128 if (!device)
1129 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001130 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001131 return reinterpret_cast<PFN_vkVoidFunction>(
1132 static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr));
Michael Lentine03c64b02015-08-26 18:27:26 -05001133 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001134 if (strcmp(name, "vkGetDeviceQueue") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001135 return reinterpret_cast<PFN_vkVoidFunction>(
1136 static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue));
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001137 }
Jesse Hall2ca1bd52015-12-02 15:40:12 -08001138 if (strcmp(name, "vkAllocateCommandBuffers") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001139 return reinterpret_cast<PFN_vkVoidFunction>(
1140 static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers));
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001141 }
1142 if (strcmp(name, "vkDestroyDevice") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001143 return reinterpret_cast<PFN_vkVoidFunction>(
1144 static_cast<PFN_vkDestroyDevice>(DestroyDevice));
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001145 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001146 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
1147}
1148
Jesse Hall606a54e2015-11-19 22:17:28 -08001149void GetDeviceQueue(VkDevice drv_device,
1150 uint32_t family,
1151 uint32_t index,
1152 VkQueue* out_queue) {
Jesse Hall04f4f472015-08-16 19:51:04 -07001153 VkResult result;
1154 VkQueue queue;
1155 const DeviceVtbl* vtbl = GetVtbl(drv_device);
Jesse Hall606a54e2015-11-19 22:17:28 -08001156 vtbl->GetDeviceQueue(drv_device, family, index, &queue);
Jesse Hall04f4f472015-08-16 19:51:04 -07001157 hwvulkan_dispatch_t* dispatch =
1158 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
Jesse Hall606a54e2015-11-19 22:17:28 -08001159 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != vtbl)
Jesse Hall04f4f472015-08-16 19:51:04 -07001160 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Jesse Hall04f4f472015-08-16 19:51:04 -07001161 dispatch->vtbl = vtbl;
1162 *out_queue = queue;
Jesse Hall04f4f472015-08-16 19:51:04 -07001163}
1164
Jesse Hall2ca1bd52015-12-02 15:40:12 -08001165VkResult AllocateCommandBuffers(VkDevice device,
1166 const VkCommandBufferAllocateInfo* alloc_info,
1167 VkCommandBuffer* cmdbufs) {
Jesse Hallfbf97b02015-11-20 14:17:03 -08001168 const DeviceVtbl* vtbl = GetVtbl(device);
Jesse Hall3fbc8562015-11-29 22:10:52 -08001169 VkResult result = vtbl->AllocateCommandBuffers(device, alloc_info, cmdbufs);
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001170 if (result != VK_SUCCESS)
1171 return result;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001172 for (uint32_t i = 0; i < alloc_info->bufferCount; i++) {
Jesse Hallfbf97b02015-11-20 14:17:03 -08001173 hwvulkan_dispatch_t* dispatch =
Jesse Hall3fbc8562015-11-29 22:10:52 -08001174 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbufs[i]);
Jesse Hallfbf97b02015-11-20 14:17:03 -08001175 ALOGE_IF(dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001176 "invalid VkCommandBuffer dispatch magic: 0x%" PRIxPTR,
Jesse Hallfbf97b02015-11-20 14:17:03 -08001177 dispatch->magic);
1178 dispatch->vtbl = vtbl;
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001179 }
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001180 return VK_SUCCESS;
1181}
1182
Jesse Hall06193802015-12-03 16:12:51 -08001183void DestroyDevice(VkDevice drv_device,
1184 const VkAllocationCallbacks* /*allocator*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -07001185 const DeviceVtbl* vtbl = GetVtbl(drv_device);
1186 Device* device = static_cast<Device*>(vtbl->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001187 for (auto it = device->active_layers.begin();
1188 it != device->active_layers.end(); ++it) {
Michael Lentine1d1e65f2015-11-19 14:23:06 -08001189 DeactivateLayer(device->instance, it);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001190 }
Jesse Hall03b6fe12015-11-24 12:44:21 -08001191 vtbl->DestroyDevice(drv_device, device->instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001192 DestroyDevice(device);
Jesse Hall04f4f472015-08-16 19:51:04 -07001193}
1194
Jesse Hall1356b0d2015-11-23 17:24:58 -08001195void* AllocMem(VkInstance instance,
1196 size_t size,
1197 size_t align,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001198 VkSystemAllocationScope scope) {
1199 const VkAllocationCallbacks* alloc_cb = instance->alloc;
1200 return alloc_cb->pfnAllocation(alloc_cb->pUserData, size, align, scope);
Jesse Hall1356b0d2015-11-23 17:24:58 -08001201}
1202
1203void FreeMem(VkInstance instance, void* ptr) {
Jesse Hall3fbc8562015-11-29 22:10:52 -08001204 const VkAllocationCallbacks* alloc_cb = instance->alloc;
Jesse Hall1356b0d2015-11-23 17:24:58 -08001205 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1206}
1207
1208void* AllocMem(VkDevice device,
1209 size_t size,
1210 size_t align,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001211 VkSystemAllocationScope scope) {
1212 const VkAllocationCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001213 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Hall3fbc8562015-11-29 22:10:52 -08001214 return alloc_cb->pfnAllocation(alloc_cb->pUserData, size, align, scope);
Jesse Halld7b994a2015-09-07 14:17:37 -07001215}
1216
Jesse Hall1356b0d2015-11-23 17:24:58 -08001217void FreeMem(VkDevice device, void* ptr) {
Jesse Hall3fbc8562015-11-29 22:10:52 -08001218 const VkAllocationCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001219 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Halld7b994a2015-09-07 14:17:37 -07001220 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1221}
1222
1223const DeviceVtbl& GetDriverVtbl(VkDevice device) {
1224 // TODO(jessehall): This actually returns the API-level vtbl for the
1225 // device, not the driver entry points. Given the current use -- getting
1226 // the driver's private swapchain-related functions -- that works, but is
1227 // misleading and likely to cause bugs. Fix as part of separating the
1228 // loader->driver interface from the app->loader interface.
1229 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
1230}
1231
1232const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
1233 // TODO(jessehall): This actually returns the API-level vtbl for the
1234 // device, not the driver entry points. Given the current use -- getting
1235 // the driver's private swapchain-related functions -- that works, but is
1236 // misleading and likely to cause bugs. Fix as part of separating the
1237 // loader->driver interface from the app->loader interface.
1238 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
1239}
1240
Jesse Hall04f4f472015-08-16 19:51:04 -07001241} // namespace vulkan