blob: 9e9b00a6666df6dbe770c20b6e1e85ba39ff688d [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),
Michael Lentine1f0f5392015-09-11 14:54:34 -0700121 active_layers(
122 CallbackAllocator<std::pair<String, SharedLibraryHandle> >(
123 alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700124 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
125 memset(physical_devices, 0, sizeof(physical_devices));
126 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
127 drv.GetDeviceProcAddr = nullptr;
128 drv.num_physical_devices = 0;
129 }
130
131 InstanceVtbl* vtbl;
132 InstanceVtbl vtbl_storage;
133
134 const VkAllocCallbacks* alloc;
135 uint32_t num_physical_devices;
136 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
137
Michael Lentine1f0f5392015-09-11 14:54:34 -0700138 Vector<std::pair<String, SharedLibraryHandle> > active_layers;
Michael Lentine03c64b02015-08-26 18:27:26 -0500139
Jesse Hall04f4f472015-08-16 19:51:04 -0700140 struct Driver {
141 // Pointers to driver entry points. Used explicitly by the loader; not
142 // set as the dispatch table for any objects.
143 InstanceVtbl vtbl;
144
145 // Pointer to the driver's get_device_proc_addr, must be valid for any
146 // of the driver's physical devices. Not part of the InstanceVtbl since
147 // it's not an Instance/PhysicalDevice function.
148 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
149
150 // Number of physical devices owned by this driver.
151 uint32_t num_physical_devices;
152 } drv; // may eventually be an array
153};
154
155// -----------------------------------------------------------------------------
156
157namespace {
158
159typedef VkInstance_T Instance;
160
161struct Device {
162 Device(const VkAllocCallbacks* alloc_callbacks) : alloc(alloc_callbacks) {
163 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
164 vtbl_storage.device = this;
165 }
166 DeviceVtbl vtbl_storage;
167 const VkAllocCallbacks* alloc;
Michael Lentine03c64b02015-08-26 18:27:26 -0500168 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700169};
170
171// -----------------------------------------------------------------------------
172// Utility Code
173
174inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
175 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
176}
177
178inline const DeviceVtbl* GetVtbl(VkDevice device) {
179 return *reinterpret_cast<DeviceVtbl**>(device);
180}
Jesse Halld7b994a2015-09-07 14:17:37 -0700181inline const DeviceVtbl* GetVtbl(VkQueue queue) {
182 return *reinterpret_cast<DeviceVtbl**>(queue);
183}
Jesse Hall04f4f472015-08-16 19:51:04 -0700184
185void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
186 return memalign(alignment, size);
187}
188
189void DefaultFree(void*, void* pMem) {
190 free(pMem);
191}
192
193const VkAllocCallbacks kDefaultAllocCallbacks = {
194 .pUserData = nullptr,
195 .pfnAlloc = DefaultAlloc,
196 .pfnFree = DefaultFree,
197};
198
199hwvulkan_device_t* g_hwdevice;
200bool EnsureInitialized() {
201 static std::once_flag once_flag;
202 static const hwvulkan_module_t* module;
203
204 std::call_once(once_flag, []() {
205 int result;
206 result = hw_get_module("vulkan",
207 reinterpret_cast<const hw_module_t**>(&module));
208 if (result != 0) {
209 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
210 result);
211 return;
212 }
213 result = module->common.methods->open(
214 &module->common, HWVULKAN_DEVICE_0,
215 reinterpret_cast<hw_device_t**>(&g_hwdevice));
216 if (result != 0) {
217 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
218 result);
219 module = nullptr;
220 return;
221 }
222 });
223
224 return module != nullptr && g_hwdevice != nullptr;
225}
226
227void DestroyDevice(Device* device) {
228 const VkAllocCallbacks* alloc = device->alloc;
229 device->~Device();
230 alloc->pfnFree(alloc->pUserData, device);
231}
232
Michael Lentine03c64b02015-08-26 18:27:26 -0500233void FindLayersInDirectory(
234 Instance& instance,
235 UnorderedMap<String, SharedLibraryHandle>& layer_name_to_handle_map,
236 const String& dir_name) {
237 DIR* directory;
238 struct dirent* entry;
239 if ((directory = opendir(dir_name.c_str()))) {
240 Vector<VkLayerProperties> properties(
241 CallbackAllocator<VkLayerProperties>(instance.alloc));
242 while ((entry = readdir(directory))) {
243 size_t length = strlen(entry->d_name);
244 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
245 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
246 continue;
247 // Open so
248 SharedLibraryHandle layer_handle = dlopen(
249 (dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
250 if (!layer_handle) {
251 ALOGE("%s failed to load with error %s; Skipping",
252 entry->d_name, dlerror());
253 continue;
254 }
255
256 // Get Layers in so
257 PFN_vkGetGlobalLayerProperties get_layer_properties =
258 reinterpret_cast<PFN_vkGetGlobalLayerProperties>(
259 dlsym(layer_handle, "vkGetGlobalLayerProperties"));
260 if (!get_layer_properties) {
261 ALOGE(
262 "%s failed to find vkGetGlobalLayerProperties with "
263 "error %s; Skipping",
264 entry->d_name, dlerror());
265 dlclose(layer_handle);
266 continue;
267 }
268 uint32_t count;
269 get_layer_properties(&count, nullptr);
270
271 properties.resize(count);
272 get_layer_properties(&count, &properties[0]);
273
274 // Add Layers to potential list
Michael Lentine03c64b02015-08-26 18:27:26 -0500275 for (uint32_t i = 0; i < count; ++i) {
276 layer_name_to_handle_map.insert(std::make_pair(
277 String(properties[i].layerName,
278 CallbackAllocator<char>(instance.alloc)),
279 layer_handle));
280 ALOGV("Found layer %s", properties[i].layerName);
281 }
282 }
283 closedir(directory);
284 } else {
285 ALOGE("Failed to Open Directory %s: %s (%d)", dir_name.c_str(),
286 strerror(errno), errno);
287 }
288}
289
290void LoadLayer(Instance* instance,
291 const String& name,
292 SharedLibraryHandle& layer_handle) {
293 ALOGV("Loading layer %s", name.c_str());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700294 instance->active_layers.push_back(std::make_pair(name, layer_handle));
Michael Lentine03c64b02015-08-26 18:27:26 -0500295}
296
297VkResult CreateDeviceNoop(VkPhysicalDevice,
298 const VkDeviceCreateInfo*,
299 VkDevice*) {
300 return VK_SUCCESS;
301}
302
303PFN_vkVoidFunction GetLayerDeviceProcAddr(VkDevice device, const char* name) {
304 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
305 return reinterpret_cast<PFN_vkVoidFunction>(GetLayerDeviceProcAddr);
306 }
307 if (strcmp(name, "vkCreateDevice") == 0) {
308 return reinterpret_cast<PFN_vkVoidFunction>(CreateDeviceNoop);
309 }
310 if (!device)
311 return GetGlobalDeviceProcAddr(name);
312 Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
313 return loader_device->GetDeviceProcAddr(device, name);
314}
315
Jesse Hall04f4f472015-08-16 19:51:04 -0700316// -----------------------------------------------------------------------------
317// "Bottom" functions. These are called at the end of the instance dispatch
318// chain.
319
320VkResult DestroyInstanceBottom(VkInstance instance) {
321 // These checks allow us to call DestroyInstanceBottom from any error path
322 // in CreateInstanceBottom, before the driver instance is fully initialized.
323 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
324 instance->drv.vtbl.DestroyInstance) {
325 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
326 }
Michael Lentine1f0f5392015-09-11 14:54:34 -0700327 for (auto& layer : instance->active_layers) {
328 dlclose(layer.second);
Michael Lentine03c64b02015-08-26 18:27:26 -0500329 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700330 const VkAllocCallbacks* alloc = instance->alloc;
331 instance->~VkInstance_T();
332 alloc->pfnFree(alloc->pUserData, instance);
333 return VK_SUCCESS;
334}
335
336VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
337 VkInstance* instance_ptr) {
338 Instance* instance = *instance_ptr;
339 VkResult result;
340
341 result =
342 g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
343 if (result != VK_SUCCESS) {
344 DestroyInstanceBottom(instance);
345 return result;
346 }
347
Michael Lentine03c64b02015-08-26 18:27:26 -0500348 if (!LoadInstanceVtbl(
349 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
350 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700351 DestroyInstanceBottom(instance);
352 return VK_ERROR_INITIALIZATION_FAILED;
353 }
354
355 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
356 // queryable from the Instance, and that the resulting function work for any
357 // VkDevice created from the instance.
358 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
359 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
360 "vkGetDeviceProcAddr"));
361 if (!instance->drv.GetDeviceProcAddr) {
362 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
363 DestroyInstanceBottom(instance);
364 return VK_ERROR_INITIALIZATION_FAILED;
365 }
366
367 hwvulkan_dispatch_t* dispatch =
368 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
369 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
370 // Skip setting dispatch->vtbl on the driver instance handle, since we
371 // never intentionally call through it; we go through Instance::drv.vtbl
372 // instead.
373 } else {
374 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
375 dispatch->magic);
376 DestroyInstanceBottom(instance);
377 return VK_ERROR_INITIALIZATION_FAILED;
378 }
379
380 uint32_t num_physical_devices = 0;
381 result = instance->drv.vtbl.EnumeratePhysicalDevices(
382 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
383 if (result != VK_SUCCESS) {
384 DestroyInstanceBottom(instance);
385 return VK_ERROR_INITIALIZATION_FAILED;
386 }
387 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
388 result = instance->drv.vtbl.EnumeratePhysicalDevices(
389 instance->drv.vtbl.instance, &num_physical_devices,
390 instance->physical_devices);
391 if (result != VK_SUCCESS) {
392 DestroyInstanceBottom(instance);
393 return VK_ERROR_INITIALIZATION_FAILED;
394 }
395 for (uint32_t i = 0; i < num_physical_devices; i++) {
396 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
397 instance->physical_devices[i]);
398 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
399 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
400 dispatch->magic);
401 DestroyInstanceBottom(instance);
402 return VK_ERROR_INITIALIZATION_FAILED;
403 }
404 dispatch->vtbl = instance->vtbl;
405 }
406 instance->drv.num_physical_devices = num_physical_devices;
407
408 instance->num_physical_devices = instance->drv.num_physical_devices;
409 return VK_SUCCESS;
410}
411
412VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
413 uint32_t* pdev_count,
414 VkPhysicalDevice* pdevs) {
415 uint32_t count = instance->num_physical_devices;
416 if (pdevs) {
417 count = std::min(count, *pdev_count);
418 std::copy(instance->physical_devices,
419 instance->physical_devices + count, pdevs);
420 }
421 *pdev_count = count;
422 return VK_SUCCESS;
423}
424
425VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
426 VkPhysicalDeviceFeatures* features) {
427 return GetVtbl(pdev)
428 ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
429}
430
431VkResult GetPhysicalDeviceFormatPropertiesBottom(
432 VkPhysicalDevice pdev,
433 VkFormat format,
434 VkFormatProperties* properties) {
435 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
436 pdev, format, properties);
437}
438
439VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
440 VkPhysicalDevice pdev,
441 VkFormat format,
442 VkImageType type,
443 VkImageTiling tiling,
444 VkImageUsageFlags usage,
445 VkImageFormatProperties* properties) {
446 return GetVtbl(pdev)
447 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
448 pdev, format, type, tiling, usage, properties);
449}
450
451VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
452 VkPhysicalDeviceLimits* limits) {
453 return GetVtbl(pdev)
454 ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
455}
456
457VkResult GetPhysicalDevicePropertiesBottom(
458 VkPhysicalDevice pdev,
459 VkPhysicalDeviceProperties* properties) {
460 return GetVtbl(pdev)
461 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
462}
463
464VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
465 uint32_t* count) {
466 return GetVtbl(pdev)
467 ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
468}
469
470VkResult GetPhysicalDeviceQueuePropertiesBottom(
471 VkPhysicalDevice pdev,
472 uint32_t count,
473 VkPhysicalDeviceQueueProperties* properties) {
474 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
475 pdev, count, properties);
476}
477
478VkResult GetPhysicalDeviceMemoryPropertiesBottom(
479 VkPhysicalDevice pdev,
480 VkPhysicalDeviceMemoryProperties* properties) {
481 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
482 pdev, properties);
483}
484
485VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
486 const VkDeviceCreateInfo* create_info,
487 VkDevice* out_device) {
488 const Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
489 VkResult result;
490
491 void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
492 sizeof(Device), alignof(Device),
493 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
494 if (!mem)
495 return VK_ERROR_OUT_OF_HOST_MEMORY;
496 Device* device = new (mem) Device(instance.alloc);
Michael Lentine03c64b02015-08-26 18:27:26 -0500497 device->GetDeviceProcAddr = instance.drv.GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700498
499 VkDevice drv_device;
500 result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
501 if (result != VK_SUCCESS) {
502 DestroyDevice(device);
503 return result;
504 }
505
Jesse Hall04f4f472015-08-16 19:51:04 -0700506 hwvulkan_dispatch_t* dispatch =
507 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
508 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
509 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500510 PFN_vkDestroyDevice destroy_device =
511 reinterpret_cast<PFN_vkDestroyDevice>(
512 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
513 destroy_device(drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700514 DestroyDevice(device);
515 return VK_ERROR_INITIALIZATION_FAILED;
516 }
517 dispatch->vtbl = &device->vtbl_storage;
518
Jesse Hallb1352bc2015-09-04 16:12:33 -0700519 device->vtbl_storage.GetSurfacePropertiesKHR = GetSurfacePropertiesKHR;
520 device->vtbl_storage.GetSurfaceFormatsKHR = GetSurfaceFormatsKHR;
521 device->vtbl_storage.GetSurfacePresentModesKHR = GetSurfacePresentModesKHR;
522 device->vtbl_storage.CreateSwapchainKHR = CreateSwapchainKHR;
523 device->vtbl_storage.DestroySwapchainKHR = DestroySwapchainKHR;
524 device->vtbl_storage.GetSwapchainImagesKHR = GetSwapchainImagesKHR;
525 device->vtbl_storage.AcquireNextImageKHR = AcquireNextImageKHR;
526 device->vtbl_storage.QueuePresentKHR = QueuePresentKHR;
527
Michael Lentine03c64b02015-08-26 18:27:26 -0500528 void* base_object = static_cast<void*>(drv_device);
529 void* next_object = base_object;
530 VkLayerLinkedListElem* next_element;
531 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
532 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700533 instance.active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500534 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
535
536 for (size_t i = elem_list.size(); i > 0; i--) {
537 size_t idx = i - 1;
538 next_element = &elem_list[idx];
539 next_element->get_proc_addr =
540 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
541 next_element->base_object = base_object;
542 next_element->next_element = next_object;
543 next_object = static_cast<void*>(next_element);
544
Michael Lentine1f0f5392015-09-11 14:54:34 -0700545 auto& name_libhandle_pair = instance.active_layers[idx];
Michael Lentine03c64b02015-08-26 18:27:26 -0500546 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700547 dlsym(name_libhandle_pair.second,
548 (name_libhandle_pair.first + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500549 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500550 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700551 dlsym(name_libhandle_pair.second, "vkGetDeviceProcAddr"));
552 if (!next_get_proc_addr) {
553 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
554 name_libhandle_pair.first.c_str(), dlerror());
555 next_object = next_element->next_element;
556 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
557 next_element->get_proc_addr);
558 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500559 }
560 }
561
562 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
563 static_cast<VkDevice>(next_object), next_get_proc_addr,
564 device->vtbl_storage)) {
565 DestroyDevice(device);
566 return VK_ERROR_INITIALIZATION_FAILED;
567 }
568
569 PFN_vkCreateDevice layer_createDevice =
570 reinterpret_cast<PFN_vkCreateDevice>(
571 device->vtbl_storage.GetDeviceProcAddr(drv_device,
572 "vkCreateDevice"));
573 layer_createDevice(pdev, create_info, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700574
575 *out_device = drv_device;
576 return VK_SUCCESS;
577}
578
579VkResult GetPhysicalDeviceExtensionPropertiesBottom(
580 VkPhysicalDevice pdev,
581 const char* layer_name,
582 uint32_t* properties_count,
583 VkExtensionProperties* properties) {
584 // TODO: what are we supposed to do with layer_name here?
585 return GetVtbl(pdev)
586 ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
587 pdev, layer_name, properties_count, properties);
588}
589
590VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
591 uint32_t* properties_count,
592 VkLayerProperties* properties) {
593 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
594 pdev, properties_count, properties);
595}
596
597VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
598 VkPhysicalDevice pdev,
599 VkFormat format,
600 VkImageType type,
601 uint32_t samples,
602 VkImageUsageFlags usage,
603 VkImageTiling tiling,
604 uint32_t* properties_count,
605 VkSparseImageFormatProperties* properties) {
606 return GetVtbl(pdev)
607 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
608 pdev, format, type, samples, usage, tiling, properties_count,
609 properties);
610}
611
612PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
613
614const InstanceVtbl kBottomInstanceFunctions = {
615 // clang-format off
616 .instance = nullptr,
617 .CreateInstance = CreateInstanceBottom,
618 .DestroyInstance = DestroyInstanceBottom,
619 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
620 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
621 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
622 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
623 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
624 .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
625 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
626 .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
627 .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
628 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
629 .CreateDevice = CreateDeviceBottom,
630 .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
631 .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
632 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700633 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700634 // clang-format on
635};
636
Michael Lentine03c64b02015-08-26 18:27:26 -0500637VkResult Noop(...) {
638 return VK_SUCCESS;
639}
640
Jesse Hall04f4f472015-08-16 19:51:04 -0700641PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500642 // TODO: Possibly move this into the instance table
643 // TODO: Possibly register the callbacks in the loader
644 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
645 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
646 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
647 }
648 if (strcmp(name, "vkCreateInstance") == 0) {
649 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
650 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700651 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
652}
653
654} // namespace
655
656// -----------------------------------------------------------------------------
657// Global functions. These are called directly from the loader entry points,
658// without going through a dispatch table.
659
660namespace vulkan {
661
662VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
663 uint32_t* count,
664 VkExtensionProperties* /*properties*/) {
665 if (!count)
666 return VK_ERROR_INVALID_POINTER;
667 if (!EnsureInitialized())
668 return VK_ERROR_UNAVAILABLE;
669
670 // TODO: not yet implemented
671 ALOGW("vkGetGlobalExtensionProperties not implemented");
672
673 *count = 0;
674 return VK_SUCCESS;
675}
676
677VkResult GetGlobalLayerProperties(uint32_t* count,
678 VkLayerProperties* /*properties*/) {
679 if (!count)
680 return VK_ERROR_INVALID_POINTER;
681 if (!EnsureInitialized())
682 return VK_ERROR_UNAVAILABLE;
683
684 // TODO: not yet implemented
685 ALOGW("vkGetGlobalLayerProperties not implemented");
686
687 *count = 0;
688 return VK_SUCCESS;
689}
690
691VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
692 VkInstance* out_instance) {
693 VkResult result;
694
695 if (!EnsureInitialized())
696 return VK_ERROR_UNAVAILABLE;
697
698 VkInstanceCreateInfo local_create_info = *create_info;
699 if (!local_create_info.pAllocCb)
700 local_create_info.pAllocCb = &kDefaultAllocCallbacks;
701 create_info = &local_create_info;
702
703 void* instance_mem = create_info->pAllocCb->pfnAlloc(
704 create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
705 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
706 if (!instance_mem)
707 return VK_ERROR_OUT_OF_HOST_MEMORY;
708 Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
709
710 instance->vtbl_storage = kBottomInstanceFunctions;
711 instance->vtbl_storage.instance = instance;
712
Michael Lentine03c64b02015-08-26 18:27:26 -0500713 // Scan layers
714 // TODO: Add more directories to scan
715 UnorderedMap<String, SharedLibraryHandle> layers(
716 CallbackAllocator<std::pair<String, SharedLibraryHandle> >(
717 instance->alloc));
718 CallbackAllocator<char> string_allocator(instance->alloc);
719 String dir_name("/data/local/tmp/vulkan/", string_allocator);
720 FindLayersInDirectory(*instance, layers, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700721
Michael Lentine950bb4f2015-09-14 13:26:30 -0500722 // Load layers
Michael Lentine03c64b02015-08-26 18:27:26 -0500723 {
724 char layer_prop[PROPERTY_VALUE_MAX];
725 property_get("vulkan.layers", layer_prop, "");
726 // TODO: Find a way to enable a large number but not all of the layers
727 size_t length = strlen(layer_prop);
728 if (length == 1 && layer_prop[0] == '+') {
729 for (auto& layer : layers) {
730 LoadLayer(instance, layer.first, layer.second);
731 }
732 } else {
733 String layer_name(string_allocator);
734 String layer_prop_str(layer_prop, string_allocator);
735 size_t end, start = 0;
736 while ((end = layer_prop_str.find(':', start)) !=
737 std::string::npos) {
738 layer_name = layer_prop_str.substr(start, end - start);
739 auto element = layers.find(layer_name);
740 if (element != layers.end()) {
741 LoadLayer(instance, layer_name, element->second);
742 layers.erase(element);
743 }
744 start = end + 1;
745 }
746 }
747 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500748 for (uint32_t i = 0; i < create_info->layerCount; ++i) {
749 String layer_name(create_info->ppEnabledLayerNames[i],
750 string_allocator);
751 auto element = layers.find(layer_name);
752 if (element != layers.end()) {
753 LoadLayer(instance, layer_name, element->second);
754 layers.erase(element);
755 }
756 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500757 for (auto& layer : layers) {
758 dlclose(layer.second);
759 }
760
761 void* base_object = static_cast<void*>(instance);
762 void* next_object = base_object;
763 VkLayerLinkedListElem* next_element;
764 PFN_vkGetInstanceProcAddr next_get_proc_addr =
765 kBottomInstanceFunctions.GetInstanceProcAddr;
766 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700767 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500768 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
769
770 for (size_t i = elem_list.size(); i > 0; i--) {
771 size_t idx = i - 1;
772 next_element = &elem_list[idx];
773 next_element->get_proc_addr =
774 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
775 next_element->base_object = base_object;
776 next_element->next_element = next_object;
777 next_object = static_cast<void*>(next_element);
778
Michael Lentine1f0f5392015-09-11 14:54:34 -0700779 auto& name_libhandle_pair = instance->active_layers[idx];
Michael Lentine03c64b02015-08-26 18:27:26 -0500780 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700781 dlsym(name_libhandle_pair.second,
782 (name_libhandle_pair.first + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500783 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500784 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700785 dlsym(name_libhandle_pair.second, "vkGetInstanceProcAddr"));
786 if (!next_get_proc_addr) {
787 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
788 name_libhandle_pair.first.c_str(), dlerror());
789 next_object = next_element->next_element;
790 next_get_proc_addr =
791 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
792 next_element->get_proc_addr);
793 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500794 }
795 }
796
797 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
798 static_cast<VkInstance>(next_object),
799 next_get_proc_addr, instance->vtbl_storage)) {
800 DestroyInstanceBottom(instance);
801 return VK_ERROR_INITIALIZATION_FAILED;
802 }
803
Michael Lentine950bb4f2015-09-14 13:26:30 -0500804 // Force enable callback extension if required
805 bool enable_callback =
806 property_get_bool("debug.vulkan.enable_layer_callback", false);
807 const char* callback_name = "DEBUG_REPORT";
808 if (enable_callback) {
809 for (uint32_t i = 0; i < create_info->extensionCount; ++i) {
810 if (!strcmp(callback_name,
811 create_info->ppEnabledExtensionNames[i])) {
812 enable_callback = false;
813 break;
814 }
815 }
816 }
817 if (enable_callback) {
818 uint32_t extension_count = local_create_info.extensionCount;
819 local_create_info.extensionCount++;
820 void* mem = instance->alloc->pfnAlloc(
821 instance->alloc->pUserData,
822 local_create_info.extensionCount * sizeof(char*), alignof(char*),
823 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
824 if (mem) {
825 const char** enabled_extensions = static_cast<const char**>(mem);
826 for (uint32_t i = 0; i < extension_count; ++i) {
827 enabled_extensions[i] =
828 local_create_info.ppEnabledExtensionNames[i];
829 }
830 enabled_extensions[extension_count] = callback_name;
831 local_create_info.ppEnabledExtensionNames = enabled_extensions;
832 } else {
833 ALOGW("DEBUG_REPORT extension cannot be enabled!");
834 enable_callback = false;
835 local_create_info.extensionCount--;
836 }
837 }
838
Jesse Hall04f4f472015-08-16 19:51:04 -0700839 *out_instance = instance;
Michael Lentine03c64b02015-08-26 18:27:26 -0500840 result = instance->vtbl_storage.CreateInstance(create_info, out_instance);
Michael Lentine950bb4f2015-09-14 13:26:30 -0500841 if (enable_callback) {
842 const char* const* enabled_extensions =
843 local_create_info.ppEnabledExtensionNames;
844 instance->alloc->pfnFree(instance->alloc->pUserData,
845 const_cast<char**>(enabled_extensions));
846 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700847 if (result <= 0) {
848 // For every layer, including the loader top and bottom layers:
849 // - If a call to the next CreateInstance fails, the layer must clean
850 // up anything it has successfully done so far, and propagate the
851 // error upwards.
852 // - If a layer successfully calls the next layer's CreateInstance, and
853 // afterwards must fail for some reason, it must call the next layer's
854 // DestroyInstance before returning.
855 // - The layer must not call the next layer's DestroyInstance if that
856 // layer's CreateInstance wasn't called, or returned failure.
857
858 // On failure, CreateInstanceBottom frees the instance struct, so it's
859 // already gone at this point. Nothing to do.
860 }
861
862 return result;
863}
864
865PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
866 if (!instance)
867 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500868 // TODO: Possibly move this into the instance table
869 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
870 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
871 if (!instance->vtbl)
872 return NULL;
873 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
874 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
875 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700876 // For special-case functions we always return the loader entry
877 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
878 strcmp(name, "vkGetDeviceProcAddr") == 0) {
879 return GetGlobalInstanceProcAddr(name);
880 }
881 return GetSpecificInstanceProcAddr(instance->vtbl, name);
882}
883
884PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
885 if (!device)
886 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500887 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
888 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
889 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700890 // For special-case functions we always return the loader entry
891 if (strcmp(name, "vkGetDeviceQueue") == 0 ||
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700892 strcmp(name, "vkCreateCommandBuffer") == 0 ||
Jesse Hall04f4f472015-08-16 19:51:04 -0700893 strcmp(name, "vkDestroyDevice") == 0) {
894 return GetGlobalDeviceProcAddr(name);
895 }
896 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
897}
898
899VkResult GetDeviceQueue(VkDevice drv_device,
900 uint32_t family,
901 uint32_t index,
902 VkQueue* out_queue) {
903 VkResult result;
904 VkQueue queue;
905 const DeviceVtbl* vtbl = GetVtbl(drv_device);
906 result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
907 if (result != VK_SUCCESS)
908 return result;
909 hwvulkan_dispatch_t* dispatch =
910 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
911 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
912 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
913 return VK_ERROR_INITIALIZATION_FAILED;
914 }
915 dispatch->vtbl = vtbl;
916 *out_queue = queue;
917 return VK_SUCCESS;
918}
919
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700920VkResult CreateCommandBuffer(VkDevice drv_device,
921 const VkCmdBufferCreateInfo* create_info,
922 VkCmdBuffer* out_cmdbuf) {
923 const DeviceVtbl* vtbl = GetVtbl(drv_device);
924 VkCmdBuffer cmdbuf;
925 VkResult result =
926 vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
927 if (result != VK_SUCCESS)
928 return result;
929 hwvulkan_dispatch_t* dispatch =
930 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
931 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
932 ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
933 dispatch->magic);
934 return VK_ERROR_INITIALIZATION_FAILED;
935 }
936 dispatch->vtbl = vtbl;
937 *out_cmdbuf = cmdbuf;
938 return VK_SUCCESS;
939}
940
Jesse Hall04f4f472015-08-16 19:51:04 -0700941VkResult DestroyDevice(VkDevice drv_device) {
942 const DeviceVtbl* vtbl = GetVtbl(drv_device);
943 Device* device = static_cast<Device*>(vtbl->device);
944 vtbl->DestroyDevice(drv_device);
945 DestroyDevice(device);
946 return VK_SUCCESS;
947}
948
Jesse Halld7b994a2015-09-07 14:17:37 -0700949void* AllocDeviceMem(VkDevice device,
950 size_t size,
951 size_t align,
952 VkSystemAllocType type) {
953 const VkAllocCallbacks* alloc_cb =
954 static_cast<Device*>(GetVtbl(device)->device)->alloc;
955 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
956}
957
958void FreeDeviceMem(VkDevice device, void* ptr) {
959 const VkAllocCallbacks* alloc_cb =
960 static_cast<Device*>(GetVtbl(device)->device)->alloc;
961 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
962}
963
964const DeviceVtbl& GetDriverVtbl(VkDevice device) {
965 // TODO(jessehall): This actually returns the API-level vtbl for the
966 // device, not the driver entry points. Given the current use -- getting
967 // the driver's private swapchain-related functions -- that works, but is
968 // misleading and likely to cause bugs. Fix as part of separating the
969 // loader->driver interface from the app->loader interface.
970 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
971}
972
973const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
974 // TODO(jessehall): This actually returns the API-level vtbl for the
975 // device, not the driver entry points. Given the current use -- getting
976 // the driver's private swapchain-related functions -- that works, but is
977 // misleading and likely to cause bugs. Fix as part of separating the
978 // loader->driver interface from the app->loader interface.
979 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
980}
981
Jesse Hall04f4f472015-08-16 19:51:04 -0700982} // namespace vulkan