blob: 10877c5b0f210d383a1f2fdffd4872d84891406f [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>
Jesse Hall04f4f472015-08-16 19:51:04 -070025#include <pthread.h>
Jesse Hall03b6fe12015-11-24 12:44:21 -080026#include <stdlib.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070027#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
Jesse Hall03b6fe12015-11-24 12:44:21 -080061// Standard-library allocator that delegates to VkAllocCallbacks.
62//
63// TODO(jessehall): This class currently always uses
64// VK_SYSTEM_ALLOC_SCOPE_INSTANCE. The scope to use could be a template
65// parameter or a constructor parameter. The former would help catch bugs
66// where we use the wrong scope, e.g. adding a command-scope string to an
67// instance-scope vector. But that might also be pretty annoying to deal with.
Michael Lentine03c64b02015-08-26 18:27:26 -050068template <class T>
69class CallbackAllocator {
70 public:
71 typedef T value_type;
72
73 CallbackAllocator(const VkAllocCallbacks* alloc_input)
74 : alloc(alloc_input) {}
75
76 template <class T2>
77 CallbackAllocator(const CallbackAllocator<T2>& other)
78 : alloc(other.alloc) {}
79
80 T* allocate(std::size_t n) {
81 void* mem = alloc->pfnAlloc(alloc->pUserData, n * sizeof(T), alignof(T),
Jesse Hall03b6fe12015-11-24 12:44:21 -080082 VK_SYSTEM_ALLOC_SCOPE_INSTANCE);
Michael Lentine03c64b02015-08-26 18:27:26 -050083 return static_cast<T*>(mem);
84 }
85
86 void deallocate(T* array, std::size_t /*n*/) {
87 alloc->pfnFree(alloc->pUserData, array);
88 }
89
90 const VkAllocCallbacks* alloc;
91};
92// These are needed in order to move Strings
93template <class T>
94bool operator==(const CallbackAllocator<T>& alloc1,
95 const CallbackAllocator<T>& alloc2) {
96 return alloc1.alloc == alloc2.alloc;
97}
98template <class T>
99bool operator!=(const CallbackAllocator<T>& alloc1,
100 const CallbackAllocator<T>& alloc2) {
101 return !(alloc1 == alloc2);
102}
103
104template <class Key,
105 class T,
106 class Hash = std::hash<Key>,
107 class Pred = std::equal_to<Key> >
108using UnorderedMap =
109 std::unordered_map<Key,
110 T,
111 Hash,
112 Pred,
113 CallbackAllocator<std::pair<const Key, T> > >;
114
115template <class T>
116using Vector = std::vector<T, CallbackAllocator<T> >;
117
118typedef std::basic_string<char,
119 std::char_traits<char>,
120 CallbackAllocator<char> > String;
121
122} // namespace
123
124// -----------------------------------------------------------------------------
125
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500126namespace {
127
128struct LayerData {
129 String path;
130 SharedLibraryHandle handle;
131 uint32_t ref_count;
132};
133
134typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
135
136} // namespace
137
Jesse Hall04f4f472015-08-16 19:51:04 -0700138struct VkInstance_T {
139 VkInstance_T(const VkAllocCallbacks* alloc_callbacks)
Michael Lentine03c64b02015-08-26 18:27:26 -0500140 : vtbl(&vtbl_storage),
141 alloc(alloc_callbacks),
142 num_physical_devices(0),
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500143 layers(CallbackAllocator<std::pair<String, LayerData> >(alloc)),
144 active_layers(CallbackAllocator<String>(alloc)) {
145 pthread_mutex_init(&layer_lock, 0);
Jesse Hall04f4f472015-08-16 19:51:04 -0700146 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
147 memset(physical_devices, 0, sizeof(physical_devices));
148 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
149 drv.GetDeviceProcAddr = nullptr;
150 drv.num_physical_devices = 0;
151 }
152
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500153 ~VkInstance_T() { pthread_mutex_destroy(&layer_lock); }
154
Jesse Hall04f4f472015-08-16 19:51:04 -0700155 InstanceVtbl* vtbl;
156 InstanceVtbl vtbl_storage;
157
158 const VkAllocCallbacks* alloc;
159 uint32_t num_physical_devices;
160 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
161
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500162 pthread_mutex_t layer_lock;
163 // Map of layer names to layer data
164 UnorderedMap<String, LayerData> layers;
165 // Vector of layers active for this instance
166 Vector<LayerMapIterator> active_layers;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500167 VkDbgMsgCallback message;
Michael Lentine03c64b02015-08-26 18:27:26 -0500168
Jesse Hall04f4f472015-08-16 19:51:04 -0700169 struct Driver {
170 // Pointers to driver entry points. Used explicitly by the loader; not
171 // set as the dispatch table for any objects.
172 InstanceVtbl vtbl;
173
174 // Pointer to the driver's get_device_proc_addr, must be valid for any
175 // of the driver's physical devices. Not part of the InstanceVtbl since
176 // it's not an Instance/PhysicalDevice function.
177 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
178
179 // Number of physical devices owned by this driver.
180 uint32_t num_physical_devices;
181 } drv; // may eventually be an array
182};
183
184// -----------------------------------------------------------------------------
185
186namespace {
187
188typedef VkInstance_T Instance;
189
190struct Device {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500191 Device(Instance* instance_input)
192 : instance(instance_input),
193 active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700194 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
195 vtbl_storage.device = this;
196 }
197 DeviceVtbl vtbl_storage;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500198 Instance* instance;
199 // Vector of layers active for this device
200 Vector<LayerMapIterator> active_layers;
Jesse Hall04f4f472015-08-16 19:51:04 -0700201};
202
203// -----------------------------------------------------------------------------
204// Utility Code
205
206inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
207 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
208}
209
210inline const DeviceVtbl* GetVtbl(VkDevice device) {
211 return *reinterpret_cast<DeviceVtbl**>(device);
212}
Jesse Halld7b994a2015-09-07 14:17:37 -0700213inline const DeviceVtbl* GetVtbl(VkQueue queue) {
214 return *reinterpret_cast<DeviceVtbl**>(queue);
215}
Jesse Hall04f4f472015-08-16 19:51:04 -0700216
Jesse Hall03b6fe12015-11-24 12:44:21 -0800217void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocScope) {
218 void* ptr = nullptr;
219 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
220 // additionally requires that it be at least sizeof(void*).
221 return posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0
222 ? ptr
223 : nullptr;
224}
225
226void* DefaultRealloc(void*,
227 void* ptr,
228 size_t size,
229 size_t alignment,
230 VkSystemAllocScope) {
231 if (size == 0) {
232 free(ptr);
233 return nullptr;
234 }
235
236 // TODO(jessehall): Right now we never shrink allocations; if the new
237 // request is smaller than the existing chunk, we just continue using it.
238 // Right now the loader never reallocs, so this doesn't matter. If that
239 // changes, or if this code is copied into some other project, this should
240 // probably have a heuristic to allocate-copy-free when doing so will save
241 // "enough" space.
242 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
243 if (size <= old_size)
244 return ptr;
245
246 void* new_ptr = nullptr;
247 if (posix_memalign(&new_ptr, alignment, size) != 0)
248 return nullptr;
249 if (ptr) {
250 memcpy(new_ptr, ptr, std::min(old_size, size));
251 free(ptr);
252 }
253 return new_ptr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700254}
255
256void DefaultFree(void*, void* pMem) {
257 free(pMem);
258}
259
260const VkAllocCallbacks kDefaultAllocCallbacks = {
261 .pUserData = nullptr,
262 .pfnAlloc = DefaultAlloc,
Jesse Hall03b6fe12015-11-24 12:44:21 -0800263 .pfnRealloc = DefaultRealloc,
Jesse Hall04f4f472015-08-16 19:51:04 -0700264 .pfnFree = DefaultFree,
265};
266
267hwvulkan_device_t* g_hwdevice;
268bool EnsureInitialized() {
269 static std::once_flag once_flag;
270 static const hwvulkan_module_t* module;
271
272 std::call_once(once_flag, []() {
273 int result;
274 result = hw_get_module("vulkan",
275 reinterpret_cast<const hw_module_t**>(&module));
276 if (result != 0) {
277 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
278 result);
279 return;
280 }
281 result = module->common.methods->open(
282 &module->common, HWVULKAN_DEVICE_0,
283 reinterpret_cast<hw_device_t**>(&g_hwdevice));
284 if (result != 0) {
285 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
286 result);
287 module = nullptr;
288 return;
289 }
290 });
291
292 return module != nullptr && g_hwdevice != nullptr;
293}
294
295void DestroyDevice(Device* device) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500296 const VkAllocCallbacks* alloc = device->instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700297 device->~Device();
298 alloc->pfnFree(alloc->pUserData, device);
299}
300
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500301void FindLayersInDirectory(Instance& instance, const String& dir_name) {
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700302 DIR* directory = opendir(dir_name.c_str());
303 if (!directory) {
304 android_LogPriority log_priority =
305 (errno == ENOENT) ? ANDROID_LOG_VERBOSE : ANDROID_LOG_ERROR;
306 LOG_PRI(log_priority, LOG_TAG,
307 "failed to open layer directory '%s': %s (%d)",
308 dir_name.c_str(), strerror(errno), errno);
309 return;
Michael Lentine03c64b02015-08-26 18:27:26 -0500310 }
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700311
312 Vector<VkLayerProperties> properties(
313 CallbackAllocator<VkLayerProperties>(instance.alloc));
314 struct dirent* entry;
315 while ((entry = readdir(directory))) {
316 size_t length = strlen(entry->d_name);
317 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
318 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
319 continue;
320 // Open so
321 SharedLibraryHandle layer_handle =
322 dlopen((dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
323 if (!layer_handle) {
324 ALOGE("%s failed to load with error %s; Skipping", entry->d_name,
325 dlerror());
326 continue;
327 }
328
329 // Get Layers in so
330 PFN_vkEnumerateInstanceLayerProperties get_layer_properties =
331 reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
332 dlsym(layer_handle, "vkEnumerateInstanceLayerProperties"));
333 if (!get_layer_properties) {
334 ALOGE(
335 "%s failed to find vkEnumerateInstanceLayerProperties with "
336 "error %s; Skipping",
337 entry->d_name, dlerror());
338 dlclose(layer_handle);
339 continue;
340 }
341 uint32_t count;
342 get_layer_properties(&count, nullptr);
343
344 properties.resize(count);
345 get_layer_properties(&count, &properties[0]);
346
347 // Add Layers to potential list
348 for (uint32_t i = 0; i < count; ++i) {
349 String layer_name(properties[i].layerName,
350 CallbackAllocator<char>(instance.alloc));
351 LayerData layer_data = {dir_name + entry->d_name, 0, 0};
352 instance.layers.insert(std::make_pair(layer_name, layer_data));
353 ALOGV("Found layer %s", properties[i].layerName);
354 }
355 dlclose(layer_handle);
356 }
357
358 closedir(directory);
Michael Lentine03c64b02015-08-26 18:27:26 -0500359}
360
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500361template <class TObject>
362void ActivateLayer(TObject* object, Instance* instance, const String& name) {
363 // If object has layer, do nothing
364 auto element = instance->layers.find(name);
Michael Lentine233ac732015-11-18 18:28:07 -0800365 if (element == instance->layers.end()) {
366 return;
367 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500368 if (std::find(object->active_layers.begin(), object->active_layers.end(),
369 element) != object->active_layers.end()) {
370 ALOGW("Layer %s already activated; skipping", name.c_str());
371 return;
372 }
373 // If layer is not open, open it
374 LayerData& layer_data = element->second;
375 pthread_mutex_lock(&instance->layer_lock);
376 if (layer_data.ref_count == 0) {
377 SharedLibraryHandle layer_handle =
378 dlopen(layer_data.path.c_str(), RTLD_NOW | RTLD_LOCAL);
379 if (!layer_handle) {
380 pthread_mutex_unlock(&instance->layer_lock);
381 ALOGE("%s failed to load with error %s; Skipping",
382 layer_data.path.c_str(), dlerror());
383 return;
384 }
385 layer_data.handle = layer_handle;
386 }
387 layer_data.ref_count++;
388 pthread_mutex_unlock(&instance->layer_lock);
389 ALOGV("Activating layer %s", name.c_str());
390 object->active_layers.push_back(element);
391}
392
Michael Lentine1d1e65f2015-11-19 14:23:06 -0800393void DeactivateLayer(Instance* instance,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500394 Vector<LayerMapIterator>::iterator& element) {
395 LayerMapIterator& layer_map_data = *element;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500396 LayerData& layer_data = layer_map_data->second;
397 pthread_mutex_lock(&instance->layer_lock);
398 layer_data.ref_count--;
399 if (!layer_data.ref_count) {
400 dlclose(layer_data.handle);
401 }
402 pthread_mutex_unlock(&instance->layer_lock);
403}
404
Michael Lentine9da191b2015-10-13 11:08:45 -0500405struct InstanceNamesPair {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500406 Instance* instance;
Michael Lentine9da191b2015-10-13 11:08:45 -0500407 Vector<String>* layer_names;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500408};
409
Michael Lentine9da191b2015-10-13 11:08:45 -0500410void SetLayerNamesFromProperty(const char* name,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500411 const char* value,
412 void* data) {
413 const char prefix[] = "debug.vulkan.layer.";
414 const size_t prefixlen = sizeof(prefix) - 1;
415 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
416 return;
Michael Lentine9da191b2015-10-13 11:08:45 -0500417 const char* number_str = name + prefixlen;
418 long layer_number = strtol(number_str, nullptr, 10);
419 if (layer_number <= 0 || layer_number == LONG_MAX) {
420 ALOGW("Cannot use a layer at number %ld from string %s", layer_number,
421 number_str);
422 return;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500423 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500424 auto instance_names_pair = static_cast<InstanceNamesPair*>(data);
425 Vector<String>* layer_names = instance_names_pair->layer_names;
426 Instance* instance = instance_names_pair->instance;
427 size_t layer_size = static_cast<size_t>(layer_number);
428 if (layer_size > layer_names->size()) {
429 layer_names->resize(layer_size,
430 String(CallbackAllocator<char>(instance->alloc)));
431 }
432 (*layer_names)[layer_size - 1] = value;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500433}
434
435template <class TInfo, class TObject>
Jesse Hall9a16f972015-10-28 15:59:53 -0700436VkResult ActivateAllLayers(TInfo create_info, Instance* instance, TObject* object) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500437 ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
438 create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
439 "Cannot activate layers for unknown object %p", object);
440 CallbackAllocator<char> string_allocator(instance->alloc);
441 // Load system layers
442 {
443 char layer_prop[PROPERTY_VALUE_MAX];
444 property_get("debug.vulkan.layers", layer_prop, "");
445 String layer_name(string_allocator);
446 String layer_prop_str(layer_prop, string_allocator);
447 size_t end, start = 0;
448 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
449 layer_name = layer_prop_str.substr(start, end - start);
Michael Lentine233ac732015-11-18 18:28:07 -0800450 ActivateLayer(object, instance, layer_name);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500451 start = end + 1;
452 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500453 Vector<String> layer_names(CallbackAllocator<String>(instance->alloc));
454 InstanceNamesPair instance_names_pair = {.instance = instance,
455 .layer_names = &layer_names};
456 property_list(SetLayerNamesFromProperty,
457 static_cast<void*>(&instance_names_pair));
458 for (auto layer_name_element : layer_names) {
459 ActivateLayer(object, instance, layer_name_element);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500460 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500461 }
462 // Load app layers
Jesse Hall03b6fe12015-11-24 12:44:21 -0800463 for (uint32_t i = 0; i < create_info->enabledLayerNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500464 String layer_name(create_info->ppEnabledLayerNames[i],
465 string_allocator);
466 auto element = instance->layers.find(layer_name);
467 if (element == instance->layers.end()) {
Jesse Hall9a16f972015-10-28 15:59:53 -0700468 ALOGE("requested %s layer '%s' not present",
469 create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ?
470 "instance" : "device",
471 layer_name.c_str());
472 return VK_ERROR_LAYER_NOT_PRESENT;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500473 } else {
474 ActivateLayer(object, instance, layer_name);
475 }
476 }
Jesse Hall9a16f972015-10-28 15:59:53 -0700477 return VK_SUCCESS;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500478}
479
480template <class TCreateInfo>
481bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
482 const char* extension_name,
483 const VkAllocCallbacks* alloc) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800484 for (uint32_t i = 0; i < local_create_info.enabledExtensionNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500485 if (!strcmp(extension_name,
486 local_create_info.ppEnabledExtensionNames[i])) {
487 return false;
488 }
489 }
Jesse Hall03b6fe12015-11-24 12:44:21 -0800490 uint32_t extension_count = local_create_info.enabledExtensionNameCount;
491 local_create_info.enabledExtensionNameCount++;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500492 void* mem = alloc->pfnAlloc(
Jesse Hall03b6fe12015-11-24 12:44:21 -0800493 alloc->pUserData,
494 local_create_info.enabledExtensionNameCount * sizeof(char*),
495 alignof(char*), VK_SYSTEM_ALLOC_SCOPE_INSTANCE);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500496 if (mem) {
497 const char** enabled_extensions = static_cast<const char**>(mem);
498 for (uint32_t i = 0; i < extension_count; ++i) {
499 enabled_extensions[i] =
500 local_create_info.ppEnabledExtensionNames[i];
501 }
502 enabled_extensions[extension_count] = extension_name;
503 local_create_info.ppEnabledExtensionNames = enabled_extensions;
504 } else {
505 ALOGW("%s extension cannot be enabled: memory allocation failed",
506 extension_name);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800507 local_create_info.enabledExtensionNameCount--;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500508 return false;
509 }
510 return true;
511}
512
513template <class T>
514void FreeAllocatedCreateInfo(T& local_create_info,
515 const VkAllocCallbacks* alloc) {
516 alloc->pfnFree(
517 alloc->pUserData,
518 const_cast<char**>(local_create_info.ppEnabledExtensionNames));
519}
520
Michael Lentineeb970862015-10-15 12:42:22 -0500521VkBool32 LogDebugMessageCallback(VkFlags message_flags,
522 VkDbgObjectType /*obj_type*/,
523 uint64_t /*src_object*/,
524 size_t /*location*/,
525 int32_t message_code,
526 const char* layer_prefix,
527 const char* message,
528 void* /*user_data*/) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500529 if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
530 ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
531 } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
532 ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
533 }
Michael Lentineeb970862015-10-15 12:42:22 -0500534 return false;
Michael Lentine03c64b02015-08-26 18:27:26 -0500535}
536
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800537VkResult Noop(...) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500538 return VK_SUCCESS;
539}
540
541PFN_vkVoidFunction GetLayerDeviceProcAddr(VkDevice device, const char* name) {
542 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
543 return reinterpret_cast<PFN_vkVoidFunction>(GetLayerDeviceProcAddr);
544 }
545 if (strcmp(name, "vkCreateDevice") == 0) {
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800546 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
Michael Lentine03c64b02015-08-26 18:27:26 -0500547 }
Michael Lentine88594d72015-11-12 12:49:45 -0800548 // WSI extensions are not in the driver so return the loader functions
549 if (strcmp(name, "vkGetSurfacePropertiesKHR") == 0) {
550 return reinterpret_cast<PFN_vkVoidFunction>(GetSurfacePropertiesKHR);
551 }
552 if (strcmp(name, "vkGetSurfaceFormatsKHR") == 0) {
553 return reinterpret_cast<PFN_vkVoidFunction>(GetSurfaceFormatsKHR);
554 }
555 if (strcmp(name, "vkGetSurfacePresentModesKHR") == 0) {
556 return reinterpret_cast<PFN_vkVoidFunction>(GetSurfacePresentModesKHR);
557 }
558 if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
559 return reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR);
560 }
561 if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
562 return reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR);
563 }
564 if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
565 return reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR);
566 }
567 if (strcmp(name, "vkAcquireNextImageKHR") == 0) {
568 return reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR);
569 }
570 if (strcmp(name, "vkQueuePresentKHR") == 0) {
571 return reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR);
572 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500573 if (!device)
574 return GetGlobalDeviceProcAddr(name);
575 Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500576 return loader_device->instance->drv.GetDeviceProcAddr(device, name);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500577}
578
Jesse Hall04f4f472015-08-16 19:51:04 -0700579// -----------------------------------------------------------------------------
580// "Bottom" functions. These are called at the end of the instance dispatch
581// chain.
582
Jesse Hall03b6fe12015-11-24 12:44:21 -0800583void DestroyInstanceBottom(VkInstance instance,
584 const VkAllocCallbacks* allocator) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700585 // These checks allow us to call DestroyInstanceBottom from any error path
586 // in CreateInstanceBottom, before the driver instance is fully initialized.
587 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
588 instance->drv.vtbl.DestroyInstance) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800589 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance,
590 allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700591 }
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500592 if (instance->message) {
593 PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500594 DebugDestroyMessageCallback =
595 reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
596 vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500597 DebugDestroyMessageCallback(instance, instance->message);
598 }
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800599 for (auto it = instance->active_layers.begin();
600 it != instance->active_layers.end(); ++it) {
Michael Lentine1d1e65f2015-11-19 14:23:06 -0800601 DeactivateLayer(instance, it);
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800602 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700603 const VkAllocCallbacks* alloc = instance->alloc;
604 instance->~VkInstance_T();
605 alloc->pfnFree(alloc->pUserData, instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700606}
607
608VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
Jesse Hall03b6fe12015-11-24 12:44:21 -0800609 const VkAllocCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700610 VkInstance* instance_ptr) {
611 Instance* instance = *instance_ptr;
612 VkResult result;
613
Jesse Hall03b6fe12015-11-24 12:44:21 -0800614 result = g_hwdevice->CreateInstance(create_info, instance->alloc,
615 &instance->drv.vtbl.instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700616 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800617 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700618 return result;
619 }
620
Michael Lentine03c64b02015-08-26 18:27:26 -0500621 if (!LoadInstanceVtbl(
622 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
623 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800624 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700625 return VK_ERROR_INITIALIZATION_FAILED;
626 }
627
628 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
629 // queryable from the Instance, and that the resulting function work for any
630 // VkDevice created from the instance.
631 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
632 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
633 "vkGetDeviceProcAddr"));
634 if (!instance->drv.GetDeviceProcAddr) {
635 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
Jesse Hall03b6fe12015-11-24 12:44:21 -0800636 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700637 return VK_ERROR_INITIALIZATION_FAILED;
638 }
639
640 hwvulkan_dispatch_t* dispatch =
641 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
642 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
643 // Skip setting dispatch->vtbl on the driver instance handle, since we
644 // never intentionally call through it; we go through Instance::drv.vtbl
645 // instead.
646 } else {
647 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
648 dispatch->magic);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800649 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700650 return VK_ERROR_INITIALIZATION_FAILED;
651 }
652
653 uint32_t num_physical_devices = 0;
654 result = instance->drv.vtbl.EnumeratePhysicalDevices(
655 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
656 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800657 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700658 return VK_ERROR_INITIALIZATION_FAILED;
659 }
660 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
661 result = instance->drv.vtbl.EnumeratePhysicalDevices(
662 instance->drv.vtbl.instance, &num_physical_devices,
663 instance->physical_devices);
664 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800665 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700666 return VK_ERROR_INITIALIZATION_FAILED;
667 }
668 for (uint32_t i = 0; i < num_physical_devices; i++) {
669 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
670 instance->physical_devices[i]);
671 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
672 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
673 dispatch->magic);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800674 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700675 return VK_ERROR_INITIALIZATION_FAILED;
676 }
677 dispatch->vtbl = instance->vtbl;
678 }
679 instance->drv.num_physical_devices = num_physical_devices;
680
681 instance->num_physical_devices = instance->drv.num_physical_devices;
682 return VK_SUCCESS;
683}
684
685VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
686 uint32_t* pdev_count,
687 VkPhysicalDevice* pdevs) {
688 uint32_t count = instance->num_physical_devices;
689 if (pdevs) {
690 count = std::min(count, *pdev_count);
691 std::copy(instance->physical_devices,
692 instance->physical_devices + count, pdevs);
693 }
694 *pdev_count = count;
695 return VK_SUCCESS;
696}
697
Jesse Hall606a54e2015-11-19 22:17:28 -0800698void GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
699 VkPhysicalDeviceFeatures* features) {
700 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
Jesse Hall04f4f472015-08-16 19:51:04 -0700701}
702
Jesse Hall606a54e2015-11-19 22:17:28 -0800703void GetPhysicalDeviceFormatPropertiesBottom(VkPhysicalDevice pdev,
704 VkFormat format,
705 VkFormatProperties* properties) {
706 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700707 pdev, format, properties);
708}
709
Jesse Hall606a54e2015-11-19 22:17:28 -0800710void GetPhysicalDeviceImageFormatPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700711 VkPhysicalDevice pdev,
712 VkFormat format,
713 VkImageType type,
714 VkImageTiling tiling,
715 VkImageUsageFlags usage,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700716 VkImageCreateFlags flags,
Jesse Hall04f4f472015-08-16 19:51:04 -0700717 VkImageFormatProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800718 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
719 pdev, format, type, tiling, usage, flags, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700720}
721
Jesse Hall606a54e2015-11-19 22:17:28 -0800722void GetPhysicalDevicePropertiesBottom(VkPhysicalDevice pdev,
723 VkPhysicalDeviceProperties* properties) {
724 GetVtbl(pdev)
Jesse Hall04f4f472015-08-16 19:51:04 -0700725 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
726}
727
Jesse Hall606a54e2015-11-19 22:17:28 -0800728void GetPhysicalDeviceQueueFamilyPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700729 VkPhysicalDevice pdev,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700730 uint32_t* pCount,
731 VkQueueFamilyProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800732 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueFamilyProperties(
733 pdev, pCount, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700734}
735
Jesse Hall606a54e2015-11-19 22:17:28 -0800736void GetPhysicalDeviceMemoryPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700737 VkPhysicalDevice pdev,
738 VkPhysicalDeviceMemoryProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800739 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700740 pdev, properties);
741}
742
743VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
744 const VkDeviceCreateInfo* create_info,
Jesse Hall03b6fe12015-11-24 12:44:21 -0800745 const VkAllocCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700746 VkDevice* out_device) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500747 Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700748 VkResult result;
749
Jesse Hall03b6fe12015-11-24 12:44:21 -0800750 if (!allocator) {
751 if (instance.alloc)
752 allocator = instance.alloc;
753 else
754 allocator = &kDefaultAllocCallbacks;
755 }
756
757 void* mem =
758 allocator->pfnAlloc(allocator->pUserData, sizeof(Device),
759 alignof(Device), VK_SYSTEM_ALLOC_SCOPE_DEVICE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700760 if (!mem)
761 return VK_ERROR_OUT_OF_HOST_MEMORY;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500762 Device* device = new (mem) Device(&instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700763
Jesse Hall9a16f972015-10-28 15:59:53 -0700764 result = ActivateAllLayers(create_info, &instance, device);
765 if (result != VK_SUCCESS) {
766 DestroyDevice(device);
767 return result;
768 }
769
Jesse Hall04f4f472015-08-16 19:51:04 -0700770 VkDevice drv_device;
Jesse Hall03b6fe12015-11-24 12:44:21 -0800771 result = instance.drv.vtbl.CreateDevice(pdev, create_info, allocator,
772 &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700773 if (result != VK_SUCCESS) {
774 DestroyDevice(device);
775 return result;
776 }
777
Jesse Hall04f4f472015-08-16 19:51:04 -0700778 hwvulkan_dispatch_t* dispatch =
779 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
780 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
781 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500782 PFN_vkDestroyDevice destroy_device =
783 reinterpret_cast<PFN_vkDestroyDevice>(
784 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800785 destroy_device(drv_device, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700786 DestroyDevice(device);
787 return VK_ERROR_INITIALIZATION_FAILED;
788 }
789 dispatch->vtbl = &device->vtbl_storage;
790
Michael Lentine03c64b02015-08-26 18:27:26 -0500791 void* base_object = static_cast<void*>(drv_device);
792 void* next_object = base_object;
793 VkLayerLinkedListElem* next_element;
794 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
795 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500796 device->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500797 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
798
799 for (size_t i = elem_list.size(); i > 0; i--) {
800 size_t idx = i - 1;
801 next_element = &elem_list[idx];
802 next_element->get_proc_addr =
803 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
804 next_element->base_object = base_object;
805 next_element->next_element = next_object;
806 next_object = static_cast<void*>(next_element);
807
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500808 auto& name = device->active_layers[idx]->first;
809 auto& handle = device->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -0500810 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500811 dlsym(handle, (name + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500812 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500813 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500814 dlsym(handle, "vkGetDeviceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -0700815 if (!next_get_proc_addr) {
816 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500817 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700818 next_object = next_element->next_element;
819 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
820 next_element->get_proc_addr);
821 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500822 }
823 }
824
825 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
826 static_cast<VkDevice>(next_object), next_get_proc_addr,
827 device->vtbl_storage)) {
828 DestroyDevice(device);
829 return VK_ERROR_INITIALIZATION_FAILED;
830 }
831
832 PFN_vkCreateDevice layer_createDevice =
833 reinterpret_cast<PFN_vkCreateDevice>(
834 device->vtbl_storage.GetDeviceProcAddr(drv_device,
835 "vkCreateDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800836 layer_createDevice(pdev, create_info, allocator, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700837
Michael Lentine88594d72015-11-12 12:49:45 -0800838 // TODO(mlentine) : This is needed to use WSI layer validation. Remove this
839 // when new version of layer initialization exits.
840 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
841 static_cast<VkDevice>(next_object), next_get_proc_addr,
842 device->vtbl_storage)) {
843 DestroyDevice(device);
844 return VK_ERROR_INITIALIZATION_FAILED;
845 }
846
Jesse Hall04f4f472015-08-16 19:51:04 -0700847 *out_device = drv_device;
848 return VK_SUCCESS;
849}
850
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700851VkResult EnumerateDeviceExtensionPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700852 VkPhysicalDevice pdev,
853 const char* layer_name,
854 uint32_t* properties_count,
855 VkExtensionProperties* properties) {
856 // TODO: what are we supposed to do with layer_name here?
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700857 return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceExtensionProperties(
858 pdev, layer_name, properties_count, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700859}
860
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700861VkResult EnumerateDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
862 uint32_t* properties_count,
863 VkLayerProperties* properties) {
864 return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceLayerProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700865 pdev, properties_count, properties);
866}
867
Jesse Hall606a54e2015-11-19 22:17:28 -0800868void GetPhysicalDeviceSparseImageFormatPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700869 VkPhysicalDevice pdev,
870 VkFormat format,
871 VkImageType type,
872 uint32_t samples,
873 VkImageUsageFlags usage,
874 VkImageTiling tiling,
875 uint32_t* properties_count,
876 VkSparseImageFormatProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800877 GetVtbl(pdev)
Jesse Hall04f4f472015-08-16 19:51:04 -0700878 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
879 pdev, format, type, samples, usage, tiling, properties_count,
880 properties);
881}
882
883PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char*);
884
885const InstanceVtbl kBottomInstanceFunctions = {
886 // clang-format off
887 .instance = nullptr,
888 .CreateInstance = CreateInstanceBottom,
889 .DestroyInstance = DestroyInstanceBottom,
890 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
891 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
892 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
893 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
894 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700895 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700896 .GetPhysicalDeviceQueueFamilyProperties = GetPhysicalDeviceQueueFamilyPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700897 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
898 .CreateDevice = CreateDeviceBottom,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700899 .EnumerateDeviceExtensionProperties = EnumerateDeviceExtensionPropertiesBottom,
900 .EnumerateDeviceLayerProperties = EnumerateDeviceLayerPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700901 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallb1352bc2015-09-04 16:12:33 -0700902 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700903 // clang-format on
904};
905
906PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500907 // TODO: Possibly move this into the instance table
908 // TODO: Possibly register the callbacks in the loader
909 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
910 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
911 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
912 }
913 if (strcmp(name, "vkCreateInstance") == 0) {
914 return reinterpret_cast<PFN_vkVoidFunction>(CreateInstanceBottom);
915 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700916 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
917}
918
919} // namespace
920
921// -----------------------------------------------------------------------------
922// Global functions. These are called directly from the loader entry points,
923// without going through a dispatch table.
924
925namespace vulkan {
926
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700927VkResult EnumerateInstanceExtensionProperties(
928 const char* /*layer_name*/,
929 uint32_t* count,
930 VkExtensionProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700931 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700932 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700933
934 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700935 ALOGW("vkEnumerateInstanceExtensionProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700936
937 *count = 0;
938 return VK_SUCCESS;
939}
940
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700941VkResult EnumerateInstanceLayerProperties(uint32_t* count,
942 VkLayerProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700943 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700944 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700945
946 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700947 ALOGW("vkEnumerateInstanceLayerProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700948
949 *count = 0;
950 return VK_SUCCESS;
951}
952
953VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
Jesse Hall03b6fe12015-11-24 12:44:21 -0800954 const VkAllocCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700955 VkInstance* out_instance) {
956 VkResult result;
957
958 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700959 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700960
Jesse Hall03b6fe12015-11-24 12:44:21 -0800961 if (!allocator)
962 allocator = &kDefaultAllocCallbacks;
963
Jesse Hall04f4f472015-08-16 19:51:04 -0700964 VkInstanceCreateInfo local_create_info = *create_info;
Jesse Hall04f4f472015-08-16 19:51:04 -0700965 create_info = &local_create_info;
966
Jesse Hall03b6fe12015-11-24 12:44:21 -0800967 void* instance_mem =
968 allocator->pfnAlloc(allocator->pUserData, sizeof(Instance),
969 alignof(Instance), VK_SYSTEM_ALLOC_SCOPE_INSTANCE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700970 if (!instance_mem)
971 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jesse Hall03b6fe12015-11-24 12:44:21 -0800972 Instance* instance = new (instance_mem) Instance(allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700973
974 instance->vtbl_storage = kBottomInstanceFunctions;
975 instance->vtbl_storage.instance = instance;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500976 instance->message = VK_NULL_HANDLE;
Jesse Hall04f4f472015-08-16 19:51:04 -0700977
Michael Lentine03c64b02015-08-26 18:27:26 -0500978 // Scan layers
Michael Lentine03c64b02015-08-26 18:27:26 -0500979 CallbackAllocator<char> string_allocator(instance->alloc);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500980
Michael Lentine03c64b02015-08-26 18:27:26 -0500981 String dir_name("/data/local/tmp/vulkan/", string_allocator);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500982 FindLayersInDirectory(*instance, dir_name);
Michael Lentine1c69b9e2015-09-14 13:26:59 -0500983 const std::string& path = LoaderData::GetInstance().layer_path;
984 dir_name.assign(path.c_str(), path.size());
985 dir_name.append("/");
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500986 FindLayersInDirectory(*instance, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700987
Jesse Hall9a16f972015-10-28 15:59:53 -0700988 result = ActivateAllLayers(create_info, instance, instance);
989 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800990 DestroyInstanceBottom(instance, allocator);
Jesse Hall9a16f972015-10-28 15:59:53 -0700991 return result;
992 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500993
994 void* base_object = static_cast<void*>(instance);
995 void* next_object = base_object;
996 VkLayerLinkedListElem* next_element;
997 PFN_vkGetInstanceProcAddr next_get_proc_addr =
998 kBottomInstanceFunctions.GetInstanceProcAddr;
999 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -07001000 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -05001001 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
1002
1003 for (size_t i = elem_list.size(); i > 0; i--) {
1004 size_t idx = i - 1;
1005 next_element = &elem_list[idx];
1006 next_element->get_proc_addr =
1007 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
1008 next_element->base_object = base_object;
1009 next_element->next_element = next_object;
1010 next_object = static_cast<void*>(next_element);
1011
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001012 auto& name = instance->active_layers[idx]->first;
1013 auto& handle = instance->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -05001014 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001015 dlsym(handle, (name + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -05001016 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -05001017 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001018 dlsym(handle, "vkGetInstanceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -07001019 if (!next_get_proc_addr) {
1020 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001021 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -07001022 next_object = next_element->next_element;
1023 next_get_proc_addr =
1024 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
1025 next_element->get_proc_addr);
1026 }
Michael Lentine03c64b02015-08-26 18:27:26 -05001027 }
1028 }
1029
1030 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
1031 static_cast<VkInstance>(next_object),
1032 next_get_proc_addr, instance->vtbl_storage)) {
Jesse Hall03b6fe12015-11-24 12:44:21 -08001033 DestroyInstanceBottom(instance, allocator);
Michael Lentine03c64b02015-08-26 18:27:26 -05001034 return VK_ERROR_INITIALIZATION_FAILED;
1035 }
1036
Michael Lentine950bb4f2015-09-14 13:26:30 -05001037 // Force enable callback extension if required
1038 bool enable_callback =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001039 property_get_bool("debug.vulkan.enable_callback", false);
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001040 bool enable_logging = enable_callback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001041 const char* extension_name = "DEBUG_REPORT";
Michael Lentine950bb4f2015-09-14 13:26:30 -05001042 if (enable_callback) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001043 enable_callback = AddExtensionToCreateInfo(
1044 local_create_info, extension_name, instance->alloc);
Michael Lentine950bb4f2015-09-14 13:26:30 -05001045 }
1046
Jesse Hall04f4f472015-08-16 19:51:04 -07001047 *out_instance = instance;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001048 result = instance->vtbl_storage.CreateInstance(create_info, allocator,
1049 out_instance);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001050 if (enable_callback)
1051 FreeAllocatedCreateInfo(local_create_info, instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001052 if (result <= 0) {
1053 // For every layer, including the loader top and bottom layers:
1054 // - If a call to the next CreateInstance fails, the layer must clean
1055 // up anything it has successfully done so far, and propagate the
1056 // error upwards.
1057 // - If a layer successfully calls the next layer's CreateInstance, and
1058 // afterwards must fail for some reason, it must call the next layer's
1059 // DestroyInstance before returning.
1060 // - The layer must not call the next layer's DestroyInstance if that
1061 // layer's CreateInstance wasn't called, or returned failure.
1062
1063 // On failure, CreateInstanceBottom frees the instance struct, so it's
1064 // already gone at this point. Nothing to do.
1065 }
1066
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001067 if (enable_logging) {
1068 PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001069 DebugCreateMessageCallback =
1070 reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
1071 vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
1072 DebugCreateMessageCallback(
1073 instance, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
1074 LogDebugMessageCallback, NULL, &instance->message);
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001075 }
1076
Jesse Hall04f4f472015-08-16 19:51:04 -07001077 return result;
1078}
1079
1080PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
1081 if (!instance)
1082 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001083 // TODO: Possibly move this into the instance table
1084 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
1085 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
1086 if (!instance->vtbl)
1087 return NULL;
1088 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
1089 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
1090 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001091 // For special-case functions we always return the loader entry
1092 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
1093 strcmp(name, "vkGetDeviceProcAddr") == 0) {
1094 return GetGlobalInstanceProcAddr(name);
1095 }
1096 return GetSpecificInstanceProcAddr(instance->vtbl, name);
1097}
1098
1099PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
1100 if (!device)
1101 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001102 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
1103 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
1104 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001105 if (strcmp(name, "vkGetDeviceQueue") == 0) {
1106 return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue);
1107 }
Jesse Hallfbf97b02015-11-20 14:17:03 -08001108 if (strcmp(name, "vkAllocCommandBuffers") == 0) {
1109 return reinterpret_cast<PFN_vkVoidFunction>(AllocCommandBuffers);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001110 }
1111 if (strcmp(name, "vkDestroyDevice") == 0) {
1112 return reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice);
1113 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001114 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
1115}
1116
Jesse Hall606a54e2015-11-19 22:17:28 -08001117void GetDeviceQueue(VkDevice drv_device,
1118 uint32_t family,
1119 uint32_t index,
1120 VkQueue* out_queue) {
Jesse Hall04f4f472015-08-16 19:51:04 -07001121 VkResult result;
1122 VkQueue queue;
1123 const DeviceVtbl* vtbl = GetVtbl(drv_device);
Jesse Hall606a54e2015-11-19 22:17:28 -08001124 vtbl->GetDeviceQueue(drv_device, family, index, &queue);
Jesse Hall04f4f472015-08-16 19:51:04 -07001125 hwvulkan_dispatch_t* dispatch =
1126 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
Jesse Hall606a54e2015-11-19 22:17:28 -08001127 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != vtbl)
Jesse Hall04f4f472015-08-16 19:51:04 -07001128 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Jesse Hall04f4f472015-08-16 19:51:04 -07001129 dispatch->vtbl = vtbl;
1130 *out_queue = queue;
Jesse Hall04f4f472015-08-16 19:51:04 -07001131}
1132
Jesse Hallfbf97b02015-11-20 14:17:03 -08001133VkResult AllocCommandBuffers(VkDevice device,
1134 const VkCmdBufferAllocInfo* alloc_info,
1135 VkCmdBuffer* cmdbuffers) {
1136 const DeviceVtbl* vtbl = GetVtbl(device);
1137 VkResult result = vtbl->AllocCommandBuffers(device, alloc_info, cmdbuffers);
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001138 if (result != VK_SUCCESS)
1139 return result;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001140 for (uint32_t i = 0; i < alloc_info->bufferCount; i++) {
Jesse Hallfbf97b02015-11-20 14:17:03 -08001141 hwvulkan_dispatch_t* dispatch =
1142 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuffers[i]);
1143 ALOGE_IF(dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
1144 "invalid VkCmdBuffer dispatch magic: 0x%" PRIxPTR,
1145 dispatch->magic);
1146 dispatch->vtbl = vtbl;
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001147 }
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001148 return VK_SUCCESS;
1149}
1150
Jesse Hall03b6fe12015-11-24 12:44:21 -08001151VkResult DestroyDevice(VkDevice drv_device,
1152 const VkAllocCallbacks* /*allocator*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -07001153 const DeviceVtbl* vtbl = GetVtbl(drv_device);
1154 Device* device = static_cast<Device*>(vtbl->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001155 for (auto it = device->active_layers.begin();
1156 it != device->active_layers.end(); ++it) {
Michael Lentine1d1e65f2015-11-19 14:23:06 -08001157 DeactivateLayer(device->instance, it);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001158 }
Jesse Hall03b6fe12015-11-24 12:44:21 -08001159 vtbl->DestroyDevice(drv_device, device->instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001160 DestroyDevice(device);
1161 return VK_SUCCESS;
1162}
1163
Jesse Hall1356b0d2015-11-23 17:24:58 -08001164void* AllocMem(VkInstance instance,
1165 size_t size,
1166 size_t align,
Jesse Hall03b6fe12015-11-24 12:44:21 -08001167 VkSystemAllocScope scope) {
Jesse Hall1356b0d2015-11-23 17:24:58 -08001168 const VkAllocCallbacks* alloc_cb = instance->alloc;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001169 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, scope);
Jesse Hall1356b0d2015-11-23 17:24:58 -08001170}
1171
1172void FreeMem(VkInstance instance, void* ptr) {
1173 const VkAllocCallbacks* alloc_cb = instance->alloc;
1174 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1175}
1176
1177void* AllocMem(VkDevice device,
1178 size_t size,
1179 size_t align,
Jesse Hall03b6fe12015-11-24 12:44:21 -08001180 VkSystemAllocScope scope) {
Jesse Halld7b994a2015-09-07 14:17:37 -07001181 const VkAllocCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001182 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001183 return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, scope);
Jesse Halld7b994a2015-09-07 14:17:37 -07001184}
1185
Jesse Hall1356b0d2015-11-23 17:24:58 -08001186void FreeMem(VkDevice device, void* ptr) {
Jesse Halld7b994a2015-09-07 14:17:37 -07001187 const VkAllocCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001188 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Halld7b994a2015-09-07 14:17:37 -07001189 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1190}
1191
1192const DeviceVtbl& GetDriverVtbl(VkDevice device) {
1193 // TODO(jessehall): This actually returns the API-level vtbl for the
1194 // device, not the driver entry points. Given the current use -- getting
1195 // the driver's private swapchain-related functions -- that works, but is
1196 // misleading and likely to cause bugs. Fix as part of separating the
1197 // loader->driver interface from the app->loader interface.
1198 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
1199}
1200
1201const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
1202 // TODO(jessehall): This actually returns the API-level vtbl for the
1203 // device, not the driver entry points. Given the current use -- getting
1204 // the driver's private swapchain-related functions -- that works, but is
1205 // misleading and likely to cause bugs. Fix as part of separating the
1206 // loader->driver interface from the app->loader interface.
1207 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
1208}
1209
Jesse Hall04f4f472015-08-16 19:51:04 -07001210} // namespace vulkan