blob: ca33be118b085ef78f36953dfc67f38b3f8c0b60 [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
Jesse Hall04f4f472015-08-16 19:51:04 -070017// module header
18#include "loader.h"
19// standard C headers
Michael Lentine03c64b02015-08-26 18:27:26 -050020#include <dirent.h>
21#include <dlfcn.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070022#include <inttypes.h>
23#include <malloc.h>
24#include <pthread.h>
25#include <string.h>
26// standard C++ headers
27#include <algorithm>
28#include <mutex>
Michael Lentine03c64b02015-08-26 18:27:26 -050029#include <sstream>
30#include <string>
31#include <unordered_map>
32#include <vector>
Jesse Hall04f4f472015-08-16 19:51:04 -070033// platform/library headers
Michael Lentine03c64b02015-08-26 18:27:26 -050034#include <cutils/properties.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070035#include <hardware/hwvulkan.h>
36#include <log/log.h>
Michael Lentinecd6cabf2015-09-14 17:32:59 -050037#include <vulkan/vk_debug_report_lunarg.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070038
39using namespace vulkan;
40
41static const uint32_t kMaxPhysicalDevices = 4;
42
Michael Lentine03c64b02015-08-26 18:27:26 -050043namespace {
44
45// These definitions are taken from the LunarG Vulkan Loader. They are used to
46// enforce compatability between the Loader and Layers.
47typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
48
49typedef struct VkLayerLinkedListElem_ {
50 PFN_vkGetProcAddr get_proc_addr;
51 void* next_element;
52 void* base_object;
53} VkLayerLinkedListElem;
54
55// Define Handle typedef to be void* as returned from dlopen.
56typedef void* SharedLibraryHandle;
57
58// Custom versions of std classes that use the vulkan alloc callback.
59template <class T>
60class CallbackAllocator {
61 public:
62 typedef T value_type;
63
64 CallbackAllocator(const VkAllocCallbacks* alloc_input)
65 : alloc(alloc_input) {}
66
67 template <class T2>
68 CallbackAllocator(const CallbackAllocator<T2>& other)
69 : alloc(other.alloc) {}
70
71 T* allocate(std::size_t n) {
72 void* mem = alloc->pfnAlloc(alloc->pUserData, n * sizeof(T), alignof(T),
73 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
74 return static_cast<T*>(mem);
75 }
76
77 void deallocate(T* array, std::size_t /*n*/) {
78 alloc->pfnFree(alloc->pUserData, array);
79 }
80
81 const VkAllocCallbacks* alloc;
82};
83// These are needed in order to move Strings
84template <class T>
85bool operator==(const CallbackAllocator<T>& alloc1,
86 const CallbackAllocator<T>& alloc2) {
87 return alloc1.alloc == alloc2.alloc;
88}
89template <class T>
90bool operator!=(const CallbackAllocator<T>& alloc1,
91 const CallbackAllocator<T>& alloc2) {
92 return !(alloc1 == alloc2);
93}
94
95template <class Key,
96 class T,
97 class Hash = std::hash<Key>,
98 class Pred = std::equal_to<Key> >
99using UnorderedMap =
100 std::unordered_map<Key,
101 T,
102 Hash,
103 Pred,
104 CallbackAllocator<std::pair<const Key, T> > >;
105
106template <class T>
107using Vector = std::vector<T, CallbackAllocator<T> >;
108
109typedef std::basic_string<char,
110 std::char_traits<char>,
111 CallbackAllocator<char> > String;
112
113} // namespace
114
115// -----------------------------------------------------------------------------
116
Jesse Hall04f4f472015-08-16 19:51:04 -0700117struct VkInstance_T {
118 VkInstance_T(const VkAllocCallbacks* alloc_callbacks)
Michael Lentine03c64b02015-08-26 18:27:26 -0500119 : vtbl(&vtbl_storage),
120 alloc(alloc_callbacks),
121 num_physical_devices(0),
Michael Lentine1f0f5392015-09-11 14:54:34 -0700122 active_layers(
123 CallbackAllocator<std::pair<String, SharedLibraryHandle> >(
124 alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700125 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
126 memset(physical_devices, 0, sizeof(physical_devices));
127 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
128 drv.GetDeviceProcAddr = nullptr;
129 drv.num_physical_devices = 0;
130 }
131
132 InstanceVtbl* vtbl;
133 InstanceVtbl vtbl_storage;
134
135 const VkAllocCallbacks* alloc;
136 uint32_t num_physical_devices;
137 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
138
Michael Lentine1f0f5392015-09-11 14:54:34 -0700139 Vector<std::pair<String, SharedLibraryHandle> > active_layers;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500140 VkDbgMsgCallback message;
Michael Lentine03c64b02015-08-26 18:27:26 -0500141
Jesse Hall04f4f472015-08-16 19:51:04 -0700142 struct Driver {
143 // Pointers to driver entry points. Used explicitly by the loader; not
144 // set as the dispatch table for any objects.
145 InstanceVtbl vtbl;
146
147 // Pointer to the driver's get_device_proc_addr, must be valid for any
148 // of the driver's physical devices. Not part of the InstanceVtbl since
149 // it's not an Instance/PhysicalDevice function.
150 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
151
152 // Number of physical devices owned by this driver.
153 uint32_t num_physical_devices;
154 } drv; // may eventually be an array
155};
156
157// -----------------------------------------------------------------------------
158
159namespace {
160
161typedef VkInstance_T Instance;
162
163struct Device {
164 Device(const VkAllocCallbacks* alloc_callbacks) : alloc(alloc_callbacks) {
165 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
166 vtbl_storage.device = this;
167 }
168 DeviceVtbl vtbl_storage;
169 const VkAllocCallbacks* alloc;
Michael Lentine03c64b02015-08-26 18:27:26 -0500170 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700171};
172
173// -----------------------------------------------------------------------------
174// Utility Code
175
176inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
177 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
178}
179
180inline const DeviceVtbl* GetVtbl(VkDevice device) {
181 return *reinterpret_cast<DeviceVtbl**>(device);
182}
Jesse Halld7b994a2015-09-07 14:17:37 -0700183inline const DeviceVtbl* GetVtbl(VkQueue queue) {
184 return *reinterpret_cast<DeviceVtbl**>(queue);
185}
Jesse Hall04f4f472015-08-16 19:51:04 -0700186
187void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
188 return memalign(alignment, size);
189}
190
191void DefaultFree(void*, void* pMem) {
192 free(pMem);
193}
194
195const VkAllocCallbacks kDefaultAllocCallbacks = {
196 .pUserData = nullptr,
197 .pfnAlloc = DefaultAlloc,
198 .pfnFree = DefaultFree,
199};
200
201hwvulkan_device_t* g_hwdevice;
202bool EnsureInitialized() {
203 static std::once_flag once_flag;
204 static const hwvulkan_module_t* module;
205
206 std::call_once(once_flag, []() {
207 int result;
208 result = hw_get_module("vulkan",
209 reinterpret_cast<const hw_module_t**>(&module));
210 if (result != 0) {
211 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
212 result);
213 return;
214 }
215 result = module->common.methods->open(
216 &module->common, HWVULKAN_DEVICE_0,
217 reinterpret_cast<hw_device_t**>(&g_hwdevice));
218 if (result != 0) {
219 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
220 result);
221 module = nullptr;
222 return;
223 }
224 });
225
226 return module != nullptr && g_hwdevice != nullptr;
227}
228
229void DestroyDevice(Device* device) {
230 const VkAllocCallbacks* alloc = device->alloc;
231 device->~Device();
232 alloc->pfnFree(alloc->pUserData, device);
233}
234
Michael Lentine03c64b02015-08-26 18:27:26 -0500235void FindLayersInDirectory(
236 Instance& instance,
237 UnorderedMap<String, SharedLibraryHandle>& layer_name_to_handle_map,
238 const String& dir_name) {
239 DIR* directory;
240 struct dirent* entry;
241 if ((directory = opendir(dir_name.c_str()))) {
242 Vector<VkLayerProperties> properties(
243 CallbackAllocator<VkLayerProperties>(instance.alloc));
244 while ((entry = readdir(directory))) {
245 size_t length = strlen(entry->d_name);
246 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
247 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
248 continue;
249 // Open so
250 SharedLibraryHandle layer_handle = dlopen(
251 (dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
252 if (!layer_handle) {
253 ALOGE("%s failed to load with error %s; Skipping",
254 entry->d_name, dlerror());
255 continue;
256 }
257
258 // Get Layers in so
259 PFN_vkGetGlobalLayerProperties get_layer_properties =
260 reinterpret_cast<PFN_vkGetGlobalLayerProperties>(
261 dlsym(layer_handle, "vkGetGlobalLayerProperties"));
262 if (!get_layer_properties) {
263 ALOGE(
264 "%s failed to find vkGetGlobalLayerProperties with "
265 "error %s; Skipping",
266 entry->d_name, dlerror());
267 dlclose(layer_handle);
268 continue;
269 }
270 uint32_t count;
271 get_layer_properties(&count, nullptr);
272
273 properties.resize(count);
274 get_layer_properties(&count, &properties[0]);
275
276 // Add Layers to potential list
Michael Lentine03c64b02015-08-26 18:27:26 -0500277 for (uint32_t i = 0; i < count; ++i) {
278 layer_name_to_handle_map.insert(std::make_pair(
279 String(properties[i].layerName,
280 CallbackAllocator<char>(instance.alloc)),
281 layer_handle));
282 ALOGV("Found layer %s", properties[i].layerName);
283 }
284 }
285 closedir(directory);
286 } else {
287 ALOGE("Failed to Open Directory %s: %s (%d)", dir_name.c_str(),
288 strerror(errno), errno);
289 }
290}
291
292void LoadLayer(Instance* instance,
293 const String& name,
294 SharedLibraryHandle& layer_handle) {
295 ALOGV("Loading layer %s", name.c_str());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700296 instance->active_layers.push_back(std::make_pair(name, layer_handle));
Michael Lentine03c64b02015-08-26 18:27:26 -0500297}
298
299VkResult CreateDeviceNoop(VkPhysicalDevice,
300 const VkDeviceCreateInfo*,
301 VkDevice*) {
302 return VK_SUCCESS;
303}
304
305PFN_vkVoidFunction GetLayerDeviceProcAddr(VkDevice device, const char* name) {
306 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
307 return reinterpret_cast<PFN_vkVoidFunction>(GetLayerDeviceProcAddr);
308 }
309 if (strcmp(name, "vkCreateDevice") == 0) {
310 return reinterpret_cast<PFN_vkVoidFunction>(CreateDeviceNoop);
311 }
312 if (!device)
313 return GetGlobalDeviceProcAddr(name);
314 Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
315 return loader_device->GetDeviceProcAddr(device, name);
316}
317
Michael Lentineb467c0d2015-09-14 14:43:49 -0500318struct InstanceLayersPair {
319 Instance* instance;
320 UnorderedMap<String, SharedLibraryHandle>* layers;
321};
322
323void LoadLayerFromProperty(const char* name, const char* value, void* data) {
324 auto instance_layers_pair = static_cast<InstanceLayersPair*>(data);
325 const char prefix[] = "debug.vulkan.layer.";
326 const size_t prefixlen = sizeof(prefix) - 1;
327 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
328 return;
329 String layer_name_str(
330 name + prefixlen,
331 CallbackAllocator<char>(instance_layers_pair->instance->alloc));
332 LoadLayer(instance_layers_pair->instance, layer_name_str,
333 (*instance_layers_pair->layers)[layer_name_str]);
334}
335
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500336void LogDebugMessageCallback(VkFlags message_flags,
337 VkDbgObjectType /*obj_type*/,
338 uint64_t /*src_object*/,
339 size_t /*location*/,
340 int32_t message_code,
341 const char* layer_prefix,
342 const char* message,
343 void* /*user_data*/) {
344 if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
345 ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
346 } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
347 ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
348 }
349}
350
Jesse Hall04f4f472015-08-16 19:51:04 -0700351// -----------------------------------------------------------------------------
352// "Bottom" functions. These are called at the end of the instance dispatch
353// chain.
354
355VkResult DestroyInstanceBottom(VkInstance instance) {
356 // These checks allow us to call DestroyInstanceBottom from any error path
357 // in CreateInstanceBottom, before the driver instance is fully initialized.
358 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
359 instance->drv.vtbl.DestroyInstance) {
360 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
361 }
Michael Lentine1f0f5392015-09-11 14:54:34 -0700362 for (auto& layer : instance->active_layers) {
363 dlclose(layer.second);
Michael Lentine03c64b02015-08-26 18:27:26 -0500364 }
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500365 if (instance->message) {
366 PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
367 DebugDestroyMessageCallback = reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
368 vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
369 DebugDestroyMessageCallback(instance, instance->message);
370 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700371 const VkAllocCallbacks* alloc = instance->alloc;
372 instance->~VkInstance_T();
373 alloc->pfnFree(alloc->pUserData, instance);
374 return VK_SUCCESS;
375}
376
377VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
378 VkInstance* instance_ptr) {
379 Instance* instance = *instance_ptr;
380 VkResult result;
381
382 result =
383 g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
384 if (result != VK_SUCCESS) {
385 DestroyInstanceBottom(instance);
386 return result;
387 }
388
Michael Lentine03c64b02015-08-26 18:27:26 -0500389 if (!LoadInstanceVtbl(
390 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
391 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700392 DestroyInstanceBottom(instance);
393 return VK_ERROR_INITIALIZATION_FAILED;
394 }
395
396 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
397 // queryable from the Instance, and that the resulting function work for any
398 // VkDevice created from the instance.
399 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
400 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
401 "vkGetDeviceProcAddr"));
402 if (!instance->drv.GetDeviceProcAddr) {
403 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
404 DestroyInstanceBottom(instance);
405 return VK_ERROR_INITIALIZATION_FAILED;
406 }
407
408 hwvulkan_dispatch_t* dispatch =
409 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
410 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
411 // Skip setting dispatch->vtbl on the driver instance handle, since we
412 // never intentionally call through it; we go through Instance::drv.vtbl
413 // instead.
414 } else {
415 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
416 dispatch->magic);
417 DestroyInstanceBottom(instance);
418 return VK_ERROR_INITIALIZATION_FAILED;
419 }
420
421 uint32_t num_physical_devices = 0;
422 result = instance->drv.vtbl.EnumeratePhysicalDevices(
423 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
424 if (result != VK_SUCCESS) {
425 DestroyInstanceBottom(instance);
426 return VK_ERROR_INITIALIZATION_FAILED;
427 }
428 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
429 result = instance->drv.vtbl.EnumeratePhysicalDevices(
430 instance->drv.vtbl.instance, &num_physical_devices,
431 instance->physical_devices);
432 if (result != VK_SUCCESS) {
433 DestroyInstanceBottom(instance);
434 return VK_ERROR_INITIALIZATION_FAILED;
435 }
436 for (uint32_t i = 0; i < num_physical_devices; i++) {
437 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
438 instance->physical_devices[i]);
439 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
440 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
441 dispatch->magic);
442 DestroyInstanceBottom(instance);
443 return VK_ERROR_INITIALIZATION_FAILED;
444 }
445 dispatch->vtbl = instance->vtbl;
446 }
447 instance->drv.num_physical_devices = num_physical_devices;
448
449 instance->num_physical_devices = instance->drv.num_physical_devices;
450 return VK_SUCCESS;
451}
452
453VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
454 uint32_t* pdev_count,
455 VkPhysicalDevice* pdevs) {
456 uint32_t count = instance->num_physical_devices;
457 if (pdevs) {
458 count = std::min(count, *pdev_count);
459 std::copy(instance->physical_devices,
460 instance->physical_devices + count, pdevs);
461 }
462 *pdev_count = count;
463 return VK_SUCCESS;
464}
465
466VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
467 VkPhysicalDeviceFeatures* features) {
468 return GetVtbl(pdev)
469 ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
470}
471
472VkResult GetPhysicalDeviceFormatPropertiesBottom(
473 VkPhysicalDevice pdev,
474 VkFormat format,
475 VkFormatProperties* properties) {
476 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
477 pdev, format, properties);
478}
479
480VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
481 VkPhysicalDevice pdev,
482 VkFormat format,
483 VkImageType type,
484 VkImageTiling tiling,
485 VkImageUsageFlags usage,
486 VkImageFormatProperties* properties) {
487 return GetVtbl(pdev)
488 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
489 pdev, format, type, tiling, usage, properties);
490}
491
492VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
493 VkPhysicalDeviceLimits* limits) {
494 return GetVtbl(pdev)
495 ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
496}
497
498VkResult GetPhysicalDevicePropertiesBottom(
499 VkPhysicalDevice pdev,
500 VkPhysicalDeviceProperties* properties) {
501 return GetVtbl(pdev)
502 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
503}
504
505VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
506 uint32_t* count) {
507 return GetVtbl(pdev)
508 ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
509}
510
511VkResult GetPhysicalDeviceQueuePropertiesBottom(
512 VkPhysicalDevice pdev,
513 uint32_t count,
514 VkPhysicalDeviceQueueProperties* properties) {
515 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
516 pdev, count, properties);
517}
518
519VkResult GetPhysicalDeviceMemoryPropertiesBottom(
520 VkPhysicalDevice pdev,
521 VkPhysicalDeviceMemoryProperties* properties) {
522 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
523 pdev, properties);
524}
525
526VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
527 const VkDeviceCreateInfo* create_info,
528 VkDevice* out_device) {
529 const Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
530 VkResult result;
531
532 void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
533 sizeof(Device), alignof(Device),
534 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
535 if (!mem)
536 return VK_ERROR_OUT_OF_HOST_MEMORY;
537 Device* device = new (mem) Device(instance.alloc);
Michael Lentine03c64b02015-08-26 18:27:26 -0500538 device->GetDeviceProcAddr = instance.drv.GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700539
540 VkDevice drv_device;
541 result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
542 if (result != VK_SUCCESS) {
543 DestroyDevice(device);
544 return result;
545 }
546
Jesse Hall04f4f472015-08-16 19:51:04 -0700547 hwvulkan_dispatch_t* dispatch =
548 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
549 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
550 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500551 PFN_vkDestroyDevice destroy_device =
552 reinterpret_cast<PFN_vkDestroyDevice>(
553 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
554 destroy_device(drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700555 DestroyDevice(device);
556 return VK_ERROR_INITIALIZATION_FAILED;
557 }
558 dispatch->vtbl = &device->vtbl_storage;
559
Jesse Hallb1352bc2015-09-04 16:12:33 -0700560 device->vtbl_storage.GetSurfacePropertiesKHR = GetSurfacePropertiesKHR;
561 device->vtbl_storage.GetSurfaceFormatsKHR = GetSurfaceFormatsKHR;
562 device->vtbl_storage.GetSurfacePresentModesKHR = GetSurfacePresentModesKHR;
563 device->vtbl_storage.CreateSwapchainKHR = CreateSwapchainKHR;
564 device->vtbl_storage.DestroySwapchainKHR = DestroySwapchainKHR;
565 device->vtbl_storage.GetSwapchainImagesKHR = GetSwapchainImagesKHR;
566 device->vtbl_storage.AcquireNextImageKHR = AcquireNextImageKHR;
567 device->vtbl_storage.QueuePresentKHR = QueuePresentKHR;
568
Michael Lentine03c64b02015-08-26 18:27:26 -0500569 void* base_object = static_cast<void*>(drv_device);
570 void* next_object = base_object;
571 VkLayerLinkedListElem* next_element;
572 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
573 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700574 instance.active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500575 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
576
577 for (size_t i = elem_list.size(); i > 0; i--) {
578 size_t idx = i - 1;
579 next_element = &elem_list[idx];
580 next_element->get_proc_addr =
581 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
582 next_element->base_object = base_object;
583 next_element->next_element = next_object;
584 next_object = static_cast<void*>(next_element);
585
Michael Lentine1f0f5392015-09-11 14:54:34 -0700586 auto& name_libhandle_pair = instance.active_layers[idx];
Michael Lentine03c64b02015-08-26 18:27:26 -0500587 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700588 dlsym(name_libhandle_pair.second,
589 (name_libhandle_pair.first + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500590 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500591 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700592 dlsym(name_libhandle_pair.second, "vkGetDeviceProcAddr"));
593 if (!next_get_proc_addr) {
594 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
595 name_libhandle_pair.first.c_str(), dlerror());
596 next_object = next_element->next_element;
597 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
598 next_element->get_proc_addr);
599 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500600 }
601 }
602
603 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
604 static_cast<VkDevice>(next_object), next_get_proc_addr,
605 device->vtbl_storage)) {
606 DestroyDevice(device);
607 return VK_ERROR_INITIALIZATION_FAILED;
608 }
609
610 PFN_vkCreateDevice layer_createDevice =
611 reinterpret_cast<PFN_vkCreateDevice>(
612 device->vtbl_storage.GetDeviceProcAddr(drv_device,
613 "vkCreateDevice"));
614 layer_createDevice(pdev, create_info, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700615
616 *out_device = drv_device;
617 return VK_SUCCESS;
618}
619
620VkResult GetPhysicalDeviceExtensionPropertiesBottom(
621 VkPhysicalDevice pdev,
622 const char* layer_name,
623 uint32_t* properties_count,
624 VkExtensionProperties* properties) {
625 // TODO: what are we supposed to do with layer_name here?
626 return GetVtbl(pdev)
627 ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
628 pdev, layer_name, properties_count, properties);
629}
630
631VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
632 uint32_t* properties_count,
633 VkLayerProperties* properties) {
634 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
635 pdev, properties_count, properties);
636}
637
638VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
639 VkPhysicalDevice pdev,
640 VkFormat format,
641 VkImageType type,
642 uint32_t samples,
643 VkImageUsageFlags usage,
644 VkImageTiling tiling,
645 uint32_t* properties_count,
646 VkSparseImageFormatProperties* properties) {
647 return GetVtbl(pdev)
648 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
649 pdev, format, type, samples, usage, tiling, properties_count,
650 properties);
651}
652
653PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
654
655const InstanceVtbl kBottomInstanceFunctions = {
656 // clang-format off
657 .instance = nullptr,
658 .CreateInstance = CreateInstanceBottom,
659 .DestroyInstance = DestroyInstanceBottom,
660 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
661 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
662 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
663 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
664 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
665 .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
666 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
667 .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
668 .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
669 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
670 .CreateDevice = CreateDeviceBottom,
671 .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
672 .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
673 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700674 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700675 // clang-format on
676};
677
Michael Lentine03c64b02015-08-26 18:27:26 -0500678VkResult Noop(...) {
679 return VK_SUCCESS;
680}
681
Jesse Hall04f4f472015-08-16 19:51:04 -0700682PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500683 // TODO: Possibly move this into the instance table
684 // TODO: Possibly register the callbacks in the loader
685 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
686 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
687 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
688 }
689 if (strcmp(name, "vkCreateInstance") == 0) {
690 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
691 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700692 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
693}
694
695} // namespace
696
697// -----------------------------------------------------------------------------
698// Global functions. These are called directly from the loader entry points,
699// without going through a dispatch table.
700
701namespace vulkan {
702
703VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
704 uint32_t* count,
705 VkExtensionProperties* /*properties*/) {
706 if (!count)
707 return VK_ERROR_INVALID_POINTER;
708 if (!EnsureInitialized())
709 return VK_ERROR_UNAVAILABLE;
710
711 // TODO: not yet implemented
712 ALOGW("vkGetGlobalExtensionProperties not implemented");
713
714 *count = 0;
715 return VK_SUCCESS;
716}
717
718VkResult GetGlobalLayerProperties(uint32_t* count,
719 VkLayerProperties* /*properties*/) {
720 if (!count)
721 return VK_ERROR_INVALID_POINTER;
722 if (!EnsureInitialized())
723 return VK_ERROR_UNAVAILABLE;
724
725 // TODO: not yet implemented
726 ALOGW("vkGetGlobalLayerProperties not implemented");
727
728 *count = 0;
729 return VK_SUCCESS;
730}
731
732VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
733 VkInstance* out_instance) {
734 VkResult result;
735
736 if (!EnsureInitialized())
737 return VK_ERROR_UNAVAILABLE;
738
739 VkInstanceCreateInfo local_create_info = *create_info;
740 if (!local_create_info.pAllocCb)
741 local_create_info.pAllocCb = &kDefaultAllocCallbacks;
742 create_info = &local_create_info;
743
744 void* instance_mem = create_info->pAllocCb->pfnAlloc(
745 create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
746 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
747 if (!instance_mem)
748 return VK_ERROR_OUT_OF_HOST_MEMORY;
749 Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
750
751 instance->vtbl_storage = kBottomInstanceFunctions;
752 instance->vtbl_storage.instance = instance;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500753 instance->message = VK_NULL_HANDLE;
Jesse Hall04f4f472015-08-16 19:51:04 -0700754
Michael Lentine03c64b02015-08-26 18:27:26 -0500755 // Scan layers
756 // TODO: Add more directories to scan
757 UnorderedMap<String, SharedLibraryHandle> layers(
758 CallbackAllocator<std::pair<String, SharedLibraryHandle> >(
759 instance->alloc));
760 CallbackAllocator<char> string_allocator(instance->alloc);
761 String dir_name("/data/local/tmp/vulkan/", string_allocator);
762 FindLayersInDirectory(*instance, layers, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700763
Michael Lentine950bb4f2015-09-14 13:26:30 -0500764 // Load layers
Michael Lentine03c64b02015-08-26 18:27:26 -0500765 {
766 char layer_prop[PROPERTY_VALUE_MAX];
Michael Lentineb467c0d2015-09-14 14:43:49 -0500767 property_get("debug.vulkan.layers", layer_prop, "");
768 String layer_name(string_allocator);
769 String layer_prop_str(layer_prop, string_allocator);
770 size_t end, start = 0;
771 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
772 layer_name = layer_prop_str.substr(start, end - start);
773 auto element = layers.find(layer_name);
774 if (element != layers.end()) {
775 LoadLayer(instance, layer_name, element->second);
776 layers.erase(element);
Michael Lentine03c64b02015-08-26 18:27:26 -0500777 }
Michael Lentineb467c0d2015-09-14 14:43:49 -0500778 start = end + 1;
Michael Lentine03c64b02015-08-26 18:27:26 -0500779 }
Michael Lentineb467c0d2015-09-14 14:43:49 -0500780 InstanceLayersPair instance_layers_pair = {.instance = instance,
781 .layers = &layers};
782 property_list(LoadLayerFromProperty,
783 static_cast<void*>(&instance_layers_pair));
Michael Lentine03c64b02015-08-26 18:27:26 -0500784 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500785 for (uint32_t i = 0; i < create_info->layerCount; ++i) {
786 String layer_name(create_info->ppEnabledLayerNames[i],
787 string_allocator);
788 auto element = layers.find(layer_name);
789 if (element != layers.end()) {
790 LoadLayer(instance, layer_name, element->second);
791 layers.erase(element);
792 }
793 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500794 for (auto& layer : layers) {
795 dlclose(layer.second);
796 }
797
798 void* base_object = static_cast<void*>(instance);
799 void* next_object = base_object;
800 VkLayerLinkedListElem* next_element;
801 PFN_vkGetInstanceProcAddr next_get_proc_addr =
802 kBottomInstanceFunctions.GetInstanceProcAddr;
803 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700804 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500805 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
806
807 for (size_t i = elem_list.size(); i > 0; i--) {
808 size_t idx = i - 1;
809 next_element = &elem_list[idx];
810 next_element->get_proc_addr =
811 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
812 next_element->base_object = base_object;
813 next_element->next_element = next_object;
814 next_object = static_cast<void*>(next_element);
815
Michael Lentine1f0f5392015-09-11 14:54:34 -0700816 auto& name_libhandle_pair = instance->active_layers[idx];
Michael Lentine03c64b02015-08-26 18:27:26 -0500817 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700818 dlsym(name_libhandle_pair.second,
819 (name_libhandle_pair.first + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500820 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500821 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700822 dlsym(name_libhandle_pair.second, "vkGetInstanceProcAddr"));
823 if (!next_get_proc_addr) {
824 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
825 name_libhandle_pair.first.c_str(), dlerror());
826 next_object = next_element->next_element;
827 next_get_proc_addr =
828 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
829 next_element->get_proc_addr);
830 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500831 }
832 }
833
834 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
835 static_cast<VkInstance>(next_object),
836 next_get_proc_addr, instance->vtbl_storage)) {
837 DestroyInstanceBottom(instance);
838 return VK_ERROR_INITIALIZATION_FAILED;
839 }
840
Michael Lentine950bb4f2015-09-14 13:26:30 -0500841 // Force enable callback extension if required
842 bool enable_callback =
843 property_get_bool("debug.vulkan.enable_layer_callback", false);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500844 bool enable_logging = enable_callback;
Michael Lentine950bb4f2015-09-14 13:26:30 -0500845 const char* callback_name = "DEBUG_REPORT";
846 if (enable_callback) {
847 for (uint32_t i = 0; i < create_info->extensionCount; ++i) {
848 if (!strcmp(callback_name,
849 create_info->ppEnabledExtensionNames[i])) {
850 enable_callback = false;
851 break;
852 }
853 }
854 }
855 if (enable_callback) {
856 uint32_t extension_count = local_create_info.extensionCount;
857 local_create_info.extensionCount++;
858 void* mem = instance->alloc->pfnAlloc(
859 instance->alloc->pUserData,
860 local_create_info.extensionCount * sizeof(char*), alignof(char*),
861 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
862 if (mem) {
863 const char** enabled_extensions = static_cast<const char**>(mem);
864 for (uint32_t i = 0; i < extension_count; ++i) {
865 enabled_extensions[i] =
866 local_create_info.ppEnabledExtensionNames[i];
867 }
868 enabled_extensions[extension_count] = callback_name;
869 local_create_info.ppEnabledExtensionNames = enabled_extensions;
870 } else {
871 ALOGW("DEBUG_REPORT extension cannot be enabled!");
872 enable_callback = false;
873 local_create_info.extensionCount--;
874 }
875 }
876
Jesse Hall04f4f472015-08-16 19:51:04 -0700877 *out_instance = instance;
Michael Lentine03c64b02015-08-26 18:27:26 -0500878 result = instance->vtbl_storage.CreateInstance(create_info, out_instance);
Michael Lentine950bb4f2015-09-14 13:26:30 -0500879 if (enable_callback) {
880 const char* const* enabled_extensions =
881 local_create_info.ppEnabledExtensionNames;
882 instance->alloc->pfnFree(instance->alloc->pUserData,
883 const_cast<char**>(enabled_extensions));
884 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700885 if (result <= 0) {
886 // For every layer, including the loader top and bottom layers:
887 // - If a call to the next CreateInstance fails, the layer must clean
888 // up anything it has successfully done so far, and propagate the
889 // error upwards.
890 // - If a layer successfully calls the next layer's CreateInstance, and
891 // afterwards must fail for some reason, it must call the next layer's
892 // DestroyInstance before returning.
893 // - The layer must not call the next layer's DestroyInstance if that
894 // layer's CreateInstance wasn't called, or returned failure.
895
896 // On failure, CreateInstanceBottom frees the instance struct, so it's
897 // already gone at this point. Nothing to do.
898 }
899
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500900 if (enable_logging) {
901 PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
902 DebugCreateMessageCallback = reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
903 vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
904 DebugCreateMessageCallback(instance,
905 VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
906 LogDebugMessageCallback, NULL, &instance->message);
907 }
908
Jesse Hall04f4f472015-08-16 19:51:04 -0700909 return result;
910}
911
912PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
913 if (!instance)
914 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500915 // TODO: Possibly move this into the instance table
916 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
917 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
918 if (!instance->vtbl)
919 return NULL;
920 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
921 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
922 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700923 // For special-case functions we always return the loader entry
924 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
925 strcmp(name, "vkGetDeviceProcAddr") == 0) {
926 return GetGlobalInstanceProcAddr(name);
927 }
928 return GetSpecificInstanceProcAddr(instance->vtbl, name);
929}
930
931PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
932 if (!device)
933 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500934 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
935 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
936 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700937 // For special-case functions we always return the loader entry
938 if (strcmp(name, "vkGetDeviceQueue") == 0 ||
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700939 strcmp(name, "vkCreateCommandBuffer") == 0 ||
Jesse Hall04f4f472015-08-16 19:51:04 -0700940 strcmp(name, "vkDestroyDevice") == 0) {
941 return GetGlobalDeviceProcAddr(name);
942 }
943 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
944}
945
946VkResult GetDeviceQueue(VkDevice drv_device,
947 uint32_t family,
948 uint32_t index,
949 VkQueue* out_queue) {
950 VkResult result;
951 VkQueue queue;
952 const DeviceVtbl* vtbl = GetVtbl(drv_device);
953 result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
954 if (result != VK_SUCCESS)
955 return result;
956 hwvulkan_dispatch_t* dispatch =
957 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
958 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
959 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
960 return VK_ERROR_INITIALIZATION_FAILED;
961 }
962 dispatch->vtbl = vtbl;
963 *out_queue = queue;
964 return VK_SUCCESS;
965}
966
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700967VkResult CreateCommandBuffer(VkDevice drv_device,
968 const VkCmdBufferCreateInfo* create_info,
969 VkCmdBuffer* out_cmdbuf) {
970 const DeviceVtbl* vtbl = GetVtbl(drv_device);
971 VkCmdBuffer cmdbuf;
972 VkResult result =
973 vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
974 if (result != VK_SUCCESS)
975 return result;
976 hwvulkan_dispatch_t* dispatch =
977 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
978 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
979 ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
980 dispatch->magic);
981 return VK_ERROR_INITIALIZATION_FAILED;
982 }
983 dispatch->vtbl = vtbl;
984 *out_cmdbuf = cmdbuf;
985 return VK_SUCCESS;
986}
987
Jesse Hall04f4f472015-08-16 19:51:04 -0700988VkResult DestroyDevice(VkDevice drv_device) {
989 const DeviceVtbl* vtbl = GetVtbl(drv_device);
990 Device* device = static_cast<Device*>(vtbl->device);
991 vtbl->DestroyDevice(drv_device);
992 DestroyDevice(device);
993 return VK_SUCCESS;
994}
995
Jesse Halld7b994a2015-09-07 14:17:37 -0700996void* AllocDeviceMem(VkDevice device,
997 size_t size,
998 size_t align,
999 VkSystemAllocType type) {
1000 const VkAllocCallbacks* alloc_cb =
1001 static_cast<Device*>(GetVtbl(device)->device)->alloc;
1002 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
1003}
1004
1005void FreeDeviceMem(VkDevice device, void* ptr) {
1006 const VkAllocCallbacks* alloc_cb =
1007 static_cast<Device*>(GetVtbl(device)->device)->alloc;
1008 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1009}
1010
1011const DeviceVtbl& GetDriverVtbl(VkDevice device) {
1012 // TODO(jessehall): This actually returns the API-level vtbl for the
1013 // device, not the driver entry points. Given the current use -- getting
1014 // the driver's private swapchain-related functions -- that works, but is
1015 // misleading and likely to cause bugs. Fix as part of separating the
1016 // loader->driver interface from the app->loader interface.
1017 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
1018}
1019
1020const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
1021 // TODO(jessehall): This actually returns the API-level vtbl for the
1022 // device, not the driver entry points. Given the current use -- getting
1023 // the driver's private swapchain-related functions -- that works, but is
1024 // misleading and likely to cause bugs. Fix as part of separating the
1025 // loader->driver interface from the app->loader interface.
1026 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
1027}
1028
Jesse Hall04f4f472015-08-16 19:51:04 -07001029} // namespace vulkan