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