blob: ae36ac9f9c6e06d2fe761b683226b9616c11be09 [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
Michael Lentine9dbe67f2015-09-16 15:53:50 -050017//#define LOG_NDEBUG 0
18
Jesse Hall04f4f472015-08-16 19:51:04 -070019// module header
20#include "loader.h"
21// standard C headers
Michael Lentine03c64b02015-08-26 18:27:26 -050022#include <dirent.h>
23#include <dlfcn.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070024#include <inttypes.h>
25#include <malloc.h>
26#include <pthread.h>
27#include <string.h>
28// standard C++ headers
29#include <algorithm>
30#include <mutex>
Michael Lentine03c64b02015-08-26 18:27:26 -050031#include <sstream>
32#include <string>
33#include <unordered_map>
34#include <vector>
Jesse Hall04f4f472015-08-16 19:51:04 -070035// platform/library headers
Michael Lentine03c64b02015-08-26 18:27:26 -050036#include <cutils/properties.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070037#include <hardware/hwvulkan.h>
38#include <log/log.h>
Michael Lentinecd6cabf2015-09-14 17:32:59 -050039#include <vulkan/vk_debug_report_lunarg.h>
Michael Lentine1c69b9e2015-09-14 13:26:59 -050040#include <vulkan/vulkan_loader_data.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070041
42using namespace vulkan;
43
44static const uint32_t kMaxPhysicalDevices = 4;
45
Michael Lentine03c64b02015-08-26 18:27:26 -050046namespace {
47
48// These definitions are taken from the LunarG Vulkan Loader. They are used to
49// enforce compatability between the Loader and Layers.
50typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
51
52typedef struct VkLayerLinkedListElem_ {
53 PFN_vkGetProcAddr get_proc_addr;
54 void* next_element;
55 void* base_object;
56} VkLayerLinkedListElem;
57
58// Define Handle typedef to be void* as returned from dlopen.
59typedef void* SharedLibraryHandle;
60
61// Custom versions of std classes that use the vulkan alloc callback.
62template <class T>
63class CallbackAllocator {
64 public:
65 typedef T value_type;
66
67 CallbackAllocator(const VkAllocCallbacks* alloc_input)
68 : alloc(alloc_input) {}
69
70 template <class T2>
71 CallbackAllocator(const CallbackAllocator<T2>& other)
72 : alloc(other.alloc) {}
73
74 T* allocate(std::size_t n) {
75 void* mem = alloc->pfnAlloc(alloc->pUserData, n * sizeof(T), alignof(T),
76 VK_SYSTEM_ALLOC_TYPE_INTERNAL);
77 return static_cast<T*>(mem);
78 }
79
80 void deallocate(T* array, std::size_t /*n*/) {
81 alloc->pfnFree(alloc->pUserData, array);
82 }
83
84 const VkAllocCallbacks* alloc;
85};
86// These are needed in order to move Strings
87template <class T>
88bool operator==(const CallbackAllocator<T>& alloc1,
89 const CallbackAllocator<T>& alloc2) {
90 return alloc1.alloc == alloc2.alloc;
91}
92template <class T>
93bool operator!=(const CallbackAllocator<T>& alloc1,
94 const CallbackAllocator<T>& alloc2) {
95 return !(alloc1 == alloc2);
96}
97
98template <class Key,
99 class T,
100 class Hash = std::hash<Key>,
101 class Pred = std::equal_to<Key> >
102using UnorderedMap =
103 std::unordered_map<Key,
104 T,
105 Hash,
106 Pred,
107 CallbackAllocator<std::pair<const Key, T> > >;
108
109template <class T>
110using Vector = std::vector<T, CallbackAllocator<T> >;
111
112typedef std::basic_string<char,
113 std::char_traits<char>,
114 CallbackAllocator<char> > String;
115
116} // namespace
117
118// -----------------------------------------------------------------------------
119
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500120namespace {
121
122struct LayerData {
123 String path;
124 SharedLibraryHandle handle;
125 uint32_t ref_count;
126};
127
128typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
129
130} // namespace
131
Jesse Hall04f4f472015-08-16 19:51:04 -0700132struct VkInstance_T {
133 VkInstance_T(const VkAllocCallbacks* alloc_callbacks)
Michael Lentine03c64b02015-08-26 18:27:26 -0500134 : vtbl(&vtbl_storage),
135 alloc(alloc_callbacks),
136 num_physical_devices(0),
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500137 layers(CallbackAllocator<std::pair<String, LayerData> >(alloc)),
138 active_layers(CallbackAllocator<String>(alloc)) {
139 pthread_mutex_init(&layer_lock, 0);
Jesse Hall04f4f472015-08-16 19:51:04 -0700140 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
141 memset(physical_devices, 0, sizeof(physical_devices));
142 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
143 drv.GetDeviceProcAddr = nullptr;
144 drv.num_physical_devices = 0;
145 }
146
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500147 ~VkInstance_T() { pthread_mutex_destroy(&layer_lock); }
148
Jesse Hall04f4f472015-08-16 19:51:04 -0700149 InstanceVtbl* vtbl;
150 InstanceVtbl vtbl_storage;
151
152 const VkAllocCallbacks* alloc;
153 uint32_t num_physical_devices;
154 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
155
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500156 pthread_mutex_t layer_lock;
157 // Map of layer names to layer data
158 UnorderedMap<String, LayerData> layers;
159 // Vector of layers active for this instance
160 Vector<LayerMapIterator> active_layers;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500161 VkDbgMsgCallback message;
Michael Lentine03c64b02015-08-26 18:27:26 -0500162
Jesse Hall04f4f472015-08-16 19:51:04 -0700163 struct Driver {
164 // Pointers to driver entry points. Used explicitly by the loader; not
165 // set as the dispatch table for any objects.
166 InstanceVtbl vtbl;
167
168 // Pointer to the driver's get_device_proc_addr, must be valid for any
169 // of the driver's physical devices. Not part of the InstanceVtbl since
170 // it's not an Instance/PhysicalDevice function.
171 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
172
173 // Number of physical devices owned by this driver.
174 uint32_t num_physical_devices;
175 } drv; // may eventually be an array
176};
177
178// -----------------------------------------------------------------------------
179
180namespace {
181
182typedef VkInstance_T Instance;
183
184struct Device {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500185 Device(Instance* instance_input)
186 : instance(instance_input),
187 active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700188 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
189 vtbl_storage.device = this;
190 }
191 DeviceVtbl vtbl_storage;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500192 Instance* instance;
193 // Vector of layers active for this device
194 Vector<LayerMapIterator> active_layers;
Jesse Hall04f4f472015-08-16 19:51:04 -0700195};
196
197// -----------------------------------------------------------------------------
198// Utility Code
199
200inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
201 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
202}
203
204inline const DeviceVtbl* GetVtbl(VkDevice device) {
205 return *reinterpret_cast<DeviceVtbl**>(device);
206}
Jesse Halld7b994a2015-09-07 14:17:37 -0700207inline const DeviceVtbl* GetVtbl(VkQueue queue) {
208 return *reinterpret_cast<DeviceVtbl**>(queue);
209}
Jesse Hall04f4f472015-08-16 19:51:04 -0700210
211void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
212 return memalign(alignment, size);
213}
214
215void DefaultFree(void*, void* pMem) {
216 free(pMem);
217}
218
219const VkAllocCallbacks kDefaultAllocCallbacks = {
220 .pUserData = nullptr,
221 .pfnAlloc = DefaultAlloc,
222 .pfnFree = DefaultFree,
223};
224
225hwvulkan_device_t* g_hwdevice;
226bool EnsureInitialized() {
227 static std::once_flag once_flag;
228 static const hwvulkan_module_t* module;
229
230 std::call_once(once_flag, []() {
231 int result;
232 result = hw_get_module("vulkan",
233 reinterpret_cast<const hw_module_t**>(&module));
234 if (result != 0) {
235 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
236 result);
237 return;
238 }
239 result = module->common.methods->open(
240 &module->common, HWVULKAN_DEVICE_0,
241 reinterpret_cast<hw_device_t**>(&g_hwdevice));
242 if (result != 0) {
243 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
244 result);
245 module = nullptr;
246 return;
247 }
248 });
249
250 return module != nullptr && g_hwdevice != nullptr;
251}
252
253void DestroyDevice(Device* device) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500254 const VkAllocCallbacks* alloc = device->instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700255 device->~Device();
256 alloc->pfnFree(alloc->pUserData, device);
257}
258
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500259void FindLayersInDirectory(Instance& instance, const String& dir_name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500260 DIR* directory;
261 struct dirent* entry;
262 if ((directory = opendir(dir_name.c_str()))) {
263 Vector<VkLayerProperties> properties(
264 CallbackAllocator<VkLayerProperties>(instance.alloc));
265 while ((entry = readdir(directory))) {
266 size_t length = strlen(entry->d_name);
267 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
268 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
269 continue;
270 // Open so
271 SharedLibraryHandle layer_handle = dlopen(
272 (dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
273 if (!layer_handle) {
274 ALOGE("%s failed to load with error %s; Skipping",
275 entry->d_name, dlerror());
276 continue;
277 }
278
279 // Get Layers in so
280 PFN_vkGetGlobalLayerProperties get_layer_properties =
281 reinterpret_cast<PFN_vkGetGlobalLayerProperties>(
282 dlsym(layer_handle, "vkGetGlobalLayerProperties"));
283 if (!get_layer_properties) {
284 ALOGE(
285 "%s failed to find vkGetGlobalLayerProperties with "
286 "error %s; Skipping",
287 entry->d_name, dlerror());
288 dlclose(layer_handle);
289 continue;
290 }
291 uint32_t count;
292 get_layer_properties(&count, nullptr);
293
294 properties.resize(count);
295 get_layer_properties(&count, &properties[0]);
296
297 // Add Layers to potential list
Michael Lentine03c64b02015-08-26 18:27:26 -0500298 for (uint32_t i = 0; i < count; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500299 String layer_name(properties[i].layerName,
300 CallbackAllocator<char>(instance.alloc));
301 LayerData layer_data = {dir_name + entry->d_name, 0, 0};
302 instance.layers.insert(std::make_pair(layer_name, layer_data));
Michael Lentine03c64b02015-08-26 18:27:26 -0500303 ALOGV("Found layer %s", properties[i].layerName);
304 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500305 dlclose(layer_handle);
Michael Lentine03c64b02015-08-26 18:27:26 -0500306 }
307 closedir(directory);
308 } else {
309 ALOGE("Failed to Open Directory %s: %s (%d)", dir_name.c_str(),
310 strerror(errno), errno);
311 }
312}
313
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500314template <class TObject>
315void ActivateLayer(TObject* object, Instance* instance, const String& name) {
316 // If object has layer, do nothing
317 auto element = instance->layers.find(name);
318 if (std::find(object->active_layers.begin(), object->active_layers.end(),
319 element) != object->active_layers.end()) {
320 ALOGW("Layer %s already activated; skipping", name.c_str());
321 return;
322 }
323 // If layer is not open, open it
324 LayerData& layer_data = element->second;
325 pthread_mutex_lock(&instance->layer_lock);
326 if (layer_data.ref_count == 0) {
327 SharedLibraryHandle layer_handle =
328 dlopen(layer_data.path.c_str(), RTLD_NOW | RTLD_LOCAL);
329 if (!layer_handle) {
330 pthread_mutex_unlock(&instance->layer_lock);
331 ALOGE("%s failed to load with error %s; Skipping",
332 layer_data.path.c_str(), dlerror());
333 return;
334 }
335 layer_data.handle = layer_handle;
336 }
337 layer_data.ref_count++;
338 pthread_mutex_unlock(&instance->layer_lock);
339 ALOGV("Activating layer %s", name.c_str());
340 object->active_layers.push_back(element);
341}
342
343template <class TObject>
344void DeactivateLayer(TObject* object,
345 Instance* instance,
346 Vector<LayerMapIterator>::iterator& element) {
347 LayerMapIterator& layer_map_data = *element;
348 object->active_layers.erase(element);
349 LayerData& layer_data = layer_map_data->second;
350 pthread_mutex_lock(&instance->layer_lock);
351 layer_data.ref_count--;
352 if (!layer_data.ref_count) {
353 dlclose(layer_data.handle);
354 }
355 pthread_mutex_unlock(&instance->layer_lock);
356}
357
358struct InstanceDevicePair {
359 Instance* instance;
360 Device* device;
361};
362
363void ActivateLayerFromProperty(const char* name,
364 const char* value,
365 void* data) {
366 const char prefix[] = "debug.vulkan.layer.";
367 const size_t prefixlen = sizeof(prefix) - 1;
368 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
369 return;
370 auto instance_device_pair = static_cast<InstanceDevicePair*>(data);
371 Instance* instance = instance_device_pair->instance;
372 Device* device = instance_device_pair->device;
373 String layer_name_str(name + prefixlen,
374 CallbackAllocator<char>(instance->alloc));
375 if (device) {
376 ActivateLayer(device, instance, layer_name_str);
377 } else {
378 ActivateLayer(instance, instance, layer_name_str);
379 }
380}
381
382template <class TInfo, class TObject>
383void ActivateAllLayers(TInfo create_info, Instance* instance, TObject* object) {
384 ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
385 create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
386 "Cannot activate layers for unknown object %p", object);
387 CallbackAllocator<char> string_allocator(instance->alloc);
388 // Load system layers
389 {
390 char layer_prop[PROPERTY_VALUE_MAX];
391 property_get("debug.vulkan.layers", layer_prop, "");
392 String layer_name(string_allocator);
393 String layer_prop_str(layer_prop, string_allocator);
394 size_t end, start = 0;
395 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
396 layer_name = layer_prop_str.substr(start, end - start);
397 auto element = instance->layers.find(layer_name);
398 if (element != instance->layers.end()) {
399 ActivateLayer(object, instance, layer_name);
400 }
401 start = end + 1;
402 }
403 InstanceDevicePair instance_device_pair = {.instance = instance,
404 .device = 0};
405 if (create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO) {
406 instance_device_pair.device = reinterpret_cast<Device*>(object);
407 }
408 property_list(ActivateLayerFromProperty,
409 static_cast<void*>(&instance_device_pair));
410 }
411 // Load app layers
412 for (uint32_t i = 0; i < create_info->layerCount; ++i) {
413 String layer_name(create_info->ppEnabledLayerNames[i],
414 string_allocator);
415 auto element = instance->layers.find(layer_name);
416 if (element == instance->layers.end()) {
417 ALOGW("Cannot activate layer %s as it was not found.",
418 layer_name.c_str());
419 } else {
420 ActivateLayer(object, instance, layer_name);
421 }
422 }
423}
424
425template <class TCreateInfo>
426bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
427 const char* extension_name,
428 const VkAllocCallbacks* alloc) {
429 for (uint32_t i = 0; i < local_create_info.extensionCount; ++i) {
430 if (!strcmp(extension_name,
431 local_create_info.ppEnabledExtensionNames[i])) {
432 return false;
433 }
434 }
435 uint32_t extension_count = local_create_info.extensionCount;
436 local_create_info.extensionCount++;
437 void* mem = alloc->pfnAlloc(
438 alloc->pUserData, local_create_info.extensionCount * sizeof(char*),
439 alignof(char*), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
440 if (mem) {
441 const char** enabled_extensions = static_cast<const char**>(mem);
442 for (uint32_t i = 0; i < extension_count; ++i) {
443 enabled_extensions[i] =
444 local_create_info.ppEnabledExtensionNames[i];
445 }
446 enabled_extensions[extension_count] = extension_name;
447 local_create_info.ppEnabledExtensionNames = enabled_extensions;
448 } else {
449 ALOGW("%s extension cannot be enabled: memory allocation failed",
450 extension_name);
451 local_create_info.extensionCount--;
452 return false;
453 }
454 return true;
455}
456
457template <class T>
458void FreeAllocatedCreateInfo(T& local_create_info,
459 const VkAllocCallbacks* alloc) {
460 alloc->pfnFree(
461 alloc->pUserData,
462 const_cast<char**>(local_create_info.ppEnabledExtensionNames));
463}
464
465void LogDebugMessageCallback(VkFlags message_flags,
466 VkDbgObjectType /*obj_type*/,
467 uint64_t /*src_object*/,
468 size_t /*location*/,
469 int32_t message_code,
470 const char* layer_prefix,
471 const char* message,
472 void* /*user_data*/) {
473 if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
474 ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
475 } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
476 ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
477 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500478}
479
480VkResult CreateDeviceNoop(VkPhysicalDevice,
481 const VkDeviceCreateInfo*,
482 VkDevice*) {
483 return VK_SUCCESS;
484}
485
486PFN_vkVoidFunction GetLayerDeviceProcAddr(VkDevice device, const char* name) {
487 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
488 return reinterpret_cast<PFN_vkVoidFunction>(GetLayerDeviceProcAddr);
489 }
490 if (strcmp(name, "vkCreateDevice") == 0) {
491 return reinterpret_cast<PFN_vkVoidFunction>(CreateDeviceNoop);
492 }
493 if (!device)
494 return GetGlobalDeviceProcAddr(name);
495 Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500496 return loader_device->instance->drv.GetDeviceProcAddr(device, name);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500497}
498
Jesse Hall04f4f472015-08-16 19:51:04 -0700499// -----------------------------------------------------------------------------
500// "Bottom" functions. These are called at the end of the instance dispatch
501// chain.
502
503VkResult DestroyInstanceBottom(VkInstance instance) {
504 // These checks allow us to call DestroyInstanceBottom from any error path
505 // in CreateInstanceBottom, before the driver instance is fully initialized.
506 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
507 instance->drv.vtbl.DestroyInstance) {
508 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance);
509 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500510 for (auto it = instance->active_layers.begin();
511 it != instance->active_layers.end(); ++it) {
512 DeactivateLayer(instance, instance, it);
Michael Lentine03c64b02015-08-26 18:27:26 -0500513 }
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500514 if (instance->message) {
515 PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500516 DebugDestroyMessageCallback =
517 reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
518 vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500519 DebugDestroyMessageCallback(instance, instance->message);
520 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700521 const VkAllocCallbacks* alloc = instance->alloc;
522 instance->~VkInstance_T();
523 alloc->pfnFree(alloc->pUserData, instance);
524 return VK_SUCCESS;
525}
526
527VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
528 VkInstance* instance_ptr) {
529 Instance* instance = *instance_ptr;
530 VkResult result;
531
532 result =
533 g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
534 if (result != VK_SUCCESS) {
535 DestroyInstanceBottom(instance);
536 return result;
537 }
538
Michael Lentine03c64b02015-08-26 18:27:26 -0500539 if (!LoadInstanceVtbl(
540 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
541 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700542 DestroyInstanceBottom(instance);
543 return VK_ERROR_INITIALIZATION_FAILED;
544 }
545
546 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
547 // queryable from the Instance, and that the resulting function work for any
548 // VkDevice created from the instance.
549 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
550 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
551 "vkGetDeviceProcAddr"));
552 if (!instance->drv.GetDeviceProcAddr) {
553 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
554 DestroyInstanceBottom(instance);
555 return VK_ERROR_INITIALIZATION_FAILED;
556 }
557
558 hwvulkan_dispatch_t* dispatch =
559 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
560 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
561 // Skip setting dispatch->vtbl on the driver instance handle, since we
562 // never intentionally call through it; we go through Instance::drv.vtbl
563 // instead.
564 } else {
565 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
566 dispatch->magic);
567 DestroyInstanceBottom(instance);
568 return VK_ERROR_INITIALIZATION_FAILED;
569 }
570
571 uint32_t num_physical_devices = 0;
572 result = instance->drv.vtbl.EnumeratePhysicalDevices(
573 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
574 if (result != VK_SUCCESS) {
575 DestroyInstanceBottom(instance);
576 return VK_ERROR_INITIALIZATION_FAILED;
577 }
578 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
579 result = instance->drv.vtbl.EnumeratePhysicalDevices(
580 instance->drv.vtbl.instance, &num_physical_devices,
581 instance->physical_devices);
582 if (result != VK_SUCCESS) {
583 DestroyInstanceBottom(instance);
584 return VK_ERROR_INITIALIZATION_FAILED;
585 }
586 for (uint32_t i = 0; i < num_physical_devices; i++) {
587 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
588 instance->physical_devices[i]);
589 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
590 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
591 dispatch->magic);
592 DestroyInstanceBottom(instance);
593 return VK_ERROR_INITIALIZATION_FAILED;
594 }
595 dispatch->vtbl = instance->vtbl;
596 }
597 instance->drv.num_physical_devices = num_physical_devices;
598
599 instance->num_physical_devices = instance->drv.num_physical_devices;
600 return VK_SUCCESS;
601}
602
603VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
604 uint32_t* pdev_count,
605 VkPhysicalDevice* pdevs) {
606 uint32_t count = instance->num_physical_devices;
607 if (pdevs) {
608 count = std::min(count, *pdev_count);
609 std::copy(instance->physical_devices,
610 instance->physical_devices + count, pdevs);
611 }
612 *pdev_count = count;
613 return VK_SUCCESS;
614}
615
616VkResult GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
617 VkPhysicalDeviceFeatures* features) {
618 return GetVtbl(pdev)
619 ->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
620}
621
622VkResult GetPhysicalDeviceFormatPropertiesBottom(
623 VkPhysicalDevice pdev,
624 VkFormat format,
625 VkFormatProperties* properties) {
626 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
627 pdev, format, properties);
628}
629
630VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
631 VkPhysicalDevice pdev,
632 VkFormat format,
633 VkImageType type,
634 VkImageTiling tiling,
635 VkImageUsageFlags usage,
636 VkImageFormatProperties* properties) {
637 return GetVtbl(pdev)
638 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
639 pdev, format, type, tiling, usage, properties);
640}
641
642VkResult GetPhysicalDeviceLimitsBottom(VkPhysicalDevice pdev,
643 VkPhysicalDeviceLimits* limits) {
644 return GetVtbl(pdev)
645 ->instance->drv.vtbl.GetPhysicalDeviceLimits(pdev, limits);
646}
647
648VkResult GetPhysicalDevicePropertiesBottom(
649 VkPhysicalDevice pdev,
650 VkPhysicalDeviceProperties* properties) {
651 return GetVtbl(pdev)
652 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
653}
654
655VkResult GetPhysicalDeviceQueueCountBottom(VkPhysicalDevice pdev,
656 uint32_t* count) {
657 return GetVtbl(pdev)
658 ->instance->drv.vtbl.GetPhysicalDeviceQueueCount(pdev, count);
659}
660
661VkResult GetPhysicalDeviceQueuePropertiesBottom(
662 VkPhysicalDevice pdev,
663 uint32_t count,
664 VkPhysicalDeviceQueueProperties* properties) {
665 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueProperties(
666 pdev, count, properties);
667}
668
669VkResult GetPhysicalDeviceMemoryPropertiesBottom(
670 VkPhysicalDevice pdev,
671 VkPhysicalDeviceMemoryProperties* properties) {
672 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
673 pdev, properties);
674}
675
676VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
677 const VkDeviceCreateInfo* create_info,
678 VkDevice* out_device) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500679 Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700680 VkResult result;
681
682 void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
683 sizeof(Device), alignof(Device),
684 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
685 if (!mem)
686 return VK_ERROR_OUT_OF_HOST_MEMORY;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500687 Device* device = new (mem) Device(&instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700688
689 VkDevice drv_device;
690 result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
691 if (result != VK_SUCCESS) {
692 DestroyDevice(device);
693 return result;
694 }
695
Jesse Hall04f4f472015-08-16 19:51:04 -0700696 hwvulkan_dispatch_t* dispatch =
697 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
698 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
699 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500700 PFN_vkDestroyDevice destroy_device =
701 reinterpret_cast<PFN_vkDestroyDevice>(
702 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
703 destroy_device(drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700704 DestroyDevice(device);
705 return VK_ERROR_INITIALIZATION_FAILED;
706 }
707 dispatch->vtbl = &device->vtbl_storage;
708
Jesse Hallb1352bc2015-09-04 16:12:33 -0700709 device->vtbl_storage.GetSurfacePropertiesKHR = GetSurfacePropertiesKHR;
710 device->vtbl_storage.GetSurfaceFormatsKHR = GetSurfaceFormatsKHR;
711 device->vtbl_storage.GetSurfacePresentModesKHR = GetSurfacePresentModesKHR;
712 device->vtbl_storage.CreateSwapchainKHR = CreateSwapchainKHR;
713 device->vtbl_storage.DestroySwapchainKHR = DestroySwapchainKHR;
714 device->vtbl_storage.GetSwapchainImagesKHR = GetSwapchainImagesKHR;
715 device->vtbl_storage.AcquireNextImageKHR = AcquireNextImageKHR;
716 device->vtbl_storage.QueuePresentKHR = QueuePresentKHR;
717
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500718 ActivateAllLayers(create_info, &instance, device);
719
Michael Lentine03c64b02015-08-26 18:27:26 -0500720 void* base_object = static_cast<void*>(drv_device);
721 void* next_object = base_object;
722 VkLayerLinkedListElem* next_element;
723 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
724 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500725 device->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500726 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
727
728 for (size_t i = elem_list.size(); i > 0; i--) {
729 size_t idx = i - 1;
730 next_element = &elem_list[idx];
731 next_element->get_proc_addr =
732 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
733 next_element->base_object = base_object;
734 next_element->next_element = next_object;
735 next_object = static_cast<void*>(next_element);
736
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500737 auto& name = device->active_layers[idx]->first;
738 auto& handle = device->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -0500739 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500740 dlsym(handle, (name + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500741 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500742 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500743 dlsym(handle, "vkGetDeviceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -0700744 if (!next_get_proc_addr) {
745 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500746 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700747 next_object = next_element->next_element;
748 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
749 next_element->get_proc_addr);
750 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500751 }
752 }
753
754 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
755 static_cast<VkDevice>(next_object), next_get_proc_addr,
756 device->vtbl_storage)) {
757 DestroyDevice(device);
758 return VK_ERROR_INITIALIZATION_FAILED;
759 }
760
761 PFN_vkCreateDevice layer_createDevice =
762 reinterpret_cast<PFN_vkCreateDevice>(
763 device->vtbl_storage.GetDeviceProcAddr(drv_device,
764 "vkCreateDevice"));
765 layer_createDevice(pdev, create_info, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700766
767 *out_device = drv_device;
768 return VK_SUCCESS;
769}
770
771VkResult GetPhysicalDeviceExtensionPropertiesBottom(
772 VkPhysicalDevice pdev,
773 const char* layer_name,
774 uint32_t* properties_count,
775 VkExtensionProperties* properties) {
776 // TODO: what are we supposed to do with layer_name here?
777 return GetVtbl(pdev)
778 ->instance->drv.vtbl.GetPhysicalDeviceExtensionProperties(
779 pdev, layer_name, properties_count, properties);
780}
781
782VkResult GetPhysicalDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
783 uint32_t* properties_count,
784 VkLayerProperties* properties) {
785 return GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceLayerProperties(
786 pdev, properties_count, properties);
787}
788
789VkResult GetPhysicalDeviceSparseImageFormatPropertiesBottom(
790 VkPhysicalDevice pdev,
791 VkFormat format,
792 VkImageType type,
793 uint32_t samples,
794 VkImageUsageFlags usage,
795 VkImageTiling tiling,
796 uint32_t* properties_count,
797 VkSparseImageFormatProperties* properties) {
798 return GetVtbl(pdev)
799 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
800 pdev, format, type, samples, usage, tiling, properties_count,
801 properties);
802}
803
804PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
805
806const InstanceVtbl kBottomInstanceFunctions = {
807 // clang-format off
808 .instance = nullptr,
809 .CreateInstance = CreateInstanceBottom,
810 .DestroyInstance = DestroyInstanceBottom,
811 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
812 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
813 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
814 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
815 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
816 .GetPhysicalDeviceLimits = GetPhysicalDeviceLimitsBottom,
817 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
818 .GetPhysicalDeviceQueueCount = GetPhysicalDeviceQueueCountBottom,
819 .GetPhysicalDeviceQueueProperties = GetPhysicalDeviceQueuePropertiesBottom,
820 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
821 .CreateDevice = CreateDeviceBottom,
822 .GetPhysicalDeviceExtensionProperties = GetPhysicalDeviceExtensionPropertiesBottom,
823 .GetPhysicalDeviceLayerProperties = GetPhysicalDeviceLayerPropertiesBottom,
824 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700825 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700826 // clang-format on
827};
828
Michael Lentine03c64b02015-08-26 18:27:26 -0500829VkResult Noop(...) {
830 return VK_SUCCESS;
831}
832
Jesse Hall04f4f472015-08-16 19:51:04 -0700833PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500834 // TODO: Possibly move this into the instance table
835 // TODO: Possibly register the callbacks in the loader
836 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
837 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
838 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
839 }
840 if (strcmp(name, "vkCreateInstance") == 0) {
841 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
842 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700843 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
844}
845
846} // namespace
847
848// -----------------------------------------------------------------------------
849// Global functions. These are called directly from the loader entry points,
850// without going through a dispatch table.
851
852namespace vulkan {
853
854VkResult GetGlobalExtensionProperties(const char* /*layer_name*/,
855 uint32_t* count,
856 VkExtensionProperties* /*properties*/) {
857 if (!count)
858 return VK_ERROR_INVALID_POINTER;
859 if (!EnsureInitialized())
860 return VK_ERROR_UNAVAILABLE;
861
862 // TODO: not yet implemented
863 ALOGW("vkGetGlobalExtensionProperties not implemented");
864
865 *count = 0;
866 return VK_SUCCESS;
867}
868
869VkResult GetGlobalLayerProperties(uint32_t* count,
870 VkLayerProperties* /*properties*/) {
871 if (!count)
872 return VK_ERROR_INVALID_POINTER;
873 if (!EnsureInitialized())
874 return VK_ERROR_UNAVAILABLE;
875
876 // TODO: not yet implemented
877 ALOGW("vkGetGlobalLayerProperties not implemented");
878
879 *count = 0;
880 return VK_SUCCESS;
881}
882
883VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
884 VkInstance* out_instance) {
885 VkResult result;
886
887 if (!EnsureInitialized())
888 return VK_ERROR_UNAVAILABLE;
889
890 VkInstanceCreateInfo local_create_info = *create_info;
891 if (!local_create_info.pAllocCb)
892 local_create_info.pAllocCb = &kDefaultAllocCallbacks;
893 create_info = &local_create_info;
894
895 void* instance_mem = create_info->pAllocCb->pfnAlloc(
896 create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
897 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
898 if (!instance_mem)
899 return VK_ERROR_OUT_OF_HOST_MEMORY;
900 Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
901
902 instance->vtbl_storage = kBottomInstanceFunctions;
903 instance->vtbl_storage.instance = instance;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500904 instance->message = VK_NULL_HANDLE;
Jesse Hall04f4f472015-08-16 19:51:04 -0700905
Michael Lentine03c64b02015-08-26 18:27:26 -0500906 // Scan layers
Michael Lentine03c64b02015-08-26 18:27:26 -0500907 CallbackAllocator<char> string_allocator(instance->alloc);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500908
Michael Lentine03c64b02015-08-26 18:27:26 -0500909 String dir_name("/data/local/tmp/vulkan/", string_allocator);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500910 FindLayersInDirectory(*instance, dir_name);
Michael Lentine1c69b9e2015-09-14 13:26:59 -0500911 const std::string& path = LoaderData::GetInstance().layer_path;
912 dir_name.assign(path.c_str(), path.size());
913 dir_name.append("/");
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500914 FindLayersInDirectory(*instance, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700915
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500916 ActivateAllLayers(create_info, instance, instance);
Michael Lentine03c64b02015-08-26 18:27:26 -0500917
918 void* base_object = static_cast<void*>(instance);
919 void* next_object = base_object;
920 VkLayerLinkedListElem* next_element;
921 PFN_vkGetInstanceProcAddr next_get_proc_addr =
922 kBottomInstanceFunctions.GetInstanceProcAddr;
923 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700924 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500925 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
926
927 for (size_t i = elem_list.size(); i > 0; i--) {
928 size_t idx = i - 1;
929 next_element = &elem_list[idx];
930 next_element->get_proc_addr =
931 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
932 next_element->base_object = base_object;
933 next_element->next_element = next_object;
934 next_object = static_cast<void*>(next_element);
935
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500936 auto& name = instance->active_layers[idx]->first;
937 auto& handle = instance->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -0500938 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500939 dlsym(handle, (name + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500940 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500941 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500942 dlsym(handle, "vkGetInstanceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -0700943 if (!next_get_proc_addr) {
944 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500945 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700946 next_object = next_element->next_element;
947 next_get_proc_addr =
948 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
949 next_element->get_proc_addr);
950 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500951 }
952 }
953
954 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
955 static_cast<VkInstance>(next_object),
956 next_get_proc_addr, instance->vtbl_storage)) {
957 DestroyInstanceBottom(instance);
958 return VK_ERROR_INITIALIZATION_FAILED;
959 }
960
Michael Lentine950bb4f2015-09-14 13:26:30 -0500961 // Force enable callback extension if required
962 bool enable_callback =
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500963 property_get_bool("debug.vulkan.enable_callback", false);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500964 bool enable_logging = enable_callback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500965 const char* extension_name = "DEBUG_REPORT";
Michael Lentine950bb4f2015-09-14 13:26:30 -0500966 if (enable_callback) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500967 enable_callback = AddExtensionToCreateInfo(
968 local_create_info, extension_name, instance->alloc);
Michael Lentine950bb4f2015-09-14 13:26:30 -0500969 }
970
Jesse Hall04f4f472015-08-16 19:51:04 -0700971 *out_instance = instance;
Michael Lentine03c64b02015-08-26 18:27:26 -0500972 result = instance->vtbl_storage.CreateInstance(create_info, out_instance);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500973 if (enable_callback)
974 FreeAllocatedCreateInfo(local_create_info, instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -0700975 if (result <= 0) {
976 // For every layer, including the loader top and bottom layers:
977 // - If a call to the next CreateInstance fails, the layer must clean
978 // up anything it has successfully done so far, and propagate the
979 // error upwards.
980 // - If a layer successfully calls the next layer's CreateInstance, and
981 // afterwards must fail for some reason, it must call the next layer's
982 // DestroyInstance before returning.
983 // - The layer must not call the next layer's DestroyInstance if that
984 // layer's CreateInstance wasn't called, or returned failure.
985
986 // On failure, CreateInstanceBottom frees the instance struct, so it's
987 // already gone at this point. Nothing to do.
988 }
989
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500990 if (enable_logging) {
991 PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500992 DebugCreateMessageCallback =
993 reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
994 vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
995 DebugCreateMessageCallback(
996 instance, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
997 LogDebugMessageCallback, NULL, &instance->message);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500998 }
999
Jesse Hall04f4f472015-08-16 19:51:04 -07001000 return result;
1001}
1002
1003PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
1004 if (!instance)
1005 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001006 // TODO: Possibly move this into the instance table
1007 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
1008 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
1009 if (!instance->vtbl)
1010 return NULL;
1011 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
1012 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
1013 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001014 // For special-case functions we always return the loader entry
1015 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
1016 strcmp(name, "vkGetDeviceProcAddr") == 0) {
1017 return GetGlobalInstanceProcAddr(name);
1018 }
1019 return GetSpecificInstanceProcAddr(instance->vtbl, name);
1020}
1021
1022PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
1023 if (!device)
1024 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001025 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
1026 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
1027 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001028 if (strcmp(name, "vkGetDeviceQueue") == 0) {
1029 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue);
1030 }
1031 if (strcmp(name, "vkCreateCommandBuffer") == 0) {
1032 return reinterpret_cast<PFN_vkVoidFunction>(CreateCommandBuffer);
1033 }
1034 if (strcmp(name, "vkDestroyDevice") == 0) {
1035 return reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice);
1036 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001037 // For special-case functions we always return the loader entry
1038 if (strcmp(name, "vkGetDeviceQueue") == 0 ||
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001039 strcmp(name, "vkCreateCommandBuffer") == 0 ||
Jesse Hall04f4f472015-08-16 19:51:04 -07001040 strcmp(name, "vkDestroyDevice") == 0) {
1041 return GetGlobalDeviceProcAddr(name);
1042 }
1043 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
1044}
1045
1046VkResult GetDeviceQueue(VkDevice drv_device,
1047 uint32_t family,
1048 uint32_t index,
1049 VkQueue* out_queue) {
1050 VkResult result;
1051 VkQueue queue;
1052 const DeviceVtbl* vtbl = GetVtbl(drv_device);
1053 result = vtbl->GetDeviceQueue(drv_device, family, index, &queue);
1054 if (result != VK_SUCCESS)
1055 return result;
1056 hwvulkan_dispatch_t* dispatch =
1057 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
1058 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != &vtbl) {
1059 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
1060 return VK_ERROR_INITIALIZATION_FAILED;
1061 }
1062 dispatch->vtbl = vtbl;
1063 *out_queue = queue;
1064 return VK_SUCCESS;
1065}
1066
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001067VkResult CreateCommandBuffer(VkDevice drv_device,
1068 const VkCmdBufferCreateInfo* create_info,
1069 VkCmdBuffer* out_cmdbuf) {
1070 const DeviceVtbl* vtbl = GetVtbl(drv_device);
1071 VkCmdBuffer cmdbuf;
1072 VkResult result =
1073 vtbl->CreateCommandBuffer(drv_device, create_info, &cmdbuf);
1074 if (result != VK_SUCCESS)
1075 return result;
1076 hwvulkan_dispatch_t* dispatch =
1077 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuf);
1078 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
1079 ALOGE("invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
1080 dispatch->magic);
1081 return VK_ERROR_INITIALIZATION_FAILED;
1082 }
1083 dispatch->vtbl = vtbl;
1084 *out_cmdbuf = cmdbuf;
1085 return VK_SUCCESS;
1086}
1087
Jesse Hall04f4f472015-08-16 19:51:04 -07001088VkResult DestroyDevice(VkDevice drv_device) {
1089 const DeviceVtbl* vtbl = GetVtbl(drv_device);
1090 Device* device = static_cast<Device*>(vtbl->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001091 for (auto it = device->active_layers.begin();
1092 it != device->active_layers.end(); ++it) {
1093 DeactivateLayer(device, device->instance, it);
1094 }
1095 device->active_layers.clear();
Jesse Hall04f4f472015-08-16 19:51:04 -07001096 vtbl->DestroyDevice(drv_device);
1097 DestroyDevice(device);
1098 return VK_SUCCESS;
1099}
1100
Jesse Halld7b994a2015-09-07 14:17:37 -07001101void* AllocDeviceMem(VkDevice device,
1102 size_t size,
1103 size_t align,
1104 VkSystemAllocType type) {
1105 const VkAllocCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001106 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Halld7b994a2015-09-07 14:17:37 -07001107 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
1108}
1109
1110void FreeDeviceMem(VkDevice device, void* ptr) {
1111 const VkAllocCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001112 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Halld7b994a2015-09-07 14:17:37 -07001113 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1114}
1115
1116const DeviceVtbl& GetDriverVtbl(VkDevice device) {
1117 // TODO(jessehall): This actually returns the API-level vtbl for the
1118 // device, not the driver entry points. Given the current use -- getting
1119 // the driver's private swapchain-related functions -- that works, but is
1120 // misleading and likely to cause bugs. Fix as part of separating the
1121 // loader->driver interface from the app->loader interface.
1122 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
1123}
1124
1125const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
1126 // TODO(jessehall): This actually returns the API-level vtbl for the
1127 // device, not the driver entry points. Given the current use -- getting
1128 // the driver's private swapchain-related functions -- that works, but is
1129 // misleading and likely to cause bugs. Fix as part of separating the
1130 // loader->driver interface from the app->loader interface.
1131 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
1132}
1133
Jesse Hall04f4f472015-08-16 19:51:04 -07001134} // namespace vulkan