blob: 6b223aa03f7dc3ee5e2bf559424b385075133012 [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>
37
38using namespace vulkan;
39
40static const uint32_t kMaxPhysicalDevices = 4;
41
Michael Lentine03c64b02015-08-26 18:27:26 -050042namespace {
43
44// These definitions are taken from the LunarG Vulkan Loader. They are used to
45// enforce compatability between the Loader and Layers.
46typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
47
48typedef struct VkLayerLinkedListElem_ {
49 PFN_vkGetProcAddr get_proc_addr;
50 void* next_element;
51 void* base_object;
52} VkLayerLinkedListElem;
53
54// Define Handle typedef to be void* as returned from dlopen.
55typedef void* SharedLibraryHandle;
56
57// Custom versions of std classes that use the vulkan alloc callback.
58template <class T>
59class CallbackAllocator {
60 public:
61 typedef T value_type;
62
63 CallbackAllocator(const VkAllocCallbacks* alloc_input)
64 : alloc(alloc_input) {}
65
66 template <class T2>
67 CallbackAllocator(const CallbackAllocator<T2>& other)
68 : alloc(other.alloc) {}
69
70 T* allocate(std::size_t n) {
71 void* mem = alloc->pfnAlloc(alloc->pUserData, n * sizeof(T), alignof(T),
72 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
73 return static_cast<T*>(mem);
74 }
75
76 void deallocate(T* array, std::size_t /*n*/) {
77 alloc->pfnFree(alloc->pUserData, array);
78 }
79
80 const VkAllocCallbacks* alloc;
81};
82// These are needed in order to move Strings
83template <class T>
84bool operator==(const CallbackAllocator<T>& alloc1,
85 const CallbackAllocator<T>& alloc2) {
86 return alloc1.alloc == alloc2.alloc;
87}
88template <class T>
89bool operator!=(const CallbackAllocator<T>& alloc1,
90 const CallbackAllocator<T>& alloc2) {
91 return !(alloc1 == alloc2);
92}
93
94template <class Key,
95 class T,
96 class Hash = std::hash<Key>,
97 class Pred = std::equal_to<Key> >
98using UnorderedMap =
99 std::unordered_map<Key,
100 T,
101 Hash,
102 Pred,
103 CallbackAllocator<std::pair<const Key, T> > >;
104
105template <class T>
106using Vector = std::vector<T, CallbackAllocator<T> >;
107
108typedef std::basic_string<char,
109 std::char_traits<char>,
110 CallbackAllocator<char> > String;
111
112} // namespace
113
114// -----------------------------------------------------------------------------
115
Jesse Hall04f4f472015-08-16 19:51:04 -0700116struct VkInstance_T {
117 VkInstance_T(const VkAllocCallbacks* alloc_callbacks)
Michael Lentine03c64b02015-08-26 18:27:26 -0500118 : vtbl(&vtbl_storage),
119 alloc(alloc_callbacks),
120 num_physical_devices(0),
121 layer_handles(CallbackAllocator<SharedLibraryHandle>(alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700122 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
123 memset(physical_devices, 0, sizeof(physical_devices));
124 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
125 drv.GetDeviceProcAddr = nullptr;
126 drv.num_physical_devices = 0;
127 }
128
129 InstanceVtbl* vtbl;
130 InstanceVtbl vtbl_storage;
131
132 const VkAllocCallbacks* alloc;
133 uint32_t num_physical_devices;
134 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
135
Michael Lentine03c64b02015-08-26 18:27:26 -0500136 Vector<SharedLibraryHandle> layer_handles;
137
Jesse Hall04f4f472015-08-16 19:51:04 -0700138 struct Driver {
139 // Pointers to driver entry points. Used explicitly by the loader; not
140 // set as the dispatch table for any objects.
141 InstanceVtbl vtbl;
142
143 // Pointer to the driver's get_device_proc_addr, must be valid for any
144 // of the driver's physical devices. Not part of the InstanceVtbl since
145 // it's not an Instance/PhysicalDevice function.
146 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
147
148 // Number of physical devices owned by this driver.
149 uint32_t num_physical_devices;
150 } drv; // may eventually be an array
151};
152
153// -----------------------------------------------------------------------------
154
155namespace {
156
157typedef VkInstance_T Instance;
158
159struct Device {
160 Device(const VkAllocCallbacks* alloc_callbacks) : alloc(alloc_callbacks) {
161 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
162 vtbl_storage.device = this;
163 }
164 DeviceVtbl vtbl_storage;
165 const VkAllocCallbacks* alloc;
Michael Lentine03c64b02015-08-26 18:27:26 -0500166 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700167};
168
169// -----------------------------------------------------------------------------
170// Utility Code
171
172inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
173 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
174}
175
176inline const DeviceVtbl* GetVtbl(VkDevice device) {
177 return *reinterpret_cast<DeviceVtbl**>(device);
178}
Jesse Halld7b994a2015-09-07 14:17:37 -0700179inline const DeviceVtbl* GetVtbl(VkQueue queue) {
180 return *reinterpret_cast<DeviceVtbl**>(queue);
181}
Jesse Hall04f4f472015-08-16 19:51:04 -0700182
183void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
184 return memalign(alignment, size);
185}
186
187void DefaultFree(void*, void* pMem) {
188 free(pMem);
189}
190
191const VkAllocCallbacks kDefaultAllocCallbacks = {
192 .pUserData = nullptr,
193 .pfnAlloc = DefaultAlloc,
194 .pfnFree = DefaultFree,
195};
196
197hwvulkan_device_t* g_hwdevice;
198bool EnsureInitialized() {
199 static std::once_flag once_flag;
200 static const hwvulkan_module_t* module;
201
202 std::call_once(once_flag, []() {
203 int result;
204 result = hw_get_module("vulkan",
205 reinterpret_cast<const hw_module_t**>(&module));
206 if (result != 0) {
207 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
208 result);
209 return;
210 }
211 result = module->common.methods->open(
212 &module->common, HWVULKAN_DEVICE_0,
213 reinterpret_cast<hw_device_t**>(&g_hwdevice));
214 if (result != 0) {
215 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
216 result);
217 module = nullptr;
218 return;
219 }
220 });
221
222 return module != nullptr && g_hwdevice != nullptr;
223}
224
225void DestroyDevice(Device* device) {
226 const VkAllocCallbacks* alloc = device->alloc;
227 device->~Device();
228 alloc->pfnFree(alloc->pUserData, device);
229}
230
Michael Lentine03c64b02015-08-26 18:27:26 -0500231void FindLayersInDirectory(
232 Instance& instance,
233 UnorderedMap<String, SharedLibraryHandle>& layer_name_to_handle_map,
234 const String& dir_name) {
235 DIR* directory;
236 struct dirent* entry;
237 if ((directory = opendir(dir_name.c_str()))) {
238 Vector<VkLayerProperties> properties(
239 CallbackAllocator<VkLayerProperties>(instance.alloc));
240 while ((entry = readdir(directory))) {
241 size_t length = strlen(entry->d_name);
242 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
243 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
244 continue;
245 // Open so
246 SharedLibraryHandle layer_handle = dlopen(
247 (dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
248 if (!layer_handle) {
249 ALOGE("%s failed to load with error %s; Skipping",
250 entry->d_name, dlerror());
251 continue;
252 }
253
254 // Get Layers in so
255 PFN_vkGetGlobalLayerProperties get_layer_properties =
256 reinterpret_cast<PFN_vkGetGlobalLayerProperties>(
257 dlsym(layer_handle, "vkGetGlobalLayerProperties"));
258 if (!get_layer_properties) {
259 ALOGE(
260 "%s failed to find vkGetGlobalLayerProperties with "
261 "error %s; Skipping",
262 entry->d_name, dlerror());
263 dlclose(layer_handle);
264 continue;
265 }
266 uint32_t count;
267 get_layer_properties(&count, nullptr);
268
269 properties.resize(count);
270 get_layer_properties(&count, &properties[0]);
271
272 // Add Layers to potential list
273 // TODO: Add support for multiple layers in 1 so.
274 ALOGW_IF(count > 1,
275 "More than 1 layer per library file is not currently "
276 "supported.");
277 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());
296 instance->layer_handles.push_back(layer_handle);
297}
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
Jesse Hall04f4f472015-08-16 19:51:04 -0700318// -----------------------------------------------------------------------------
319// "Bottom" functions. These are called at the end of the instance dispatch
320// chain.
321
322VkResult DestroyInstanceBottom(VkInstance instance) {
323 // These checks allow us to call DestroyInstanceBottom from any error path
324 // in CreateInstanceBottom, before the driver instance is fully initialized.
325 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
326 instance->drv.vtbl.DestroyInstance) {
327 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
328 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500329 for (auto layer_handle : instance->layer_handles) {
330 dlclose(layer_handle);
331 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700332 const VkAllocCallbacks* alloc = instance->alloc;
333 instance->~VkInstance_T();
334 alloc->pfnFree(alloc->pUserData, instance);
335 return VK_SUCCESS;
336}
337
338VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
339 VkInstance* instance_ptr) {
340 Instance* instance = *instance_ptr;
341 VkResult result;
342
343 result =
344 g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
345 if (result != VK_SUCCESS) {
346 DestroyInstanceBottom(instance);
347 return result;
348 }
349
Michael Lentine03c64b02015-08-26 18:27:26 -0500350 if (!LoadInstanceVtbl(
351 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
352 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700353 DestroyInstanceBottom(instance);
354 return VK_ERROR_INITIALIZATION_FAILED;
355 }
356
357 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
358 // queryable from the Instance, and that the resulting function work for any
359 // VkDevice created from the instance.
360 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
361 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
362 "vkGetDeviceProcAddr"));
363 if (!instance->drv.GetDeviceProcAddr) {
364 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
365 DestroyInstanceBottom(instance);
366 return VK_ERROR_INITIALIZATION_FAILED;
367 }
368
369 hwvulkan_dispatch_t* dispatch =
370 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
371 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
372 // Skip setting dispatch->vtbl on the driver instance handle, since we
373 // never intentionally call through it; we go through Instance::drv.vtbl
374 // instead.
375 } else {
376 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
377 dispatch->magic);
378 DestroyInstanceBottom(instance);
379 return VK_ERROR_INITIALIZATION_FAILED;
380 }
381
382 uint32_t num_physical_devices = 0;
383 result = instance->drv.vtbl.EnumeratePhysicalDevices(
384 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
385 if (result != VK_SUCCESS) {
386 DestroyInstanceBottom(instance);
387 return VK_ERROR_INITIALIZATION_FAILED;
388 }
389 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
390 result = instance->drv.vtbl.EnumeratePhysicalDevices(
391 instance->drv.vtbl.instance, &num_physical_devices,
392 instance->physical_devices);
393 if (result != VK_SUCCESS) {
394 DestroyInstanceBottom(instance);
395 return VK_ERROR_INITIALIZATION_FAILED;
396 }
397 for (uint32_t i = 0; i < num_physical_devices; i++) {
398 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
399 instance->physical_devices[i]);
400 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
401 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
402 dispatch->magic);
403 DestroyInstanceBottom(instance);
404 return VK_ERROR_INITIALIZATION_FAILED;
405 }
406 dispatch->vtbl = instance->vtbl;
407 }
408 instance->drv.num_physical_devices = num_physical_devices;
409
410 instance->num_physical_devices = instance->drv.num_physical_devices;
411 return VK_SUCCESS;
412}
413
414VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
415 uint32_t* pdev_count,
416 VkPhysicalDevice* pdevs) {
417 uint32_t count = instance->num_physical_devices;
418 if (pdevs) {
419 count = std::min(count, *pdev_count);
420 std::copy(instance->physical_devices,
421 instance->physical_devices + count, pdevs);
422 }
423 *pdev_count = count;
424 return VK_SUCCESS;
425}
426
427VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
428 VkPhysicalDeviceFeatures* features) {
429 return GetVtbl(pdev)
430 ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
431}
432
433VkResult GetPhysicalDeviceFormatPropertiesBottom(
434 VkPhysicalDevice pdev,
435 VkFormat format,
436 VkFormatProperties* properties) {
437 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
438 pdev, format, properties);
439}
440
441VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
442 VkPhysicalDevice pdev,
443 VkFormat format,
444 VkImageType type,
445 VkImageTiling tiling,
446 VkImageUsageFlags usage,
447 VkImageFormatProperties* properties) {
448 return GetVtbl(pdev)
449 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
450 pdev, format, type, tiling, usage, properties);
451}
452
453VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
454 VkPhysicalDeviceLimits* limits) {
455 return GetVtbl(pdev)
456 ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
457}
458
459VkResult GetPhysicalDevicePropertiesBottom(
460 VkPhysicalDevice pdev,
461 VkPhysicalDeviceProperties* properties) {
462 return GetVtbl(pdev)
463 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
464}
465
466VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
467 uint32_t* count) {
468 return GetVtbl(pdev)
469 ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
470}
471
472VkResult GetPhysicalDeviceQueuePropertiesBottom(
473 VkPhysicalDevice pdev,
474 uint32_t count,
475 VkPhysicalDeviceQueueProperties* properties) {
476 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
477 pdev, count, properties);
478}
479
480VkResult GetPhysicalDeviceMemoryPropertiesBottom(
481 VkPhysicalDevice pdev,
482 VkPhysicalDeviceMemoryProperties* properties) {
483 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
484 pdev, properties);
485}
486
487VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
488 const VkDeviceCreateInfo* create_info,
489 VkDevice* out_device) {
490 const Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
491 VkResult result;
492
493 void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
494 sizeof(Device), alignof(Device),
495 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
496 if (!mem)
497 return VK_ERROR_OUT_OF_HOST_MEMORY;
498 Device* device = new (mem) Device(instance.alloc);
Michael Lentine03c64b02015-08-26 18:27:26 -0500499 device->GetDeviceProcAddr = instance.drv.GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700500
501 VkDevice drv_device;
502 result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
503 if (result != VK_SUCCESS) {
504 DestroyDevice(device);
505 return result;
506 }
507
Jesse Hall04f4f472015-08-16 19:51:04 -0700508 hwvulkan_dispatch_t* dispatch =
509 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
510 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
511 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500512 PFN_vkDestroyDevice destroy_device =
513 reinterpret_cast<PFN_vkDestroyDevice>(
514 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
515 destroy_device(drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700516 DestroyDevice(device);
517 return VK_ERROR_INITIALIZATION_FAILED;
518 }
519 dispatch->vtbl = &device->vtbl_storage;
520
Jesse Hallb1352bc2015-09-04 16:12:33 -0700521 device->vtbl_storage.GetSurfacePropertiesKHR = GetSurfacePropertiesKHR;
522 device->vtbl_storage.GetSurfaceFormatsKHR = GetSurfaceFormatsKHR;
523 device->vtbl_storage.GetSurfacePresentModesKHR = GetSurfacePresentModesKHR;
524 device->vtbl_storage.CreateSwapchainKHR = CreateSwapchainKHR;
525 device->vtbl_storage.DestroySwapchainKHR = DestroySwapchainKHR;
526 device->vtbl_storage.GetSwapchainImagesKHR = GetSwapchainImagesKHR;
527 device->vtbl_storage.AcquireNextImageKHR = AcquireNextImageKHR;
528 device->vtbl_storage.QueuePresentKHR = QueuePresentKHR;
529
Michael Lentine03c64b02015-08-26 18:27:26 -0500530 void* base_object = static_cast<void*>(drv_device);
531 void* next_object = base_object;
532 VkLayerLinkedListElem* next_element;
533 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
534 Vector<VkLayerLinkedListElem> elem_list(
535 instance.layer_handles.size(),
536 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
537
538 for (size_t i = elem_list.size(); i > 0; i--) {
539 size_t idx = i - 1;
540 next_element = &elem_list[idx];
541 next_element->get_proc_addr =
542 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
543 next_element->base_object = base_object;
544 next_element->next_element = next_object;
545 next_object = static_cast<void*>(next_element);
546
547 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
548 dlsym(instance.layer_handles[idx], "vkGetDeviceProcAddr"));
549 if (!next_get_proc_addr) {
550 ALOGE("Cannot find vkGetDeviceProcAddr, error is %s", dlerror());
551 next_object = next_element->next_element;
552 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
553 next_element->get_proc_addr);
554 }
555 }
556
557 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
558 static_cast<VkDevice>(next_object), next_get_proc_addr,
559 device->vtbl_storage)) {
560 DestroyDevice(device);
561 return VK_ERROR_INITIALIZATION_FAILED;
562 }
563
564 PFN_vkCreateDevice layer_createDevice =
565 reinterpret_cast<PFN_vkCreateDevice>(
566 device->vtbl_storage.GetDeviceProcAddr(drv_device,
567 "vkCreateDevice"));
568 layer_createDevice(pdev, create_info, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700569
570 *out_device = drv_device;
571 return VK_SUCCESS;
572}
573
574VkResult GetPhysicalDeviceExtensionPropertiesBottom(
575 VkPhysicalDevice pdev,
576 const char* layer_name,
577 uint32_t* properties_count,
578 VkExtensionProperties* properties) {
579 // TODO: what are we supposed to do with layer_name here?
580 return GetVtbl(pdev)
581 ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
582 pdev, layer_name, properties_count, properties);
583}
584
585VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
586 uint32_t* properties_count,
587 VkLayerProperties* properties) {
588 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
589 pdev, properties_count, properties);
590}
591
592VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
593 VkPhysicalDevice pdev,
594 VkFormat format,
595 VkImageType type,
596 uint32_t samples,
597 VkImageUsageFlags usage,
598 VkImageTiling tiling,
599 uint32_t* properties_count,
600 VkSparseImageFormatProperties* properties) {
601 return GetVtbl(pdev)
602 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
603 pdev, format, type, samples, usage, tiling, properties_count,
604 properties);
605}
606
607PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
608
609const InstanceVtbl kBottomInstanceFunctions = {
610 // clang-format off
611 .instance = nullptr,
612 .CreateInstance = CreateInstanceBottom,
613 .DestroyInstance = DestroyInstanceBottom,
614 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
615 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
616 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
617 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
618 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
619 .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
620 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
621 .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
622 .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
623 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
624 .CreateDevice = CreateDeviceBottom,
625 .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
626 .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
627 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700628 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700629 // clang-format on
630};
631
Michael Lentine03c64b02015-08-26 18:27:26 -0500632VkResult Noop(...) {
633 return VK_SUCCESS;
634}
635
Jesse Hall04f4f472015-08-16 19:51:04 -0700636PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500637 // TODO: Possibly move this into the instance table
638 // TODO: Possibly register the callbacks in the loader
639 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
640 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
641 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
642 }
643 if (strcmp(name, "vkCreateInstance") == 0) {
644 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
645 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700646 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
647}
648
649} // namespace
650
651// -----------------------------------------------------------------------------
652// Global functions. These are called directly from the loader entry points,
653// without going through a dispatch table.
654
655namespace vulkan {
656
657VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
658 uint32_t* count,
659 VkExtensionProperties* /*properties*/) {
660 if (!count)
661 return VK_ERROR_INVALID_POINTER;
662 if (!EnsureInitialized())
663 return VK_ERROR_UNAVAILABLE;
664
665 // TODO: not yet implemented
666 ALOGW("vkGetGlobalExtensionProperties not implemented");
667
668 *count = 0;
669 return VK_SUCCESS;
670}
671
672VkResult GetGlobalLayerProperties(uint32_t* count,
673 VkLayerProperties* /*properties*/) {
674 if (!count)
675 return VK_ERROR_INVALID_POINTER;
676 if (!EnsureInitialized())
677 return VK_ERROR_UNAVAILABLE;
678
679 // TODO: not yet implemented
680 ALOGW("vkGetGlobalLayerProperties not implemented");
681
682 *count = 0;
683 return VK_SUCCESS;
684}
685
686VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
687 VkInstance* out_instance) {
688 VkResult result;
689
690 if (!EnsureInitialized())
691 return VK_ERROR_UNAVAILABLE;
692
693 VkInstanceCreateInfo local_create_info = *create_info;
694 if (!local_create_info.pAllocCb)
695 local_create_info.pAllocCb = &kDefaultAllocCallbacks;
696 create_info = &local_create_info;
697
698 void* instance_mem = create_info->pAllocCb->pfnAlloc(
699 create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
700 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
701 if (!instance_mem)
702 return VK_ERROR_OUT_OF_HOST_MEMORY;
703 Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
704
705 instance->vtbl_storage = kBottomInstanceFunctions;
706 instance->vtbl_storage.instance = instance;
707
Michael Lentine03c64b02015-08-26 18:27:26 -0500708 // Scan layers
709 // TODO: Add more directories to scan
710 UnorderedMap<String, SharedLibraryHandle> layers(
711 CallbackAllocator<std::pair<String, SharedLibraryHandle> >(
712 instance->alloc));
713 CallbackAllocator<char> string_allocator(instance->alloc);
714 String dir_name("/data/local/tmp/vulkan/", string_allocator);
715 FindLayersInDirectory(*instance, layers, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700716
Michael Lentine03c64b02015-08-26 18:27:26 -0500717 // TODO: Add auto enabling of the layer extension
718
719 {
720 char layer_prop[PROPERTY_VALUE_MAX];
721 property_get("vulkan.layers", layer_prop, "");
722 // TODO: Find a way to enable a large number but not all of the layers
723 size_t length = strlen(layer_prop);
724 if (length == 1 && layer_prop[0] == '+') {
725 for (auto& layer : layers) {
726 LoadLayer(instance, layer.first, layer.second);
727 }
728 } else {
729 String layer_name(string_allocator);
730 String layer_prop_str(layer_prop, string_allocator);
731 size_t end, start = 0;
732 while ((end = layer_prop_str.find(':', start)) !=
733 std::string::npos) {
734 layer_name = layer_prop_str.substr(start, end - start);
735 auto element = layers.find(layer_name);
736 if (element != layers.end()) {
737 LoadLayer(instance, layer_name, element->second);
738 layers.erase(element);
739 }
740 start = end + 1;
741 }
742 }
743 }
744
745 for (uint32_t i = 0; i < create_info->layerCount; ++i) {
746 String layer_name(create_info->ppEnabledLayerNames[i],
747 string_allocator);
748 auto element = layers.find(layer_name);
749 if (element != layers.end()) {
750 LoadLayer(instance, layer_name, element->second);
751 layers.erase(element);
752 }
753 }
754
755 for (auto& layer : layers) {
756 dlclose(layer.second);
757 }
758
759 void* base_object = static_cast<void*>(instance);
760 void* next_object = base_object;
761 VkLayerLinkedListElem* next_element;
762 PFN_vkGetInstanceProcAddr next_get_proc_addr =
763 kBottomInstanceFunctions.GetInstanceProcAddr;
764 Vector<VkLayerLinkedListElem> elem_list(
765 instance->layer_handles.size(),
766 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
767
768 for (size_t i = elem_list.size(); i > 0; i--) {
769 size_t idx = i - 1;
770 next_element = &elem_list[idx];
771 next_element->get_proc_addr =
772 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
773 next_element->base_object = base_object;
774 next_element->next_element = next_object;
775 next_object = static_cast<void*>(next_element);
776
777 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
778 dlsym(instance->layer_handles[idx], "vkGetInstanceProcAddr"));
779 if (!next_get_proc_addr) {
780 ALOGE("Cannot find vkGetInstanceProcAddr for, error is %s",
781 dlerror());
782 next_object = next_element->next_element;
783 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
784 next_element->get_proc_addr);
785 }
786 }
787
788 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
789 static_cast<VkInstance>(next_object),
790 next_get_proc_addr, instance->vtbl_storage)) {
791 DestroyInstanceBottom(instance);
792 return VK_ERROR_INITIALIZATION_FAILED;
793 }
794
Jesse Hall04f4f472015-08-16 19:51:04 -0700795 *out_instance = instance;
Michael Lentine03c64b02015-08-26 18:27:26 -0500796 result = instance->vtbl_storage.CreateInstance(create_info, out_instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700797 if (result <= 0) {
798 // For every layer, including the loader top and bottom layers:
799 // - If a call to the next CreateInstance fails, the layer must clean
800 // up anything it has successfully done so far, and propagate the
801 // error upwards.
802 // - If a layer successfully calls the next layer's CreateInstance, and
803 // afterwards must fail for some reason, it must call the next layer's
804 // DestroyInstance before returning.
805 // - The layer must not call the next layer's DestroyInstance if that
806 // layer's CreateInstance wasn't called, or returned failure.
807
808 // On failure, CreateInstanceBottom frees the instance struct, so it's
809 // already gone at this point. Nothing to do.
810 }
811
812 return result;
813}
814
815PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
816 if (!instance)
817 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500818 // TODO: Possibly move this into the instance table
819 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
820 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
821 if (!instance->vtbl)
822 return NULL;
823 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
824 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
825 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700826 // For special-case functions we always return the loader entry
827 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
828 strcmp(name, "vkGetDeviceProcAddr") == 0) {
829 return GetGlobalInstanceProcAddr(name);
830 }
831 return GetSpecificInstanceProcAddr(instance->vtbl, name);
832}
833
834PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
835 if (!device)
836 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500837 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
838 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
839 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700840 // For special-case functions we always return the loader entry
841 if (strcmp(name, "vkGetDeviceQueue") == 0 ||
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700842 strcmp(name, "vkCreateCommandBuffer") == 0 ||
Jesse Hall04f4f472015-08-16 19:51:04 -0700843 strcmp(name, "vkDestroyDevice") == 0) {
844 return GetGlobalDeviceProcAddr(name);
845 }
846 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
847}
848
849VkResult GetDeviceQueue(VkDevice drv_device,
850 uint32_t family,
851 uint32_t index,
852 VkQueue* out_queue) {
853 VkResult result;
854 VkQueue queue;
855 const DeviceVtbl* vtbl = GetVtbl(drv_device);
856 result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
857 if (result != VK_SUCCESS)
858 return result;
859 hwvulkan_dispatch_t* dispatch =
860 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
861 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
862 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
863 return VK_ERROR_INITIALIZATION_FAILED;
864 }
865 dispatch->vtbl = vtbl;
866 *out_queue = queue;
867 return VK_SUCCESS;
868}
869
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700870VkResult CreateCommandBuffer(VkDevice drv_device,
871 const VkCmdBufferCreateInfo* create_info,
872 VkCmdBuffer* out_cmdbuf) {
873 const DeviceVtbl* vtbl = GetVtbl(drv_device);
874 VkCmdBuffer cmdbuf;
875 VkResult result =
876 vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
877 if (result != VK_SUCCESS)
878 return result;
879 hwvulkan_dispatch_t* dispatch =
880 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
881 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
882 ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
883 dispatch->magic);
884 return VK_ERROR_INITIALIZATION_FAILED;
885 }
886 dispatch->vtbl = vtbl;
887 *out_cmdbuf = cmdbuf;
888 return VK_SUCCESS;
889}
890
Jesse Hall04f4f472015-08-16 19:51:04 -0700891VkResult DestroyDevice(VkDevice drv_device) {
892 const DeviceVtbl* vtbl = GetVtbl(drv_device);
893 Device* device = static_cast<Device*>(vtbl->device);
894 vtbl->DestroyDevice(drv_device);
895 DestroyDevice(device);
896 return VK_SUCCESS;
897}
898
Jesse Halld7b994a2015-09-07 14:17:37 -0700899void* AllocDeviceMem(VkDevice device,
900 size_t size,
901 size_t align,
902 VkSystemAllocType type) {
903 const VkAllocCallbacks* alloc_cb =
904 static_cast<Device*>(GetVtbl(device)->device)->alloc;
905 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
906}
907
908void FreeDeviceMem(VkDevice device, void* ptr) {
909 const VkAllocCallbacks* alloc_cb =
910 static_cast<Device*>(GetVtbl(device)->device)->alloc;
911 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
912}
913
914const DeviceVtbl& GetDriverVtbl(VkDevice device) {
915 // TODO(jessehall): This actually returns the API-level vtbl for the
916 // device, not the driver entry points. Given the current use -- getting
917 // the driver's private swapchain-related functions -- that works, but is
918 // misleading and likely to cause bugs. Fix as part of separating the
919 // loader->driver interface from the app->loader interface.
920 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
921}
922
923const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
924 // TODO(jessehall): This actually returns the API-level vtbl for the
925 // device, not the driver entry points. Given the current use -- getting
926 // the driver's private swapchain-related functions -- that works, but is
927 // misleading and likely to cause bugs. Fix as part of separating the
928 // loader->driver interface from the app->loader interface.
929 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
930}
931
Jesse Hall04f4f472015-08-16 19:51:04 -0700932} // namespace vulkan