blob: f884e8bc1ad16c9d812be67a75367531436aaf02 [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>
Jesse Hall21597662015-12-18 13:48:24 -080028#include <sys/prctl.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070029// standard C++ headers
30#include <algorithm>
31#include <mutex>
Michael Lentine03c64b02015-08-26 18:27:26 -050032#include <sstream>
33#include <string>
34#include <unordered_map>
35#include <vector>
Jesse Hall04f4f472015-08-16 19:51:04 -070036// platform/library headers
Michael Lentine03c64b02015-08-26 18:27:26 -050037#include <cutils/properties.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070038#include <hardware/hwvulkan.h>
39#include <log/log.h>
Michael Lentinecd6cabf2015-09-14 17:32:59 -050040#include <vulkan/vk_debug_report_lunarg.h>
Michael Lentine1c69b9e2015-09-14 13:26:59 -050041#include <vulkan/vulkan_loader_data.h>
Jesse Hall04f4f472015-08-16 19:51:04 -070042
43using namespace vulkan;
44
45static const uint32_t kMaxPhysicalDevices = 4;
46
Michael Lentine03c64b02015-08-26 18:27:26 -050047namespace {
48
Jesse Hall1f91d392015-12-11 16:28:44 -080049// Define Handle typedef to be void* as returned from dlopen.
50typedef void* SharedLibraryHandle;
51
Michael Lentine03c64b02015-08-26 18:27:26 -050052// These definitions are taken from the LunarG Vulkan Loader. They are used to
53// enforce compatability between the Loader and Layers.
54typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
55
56typedef struct VkLayerLinkedListElem_ {
57 PFN_vkGetProcAddr get_proc_addr;
58 void* next_element;
59 void* base_object;
60} VkLayerLinkedListElem;
61
Jesse Hall1f91d392015-12-11 16:28:44 -080062// ----------------------------------------------------------------------------
Michael Lentine03c64b02015-08-26 18:27:26 -050063
Jesse Hall3fbc8562015-11-29 22:10:52 -080064// Standard-library allocator that delegates to VkAllocationCallbacks.
Jesse Hall03b6fe12015-11-24 12:44:21 -080065//
66// TODO(jessehall): This class currently always uses
Jesse Hall3fbc8562015-11-29 22:10:52 -080067// VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE. The scope to use could be a template
Jesse Hall03b6fe12015-11-24 12:44:21 -080068// parameter or a constructor parameter. The former would help catch bugs
69// where we use the wrong scope, e.g. adding a command-scope string to an
70// instance-scope vector. But that might also be pretty annoying to deal with.
Michael Lentine03c64b02015-08-26 18:27:26 -050071template <class T>
72class CallbackAllocator {
73 public:
74 typedef T value_type;
75
Jesse Hall3fbc8562015-11-29 22:10:52 -080076 CallbackAllocator(const VkAllocationCallbacks* alloc_input)
Michael Lentine03c64b02015-08-26 18:27:26 -050077 : alloc(alloc_input) {}
78
79 template <class T2>
80 CallbackAllocator(const CallbackAllocator<T2>& other)
81 : alloc(other.alloc) {}
82
83 T* allocate(std::size_t n) {
Jesse Hall3fbc8562015-11-29 22:10:52 -080084 void* mem =
85 alloc->pfnAllocation(alloc->pUserData, n * sizeof(T), alignof(T),
86 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Michael Lentine03c64b02015-08-26 18:27:26 -050087 return static_cast<T*>(mem);
88 }
89
90 void deallocate(T* array, std::size_t /*n*/) {
91 alloc->pfnFree(alloc->pUserData, array);
92 }
93
Jesse Hall3fbc8562015-11-29 22:10:52 -080094 const VkAllocationCallbacks* alloc;
Michael Lentine03c64b02015-08-26 18:27:26 -050095};
96// These are needed in order to move Strings
97template <class T>
98bool operator==(const CallbackAllocator<T>& alloc1,
99 const CallbackAllocator<T>& alloc2) {
100 return alloc1.alloc == alloc2.alloc;
101}
102template <class T>
103bool operator!=(const CallbackAllocator<T>& alloc1,
104 const CallbackAllocator<T>& alloc2) {
105 return !(alloc1 == alloc2);
106}
107
108template <class Key,
109 class T,
110 class Hash = std::hash<Key>,
Jesse Hall1f91d392015-12-11 16:28:44 -0800111 class Pred = std::equal_to<Key>>
Michael Lentine03c64b02015-08-26 18:27:26 -0500112using UnorderedMap =
113 std::unordered_map<Key,
114 T,
115 Hash,
116 Pred,
Jesse Hall1f91d392015-12-11 16:28:44 -0800117 CallbackAllocator<std::pair<const Key, T>>>;
Michael Lentine03c64b02015-08-26 18:27:26 -0500118
119template <class T>
Jesse Hall1f91d392015-12-11 16:28:44 -0800120using Vector = std::vector<T, CallbackAllocator<T>>;
Michael Lentine03c64b02015-08-26 18:27:26 -0500121
Jesse Hall1f91d392015-12-11 16:28:44 -0800122typedef std::basic_string<char, std::char_traits<char>, CallbackAllocator<char>>
123 String;
Michael Lentine03c64b02015-08-26 18:27:26 -0500124
Jesse Hall1f91d392015-12-11 16:28:44 -0800125// ----------------------------------------------------------------------------
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500126
127struct LayerData {
128 String path;
129 SharedLibraryHandle handle;
130 uint32_t ref_count;
131};
132
133typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
134
Jesse Hall1f91d392015-12-11 16:28:44 -0800135// ----------------------------------------------------------------------------
Jesse Hall04f4f472015-08-16 19:51:04 -0700136
Jesse Halle1b12782015-11-30 11:27:32 -0800137VKAPI_ATTR void* DefaultAllocate(void*,
138 size_t size,
139 size_t alignment,
140 VkSystemAllocationScope) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800141 void* ptr = nullptr;
142 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
143 // additionally requires that it be at least sizeof(void*).
144 return posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0
145 ? ptr
146 : nullptr;
147}
148
Jesse Halle1b12782015-11-30 11:27:32 -0800149VKAPI_ATTR void* DefaultReallocate(void*,
150 void* ptr,
151 size_t size,
152 size_t alignment,
153 VkSystemAllocationScope) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800154 if (size == 0) {
155 free(ptr);
156 return nullptr;
157 }
158
159 // TODO(jessehall): Right now we never shrink allocations; if the new
160 // request is smaller than the existing chunk, we just continue using it.
161 // Right now the loader never reallocs, so this doesn't matter. If that
162 // changes, or if this code is copied into some other project, this should
163 // probably have a heuristic to allocate-copy-free when doing so will save
164 // "enough" space.
165 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
166 if (size <= old_size)
167 return ptr;
168
169 void* new_ptr = nullptr;
170 if (posix_memalign(&new_ptr, alignment, size) != 0)
171 return nullptr;
172 if (ptr) {
173 memcpy(new_ptr, ptr, std::min(old_size, size));
174 free(ptr);
175 }
176 return new_ptr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700177}
178
Jesse Halle1b12782015-11-30 11:27:32 -0800179VKAPI_ATTR void DefaultFree(void*, void* pMem) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700180 free(pMem);
181}
182
Jesse Hall3fbc8562015-11-29 22:10:52 -0800183const VkAllocationCallbacks kDefaultAllocCallbacks = {
Jesse Hall04f4f472015-08-16 19:51:04 -0700184 .pUserData = nullptr,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800185 .pfnAllocation = DefaultAllocate,
186 .pfnReallocation = DefaultReallocate,
Jesse Hall04f4f472015-08-16 19:51:04 -0700187 .pfnFree = DefaultFree,
188};
189
Jesse Hall1f91d392015-12-11 16:28:44 -0800190// ----------------------------------------------------------------------------
191
Jesse Hall04f4f472015-08-16 19:51:04 -0700192hwvulkan_device_t* g_hwdevice;
193bool EnsureInitialized() {
194 static std::once_flag once_flag;
195 static const hwvulkan_module_t* module;
196
197 std::call_once(once_flag, []() {
198 int result;
199 result = hw_get_module("vulkan",
200 reinterpret_cast<const hw_module_t**>(&module));
201 if (result != 0) {
202 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
203 result);
204 return;
205 }
206 result = module->common.methods->open(
207 &module->common, HWVULKAN_DEVICE_0,
208 reinterpret_cast<hw_device_t**>(&g_hwdevice));
209 if (result != 0) {
210 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
211 result);
212 module = nullptr;
213 return;
214 }
215 });
216
217 return module != nullptr && g_hwdevice != nullptr;
218}
219
Jesse Hall1f91d392015-12-11 16:28:44 -0800220// -----------------------------------------------------------------------------
221
222struct Instance {
223 Instance(const VkAllocationCallbacks* alloc_callbacks)
224 : dispatch_ptr(&dispatch),
225 handle(reinterpret_cast<VkInstance>(&dispatch_ptr)),
226 get_instance_proc_addr(nullptr),
227 alloc(alloc_callbacks),
228 num_physical_devices(0),
229 layers(CallbackAllocator<std::pair<String, LayerData>>(alloc)),
230 active_layers(CallbackAllocator<String>(alloc)),
231 message(VK_NULL_HANDLE) {
232 memset(&dispatch, 0, sizeof(dispatch));
233 memset(physical_devices, 0, sizeof(physical_devices));
234 pthread_mutex_init(&layer_lock, 0);
235 drv.instance = VK_NULL_HANDLE;
236 memset(&drv.dispatch, 0, sizeof(drv.dispatch));
237 drv.num_physical_devices = 0;
238 }
239
240 ~Instance() { pthread_mutex_destroy(&layer_lock); }
241
242 const InstanceDispatchTable* dispatch_ptr;
243 const VkInstance handle;
244 InstanceDispatchTable dispatch;
245
246 // TODO(jessehall): Only needed by GetInstanceProcAddr_Top for
247 // vkDbg*MessageCallback. Points to the outermost layer's function. Remove
248 // once the DEBUG_CALLBACK is integrated into the API file.
249 PFN_vkGetInstanceProcAddr get_instance_proc_addr;
250
251 const VkAllocationCallbacks* alloc;
252 uint32_t num_physical_devices;
253 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
254
255 pthread_mutex_t layer_lock;
256 // Map of layer names to layer data
257 UnorderedMap<String, LayerData> layers;
258 // Vector of layers active for this instance
259 Vector<LayerMapIterator> active_layers;
260 VkDbgMsgCallback message;
261
262 struct {
263 VkInstance instance;
264 DriverDispatchTable dispatch;
265 uint32_t num_physical_devices;
266 } drv; // may eventually be an array
267};
268
269struct Device {
270 Device(Instance* instance_)
271 : instance(instance_),
272 active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
273 memset(&dispatch, 0, sizeof(dispatch));
274 }
275 DeviceDispatchTable dispatch;
276 Instance* instance;
277 PFN_vkGetDeviceProcAddr get_device_proc_addr;
278 // Vector of layers active for this device
279 Vector<LayerMapIterator> active_layers;
280};
281
282template <typename THandle>
283struct HandleTraits {};
284template <>
285struct HandleTraits<VkInstance> {
286 typedef Instance LoaderObjectType;
287};
288template <>
289struct HandleTraits<VkPhysicalDevice> {
290 typedef Instance LoaderObjectType;
291};
292template <>
293struct HandleTraits<VkDevice> {
294 typedef Device LoaderObjectType;
295};
296template <>
297struct HandleTraits<VkQueue> {
298 typedef Device LoaderObjectType;
299};
300template <>
301struct HandleTraits<VkCommandBuffer> {
302 typedef Device LoaderObjectType;
303};
304
305template <typename THandle>
306typename HandleTraits<THandle>::LoaderObjectType& GetDispatchParent(
307 THandle handle) {
308 // TODO(jessehall): Make Instance and Device POD types (by removing the
309 // non-default constructors), so that offsetof is actually legal to use.
310 // The specific case we're using here is safe in gcc/clang (and probably
311 // most other C++ compilers), but isn't guaranteed by C++.
312 typedef typename HandleTraits<THandle>::LoaderObjectType ObjectType;
313#pragma clang diagnostic push
314#pragma clang diagnostic ignored "-Winvalid-offsetof"
315 const size_t kDispatchOffset = offsetof(ObjectType, dispatch);
316#pragma clang diagnostic pop
317
318 const auto& dispatch = GetDispatchTable(handle);
319 uintptr_t dispatch_addr = reinterpret_cast<uintptr_t>(&dispatch);
320 uintptr_t object_addr = dispatch_addr - kDispatchOffset;
321 return *reinterpret_cast<ObjectType*>(object_addr);
322}
323
324// -----------------------------------------------------------------------------
325
Jesse Hall04f4f472015-08-16 19:51:04 -0700326void DestroyDevice(Device* device) {
Jesse Hall3fbc8562015-11-29 22:10:52 -0800327 const VkAllocationCallbacks* alloc = device->instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700328 device->~Device();
329 alloc->pfnFree(alloc->pUserData, device);
330}
331
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500332void FindLayersInDirectory(Instance& instance, const String& dir_name) {
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700333 DIR* directory = opendir(dir_name.c_str());
334 if (!directory) {
Jesse Hall21597662015-12-18 13:48:24 -0800335 int err = errno;
336 ALOGW_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
337 dir_name.c_str(), strerror(err), err);
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700338 return;
Michael Lentine03c64b02015-08-26 18:27:26 -0500339 }
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700340
341 Vector<VkLayerProperties> properties(
342 CallbackAllocator<VkLayerProperties>(instance.alloc));
343 struct dirent* entry;
344 while ((entry = readdir(directory))) {
345 size_t length = strlen(entry->d_name);
346 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
347 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
348 continue;
349 // Open so
350 SharedLibraryHandle layer_handle =
351 dlopen((dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
352 if (!layer_handle) {
353 ALOGE("%s failed to load with error %s; Skipping", entry->d_name,
354 dlerror());
355 continue;
356 }
357
358 // Get Layers in so
359 PFN_vkEnumerateInstanceLayerProperties get_layer_properties =
360 reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
361 dlsym(layer_handle, "vkEnumerateInstanceLayerProperties"));
362 if (!get_layer_properties) {
363 ALOGE(
364 "%s failed to find vkEnumerateInstanceLayerProperties with "
365 "error %s; Skipping",
366 entry->d_name, dlerror());
367 dlclose(layer_handle);
368 continue;
369 }
370 uint32_t count;
371 get_layer_properties(&count, nullptr);
372
373 properties.resize(count);
374 get_layer_properties(&count, &properties[0]);
375
376 // Add Layers to potential list
377 for (uint32_t i = 0; i < count; ++i) {
378 String layer_name(properties[i].layerName,
379 CallbackAllocator<char>(instance.alloc));
380 LayerData layer_data = {dir_name + entry->d_name, 0, 0};
381 instance.layers.insert(std::make_pair(layer_name, layer_data));
382 ALOGV("Found layer %s", properties[i].layerName);
383 }
384 dlclose(layer_handle);
385 }
386
387 closedir(directory);
Michael Lentine03c64b02015-08-26 18:27:26 -0500388}
389
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500390template <class TObject>
391void ActivateLayer(TObject* object, Instance* instance, const String& name) {
392 // If object has layer, do nothing
393 auto element = instance->layers.find(name);
Michael Lentine233ac732015-11-18 18:28:07 -0800394 if (element == instance->layers.end()) {
395 return;
396 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500397 if (std::find(object->active_layers.begin(), object->active_layers.end(),
398 element) != object->active_layers.end()) {
399 ALOGW("Layer %s already activated; skipping", name.c_str());
400 return;
401 }
402 // If layer is not open, open it
403 LayerData& layer_data = element->second;
404 pthread_mutex_lock(&instance->layer_lock);
405 if (layer_data.ref_count == 0) {
406 SharedLibraryHandle layer_handle =
407 dlopen(layer_data.path.c_str(), RTLD_NOW | RTLD_LOCAL);
408 if (!layer_handle) {
409 pthread_mutex_unlock(&instance->layer_lock);
410 ALOGE("%s failed to load with error %s; Skipping",
411 layer_data.path.c_str(), dlerror());
412 return;
413 }
414 layer_data.handle = layer_handle;
415 }
416 layer_data.ref_count++;
417 pthread_mutex_unlock(&instance->layer_lock);
418 ALOGV("Activating layer %s", name.c_str());
419 object->active_layers.push_back(element);
420}
421
Jesse Hall1f91d392015-12-11 16:28:44 -0800422void DeactivateLayer(Instance& instance,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500423 Vector<LayerMapIterator>::iterator& element) {
424 LayerMapIterator& layer_map_data = *element;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500425 LayerData& layer_data = layer_map_data->second;
Jesse Hall1f91d392015-12-11 16:28:44 -0800426 pthread_mutex_lock(&instance.layer_lock);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500427 layer_data.ref_count--;
428 if (!layer_data.ref_count) {
429 dlclose(layer_data.handle);
430 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800431 pthread_mutex_unlock(&instance.layer_lock);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500432}
433
Michael Lentine9da191b2015-10-13 11:08:45 -0500434struct InstanceNamesPair {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500435 Instance* instance;
Michael Lentine9da191b2015-10-13 11:08:45 -0500436 Vector<String>* layer_names;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500437};
438
Michael Lentine9da191b2015-10-13 11:08:45 -0500439void SetLayerNamesFromProperty(const char* name,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500440 const char* value,
441 void* data) {
442 const char prefix[] = "debug.vulkan.layer.";
443 const size_t prefixlen = sizeof(prefix) - 1;
444 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
445 return;
Michael Lentine9da191b2015-10-13 11:08:45 -0500446 const char* number_str = name + prefixlen;
447 long layer_number = strtol(number_str, nullptr, 10);
448 if (layer_number <= 0 || layer_number == LONG_MAX) {
449 ALOGW("Cannot use a layer at number %ld from string %s", layer_number,
450 number_str);
451 return;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500452 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500453 auto instance_names_pair = static_cast<InstanceNamesPair*>(data);
454 Vector<String>* layer_names = instance_names_pair->layer_names;
455 Instance* instance = instance_names_pair->instance;
456 size_t layer_size = static_cast<size_t>(layer_number);
457 if (layer_size > layer_names->size()) {
458 layer_names->resize(layer_size,
459 String(CallbackAllocator<char>(instance->alloc)));
460 }
461 (*layer_names)[layer_size - 1] = value;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500462}
463
464template <class TInfo, class TObject>
Jesse Hall1f91d392015-12-11 16:28:44 -0800465VkResult ActivateAllLayers(TInfo create_info,
466 Instance* instance,
467 TObject* object) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500468 ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
469 create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
470 "Cannot activate layers for unknown object %p", object);
471 CallbackAllocator<char> string_allocator(instance->alloc);
472 // Load system layers
Jesse Hall21597662015-12-18 13:48:24 -0800473 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500474 char layer_prop[PROPERTY_VALUE_MAX];
475 property_get("debug.vulkan.layers", layer_prop, "");
476 String layer_name(string_allocator);
477 String layer_prop_str(layer_prop, string_allocator);
478 size_t end, start = 0;
479 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
480 layer_name = layer_prop_str.substr(start, end - start);
Michael Lentine233ac732015-11-18 18:28:07 -0800481 ActivateLayer(object, instance, layer_name);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500482 start = end + 1;
483 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500484 Vector<String> layer_names(CallbackAllocator<String>(instance->alloc));
485 InstanceNamesPair instance_names_pair = {.instance = instance,
486 .layer_names = &layer_names};
487 property_list(SetLayerNamesFromProperty,
488 static_cast<void*>(&instance_names_pair));
489 for (auto layer_name_element : layer_names) {
490 ActivateLayer(object, instance, layer_name_element);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500491 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500492 }
493 // Load app layers
Jesse Hall03b6fe12015-11-24 12:44:21 -0800494 for (uint32_t i = 0; i < create_info->enabledLayerNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500495 String layer_name(create_info->ppEnabledLayerNames[i],
496 string_allocator);
497 auto element = instance->layers.find(layer_name);
498 if (element == instance->layers.end()) {
Jesse Hall9a16f972015-10-28 15:59:53 -0700499 ALOGE("requested %s layer '%s' not present",
Jesse Hall1f91d392015-12-11 16:28:44 -0800500 create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
501 ? "instance"
502 : "device",
503 layer_name.c_str());
Jesse Hall9a16f972015-10-28 15:59:53 -0700504 return VK_ERROR_LAYER_NOT_PRESENT;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500505 } else {
506 ActivateLayer(object, instance, layer_name);
507 }
508 }
Jesse Hall9a16f972015-10-28 15:59:53 -0700509 return VK_SUCCESS;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500510}
511
512template <class TCreateInfo>
513bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
514 const char* extension_name,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800515 const VkAllocationCallbacks* alloc) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800516 for (uint32_t i = 0; i < local_create_info.enabledExtensionNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500517 if (!strcmp(extension_name,
518 local_create_info.ppEnabledExtensionNames[i])) {
519 return false;
520 }
521 }
Jesse Hall03b6fe12015-11-24 12:44:21 -0800522 uint32_t extension_count = local_create_info.enabledExtensionNameCount;
523 local_create_info.enabledExtensionNameCount++;
Jesse Hall3fbc8562015-11-29 22:10:52 -0800524 void* mem = alloc->pfnAllocation(
Jesse Hall03b6fe12015-11-24 12:44:21 -0800525 alloc->pUserData,
526 local_create_info.enabledExtensionNameCount * sizeof(char*),
Jesse Hall3fbc8562015-11-29 22:10:52 -0800527 alignof(char*), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500528 if (mem) {
529 const char** enabled_extensions = static_cast<const char**>(mem);
530 for (uint32_t i = 0; i < extension_count; ++i) {
531 enabled_extensions[i] =
532 local_create_info.ppEnabledExtensionNames[i];
533 }
534 enabled_extensions[extension_count] = extension_name;
535 local_create_info.ppEnabledExtensionNames = enabled_extensions;
536 } else {
537 ALOGW("%s extension cannot be enabled: memory allocation failed",
538 extension_name);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800539 local_create_info.enabledExtensionNameCount--;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500540 return false;
541 }
542 return true;
543}
544
545template <class T>
546void FreeAllocatedCreateInfo(T& local_create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800547 const VkAllocationCallbacks* alloc) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500548 alloc->pfnFree(
549 alloc->pUserData,
550 const_cast<char**>(local_create_info.ppEnabledExtensionNames));
551}
552
Jesse Halle1b12782015-11-30 11:27:32 -0800553VKAPI_ATTR
Michael Lentineeb970862015-10-15 12:42:22 -0500554VkBool32 LogDebugMessageCallback(VkFlags message_flags,
555 VkDbgObjectType /*obj_type*/,
556 uint64_t /*src_object*/,
557 size_t /*location*/,
558 int32_t message_code,
559 const char* layer_prefix,
560 const char* message,
561 void* /*user_data*/) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500562 if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
563 ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
564 } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
565 ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
566 }
Michael Lentineeb970862015-10-15 12:42:22 -0500567 return false;
Michael Lentine03c64b02015-08-26 18:27:26 -0500568}
569
Jesse Hall06193802015-12-03 16:12:51 -0800570VkResult Noop() {
Michael Lentine03c64b02015-08-26 18:27:26 -0500571 return VK_SUCCESS;
572}
573
Jesse Hall1f91d392015-12-11 16:28:44 -0800574} // anonymous namespace
575
576namespace vulkan {
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500577
Jesse Hall04f4f472015-08-16 19:51:04 -0700578// -----------------------------------------------------------------------------
579// "Bottom" functions. These are called at the end of the instance dispatch
580// chain.
581
Jesse Hall1f91d392015-12-11 16:28:44 -0800582VkResult CreateInstance_Bottom(const VkInstanceCreateInfo* create_info,
583 const VkAllocationCallbacks* allocator,
584 VkInstance* vkinstance) {
585 Instance& instance = GetDispatchParent(*vkinstance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700586 VkResult result;
587
Jesse Hall1f91d392015-12-11 16:28:44 -0800588 result = g_hwdevice->CreateInstance(create_info, instance.alloc,
589 &instance.drv.instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700590 if (result != VK_SUCCESS) {
Jesse Hall1f91d392015-12-11 16:28:44 -0800591 DestroyInstance_Bottom(instance.handle, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700592 return result;
593 }
594
Jesse Hall1f91d392015-12-11 16:28:44 -0800595 if (!LoadDriverDispatchTable(instance.drv.instance,
596 g_hwdevice->GetInstanceProcAddr,
597 instance.drv.dispatch)) {
598 DestroyInstance_Bottom(instance.handle, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700599 return VK_ERROR_INITIALIZATION_FAILED;
600 }
601
Jesse Hall1f91d392015-12-11 16:28:44 -0800602 hwvulkan_dispatch_t* drv_dispatch =
603 reinterpret_cast<hwvulkan_dispatch_t*>(instance.drv.instance);
604 if (drv_dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
605 // Skip setting drv_dispatch->vtbl, since we never call through it;
606 // we go through instance.drv.dispatch instead.
Jesse Hall04f4f472015-08-16 19:51:04 -0700607 } else {
608 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
Jesse Hall1f91d392015-12-11 16:28:44 -0800609 drv_dispatch->magic);
610 DestroyInstance_Bottom(instance.handle, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700611 return VK_ERROR_INITIALIZATION_FAILED;
612 }
613
614 uint32_t num_physical_devices = 0;
Jesse Hall1f91d392015-12-11 16:28:44 -0800615 result = instance.drv.dispatch.EnumeratePhysicalDevices(
616 instance.drv.instance, &num_physical_devices, nullptr);
Jesse Hall04f4f472015-08-16 19:51:04 -0700617 if (result != VK_SUCCESS) {
Jesse Hall1f91d392015-12-11 16:28:44 -0800618 DestroyInstance_Bottom(instance.handle, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700619 return VK_ERROR_INITIALIZATION_FAILED;
620 }
621 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
Jesse Hall1f91d392015-12-11 16:28:44 -0800622 result = instance.drv.dispatch.EnumeratePhysicalDevices(
623 instance.drv.instance, &num_physical_devices,
624 instance.physical_devices);
Jesse Hall04f4f472015-08-16 19:51:04 -0700625 if (result != VK_SUCCESS) {
Jesse Hall1f91d392015-12-11 16:28:44 -0800626 DestroyInstance_Bottom(instance.handle, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700627 return VK_ERROR_INITIALIZATION_FAILED;
628 }
629 for (uint32_t i = 0; i < num_physical_devices; i++) {
Jesse Hall1f91d392015-12-11 16:28:44 -0800630 hwvulkan_dispatch_t* pdev_dispatch =
631 reinterpret_cast<hwvulkan_dispatch_t*>(
632 instance.physical_devices[i]);
633 if (pdev_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700634 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
Jesse Hall1f91d392015-12-11 16:28:44 -0800635 pdev_dispatch->magic);
636 DestroyInstance_Bottom(instance.handle, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700637 return VK_ERROR_INITIALIZATION_FAILED;
638 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800639 pdev_dispatch->vtbl = instance.dispatch_ptr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700640 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800641 instance.drv.num_physical_devices = num_physical_devices;
Jesse Hall04f4f472015-08-16 19:51:04 -0700642
Jesse Hall1f91d392015-12-11 16:28:44 -0800643 instance.num_physical_devices = instance.drv.num_physical_devices;
Jesse Hall04f4f472015-08-16 19:51:04 -0700644 return VK_SUCCESS;
645}
646
Jesse Hall1f91d392015-12-11 16:28:44 -0800647PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance, const char* name) {
648 PFN_vkVoidFunction pfn;
649 if ((pfn = GetLoaderBottomProcAddr(name)))
650 return pfn;
651 // TODO: Possibly move this into the instance table
652 // TODO: Possibly register the callbacks in the loader
653 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
654 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
655 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
656 }
657 return nullptr;
658}
659
660VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance,
661 uint32_t* pdev_count,
662 VkPhysicalDevice* pdevs) {
663 Instance& instance = GetDispatchParent(vkinstance);
664 uint32_t count = instance.num_physical_devices;
Jesse Hall04f4f472015-08-16 19:51:04 -0700665 if (pdevs) {
666 count = std::min(count, *pdev_count);
Jesse Hall1f91d392015-12-11 16:28:44 -0800667 std::copy(instance.physical_devices, instance.physical_devices + count,
668 pdevs);
Jesse Hall04f4f472015-08-16 19:51:04 -0700669 }
670 *pdev_count = count;
671 return VK_SUCCESS;
672}
673
Jesse Hall1f91d392015-12-11 16:28:44 -0800674void GetPhysicalDeviceProperties_Bottom(
675 VkPhysicalDevice pdev,
676 VkPhysicalDeviceProperties* properties) {
677 GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceProperties(
678 pdev, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700679}
680
Jesse Hall1f91d392015-12-11 16:28:44 -0800681void GetPhysicalDeviceFeatures_Bottom(VkPhysicalDevice pdev,
682 VkPhysicalDeviceFeatures* features) {
683 GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFeatures(pdev,
684 features);
685}
686
687void GetPhysicalDeviceMemoryProperties_Bottom(
688 VkPhysicalDevice pdev,
689 VkPhysicalDeviceMemoryProperties* properties) {
690 GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceMemoryProperties(
691 pdev, properties);
692}
693
694void GetPhysicalDeviceQueueFamilyProperties_Bottom(
695 VkPhysicalDevice pdev,
696 uint32_t* pCount,
697 VkQueueFamilyProperties* properties) {
698 GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceQueueFamilyProperties(
699 pdev, pCount, properties);
700}
701
702void GetPhysicalDeviceFormatProperties_Bottom(VkPhysicalDevice pdev,
703 VkFormat format,
704 VkFormatProperties* properties) {
705 GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFormatProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700706 pdev, format, properties);
707}
708
Jesse Hall1f91d392015-12-11 16:28:44 -0800709VkResult GetPhysicalDeviceImageFormatProperties_Bottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700710 VkPhysicalDevice pdev,
711 VkFormat format,
712 VkImageType type,
713 VkImageTiling tiling,
714 VkImageUsageFlags usage,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700715 VkImageCreateFlags flags,
Jesse Hall04f4f472015-08-16 19:51:04 -0700716 VkImageFormatProperties* properties) {
Jesse Hall1f91d392015-12-11 16:28:44 -0800717 return GetDispatchParent(pdev)
718 .drv.dispatch.GetPhysicalDeviceImageFormatProperties(
Jesse Halla9e57032015-11-30 01:03:10 -0800719 pdev, format, type, tiling, usage, flags, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700720}
721
Jesse Hall1f91d392015-12-11 16:28:44 -0800722void GetPhysicalDeviceSparseImageFormatProperties_Bottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700723 VkPhysicalDevice pdev,
Jesse Hall1f91d392015-12-11 16:28:44 -0800724 VkFormat format,
725 VkImageType type,
726 VkSampleCountFlagBits samples,
727 VkImageUsageFlags usage,
728 VkImageTiling tiling,
729 uint32_t* properties_count,
730 VkSparseImageFormatProperties* properties) {
731 GetDispatchParent(pdev)
732 .drv.dispatch.GetPhysicalDeviceSparseImageFormatProperties(
733 pdev, format, type, samples, usage, tiling, properties_count,
734 properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700735}
736
Jesse Halle1b12782015-11-30 11:27:32 -0800737VKAPI_ATTR
Jesse Hall1f91d392015-12-11 16:28:44 -0800738VkResult EnumerateDeviceExtensionProperties_Bottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700739 VkPhysicalDevice pdev,
Jesse Hall1f91d392015-12-11 16:28:44 -0800740 const char* layer_name,
741 uint32_t* properties_count,
742 VkExtensionProperties* properties) {
743 // TODO: what are we supposed to do with layer_name here?
744 return GetDispatchParent(pdev)
745 .drv.dispatch.EnumerateDeviceExtensionProperties(
746 pdev, layer_name, properties_count, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700747}
748
Jesse Halle1b12782015-11-30 11:27:32 -0800749VKAPI_ATTR
Jesse Hall1f91d392015-12-11 16:28:44 -0800750VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice pdev,
751 uint32_t* properties_count,
752 VkLayerProperties* properties) {
753 return GetDispatchParent(pdev).drv.dispatch.EnumerateDeviceLayerProperties(
754 pdev, properties_count, properties);
755}
756
757VKAPI_ATTR
758VkResult CreateDevice_Bottom(VkPhysicalDevice pdev,
759 const VkDeviceCreateInfo* create_info,
760 const VkAllocationCallbacks* allocator,
761 VkDevice* device_out) {
762 Instance& instance = GetDispatchParent(pdev);
Jesse Hall04f4f472015-08-16 19:51:04 -0700763 VkResult result;
764
Jesse Hall03b6fe12015-11-24 12:44:21 -0800765 if (!allocator) {
766 if (instance.alloc)
767 allocator = instance.alloc;
768 else
769 allocator = &kDefaultAllocCallbacks;
770 }
771
Jesse Hall3fbc8562015-11-29 22:10:52 -0800772 void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Device),
773 alignof(Device),
774 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700775 if (!mem)
776 return VK_ERROR_OUT_OF_HOST_MEMORY;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500777 Device* device = new (mem) Device(&instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700778
Jesse Hall9a16f972015-10-28 15:59:53 -0700779 result = ActivateAllLayers(create_info, &instance, device);
780 if (result != VK_SUCCESS) {
781 DestroyDevice(device);
782 return result;
783 }
784
Jesse Hall04f4f472015-08-16 19:51:04 -0700785 VkDevice drv_device;
Jesse Hall1f91d392015-12-11 16:28:44 -0800786 result = instance.drv.dispatch.CreateDevice(pdev, create_info, allocator,
787 &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700788 if (result != VK_SUCCESS) {
789 DestroyDevice(device);
790 return result;
791 }
792
Jesse Hall1f91d392015-12-11 16:28:44 -0800793 hwvulkan_dispatch_t* drv_dispatch =
Jesse Hall04f4f472015-08-16 19:51:04 -0700794 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
Jesse Hall1f91d392015-12-11 16:28:44 -0800795 if (drv_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
796 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR,
797 drv_dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500798 PFN_vkDestroyDevice destroy_device =
799 reinterpret_cast<PFN_vkDestroyDevice>(
Jesse Hall1f91d392015-12-11 16:28:44 -0800800 instance.drv.dispatch.GetDeviceProcAddr(drv_device,
801 "vkDestroyDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800802 destroy_device(drv_device, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700803 DestroyDevice(device);
804 return VK_ERROR_INITIALIZATION_FAILED;
805 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800806 drv_dispatch->vtbl = &device->dispatch;
807 device->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
808 instance.drv.dispatch.GetDeviceProcAddr(drv_device,
809 "vkGetDeviceProcAddr"));
Jesse Hall04f4f472015-08-16 19:51:04 -0700810
Michael Lentine03c64b02015-08-26 18:27:26 -0500811 void* base_object = static_cast<void*>(drv_device);
812 void* next_object = base_object;
813 VkLayerLinkedListElem* next_element;
Jesse Hall1f91d392015-12-11 16:28:44 -0800814 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetDeviceProcAddr_Bottom;
Michael Lentine03c64b02015-08-26 18:27:26 -0500815 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500816 device->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500817 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
818
819 for (size_t i = elem_list.size(); i > 0; i--) {
820 size_t idx = i - 1;
821 next_element = &elem_list[idx];
822 next_element->get_proc_addr =
823 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
824 next_element->base_object = base_object;
825 next_element->next_element = next_object;
826 next_object = static_cast<void*>(next_element);
827
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500828 auto& name = device->active_layers[idx]->first;
829 auto& handle = device->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -0500830 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500831 dlsym(handle, (name + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500832 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500833 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500834 dlsym(handle, "vkGetDeviceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -0700835 if (!next_get_proc_addr) {
836 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500837 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700838 next_object = next_element->next_element;
839 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
840 next_element->get_proc_addr);
841 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500842 }
843 }
844
Jesse Hall1f91d392015-12-11 16:28:44 -0800845 // This is the magic call that initializes all the layer devices and
846 // allows them to create their device_handle -> device_data mapping.
847 next_get_proc_addr(static_cast<VkDevice>(next_object),
848 "vkGetDeviceProcAddr");
849
850 // We must create all the layer devices *before* retrieving the device
851 // procaddrs, so that the layers know which extensions are enabled and
852 // therefore which functions to return procaddrs for.
853 PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
854 next_get_proc_addr(drv_device, "vkCreateDevice"));
855 create_device(pdev, create_info, allocator, &drv_device);
856
857 if (!LoadDeviceDispatchTable(static_cast<VkDevice>(base_object),
858 next_get_proc_addr, device->dispatch)) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500859 DestroyDevice(device);
860 return VK_ERROR_INITIALIZATION_FAILED;
861 }
862
Jesse Hall1f91d392015-12-11 16:28:44 -0800863 *device_out = drv_device;
Jesse Hall04f4f472015-08-16 19:51:04 -0700864 return VK_SUCCESS;
865}
866
Jesse Hall1f91d392015-12-11 16:28:44 -0800867void DestroyInstance_Bottom(VkInstance vkinstance,
868 const VkAllocationCallbacks* allocator) {
869 Instance& instance = GetDispatchParent(vkinstance);
870
871 // These checks allow us to call DestroyInstance_Bottom from any error
872 // path in CreateInstance_Bottom, before the driver instance is fully
873 // initialized.
874 if (instance.drv.instance != VK_NULL_HANDLE &&
875 instance.drv.dispatch.DestroyInstance) {
876 instance.drv.dispatch.DestroyInstance(instance.drv.instance, allocator);
877 }
878 if (instance.message) {
879 PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
880 DebugDestroyMessageCallback =
881 reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
882 vkGetInstanceProcAddr(vkinstance, "vkDbgDestroyMsgCallback"));
883 DebugDestroyMessageCallback(vkinstance, instance.message);
884 }
885 for (auto it = instance.active_layers.begin();
886 it != instance.active_layers.end(); ++it) {
887 DeactivateLayer(instance, it);
888 }
889 const VkAllocationCallbacks* alloc = instance.alloc;
890 instance.~Instance();
891 alloc->pfnFree(alloc->pUserData, &instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700892}
893
Jesse Hall1f91d392015-12-11 16:28:44 -0800894PFN_vkVoidFunction GetDeviceProcAddr_Bottom(VkDevice vkdevice,
895 const char* name) {
896 if (strcmp(name, "vkCreateDevice") == 0) {
897 // TODO(jessehall): Blegh, having this here is disgusting. The current
898 // layer init process can't call through the instance dispatch table's
899 // vkCreateDevice, because that goes through the instance layers rather
900 // than through the device layers. So we need to be able to get the
901 // vkCreateDevice pointer through the *device* layer chain.
902 //
903 // Because we've already created the driver device before calling
904 // through the layer vkCreateDevice functions, the loader bottom proc
905 // is a no-op.
Michael Lentine03c64b02015-08-26 18:27:26 -0500906 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
907 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800908
909 // VK_ANDROID_native_buffer should be hidden from applications and layers.
910 // TODO(jessehall): Generate this as part of GetLoaderBottomProcAddr.
911 PFN_vkVoidFunction pfn;
912 if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0 ||
913 strcmp(name, "vkAcquireImageANDROID") == 0 ||
914 strcmp(name, "vkQueueSignalReleaseImageANDROID") == 0) {
915 return nullptr;
Michael Lentine03c64b02015-08-26 18:27:26 -0500916 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800917 if ((pfn = GetLoaderBottomProcAddr(name)))
918 return pfn;
919 return GetDispatchParent(vkdevice).get_device_proc_addr(vkdevice, name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700920}
921
Jesse Hall04f4f472015-08-16 19:51:04 -0700922// -----------------------------------------------------------------------------
Jesse Hall1f91d392015-12-11 16:28:44 -0800923// Loader top functions. These are called directly from the loader entry
924// points or from the application (via vkGetInstanceProcAddr) without going
925// through a dispatch table.
Jesse Hall04f4f472015-08-16 19:51:04 -0700926
Jesse Hall1f91d392015-12-11 16:28:44 -0800927VkResult EnumerateInstanceExtensionProperties_Top(
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700928 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 Hall1f91d392015-12-11 16:28:44 -0800941VkResult EnumerateInstanceLayerProperties_Top(
942 uint32_t* count,
943 VkLayerProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700944 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700945 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700946
947 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700948 ALOGW("vkEnumerateInstanceLayerProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700949
950 *count = 0;
951 return VK_SUCCESS;
952}
953
Jesse Hall1f91d392015-12-11 16:28:44 -0800954VkResult CreateInstance_Top(const VkInstanceCreateInfo* create_info,
955 const VkAllocationCallbacks* allocator,
956 VkInstance* instance_out) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700957 VkResult result;
958
959 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700960 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700961
Jesse Hall03b6fe12015-11-24 12:44:21 -0800962 if (!allocator)
963 allocator = &kDefaultAllocCallbacks;
964
Jesse Hall04f4f472015-08-16 19:51:04 -0700965 VkInstanceCreateInfo local_create_info = *create_info;
Jesse Hall04f4f472015-08-16 19:51:04 -0700966 create_info = &local_create_info;
967
Jesse Hall3fbc8562015-11-29 22:10:52 -0800968 void* instance_mem = allocator->pfnAllocation(
969 allocator->pUserData, sizeof(Instance), alignof(Instance),
970 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700971 if (!instance_mem)
972 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jesse Hall03b6fe12015-11-24 12:44:21 -0800973 Instance* instance = new (instance_mem) Instance(allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700974
Michael Lentine03c64b02015-08-26 18:27:26 -0500975 // Scan layers
Michael Lentine03c64b02015-08-26 18:27:26 -0500976 CallbackAllocator<char> string_allocator(instance->alloc);
Jesse Hall21597662015-12-18 13:48:24 -0800977 String dir_name("/data/local/debug/vulkan/", string_allocator);
978 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
979 FindLayersInDirectory(*instance, dir_name);
Michael Lentine1c69b9e2015-09-14 13:26:59 -0500980 const std::string& path = LoaderData::GetInstance().layer_path;
981 dir_name.assign(path.c_str(), path.size());
982 dir_name.append("/");
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500983 FindLayersInDirectory(*instance, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -0700984
Jesse Hall9a16f972015-10-28 15:59:53 -0700985 result = ActivateAllLayers(create_info, instance, instance);
986 if (result != VK_SUCCESS) {
Jesse Hall1f91d392015-12-11 16:28:44 -0800987 DestroyInstance_Bottom(instance->handle, allocator);
Jesse Hall9a16f972015-10-28 15:59:53 -0700988 return result;
989 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500990
Jesse Hall1f91d392015-12-11 16:28:44 -0800991 void* base_object = static_cast<void*>(instance->handle);
Michael Lentine03c64b02015-08-26 18:27:26 -0500992 void* next_object = base_object;
993 VkLayerLinkedListElem* next_element;
Jesse Hall1f91d392015-12-11 16:28:44 -0800994 PFN_vkGetInstanceProcAddr next_get_proc_addr = GetInstanceProcAddr_Bottom;
Michael Lentine03c64b02015-08-26 18:27:26 -0500995 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -0700996 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500997 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
998
999 for (size_t i = elem_list.size(); i > 0; i--) {
1000 size_t idx = i - 1;
1001 next_element = &elem_list[idx];
1002 next_element->get_proc_addr =
1003 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
1004 next_element->base_object = base_object;
1005 next_element->next_element = next_object;
1006 next_object = static_cast<void*>(next_element);
1007
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001008 auto& name = instance->active_layers[idx]->first;
1009 auto& handle = instance->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -05001010 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001011 dlsym(handle, (name + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -05001012 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -05001013 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001014 dlsym(handle, "vkGetInstanceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -07001015 if (!next_get_proc_addr) {
1016 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001017 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -07001018 next_object = next_element->next_element;
1019 next_get_proc_addr =
1020 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
1021 next_element->get_proc_addr);
1022 }
Michael Lentine03c64b02015-08-26 18:27:26 -05001023 }
1024 }
Jesse Hall1f91d392015-12-11 16:28:44 -08001025 instance->get_instance_proc_addr = next_get_proc_addr;
Michael Lentine03c64b02015-08-26 18:27:26 -05001026
Jesse Hall1f91d392015-12-11 16:28:44 -08001027 // This is the magic call that initializes all the layer instances and
1028 // allows them to create their instance_handle -> instance_data mapping.
1029 next_get_proc_addr(static_cast<VkInstance>(next_object),
1030 "vkGetInstanceProcAddr");
1031
1032 if (!LoadInstanceDispatchTable(static_cast<VkInstance>(base_object),
1033 next_get_proc_addr, instance->dispatch)) {
1034 DestroyInstance_Bottom(instance->handle, allocator);
Michael Lentine03c64b02015-08-26 18:27:26 -05001035 return VK_ERROR_INITIALIZATION_FAILED;
1036 }
1037
Michael Lentine950bb4f2015-09-14 13:26:30 -05001038 // Force enable callback extension if required
Jesse Hall21597662015-12-18 13:48:24 -08001039 bool enable_callback = false;
1040 bool enable_logging = false;
1041 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
1042 enable_callback =
1043 property_get_bool("debug.vulkan.enable_callback", false);
1044 enable_logging = enable_callback;
1045 if (enable_callback) {
1046 enable_callback = AddExtensionToCreateInfo(
1047 local_create_info, "DEBUG_REPORT", instance->alloc);
1048 }
Michael Lentine950bb4f2015-09-14 13:26:30 -05001049 }
1050
Jesse Hall1f91d392015-12-11 16:28:44 -08001051 *instance_out = instance->handle;
1052 PFN_vkCreateInstance create_instance =
1053 reinterpret_cast<PFN_vkCreateInstance>(
1054 next_get_proc_addr(instance->handle, "vkCreateInstance"));
1055 result = create_instance(create_info, allocator, instance_out);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001056 if (enable_callback)
1057 FreeAllocatedCreateInfo(local_create_info, instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001058 if (result <= 0) {
1059 // For every layer, including the loader top and bottom layers:
1060 // - If a call to the next CreateInstance fails, the layer must clean
1061 // up anything it has successfully done so far, and propagate the
1062 // error upwards.
1063 // - If a layer successfully calls the next layer's CreateInstance, and
1064 // afterwards must fail for some reason, it must call the next layer's
1065 // DestroyInstance before returning.
1066 // - The layer must not call the next layer's DestroyInstance if that
1067 // layer's CreateInstance wasn't called, or returned failure.
1068
Jesse Hall1f91d392015-12-11 16:28:44 -08001069 // On failure, CreateInstance_Bottom frees the instance struct, so it's
Jesse Hall04f4f472015-08-16 19:51:04 -07001070 // already gone at this point. Nothing to do.
1071 }
1072
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001073 if (enable_logging) {
Jesse Hall1f91d392015-12-11 16:28:44 -08001074 PFN_vkDbgCreateMsgCallback dbg_create_msg_callback;
1075 dbg_create_msg_callback = reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
1076 GetInstanceProcAddr_Top(instance->handle,
1077 "vkDbgCreateMsgCallback"));
1078 dbg_create_msg_callback(
1079 instance->handle, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
1080 LogDebugMessageCallback, nullptr, &instance->message);
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001081 }
1082
Jesse Hall04f4f472015-08-16 19:51:04 -07001083 return result;
1084}
1085
Jesse Hall1f91d392015-12-11 16:28:44 -08001086PFN_vkVoidFunction GetInstanceProcAddr_Top(VkInstance vkinstance,
1087 const char* name) {
1088 // vkGetInstanceProcAddr(NULL_HANDLE, ..) only works for global commands
1089 if (!vkinstance)
1090 return GetLoaderGlobalProcAddr(name);
1091
1092 const InstanceDispatchTable& dispatch = GetDispatchTable(vkinstance);
1093 PFN_vkVoidFunction pfn;
1094 // Always go through the loader-top function if there is one.
1095 if ((pfn = GetLoaderTopProcAddr(name)))
1096 return pfn;
1097 // Otherwise, look up the handler in the instance dispatch table
1098 if ((pfn = GetDispatchProcAddr(dispatch, name)))
1099 return pfn;
1100 // TODO(jessehall): Generate these into the instance dispatch table, and
1101 // add loader-bottom procs for them.
Michael Lentine03c64b02015-08-26 18:27:26 -05001102 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
1103 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
Jesse Hall1f91d392015-12-11 16:28:44 -08001104 return GetDispatchParent(vkinstance)
1105 .get_instance_proc_addr(vkinstance, name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001106 }
Jesse Hall1f91d392015-12-11 16:28:44 -08001107 // Anything not handled already must be a device-dispatched function
1108 // without a loader-top. We must return a function that will dispatch based
1109 // on the dispatchable object parameter -- which is exactly what the
1110 // exported functions do. So just return them here.
1111 return GetLoaderExportProcAddr(name);
Jesse Hall04f4f472015-08-16 19:51:04 -07001112}
1113
Jesse Hall1f91d392015-12-11 16:28:44 -08001114void DestroyInstance_Top(VkInstance instance,
1115 const VkAllocationCallbacks* allocator) {
1116 if (!instance)
1117 return;
1118 GetDispatchTable(instance).DestroyInstance(instance, allocator);
1119}
1120
1121PFN_vkVoidFunction GetDeviceProcAddr_Top(VkDevice device, const char* name) {
1122 PFN_vkVoidFunction pfn;
Jesse Hall04f4f472015-08-16 19:51:04 -07001123 if (!device)
Jesse Hall1f91d392015-12-11 16:28:44 -08001124 return nullptr;
1125 if ((pfn = GetLoaderTopProcAddr(name)))
1126 return pfn;
1127 return GetDispatchProcAddr(GetDispatchTable(device), name);
Jesse Hall04f4f472015-08-16 19:51:04 -07001128}
1129
Jesse Hall1f91d392015-12-11 16:28:44 -08001130void GetDeviceQueue_Top(VkDevice vkdevice,
1131 uint32_t family,
1132 uint32_t index,
1133 VkQueue* queue_out) {
1134 const auto& table = GetDispatchTable(vkdevice);
1135 table.GetDeviceQueue(vkdevice, family, index, queue_out);
1136 hwvulkan_dispatch_t* queue_dispatch =
1137 reinterpret_cast<hwvulkan_dispatch_t*>(*queue_out);
1138 if (queue_dispatch->magic != HWVULKAN_DISPATCH_MAGIC &&
1139 queue_dispatch->vtbl != &table)
1140 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR,
1141 queue_dispatch->magic);
1142 queue_dispatch->vtbl = &table;
Jesse Hall04f4f472015-08-16 19:51:04 -07001143}
1144
Jesse Hall1f91d392015-12-11 16:28:44 -08001145VkResult AllocateCommandBuffers_Top(
1146 VkDevice vkdevice,
1147 const VkCommandBufferAllocateInfo* alloc_info,
1148 VkCommandBuffer* cmdbufs) {
1149 const auto& table = GetDispatchTable(vkdevice);
1150 VkResult result =
1151 table.AllocateCommandBuffers(vkdevice, alloc_info, cmdbufs);
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001152 if (result != VK_SUCCESS)
1153 return result;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001154 for (uint32_t i = 0; i < alloc_info->bufferCount; i++) {
Jesse Hall1f91d392015-12-11 16:28:44 -08001155 hwvulkan_dispatch_t* cmdbuf_dispatch =
Jesse Hall3fbc8562015-11-29 22:10:52 -08001156 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbufs[i]);
Jesse Hall1f91d392015-12-11 16:28:44 -08001157 ALOGE_IF(cmdbuf_dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001158 "invalid VkCommandBuffer dispatch magic: 0x%" PRIxPTR,
Jesse Hall1f91d392015-12-11 16:28:44 -08001159 cmdbuf_dispatch->magic);
1160 cmdbuf_dispatch->vtbl = &table;
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001161 }
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001162 return VK_SUCCESS;
1163}
1164
Jesse Hall1f91d392015-12-11 16:28:44 -08001165void DestroyDevice_Top(VkDevice vkdevice,
1166 const VkAllocationCallbacks* /*allocator*/) {
1167 if (!vkdevice)
1168 return;
1169 Device& device = GetDispatchParent(vkdevice);
1170 // TODO(jessehall): This seems very wrong. We might close a layer library
1171 // right before we call DestroyDevice in it.
1172 for (auto it = device.active_layers.begin();
1173 it != device.active_layers.end(); ++it) {
1174 DeactivateLayer(*device.instance, it);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001175 }
Jesse Hall1f91d392015-12-11 16:28:44 -08001176 device.dispatch.DestroyDevice(vkdevice, device.instance->alloc);
1177 DestroyDevice(&device);
Jesse Hall04f4f472015-08-16 19:51:04 -07001178}
1179
Jesse Hall1f91d392015-12-11 16:28:44 -08001180// -----------------------------------------------------------------------------
1181
1182const VkAllocationCallbacks* GetAllocator(VkInstance vkinstance) {
1183 return GetDispatchParent(vkinstance).alloc;
Jesse Hall1356b0d2015-11-23 17:24:58 -08001184}
1185
Jesse Hall1f91d392015-12-11 16:28:44 -08001186const VkAllocationCallbacks* GetAllocator(VkDevice vkdevice) {
1187 return GetDispatchParent(vkdevice).instance->alloc;
Jesse Hall1356b0d2015-11-23 17:24:58 -08001188}
1189
Jesse Hall1f91d392015-12-11 16:28:44 -08001190const DriverDispatchTable& GetDriverDispatch(VkDevice device) {
1191 return GetDispatchParent(device).instance->drv.dispatch;
Jesse Halld7b994a2015-09-07 14:17:37 -07001192}
1193
Jesse Hall1f91d392015-12-11 16:28:44 -08001194const DriverDispatchTable& GetDriverDispatch(VkQueue queue) {
1195 return GetDispatchParent(queue).instance->drv.dispatch;
Jesse Halld7b994a2015-09-07 14:17:37 -07001196}
1197
Jesse Hall04f4f472015-08-16 19:51:04 -07001198} // namespace vulkan