blob: 3ba47b3b8db96eec7c476861faede4c6c4ab0d70 [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
20#include <inttypes.h>
21#include <malloc.h>
22#include <pthread.h>
23#include <string.h>
24// standard C++ headers
25#include <algorithm>
26#include <mutex>
27// platform/library headers
28#include <hardware/hwvulkan.h>
29#include <log/log.h>
30
31using namespace vulkan;
32
33static const uint32_t kMaxPhysicalDevices = 4;
34
35struct VkInstance_T {
36 VkInstance_T(const VkAllocCallbacks* alloc_callbacks)
37 : vtbl(&vtbl_storage), alloc(alloc_callbacks), num_physical_devices(0) {
38 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
39 memset(physical_devices, 0, sizeof(physical_devices));
40 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
41 drv.GetDeviceProcAddr = nullptr;
42 drv.num_physical_devices = 0;
43 }
44
45 InstanceVtbl* vtbl;
46 InstanceVtbl vtbl_storage;
47
48 const VkAllocCallbacks* alloc;
49 uint32_t num_physical_devices;
50 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
51
52 struct Driver {
53 // Pointers to driver entry points. Used explicitly by the loader; not
54 // set as the dispatch table for any objects.
55 InstanceVtbl vtbl;
56
57 // Pointer to the driver's get_device_proc_addr, must be valid for any
58 // of the driver's physical devices. Not part of the InstanceVtbl since
59 // it's not an Instance/PhysicalDevice function.
60 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
61
62 // Number of physical devices owned by this driver.
63 uint32_t num_physical_devices;
64 } drv; // may eventually be an array
65};
66
67// -----------------------------------------------------------------------------
68
69namespace {
70
71typedef VkInstance_T Instance;
72
73struct Device {
74 Device(const VkAllocCallbacks* alloc_callbacks) : alloc(alloc_callbacks) {
75 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
76 vtbl_storage.device = this;
77 }
78 DeviceVtbl vtbl_storage;
79 const VkAllocCallbacks* alloc;
80};
81
82// -----------------------------------------------------------------------------
83// Utility Code
84
85inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
86 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
87}
88
89inline const DeviceVtbl* GetVtbl(VkDevice device) {
90 return *reinterpret_cast<DeviceVtbl**>(device);
91}
Jesse Halld7b994a2015-09-07 14:17:37 -070092inline const DeviceVtbl* GetVtbl(VkQueue queue) {
93 return *reinterpret_cast<DeviceVtbl**>(queue);
94}
Jesse Hall04f4f472015-08-16 19:51:04 -070095
96void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
97 return memalign(alignment, size);
98}
99
100void DefaultFree(void*, void* pMem) {
101 free(pMem);
102}
103
104const VkAllocCallbacks kDefaultAllocCallbacks = {
105 .pUserData = nullptr,
106 .pfnAlloc = DefaultAlloc,
107 .pfnFree = DefaultFree,
108};
109
110hwvulkan_device_t* g_hwdevice;
111bool EnsureInitialized() {
112 static std::once_flag once_flag;
113 static const hwvulkan_module_t* module;
114
115 std::call_once(once_flag, []() {
116 int result;
117 result = hw_get_module("vulkan",
118 reinterpret_cast<const hw_module_t**>(&module));
119 if (result != 0) {
120 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
121 result);
122 return;
123 }
124 result = module->common.methods->open(
125 &module->common, HWVULKAN_DEVICE_0,
126 reinterpret_cast<hw_device_t**>(&g_hwdevice));
127 if (result != 0) {
128 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
129 result);
130 module = nullptr;
131 return;
132 }
133 });
134
135 return module != nullptr && g_hwdevice != nullptr;
136}
137
138void DestroyDevice(Device* device) {
139 const VkAllocCallbacks* alloc = device->alloc;
140 device->~Device();
141 alloc->pfnFree(alloc->pUserData, device);
142}
143
144// -----------------------------------------------------------------------------
145// "Bottom" functions. These are called at the end of the instance dispatch
146// chain.
147
148VkResult DestroyInstanceBottom(VkInstance instance) {
149 // These checks allow us to call DestroyInstanceBottom from any error path
150 // in CreateInstanceBottom, before the driver instance is fully initialized.
151 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
152 instance->drv.vtbl.DestroyInstance) {
153 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
154 }
155 const VkAllocCallbacks* alloc = instance->alloc;
156 instance->~VkInstance_T();
157 alloc->pfnFree(alloc->pUserData, instance);
158 return VK_SUCCESS;
159}
160
161VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
162 VkInstance* instance_ptr) {
163 Instance* instance = *instance_ptr;
164 VkResult result;
165
166 result =
167 g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
168 if (result != VK_SUCCESS) {
169 DestroyInstanceBottom(instance);
170 return result;
171 }
172
173 if (!LoadInstanceVtbl(instance->drv.vtbl.instance,
174 g_hwdevice->GetInstanceProcAddr,
175 instance->drv.vtbl)) {
176 DestroyInstanceBottom(instance);
177 return VK_ERROR_INITIALIZATION_FAILED;
178 }
179
180 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
181 // queryable from the Instance, and that the resulting function work for any
182 // VkDevice created from the instance.
183 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
184 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
185 "vkGetDeviceProcAddr"));
186 if (!instance->drv.GetDeviceProcAddr) {
187 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
188 DestroyInstanceBottom(instance);
189 return VK_ERROR_INITIALIZATION_FAILED;
190 }
191
192 hwvulkan_dispatch_t* dispatch =
193 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
194 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
195 // Skip setting dispatch->vtbl on the driver instance handle, since we
196 // never intentionally call through it; we go through Instance::drv.vtbl
197 // instead.
198 } else {
199 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
200 dispatch->magic);
201 DestroyInstanceBottom(instance);
202 return VK_ERROR_INITIALIZATION_FAILED;
203 }
204
205 uint32_t num_physical_devices = 0;
206 result = instance->drv.vtbl.EnumeratePhysicalDevices(
207 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
208 if (result != VK_SUCCESS) {
209 DestroyInstanceBottom(instance);
210 return VK_ERROR_INITIALIZATION_FAILED;
211 }
212 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
213 result = instance->drv.vtbl.EnumeratePhysicalDevices(
214 instance->drv.vtbl.instance, &num_physical_devices,
215 instance->physical_devices);
216 if (result != VK_SUCCESS) {
217 DestroyInstanceBottom(instance);
218 return VK_ERROR_INITIALIZATION_FAILED;
219 }
220 for (uint32_t i = 0; i < num_physical_devices; i++) {
221 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
222 instance->physical_devices[i]);
223 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
224 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
225 dispatch->magic);
226 DestroyInstanceBottom(instance);
227 return VK_ERROR_INITIALIZATION_FAILED;
228 }
229 dispatch->vtbl = instance->vtbl;
230 }
231 instance->drv.num_physical_devices = num_physical_devices;
232
233 instance->num_physical_devices = instance->drv.num_physical_devices;
234 return VK_SUCCESS;
235}
236
237VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
238 uint32_t* pdev_count,
239 VkPhysicalDevice* pdevs) {
240 uint32_t count = instance->num_physical_devices;
241 if (pdevs) {
242 count = std::min(count, *pdev_count);
243 std::copy(instance->physical_devices,
244 instance->physical_devices + count, pdevs);
245 }
246 *pdev_count = count;
247 return VK_SUCCESS;
248}
249
250VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
251 VkPhysicalDeviceFeatures* features) {
252 return GetVtbl(pdev)
253 ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
254}
255
256VkResult GetPhysicalDeviceFormatPropertiesBottom(
257 VkPhysicalDevice pdev,
258 VkFormat format,
259 VkFormatProperties* properties) {
260 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
261 pdev, format, properties);
262}
263
264VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
265 VkPhysicalDevice pdev,
266 VkFormat format,
267 VkImageType type,
268 VkImageTiling tiling,
269 VkImageUsageFlags usage,
270 VkImageFormatProperties* properties) {
271 return GetVtbl(pdev)
272 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
273 pdev, format, type, tiling, usage, properties);
274}
275
276VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
277 VkPhysicalDeviceLimits* limits) {
278 return GetVtbl(pdev)
279 ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
280}
281
282VkResult GetPhysicalDevicePropertiesBottom(
283 VkPhysicalDevice pdev,
284 VkPhysicalDeviceProperties* properties) {
285 return GetVtbl(pdev)
286 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
287}
288
289VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
290 uint32_t* count) {
291 return GetVtbl(pdev)
292 ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
293}
294
295VkResult GetPhysicalDeviceQueuePropertiesBottom(
296 VkPhysicalDevice pdev,
297 uint32_t count,
298 VkPhysicalDeviceQueueProperties* properties) {
299 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
300 pdev, count, properties);
301}
302
303VkResult GetPhysicalDeviceMemoryPropertiesBottom(
304 VkPhysicalDevice pdev,
305 VkPhysicalDeviceMemoryProperties* properties) {
306 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
307 pdev, properties);
308}
309
310VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
311 const VkDeviceCreateInfo* create_info,
312 VkDevice* out_device) {
313 const Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
314 VkResult result;
315
316 void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
317 sizeof(Device), alignof(Device),
318 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
319 if (!mem)
320 return VK_ERROR_OUT_OF_HOST_MEMORY;
321 Device* device = new (mem) Device(instance.alloc);
322
323 VkDevice drv_device;
324 result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
325 if (result != VK_SUCCESS) {
326 DestroyDevice(device);
327 return result;
328 }
329
330 if (!LoadDeviceVtbl(drv_device, instance.drv.GetDeviceProcAddr,
331 device->vtbl_storage)) {
332 if (device->vtbl_storage.DestroyDevice)
333 device->vtbl_storage.DestroyDevice(drv_device);
334 DestroyDevice(device);
335 return VK_ERROR_INITIALIZATION_FAILED;
336 }
337
338 hwvulkan_dispatch_t* dispatch =
339 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
340 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
341 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
342 device->vtbl_storage.DestroyDevice(drv_device);
343 DestroyDevice(device);
344 return VK_ERROR_INITIALIZATION_FAILED;
345 }
346 dispatch->vtbl = &device->vtbl_storage;
347
Jesse Hallb1352bc2015-09-04 16:12:33 -0700348 device->vtbl_storage.GetSurfacePropertiesKHR = GetSurfacePropertiesKHR;
349 device->vtbl_storage.GetSurfaceFormatsKHR = GetSurfaceFormatsKHR;
350 device->vtbl_storage.GetSurfacePresentModesKHR = GetSurfacePresentModesKHR;
351 device->vtbl_storage.CreateSwapchainKHR = CreateSwapchainKHR;
352 device->vtbl_storage.DestroySwapchainKHR = DestroySwapchainKHR;
353 device->vtbl_storage.GetSwapchainImagesKHR = GetSwapchainImagesKHR;
354 device->vtbl_storage.AcquireNextImageKHR = AcquireNextImageKHR;
355 device->vtbl_storage.QueuePresentKHR = QueuePresentKHR;
356
Jesse Hall04f4f472015-08-16 19:51:04 -0700357 // TODO: insert device layer entry points into device->vtbl_storage here?
358
359 *out_device = drv_device;
360 return VK_SUCCESS;
361}
362
363VkResult GetPhysicalDeviceExtensionPropertiesBottom(
364 VkPhysicalDevice pdev,
365 const char* layer_name,
366 uint32_t* properties_count,
367 VkExtensionProperties* properties) {
368 // TODO: what are we supposed to do with layer_name here?
369 return GetVtbl(pdev)
370 ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
371 pdev, layer_name, properties_count, properties);
372}
373
374VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
375 uint32_t* properties_count,
376 VkLayerProperties* properties) {
377 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
378 pdev, properties_count, properties);
379}
380
381VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
382 VkPhysicalDevice pdev,
383 VkFormat format,
384 VkImageType type,
385 uint32_t samples,
386 VkImageUsageFlags usage,
387 VkImageTiling tiling,
388 uint32_t* properties_count,
389 VkSparseImageFormatProperties* properties) {
390 return GetVtbl(pdev)
391 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
392 pdev, format, type, samples, usage, tiling, properties_count,
393 properties);
394}
395
396PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
397
398const InstanceVtbl kBottomInstanceFunctions = {
399 // clang-format off
400 .instance = nullptr,
401 .CreateInstance = CreateInstanceBottom,
402 .DestroyInstance = DestroyInstanceBottom,
403 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
404 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
405 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
406 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
407 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
408 .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
409 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
410 .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
411 .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
412 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
413 .CreateDevice = CreateDeviceBottom,
414 .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
415 .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
416 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700417 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700418 // clang-format on
419};
420
421PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
422 // The bottom GetInstanceProcAddr is only called by the innermost layer,
423 // when there is one, when it initializes its own dispatch table.
424 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
425}
426
427} // namespace
428
429// -----------------------------------------------------------------------------
430// Global functions. These are called directly from the loader entry points,
431// without going through a dispatch table.
432
433namespace vulkan {
434
435VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
436 uint32_t* count,
437 VkExtensionProperties* /*properties*/) {
438 if (!count)
439 return VK_ERROR_INVALID_POINTER;
440 if (!EnsureInitialized())
441 return VK_ERROR_UNAVAILABLE;
442
443 // TODO: not yet implemented
444 ALOGW("vkGetGlobalExtensionProperties not implemented");
445
446 *count = 0;
447 return VK_SUCCESS;
448}
449
450VkResult GetGlobalLayerProperties(uint32_t* count,
451 VkLayerProperties* /*properties*/) {
452 if (!count)
453 return VK_ERROR_INVALID_POINTER;
454 if (!EnsureInitialized())
455 return VK_ERROR_UNAVAILABLE;
456
457 // TODO: not yet implemented
458 ALOGW("vkGetGlobalLayerProperties not implemented");
459
460 *count = 0;
461 return VK_SUCCESS;
462}
463
464VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
465 VkInstance* out_instance) {
466 VkResult result;
467
468 if (!EnsureInitialized())
469 return VK_ERROR_UNAVAILABLE;
470
471 VkInstanceCreateInfo local_create_info = *create_info;
472 if (!local_create_info.pAllocCb)
473 local_create_info.pAllocCb = &kDefaultAllocCallbacks;
474 create_info = &local_create_info;
475
476 void* instance_mem = create_info->pAllocCb->pfnAlloc(
477 create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
478 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
479 if (!instance_mem)
480 return VK_ERROR_OUT_OF_HOST_MEMORY;
481 Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
482
483 instance->vtbl_storage = kBottomInstanceFunctions;
484 instance->vtbl_storage.instance = instance;
485
486 // TODO: Insert enabled layers into instance->dispatch_vtbl here.
487
488 // TODO: We'll want to call CreateInstance through the dispatch table
489 // instead of calling the loader's terminator
490 *out_instance = instance;
491 result = CreateInstanceBottom(create_info, out_instance);
492 if (result <= 0) {
493 // For every layer, including the loader top and bottom layers:
494 // - If a call to the next CreateInstance fails, the layer must clean
495 // up anything it has successfully done so far, and propagate the
496 // error upwards.
497 // - If a layer successfully calls the next layer's CreateInstance, and
498 // afterwards must fail for some reason, it must call the next layer's
499 // DestroyInstance before returning.
500 // - The layer must not call the next layer's DestroyInstance if that
501 // layer's CreateInstance wasn't called, or returned failure.
502
503 // On failure, CreateInstanceBottom frees the instance struct, so it's
504 // already gone at this point. Nothing to do.
505 }
506
507 return result;
508}
509
510PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
511 if (!instance)
512 return GetGlobalInstanceProcAddr(name);
513 // For special-case functions we always return the loader entry
514 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
515 strcmp(name, "vkGetDeviceProcAddr") == 0) {
516 return GetGlobalInstanceProcAddr(name);
517 }
518 return GetSpecificInstanceProcAddr(instance->vtbl, name);
519}
520
521PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
522 if (!device)
523 return GetGlobalDeviceProcAddr(name);
524 // For special-case functions we always return the loader entry
525 if (strcmp(name, "vkGetDeviceQueue") == 0 ||
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700526 strcmp(name, "vkCreateCommandBuffer") == 0 ||
Jesse Hall04f4f472015-08-16 19:51:04 -0700527 strcmp(name, "vkDestroyDevice") == 0) {
528 return GetGlobalDeviceProcAddr(name);
529 }
530 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
531}
532
533VkResult GetDeviceQueue(VkDevice drv_device,
534 uint32_t family,
535 uint32_t index,
536 VkQueue* out_queue) {
537 VkResult result;
538 VkQueue queue;
539 const DeviceVtbl* vtbl = GetVtbl(drv_device);
540 result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
541 if (result != VK_SUCCESS)
542 return result;
543 hwvulkan_dispatch_t* dispatch =
544 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
545 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
546 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
547 return VK_ERROR_INITIALIZATION_FAILED;
548 }
549 dispatch->vtbl = vtbl;
550 *out_queue = queue;
551 return VK_SUCCESS;
552}
553
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700554VkResult CreateCommandBuffer(VkDevice drv_device,
555 const VkCmdBufferCreateInfo* create_info,
556 VkCmdBuffer* out_cmdbuf) {
557 const DeviceVtbl* vtbl = GetVtbl(drv_device);
558 VkCmdBuffer cmdbuf;
559 VkResult result =
560 vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
561 if (result != VK_SUCCESS)
562 return result;
563 hwvulkan_dispatch_t* dispatch =
564 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
565 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
566 ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
567 dispatch->magic);
568 return VK_ERROR_INITIALIZATION_FAILED;
569 }
570 dispatch->vtbl = vtbl;
571 *out_cmdbuf = cmdbuf;
572 return VK_SUCCESS;
573}
574
Jesse Hall04f4f472015-08-16 19:51:04 -0700575VkResult DestroyDevice(VkDevice drv_device) {
576 const DeviceVtbl* vtbl = GetVtbl(drv_device);
577 Device* device = static_cast<Device*>(vtbl->device);
578 vtbl->DestroyDevice(drv_device);
579 DestroyDevice(device);
580 return VK_SUCCESS;
581}
582
Jesse Halld7b994a2015-09-07 14:17:37 -0700583void* AllocDeviceMem(VkDevice device,
584 size_t size,
585 size_t align,
586 VkSystemAllocType type) {
587 const VkAllocCallbacks* alloc_cb =
588 static_cast<Device*>(GetVtbl(device)->device)->alloc;
589 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
590}
591
592void FreeDeviceMem(VkDevice device, void* ptr) {
593 const VkAllocCallbacks* alloc_cb =
594 static_cast<Device*>(GetVtbl(device)->device)->alloc;
595 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
596}
597
598const DeviceVtbl& GetDriverVtbl(VkDevice device) {
599 // TODO(jessehall): This actually returns the API-level vtbl for the
600 // device, not the driver entry points. Given the current use -- getting
601 // the driver's private swapchain-related functions -- that works, but is
602 // misleading and likely to cause bugs. Fix as part of separating the
603 // loader->driver interface from the app->loader interface.
604 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
605}
606
607const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
608 // TODO(jessehall): This actually returns the API-level vtbl for the
609 // device, not the driver entry points. Given the current use -- getting
610 // the driver's private swapchain-related functions -- that works, but is
611 // misleading and likely to cause bugs. Fix as part of separating the
612 // loader->driver interface from the app->loader interface.
613 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
614}
615
Jesse Hall04f4f472015-08-16 19:51:04 -0700616} // namespace vulkan