blob: 694d8fd84260e4af5cf5c5ebda22b2c6084c64d3 [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
Michael Lentineb467c0d2015-09-14 14:43:49 -0500316struct InstanceLayersPair {
317 Instance* instance;
318 UnorderedMap<String, SharedLibraryHandle>* layers;
319};
320
321void LoadLayerFromProperty(const char* name, const char* value, void* data) {
322 auto instance_layers_pair = static_cast<InstanceLayersPair*>(data);
323 const char prefix[] = "debug.vulkan.layer.";
324 const size_t prefixlen = sizeof(prefix) - 1;
325 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
326 return;
327 String layer_name_str(
328 name + prefixlen,
329 CallbackAllocator<char>(instance_layers_pair->instance->alloc));
330 LoadLayer(instance_layers_pair->instance, layer_name_str,
331 (*instance_layers_pair->layers)[layer_name_str]);
332}
333
Jesse Hall04f4f472015-08-16 19:51:04 -0700334// -----------------------------------------------------------------------------
335// "Bottom" functions. These are called at the end of the instance dispatch
336// chain.
337
338VkResult DestroyInstanceBottom(VkInstance instance) {
339 // These checks allow us to call DestroyInstanceBottom from any error path
340 // in CreateInstanceBottom, before the driver instance is fully initialized.
341 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
342 instance->drv.vtbl.DestroyInstance) {
343 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
344 }
Michael Lentine1f0f5392015-09-11 14:54:34 -0700345 for (auto& layer : instance->active_layers) {
346 dlclose(layer.second);
Michael Lentine03c64b02015-08-26 18:27:26 -0500347 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700348 const VkAllocCallbacks* alloc = instance->alloc;
349 instance->~VkInstance_T();
350 alloc->pfnFree(alloc->pUserData, instance);
351 return VK_SUCCESS;
352}
353
354VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
355 VkInstance* instance_ptr) {
356 Instance* instance = *instance_ptr;
357 VkResult result;
358
359 result =
360 g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
361 if (result != VK_SUCCESS) {
362 DestroyInstanceBottom(instance);
363 return result;
364 }
365
Michael Lentine03c64b02015-08-26 18:27:26 -0500366 if (!LoadInstanceVtbl(
367 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
368 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700369 DestroyInstanceBottom(instance);
370 return VK_ERROR_INITIALIZATION_FAILED;
371 }
372
373 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
374 // queryable from the Instance, and that the resulting function work for any
375 // VkDevice created from the instance.
376 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
377 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
378 "vkGetDeviceProcAddr"));
379 if (!instance->drv.GetDeviceProcAddr) {
380 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
381 DestroyInstanceBottom(instance);
382 return VK_ERROR_INITIALIZATION_FAILED;
383 }
384
385 hwvulkan_dispatch_t* dispatch =
386 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
387 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
388 // Skip setting dispatch->vtbl on the driver instance handle, since we
389 // never intentionally call through it; we go through Instance::drv.vtbl
390 // instead.
391 } else {
392 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
393 dispatch->magic);
394 DestroyInstanceBottom(instance);
395 return VK_ERROR_INITIALIZATION_FAILED;
396 }
397
398 uint32_t num_physical_devices = 0;
399 result = instance->drv.vtbl.EnumeratePhysicalDevices(
400 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
401 if (result != VK_SUCCESS) {
402 DestroyInstanceBottom(instance);
403 return VK_ERROR_INITIALIZATION_FAILED;
404 }
405 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
406 result = instance->drv.vtbl.EnumeratePhysicalDevices(
407 instance->drv.vtbl.instance, &num_physical_devices,
408 instance->physical_devices);
409 if (result != VK_SUCCESS) {
410 DestroyInstanceBottom(instance);
411 return VK_ERROR_INITIALIZATION_FAILED;
412 }
413 for (uint32_t i = 0; i < num_physical_devices; i++) {
414 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
415 instance->physical_devices[i]);
416 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
417 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
418 dispatch->magic);
419 DestroyInstanceBottom(instance);
420 return VK_ERROR_INITIALIZATION_FAILED;
421 }
422 dispatch->vtbl = instance->vtbl;
423 }
424 instance->drv.num_physical_devices = num_physical_devices;
425
426 instance->num_physical_devices = instance->drv.num_physical_devices;
427 return VK_SUCCESS;
428}
429
430VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
431 uint32_t* pdev_count,
432 VkPhysicalDevice* pdevs) {
433 uint32_t count = instance->num_physical_devices;
434 if (pdevs) {
435 count = std::min(count, *pdev_count);
436 std::copy(instance->physical_devices,
437 instance->physical_devices + count, pdevs);
438 }
439 *pdev_count = count;
440 return VK_SUCCESS;
441}
442
443VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
444 VkPhysicalDeviceFeatures* features) {
445 return GetVtbl(pdev)
446 ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
447}
448
449VkResult GetPhysicalDeviceFormatPropertiesBottom(
450 VkPhysicalDevice pdev,
451 VkFormat format,
452 VkFormatProperties* properties) {
453 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
454 pdev, format, properties);
455}
456
457VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
458 VkPhysicalDevice pdev,
459 VkFormat format,
460 VkImageType type,
461 VkImageTiling tiling,
462 VkImageUsageFlags usage,
463 VkImageFormatProperties* properties) {
464 return GetVtbl(pdev)
465 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
466 pdev, format, type, tiling, usage, properties);
467}
468
469VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
470 VkPhysicalDeviceLimits* limits) {
471 return GetVtbl(pdev)
472 ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
473}
474
475VkResult GetPhysicalDevicePropertiesBottom(
476 VkPhysicalDevice pdev,
477 VkPhysicalDeviceProperties* properties) {
478 return GetVtbl(pdev)
479 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
480}
481
482VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
483 uint32_t* count) {
484 return GetVtbl(pdev)
485 ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
486}
487
488VkResult GetPhysicalDeviceQueuePropertiesBottom(
489 VkPhysicalDevice pdev,
490 uint32_t count,
491 VkPhysicalDeviceQueueProperties* properties) {
492 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
493 pdev, count, properties);
494}
495
496VkResult GetPhysicalDeviceMemoryPropertiesBottom(
497 VkPhysicalDevice pdev,
498 VkPhysicalDeviceMemoryProperties* properties) {
499 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
500 pdev, properties);
501}
502
503VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
504 const VkDeviceCreateInfo* create_info,
505 VkDevice* out_device) {
506 const Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
507 VkResult result;
508
509 void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
510 sizeof(Device), alignof(Device),
511 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
512 if (!mem)
513 return VK_ERROR_OUT_OF_HOST_MEMORY;
514 Device* device = new (mem) Device(instance.alloc);
Michael Lentine03c64b02015-08-26 18:27:26 -0500515 device->GetDeviceProcAddr = instance.drv.GetDeviceProcAddr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700516
517 VkDevice drv_device;
518 result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
519 if (result != VK_SUCCESS) {
520 DestroyDevice(device);
521 return result;
522 }
523
Jesse Hall04f4f472015-08-16 19:51:04 -0700524 hwvulkan_dispatch_t* dispatch =
525 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
526 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
527 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500528 PFN_vkDestroyDevice destroy_device =
529 reinterpret_cast<PFN_vkDestroyDevice>(
530 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
531 destroy_device(drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700532 DestroyDevice(device);
533 return VK_ERROR_INITIALIZATION_FAILED;
534 }
535 dispatch->vtbl = &device->vtbl_storage;
536
Jesse Hallb1352bc2015-09-04 16:12:33 -0700537 device->vtbl_storage.GetSurfacePropertiesKHR = GetSurfacePropertiesKHR;
538 device->vtbl_storage.GetSurfaceFormatsKHR = GetSurfaceFormatsKHR;
539 device->vtbl_storage.GetSurfacePresentModesKHR = GetSurfacePresentModesKHR;
540 device->vtbl_storage.CreateSwapchainKHR = CreateSwapchainKHR;
541 device->vtbl_storage.DestroySwapchainKHR = DestroySwapchainKHR;
542 device->vtbl_storage.GetSwapchainImagesKHR = GetSwapchainImagesKHR;
543 device->vtbl_storage.AcquireNextImageKHR = AcquireNextImageKHR;
544 device->vtbl_storage.QueuePresentKHR = QueuePresentKHR;
545
Michael Lentine03c64b02015-08-26 18:27:26 -0500546 void* base_object = static_cast<void*>(drv_device);
547 void* next_object = base_object;
548 VkLayerLinkedListElem* next_element;
549 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
550 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700551 instance.active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500552 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
553
554 for (size_t i = elem_list.size(); i > 0; i--) {
555 size_t idx = i - 1;
556 next_element = &elem_list[idx];
557 next_element->get_proc_addr =
558 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
559 next_element->base_object = base_object;
560 next_element->next_element = next_object;
561 next_object = static_cast<void*>(next_element);
562
Michael Lentine1f0f5392015-09-11 14:54:34 -0700563 auto& name_libhandle_pair = instance.active_layers[idx];
Michael Lentine03c64b02015-08-26 18:27:26 -0500564 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700565 dlsym(name_libhandle_pair.second,
566 (name_libhandle_pair.first + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500567 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500568 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700569 dlsym(name_libhandle_pair.second, "vkGetDeviceProcAddr"));
570 if (!next_get_proc_addr) {
571 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
572 name_libhandle_pair.first.c_str(), dlerror());
573 next_object = next_element->next_element;
574 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
575 next_element->get_proc_addr);
576 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500577 }
578 }
579
580 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
581 static_cast<VkDevice>(next_object), next_get_proc_addr,
582 device->vtbl_storage)) {
583 DestroyDevice(device);
584 return VK_ERROR_INITIALIZATION_FAILED;
585 }
586
587 PFN_vkCreateDevice layer_createDevice =
588 reinterpret_cast<PFN_vkCreateDevice>(
589 device->vtbl_storage.GetDeviceProcAddr(drv_device,
590 "vkCreateDevice"));
591 layer_createDevice(pdev, create_info, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700592
593 *out_device = drv_device;
594 return VK_SUCCESS;
595}
596
597VkResult GetPhysicalDeviceExtensionPropertiesBottom(
598 VkPhysicalDevice pdev,
599 const char* layer_name,
600 uint32_t* properties_count,
601 VkExtensionProperties* properties) {
602 // TODO: what are we supposed to do with layer_name here?
603 return GetVtbl(pdev)
604 ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
605 pdev, layer_name, properties_count, properties);
606}
607
608VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
609 uint32_t* properties_count,
610 VkLayerProperties* properties) {
611 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
612 pdev, properties_count, properties);
613}
614
615VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
616 VkPhysicalDevice pdev,
617 VkFormat format,
618 VkImageType type,
619 uint32_t samples,
620 VkImageUsageFlags usage,
621 VkImageTiling tiling,
622 uint32_t* properties_count,
623 VkSparseImageFormatProperties* properties) {
624 return GetVtbl(pdev)
625 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
626 pdev, format, type, samples, usage, tiling, properties_count,
627 properties);
628}
629
630PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
631
632const InstanceVtbl kBottomInstanceFunctions = {
633 // clang-format off
634 .instance = nullptr,
635 .CreateInstance = CreateInstanceBottom,
636 .DestroyInstance = DestroyInstanceBottom,
637 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
638 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
639 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
640 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
641 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
642 .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
643 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
644 .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
645 .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
646 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
647 .CreateDevice = CreateDeviceBottom,
648 .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
649 .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
650 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700651 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700652 // clang-format on
653};
654
Michael Lentine03c64b02015-08-26 18:27:26 -0500655VkResult Noop(...) {
656 return VK_SUCCESS;
657}
658
Jesse Hall04f4f472015-08-16 19:51:04 -0700659PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500660 // TODO: Possibly move this into the instance table
661 // TODO: Possibly register the callbacks in the loader
662 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
663 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
664 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
665 }
666 if (strcmp(name, "vkCreateInstance") == 0) {
667 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
668 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700669 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
670}
671
672} // namespace
673
674// -----------------------------------------------------------------------------
675// Global functions. These are called directly from the loader entry points,
676// without going through a dispatch table.
677
678namespace vulkan {
679
680VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
681 uint32_t* count,
682 VkExtensionProperties* /*properties*/) {
683 if (!count)
684 return VK_ERROR_INVALID_POINTER;
685 if (!EnsureInitialized())
686 return VK_ERROR_UNAVAILABLE;
687
688 // TODO: not yet implemented
689 ALOGW("vkGetGlobalExtensionProperties not implemented");
690
691 *count = 0;
692 return VK_SUCCESS;
693}
694
695VkResult GetGlobalLayerProperties(uint32_t* count,
696 VkLayerProperties* /*properties*/) {
697 if (!count)
698 return VK_ERROR_INVALID_POINTER;
699 if (!EnsureInitialized())
700 return VK_ERROR_UNAVAILABLE;
701
702 // TODO: not yet implemented
703 ALOGW("vkGetGlobalLayerProperties not implemented");
704
705 *count = 0;
706 return VK_SUCCESS;
707}
708
709VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
710 VkInstance* out_instance) {
711 VkResult result;
712
713 if (!EnsureInitialized())
714 return VK_ERROR_UNAVAILABLE;
715
716 VkInstanceCreateInfo local_create_info = *create_info;
717 if (!local_create_info.pAllocCb)
718 local_create_info.pAllocCb = &kDefaultAllocCallbacks;
719 create_info = &local_create_info;
720
721 void* instance_mem = create_info->pAllocCb->pfnAlloc(
722 create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
723 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
724 if (!instance_mem)
725 return VK_ERROR_OUT_OF_HOST_MEMORY;
726 Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
727
728 instance->vtbl_storage = kBottomInstanceFunctions;
729 instance->vtbl_storage.instance = instance;
730
Michael Lentine03c64b02015-08-26 18:27:26 -0500731 // Scan layers
732 // TODO: Add more directories to scan
733 UnorderedMap<String, SharedLibraryHandle> layers(
734 CallbackAllocator<std::pair<String, SharedLibraryHandle> >(
735 instance->alloc));
736 CallbackAllocator<char> string_allocator(instance->alloc);
737 String dir_name("/data/local/tmp/vulkan/", string_allocator);
738 FindLayersInDirectory(*instance, layers, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700739
Michael Lentine950bb4f2015-09-14 13:26:30 -0500740 // Load layers
Michael Lentine03c64b02015-08-26 18:27:26 -0500741 {
742 char layer_prop[PROPERTY_VALUE_MAX];
Michael Lentineb467c0d2015-09-14 14:43:49 -0500743 property_get("debug.vulkan.layers", layer_prop, "");
744 String layer_name(string_allocator);
745 String layer_prop_str(layer_prop, string_allocator);
746 size_t end, start = 0;
747 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
748 layer_name = layer_prop_str.substr(start, end - start);
749 auto element = layers.find(layer_name);
750 if (element != layers.end()) {
751 LoadLayer(instance, layer_name, element->second);
752 layers.erase(element);
Michael Lentine03c64b02015-08-26 18:27:26 -0500753 }
Michael Lentineb467c0d2015-09-14 14:43:49 -0500754 start = end + 1;
Michael Lentine03c64b02015-08-26 18:27:26 -0500755 }
Michael Lentineb467c0d2015-09-14 14:43:49 -0500756 InstanceLayersPair instance_layers_pair = {.instance = instance,
757 .layers = &layers};
758 property_list(LoadLayerFromProperty,
759 static_cast<void*>(&instance_layers_pair));
Michael Lentine03c64b02015-08-26 18:27:26 -0500760 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500761 for (uint32_t i = 0; i < create_info->layerCount; ++i) {
762 String layer_name(create_info->ppEnabledLayerNames[i],
763 string_allocator);
764 auto element = layers.find(layer_name);
765 if (element != layers.end()) {
766 LoadLayer(instance, layer_name, element->second);
767 layers.erase(element);
768 }
769 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500770 for (auto& layer : layers) {
771 dlclose(layer.second);
772 }
773
774 void* base_object = static_cast<void*>(instance);
775 void* next_object = base_object;
776 VkLayerLinkedListElem* next_element;
777 PFN_vkGetInstanceProcAddr next_get_proc_addr =
778 kBottomInstanceFunctions.GetInstanceProcAddr;
779 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700780 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500781 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
782
783 for (size_t i = elem_list.size(); i > 0; i--) {
784 size_t idx = i - 1;
785 next_element = &elem_list[idx];
786 next_element->get_proc_addr =
787 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
788 next_element->base_object = base_object;
789 next_element->next_element = next_object;
790 next_object = static_cast<void*>(next_element);
791
Michael Lentine1f0f5392015-09-11 14:54:34 -0700792 auto& name_libhandle_pair = instance->active_layers[idx];
Michael Lentine03c64b02015-08-26 18:27:26 -0500793 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700794 dlsym(name_libhandle_pair.second,
795 (name_libhandle_pair.first + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500796 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500797 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700798 dlsym(name_libhandle_pair.second, "vkGetInstanceProcAddr"));
799 if (!next_get_proc_addr) {
800 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
801 name_libhandle_pair.first.c_str(), dlerror());
802 next_object = next_element->next_element;
803 next_get_proc_addr =
804 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
805 next_element->get_proc_addr);
806 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500807 }
808 }
809
810 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
811 static_cast<VkInstance>(next_object),
812 next_get_proc_addr, instance->vtbl_storage)) {
813 DestroyInstanceBottom(instance);
814 return VK_ERROR_INITIALIZATION_FAILED;
815 }
816
Michael Lentine950bb4f2015-09-14 13:26:30 -0500817 // Force enable callback extension if required
818 bool enable_callback =
819 property_get_bool("debug.vulkan.enable_layer_callback", false);
820 const char* callback_name = "DEBUG_REPORT";
821 if (enable_callback) {
822 for (uint32_t i = 0; i < create_info->extensionCount; ++i) {
823 if (!strcmp(callback_name,
824 create_info->ppEnabledExtensionNames[i])) {
825 enable_callback = false;
826 break;
827 }
828 }
829 }
830 if (enable_callback) {
831 uint32_t extension_count = local_create_info.extensionCount;
832 local_create_info.extensionCount++;
833 void* mem = instance->alloc->pfnAlloc(
834 instance->alloc->pUserData,
835 local_create_info.extensionCount * sizeof(char*), alignof(char*),
836 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
837 if (mem) {
838 const char** enabled_extensions = static_cast<const char**>(mem);
839 for (uint32_t i = 0; i < extension_count; ++i) {
840 enabled_extensions[i] =
841 local_create_info.ppEnabledExtensionNames[i];
842 }
843 enabled_extensions[extension_count] = callback_name;
844 local_create_info.ppEnabledExtensionNames = enabled_extensions;
845 } else {
846 ALOGW("DEBUG_REPORT extension cannot be enabled!");
847 enable_callback = false;
848 local_create_info.extensionCount--;
849 }
850 }
851
Jesse Hall04f4f472015-08-16 19:51:04 -0700852 *out_instance = instance;
Michael Lentine03c64b02015-08-26 18:27:26 -0500853 result = instance->vtbl_storage.CreateInstance(create_info, out_instance);
Michael Lentine950bb4f2015-09-14 13:26:30 -0500854 if (enable_callback) {
855 const char* const* enabled_extensions =
856 local_create_info.ppEnabledExtensionNames;
857 instance->alloc->pfnFree(instance->alloc->pUserData,
858 const_cast<char**>(enabled_extensions));
859 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700860 if (result <= 0) {
861 // For every layer, including the loader top and bottom layers:
862 // - If a call to the next CreateInstance fails, the layer must clean
863 // up anything it has successfully done so far, and propagate the
864 // error upwards.
865 // - If a layer successfully calls the next layer's CreateInstance, and
866 // afterwards must fail for some reason, it must call the next layer's
867 // DestroyInstance before returning.
868 // - The layer must not call the next layer's DestroyInstance if that
869 // layer's CreateInstance wasn't called, or returned failure.
870
871 // On failure, CreateInstanceBottom frees the instance struct, so it's
872 // already gone at this point. Nothing to do.
873 }
874
875 return result;
876}
877
878PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
879 if (!instance)
880 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500881 // TODO: Possibly move this into the instance table
882 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
883 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
884 if (!instance->vtbl)
885 return NULL;
886 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
887 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
888 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700889 // For special-case functions we always return the loader entry
890 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
891 strcmp(name, "vkGetDeviceProcAddr") == 0) {
892 return GetGlobalInstanceProcAddr(name);
893 }
894 return GetSpecificInstanceProcAddr(instance->vtbl, name);
895}
896
897PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
898 if (!device)
899 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -0500900 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
901 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
902 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700903 // For special-case functions we always return the loader entry
904 if (strcmp(name, "vkGetDeviceQueue") == 0 ||
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700905 strcmp(name, "vkCreateCommandBuffer") == 0 ||
Jesse Hall04f4f472015-08-16 19:51:04 -0700906 strcmp(name, "vkDestroyDevice") == 0) {
907 return GetGlobalDeviceProcAddr(name);
908 }
909 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
910}
911
912VkResult GetDeviceQueue(VkDevice drv_device,
913 uint32_t family,
914 uint32_t index,
915 VkQueue* out_queue) {
916 VkResult result;
917 VkQueue queue;
918 const DeviceVtbl* vtbl = GetVtbl(drv_device);
919 result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
920 if (result != VK_SUCCESS)
921 return result;
922 hwvulkan_dispatch_t* dispatch =
923 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
924 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
925 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
926 return VK_ERROR_INITIALIZATION_FAILED;
927 }
928 dispatch->vtbl = vtbl;
929 *out_queue = queue;
930 return VK_SUCCESS;
931}
932
Jesse Hallc7a6eb52015-08-31 12:52:03 -0700933VkResult CreateCommandBuffer(VkDevice drv_device,
934 const VkCmdBufferCreateInfo* create_info,
935 VkCmdBuffer* out_cmdbuf) {
936 const DeviceVtbl* vtbl = GetVtbl(drv_device);
937 VkCmdBuffer cmdbuf;
938 VkResult result =
939 vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
940 if (result != VK_SUCCESS)
941 return result;
942 hwvulkan_dispatch_t* dispatch =
943 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
944 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
945 ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
946 dispatch->magic);
947 return VK_ERROR_INITIALIZATION_FAILED;
948 }
949 dispatch->vtbl = vtbl;
950 *out_cmdbuf = cmdbuf;
951 return VK_SUCCESS;
952}
953
Jesse Hall04f4f472015-08-16 19:51:04 -0700954VkResult DestroyDevice(VkDevice drv_device) {
955 const DeviceVtbl* vtbl = GetVtbl(drv_device);
956 Device* device = static_cast<Device*>(vtbl->device);
957 vtbl->DestroyDevice(drv_device);
958 DestroyDevice(device);
959 return VK_SUCCESS;
960}
961
Jesse Halld7b994a2015-09-07 14:17:37 -0700962void* AllocDeviceMem(VkDevice device,
963 size_t size,
964 size_t align,
965 VkSystemAllocType type) {
966 const VkAllocCallbacks* alloc_cb =
967 static_cast<Device*>(GetVtbl(device)->device)->alloc;
968 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
969}
970
971void FreeDeviceMem(VkDevice device, void* ptr) {
972 const VkAllocCallbacks* alloc_cb =
973 static_cast<Device*>(GetVtbl(device)->device)->alloc;
974 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
975}
976
977const DeviceVtbl& GetDriverVtbl(VkDevice device) {
978 // TODO(jessehall): This actually returns the API-level vtbl for the
979 // device, not the driver entry points. Given the current use -- getting
980 // the driver's private swapchain-related functions -- that works, but is
981 // misleading and likely to cause bugs. Fix as part of separating the
982 // loader->driver interface from the app->loader interface.
983 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
984}
985
986const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
987 // TODO(jessehall): This actually returns the API-level vtbl for the
988 // device, not the driver entry points. Given the current use -- getting
989 // the driver's private swapchain-related functions -- that works, but is
990 // misleading and likely to cause bugs. Fix as part of separating the
991 // loader->driver interface from the app->loader interface.
992 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
993}
994
Jesse Hall04f4f472015-08-16 19:51:04 -0700995} // namespace vulkan