blob: cd3503f0723c47cecacba479d04bea8206b44664 [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
49// These definitions are taken from the LunarG Vulkan Loader. They are used to
50// enforce compatability between the Loader and Layers.
51typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
52
53typedef struct VkLayerLinkedListElem_ {
54 PFN_vkGetProcAddr get_proc_addr;
55 void* next_element;
56 void* base_object;
57} VkLayerLinkedListElem;
58
59// Define Handle typedef to be void* as returned from dlopen.
60typedef void* SharedLibraryHandle;
61
Jesse Hall3fbc8562015-11-29 22:10:52 -080062// Standard-library allocator that delegates to VkAllocationCallbacks.
Jesse Hall03b6fe12015-11-24 12:44:21 -080063//
64// TODO(jessehall): This class currently always uses
Jesse Hall3fbc8562015-11-29 22:10:52 -080065// VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE. The scope to use could be a template
Jesse Hall03b6fe12015-11-24 12:44:21 -080066// parameter or a constructor parameter. The former would help catch bugs
67// where we use the wrong scope, e.g. adding a command-scope string to an
68// instance-scope vector. But that might also be pretty annoying to deal with.
Michael Lentine03c64b02015-08-26 18:27:26 -050069template <class T>
70class CallbackAllocator {
71 public:
72 typedef T value_type;
73
Jesse Hall3fbc8562015-11-29 22:10:52 -080074 CallbackAllocator(const VkAllocationCallbacks* alloc_input)
Michael Lentine03c64b02015-08-26 18:27:26 -050075 : alloc(alloc_input) {}
76
77 template <class T2>
78 CallbackAllocator(const CallbackAllocator<T2>& other)
79 : alloc(other.alloc) {}
80
81 T* allocate(std::size_t n) {
Jesse Hall3fbc8562015-11-29 22:10:52 -080082 void* mem =
83 alloc->pfnAllocation(alloc->pUserData, n * sizeof(T), alignof(T),
84 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Michael Lentine03c64b02015-08-26 18:27:26 -050085 return static_cast<T*>(mem);
86 }
87
88 void deallocate(T* array, std::size_t /*n*/) {
89 alloc->pfnFree(alloc->pUserData, array);
90 }
91
Jesse Hall3fbc8562015-11-29 22:10:52 -080092 const VkAllocationCallbacks* alloc;
Michael Lentine03c64b02015-08-26 18:27:26 -050093};
94// These are needed in order to move Strings
95template <class T>
96bool operator==(const CallbackAllocator<T>& alloc1,
97 const CallbackAllocator<T>& alloc2) {
98 return alloc1.alloc == alloc2.alloc;
99}
100template <class T>
101bool operator!=(const CallbackAllocator<T>& alloc1,
102 const CallbackAllocator<T>& alloc2) {
103 return !(alloc1 == alloc2);
104}
105
106template <class Key,
107 class T,
108 class Hash = std::hash<Key>,
109 class Pred = std::equal_to<Key> >
110using UnorderedMap =
111 std::unordered_map<Key,
112 T,
113 Hash,
114 Pred,
115 CallbackAllocator<std::pair<const Key, T> > >;
116
117template <class T>
118using Vector = std::vector<T, CallbackAllocator<T> >;
119
120typedef std::basic_string<char,
121 std::char_traits<char>,
122 CallbackAllocator<char> > String;
123
124} // namespace
125
126// -----------------------------------------------------------------------------
127
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500128namespace {
129
130struct LayerData {
131 String path;
132 SharedLibraryHandle handle;
133 uint32_t ref_count;
134};
135
136typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
137
138} // namespace
139
Jesse Hall04f4f472015-08-16 19:51:04 -0700140struct VkInstance_T {
Jesse Hall3fbc8562015-11-29 22:10:52 -0800141 VkInstance_T(const VkAllocationCallbacks* alloc_callbacks)
Michael Lentine03c64b02015-08-26 18:27:26 -0500142 : vtbl(&vtbl_storage),
143 alloc(alloc_callbacks),
144 num_physical_devices(0),
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500145 layers(CallbackAllocator<std::pair<String, LayerData> >(alloc)),
146 active_layers(CallbackAllocator<String>(alloc)) {
147 pthread_mutex_init(&layer_lock, 0);
Jesse Hall04f4f472015-08-16 19:51:04 -0700148 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
149 memset(physical_devices, 0, sizeof(physical_devices));
150 memset(&drv.vtbl, 0, sizeof(drv.vtbl));
151 drv.GetDeviceProcAddr = nullptr;
152 drv.num_physical_devices = 0;
153 }
154
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500155 ~VkInstance_T() { pthread_mutex_destroy(&layer_lock); }
156
Jesse Hall04f4f472015-08-16 19:51:04 -0700157 InstanceVtbl* vtbl;
158 InstanceVtbl vtbl_storage;
159
Jesse Hall3fbc8562015-11-29 22:10:52 -0800160 const VkAllocationCallbacks* alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700161 uint32_t num_physical_devices;
162 VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
163
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500164 pthread_mutex_t layer_lock;
165 // Map of layer names to layer data
166 UnorderedMap<String, LayerData> layers;
167 // Vector of layers active for this instance
168 Vector<LayerMapIterator> active_layers;
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500169 VkDbgMsgCallback message;
Michael Lentine03c64b02015-08-26 18:27:26 -0500170
Jesse Hall04f4f472015-08-16 19:51:04 -0700171 struct Driver {
172 // Pointers to driver entry points. Used explicitly by the loader; not
173 // set as the dispatch table for any objects.
174 InstanceVtbl vtbl;
175
176 // Pointer to the driver's get_device_proc_addr, must be valid for any
177 // of the driver's physical devices. Not part of the InstanceVtbl since
178 // it's not an Instance/PhysicalDevice function.
179 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
180
181 // Number of physical devices owned by this driver.
182 uint32_t num_physical_devices;
183 } drv; // may eventually be an array
184};
185
186// -----------------------------------------------------------------------------
187
188namespace {
189
190typedef VkInstance_T Instance;
191
192struct Device {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500193 Device(Instance* instance_input)
194 : instance(instance_input),
195 active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700196 memset(&vtbl_storage, 0, sizeof(vtbl_storage));
197 vtbl_storage.device = this;
198 }
199 DeviceVtbl vtbl_storage;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500200 Instance* instance;
201 // Vector of layers active for this device
202 Vector<LayerMapIterator> active_layers;
Jesse Hall04f4f472015-08-16 19:51:04 -0700203};
204
205// -----------------------------------------------------------------------------
206// Utility Code
207
208inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
209 return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
210}
211
212inline const DeviceVtbl* GetVtbl(VkDevice device) {
213 return *reinterpret_cast<DeviceVtbl**>(device);
214}
Jesse Halld7b994a2015-09-07 14:17:37 -0700215inline const DeviceVtbl* GetVtbl(VkQueue queue) {
216 return *reinterpret_cast<DeviceVtbl**>(queue);
217}
Jesse Hall04f4f472015-08-16 19:51:04 -0700218
Jesse Halle1b12782015-11-30 11:27:32 -0800219VKAPI_ATTR void* DefaultAllocate(void*,
220 size_t size,
221 size_t alignment,
222 VkSystemAllocationScope) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800223 void* ptr = nullptr;
224 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
225 // additionally requires that it be at least sizeof(void*).
226 return posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0
227 ? ptr
228 : nullptr;
229}
230
Jesse Halle1b12782015-11-30 11:27:32 -0800231VKAPI_ATTR void* DefaultReallocate(void*,
232 void* ptr,
233 size_t size,
234 size_t alignment,
235 VkSystemAllocationScope) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800236 if (size == 0) {
237 free(ptr);
238 return nullptr;
239 }
240
241 // TODO(jessehall): Right now we never shrink allocations; if the new
242 // request is smaller than the existing chunk, we just continue using it.
243 // Right now the loader never reallocs, so this doesn't matter. If that
244 // changes, or if this code is copied into some other project, this should
245 // probably have a heuristic to allocate-copy-free when doing so will save
246 // "enough" space.
247 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
248 if (size <= old_size)
249 return ptr;
250
251 void* new_ptr = nullptr;
252 if (posix_memalign(&new_ptr, alignment, size) != 0)
253 return nullptr;
254 if (ptr) {
255 memcpy(new_ptr, ptr, std::min(old_size, size));
256 free(ptr);
257 }
258 return new_ptr;
Jesse Hall04f4f472015-08-16 19:51:04 -0700259}
260
Jesse Halle1b12782015-11-30 11:27:32 -0800261VKAPI_ATTR void DefaultFree(void*, void* pMem) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700262 free(pMem);
263}
264
Jesse Hall3fbc8562015-11-29 22:10:52 -0800265const VkAllocationCallbacks kDefaultAllocCallbacks = {
Jesse Hall04f4f472015-08-16 19:51:04 -0700266 .pUserData = nullptr,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800267 .pfnAllocation = DefaultAllocate,
268 .pfnReallocation = DefaultReallocate,
Jesse Hall04f4f472015-08-16 19:51:04 -0700269 .pfnFree = DefaultFree,
270};
271
272hwvulkan_device_t* g_hwdevice;
273bool EnsureInitialized() {
274 static std::once_flag once_flag;
275 static const hwvulkan_module_t* module;
276
277 std::call_once(once_flag, []() {
278 int result;
279 result = hw_get_module("vulkan",
280 reinterpret_cast<const hw_module_t**>(&module));
281 if (result != 0) {
282 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result),
283 result);
284 return;
285 }
286 result = module->common.methods->open(
287 &module->common, HWVULKAN_DEVICE_0,
288 reinterpret_cast<hw_device_t**>(&g_hwdevice));
289 if (result != 0) {
290 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
291 result);
292 module = nullptr;
293 return;
294 }
295 });
296
297 return module != nullptr && g_hwdevice != nullptr;
298}
299
300void DestroyDevice(Device* device) {
Jesse Hall3fbc8562015-11-29 22:10:52 -0800301 const VkAllocationCallbacks* alloc = device->instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700302 device->~Device();
303 alloc->pfnFree(alloc->pUserData, device);
304}
305
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500306void FindLayersInDirectory(Instance& instance, const String& dir_name) {
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700307 DIR* directory = opendir(dir_name.c_str());
308 if (!directory) {
Jesse Hall21597662015-12-18 13:48:24 -0800309 int err = errno;
310 ALOGW_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
311 dir_name.c_str(), strerror(err), err);
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700312 return;
Michael Lentine03c64b02015-08-26 18:27:26 -0500313 }
Jesse Hall0ecdd3e2015-10-29 11:20:07 -0700314
315 Vector<VkLayerProperties> properties(
316 CallbackAllocator<VkLayerProperties>(instance.alloc));
317 struct dirent* entry;
318 while ((entry = readdir(directory))) {
319 size_t length = strlen(entry->d_name);
320 if (strncmp(entry->d_name, "libVKLayer", 10) != 0 ||
321 strncmp(entry->d_name + length - 3, ".so", 3) != 0)
322 continue;
323 // Open so
324 SharedLibraryHandle layer_handle =
325 dlopen((dir_name + entry->d_name).c_str(), RTLD_NOW | RTLD_LOCAL);
326 if (!layer_handle) {
327 ALOGE("%s failed to load with error %s; Skipping", entry->d_name,
328 dlerror());
329 continue;
330 }
331
332 // Get Layers in so
333 PFN_vkEnumerateInstanceLayerProperties get_layer_properties =
334 reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
335 dlsym(layer_handle, "vkEnumerateInstanceLayerProperties"));
336 if (!get_layer_properties) {
337 ALOGE(
338 "%s failed to find vkEnumerateInstanceLayerProperties with "
339 "error %s; Skipping",
340 entry->d_name, dlerror());
341 dlclose(layer_handle);
342 continue;
343 }
344 uint32_t count;
345 get_layer_properties(&count, nullptr);
346
347 properties.resize(count);
348 get_layer_properties(&count, &properties[0]);
349
350 // Add Layers to potential list
351 for (uint32_t i = 0; i < count; ++i) {
352 String layer_name(properties[i].layerName,
353 CallbackAllocator<char>(instance.alloc));
354 LayerData layer_data = {dir_name + entry->d_name, 0, 0};
355 instance.layers.insert(std::make_pair(layer_name, layer_data));
356 ALOGV("Found layer %s", properties[i].layerName);
357 }
358 dlclose(layer_handle);
359 }
360
361 closedir(directory);
Michael Lentine03c64b02015-08-26 18:27:26 -0500362}
363
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500364template <class TObject>
365void ActivateLayer(TObject* object, Instance* instance, const String& name) {
366 // If object has layer, do nothing
367 auto element = instance->layers.find(name);
Michael Lentine233ac732015-11-18 18:28:07 -0800368 if (element == instance->layers.end()) {
369 return;
370 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500371 if (std::find(object->active_layers.begin(), object->active_layers.end(),
372 element) != object->active_layers.end()) {
373 ALOGW("Layer %s already activated; skipping", name.c_str());
374 return;
375 }
376 // If layer is not open, open it
377 LayerData& layer_data = element->second;
378 pthread_mutex_lock(&instance->layer_lock);
379 if (layer_data.ref_count == 0) {
380 SharedLibraryHandle layer_handle =
381 dlopen(layer_data.path.c_str(), RTLD_NOW | RTLD_LOCAL);
382 if (!layer_handle) {
383 pthread_mutex_unlock(&instance->layer_lock);
384 ALOGE("%s failed to load with error %s; Skipping",
385 layer_data.path.c_str(), dlerror());
386 return;
387 }
388 layer_data.handle = layer_handle;
389 }
390 layer_data.ref_count++;
391 pthread_mutex_unlock(&instance->layer_lock);
392 ALOGV("Activating layer %s", name.c_str());
393 object->active_layers.push_back(element);
394}
395
Michael Lentine1d1e65f2015-11-19 14:23:06 -0800396void DeactivateLayer(Instance* instance,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500397 Vector<LayerMapIterator>::iterator& element) {
398 LayerMapIterator& layer_map_data = *element;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500399 LayerData& layer_data = layer_map_data->second;
400 pthread_mutex_lock(&instance->layer_lock);
401 layer_data.ref_count--;
402 if (!layer_data.ref_count) {
403 dlclose(layer_data.handle);
404 }
405 pthread_mutex_unlock(&instance->layer_lock);
406}
407
Michael Lentine9da191b2015-10-13 11:08:45 -0500408struct InstanceNamesPair {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500409 Instance* instance;
Michael Lentine9da191b2015-10-13 11:08:45 -0500410 Vector<String>* layer_names;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500411};
412
Michael Lentine9da191b2015-10-13 11:08:45 -0500413void SetLayerNamesFromProperty(const char* name,
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500414 const char* value,
415 void* data) {
416 const char prefix[] = "debug.vulkan.layer.";
417 const size_t prefixlen = sizeof(prefix) - 1;
418 if (value[0] == '\0' || strncmp(name, prefix, prefixlen) != 0)
419 return;
Michael Lentine9da191b2015-10-13 11:08:45 -0500420 const char* number_str = name + prefixlen;
421 long layer_number = strtol(number_str, nullptr, 10);
422 if (layer_number <= 0 || layer_number == LONG_MAX) {
423 ALOGW("Cannot use a layer at number %ld from string %s", layer_number,
424 number_str);
425 return;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500426 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500427 auto instance_names_pair = static_cast<InstanceNamesPair*>(data);
428 Vector<String>* layer_names = instance_names_pair->layer_names;
429 Instance* instance = instance_names_pair->instance;
430 size_t layer_size = static_cast<size_t>(layer_number);
431 if (layer_size > layer_names->size()) {
432 layer_names->resize(layer_size,
433 String(CallbackAllocator<char>(instance->alloc)));
434 }
435 (*layer_names)[layer_size - 1] = value;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500436}
437
438template <class TInfo, class TObject>
Jesse Hall9a16f972015-10-28 15:59:53 -0700439VkResult ActivateAllLayers(TInfo create_info, Instance* instance, TObject* object) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500440 ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
441 create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
442 "Cannot activate layers for unknown object %p", object);
443 CallbackAllocator<char> string_allocator(instance->alloc);
444 // Load system layers
Jesse Hall21597662015-12-18 13:48:24 -0800445 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500446 char layer_prop[PROPERTY_VALUE_MAX];
447 property_get("debug.vulkan.layers", layer_prop, "");
448 String layer_name(string_allocator);
449 String layer_prop_str(layer_prop, string_allocator);
450 size_t end, start = 0;
451 while ((end = layer_prop_str.find(':', start)) != std::string::npos) {
452 layer_name = layer_prop_str.substr(start, end - start);
Michael Lentine233ac732015-11-18 18:28:07 -0800453 ActivateLayer(object, instance, layer_name);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500454 start = end + 1;
455 }
Michael Lentine9da191b2015-10-13 11:08:45 -0500456 Vector<String> layer_names(CallbackAllocator<String>(instance->alloc));
457 InstanceNamesPair instance_names_pair = {.instance = instance,
458 .layer_names = &layer_names};
459 property_list(SetLayerNamesFromProperty,
460 static_cast<void*>(&instance_names_pair));
461 for (auto layer_name_element : layer_names) {
462 ActivateLayer(object, instance, layer_name_element);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500463 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500464 }
465 // Load app layers
Jesse Hall03b6fe12015-11-24 12:44:21 -0800466 for (uint32_t i = 0; i < create_info->enabledLayerNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500467 String layer_name(create_info->ppEnabledLayerNames[i],
468 string_allocator);
469 auto element = instance->layers.find(layer_name);
470 if (element == instance->layers.end()) {
Jesse Hall9a16f972015-10-28 15:59:53 -0700471 ALOGE("requested %s layer '%s' not present",
472 create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ?
473 "instance" : "device",
474 layer_name.c_str());
475 return VK_ERROR_LAYER_NOT_PRESENT;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500476 } else {
477 ActivateLayer(object, instance, layer_name);
478 }
479 }
Jesse Hall9a16f972015-10-28 15:59:53 -0700480 return VK_SUCCESS;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500481}
482
483template <class TCreateInfo>
484bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
485 const char* extension_name,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800486 const VkAllocationCallbacks* alloc) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800487 for (uint32_t i = 0; i < local_create_info.enabledExtensionNameCount; ++i) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500488 if (!strcmp(extension_name,
489 local_create_info.ppEnabledExtensionNames[i])) {
490 return false;
491 }
492 }
Jesse Hall03b6fe12015-11-24 12:44:21 -0800493 uint32_t extension_count = local_create_info.enabledExtensionNameCount;
494 local_create_info.enabledExtensionNameCount++;
Jesse Hall3fbc8562015-11-29 22:10:52 -0800495 void* mem = alloc->pfnAllocation(
Jesse Hall03b6fe12015-11-24 12:44:21 -0800496 alloc->pUserData,
497 local_create_info.enabledExtensionNameCount * sizeof(char*),
Jesse Hall3fbc8562015-11-29 22:10:52 -0800498 alignof(char*), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500499 if (mem) {
500 const char** enabled_extensions = static_cast<const char**>(mem);
501 for (uint32_t i = 0; i < extension_count; ++i) {
502 enabled_extensions[i] =
503 local_create_info.ppEnabledExtensionNames[i];
504 }
505 enabled_extensions[extension_count] = extension_name;
506 local_create_info.ppEnabledExtensionNames = enabled_extensions;
507 } else {
508 ALOGW("%s extension cannot be enabled: memory allocation failed",
509 extension_name);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800510 local_create_info.enabledExtensionNameCount--;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500511 return false;
512 }
513 return true;
514}
515
516template <class T>
517void FreeAllocatedCreateInfo(T& local_create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800518 const VkAllocationCallbacks* alloc) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500519 alloc->pfnFree(
520 alloc->pUserData,
521 const_cast<char**>(local_create_info.ppEnabledExtensionNames));
522}
523
Jesse Halle1b12782015-11-30 11:27:32 -0800524VKAPI_ATTR
Michael Lentineeb970862015-10-15 12:42:22 -0500525VkBool32 LogDebugMessageCallback(VkFlags message_flags,
526 VkDbgObjectType /*obj_type*/,
527 uint64_t /*src_object*/,
528 size_t /*location*/,
529 int32_t message_code,
530 const char* layer_prefix,
531 const char* message,
532 void* /*user_data*/) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500533 if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
534 ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
535 } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
536 ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
537 }
Michael Lentineeb970862015-10-15 12:42:22 -0500538 return false;
Michael Lentine03c64b02015-08-26 18:27:26 -0500539}
540
Jesse Hall06193802015-12-03 16:12:51 -0800541VkResult Noop() {
Michael Lentine03c64b02015-08-26 18:27:26 -0500542 return VK_SUCCESS;
543}
544
Jesse Halle1b12782015-11-30 11:27:32 -0800545VKAPI_ATTR PFN_vkVoidFunction
546GetLayerDeviceProcAddr(VkDevice device, const char* name) {
Jesse Hall06193802015-12-03 16:12:51 -0800547 // The static_casts are used to ensure that our function actually
548 // matches the API function prototype. Otherwise, if the API function
549 // prototype changes (only a problem during API development), the compiler
550 // has no way of knowing that the function is supposed to match the
551 // prototype, so won't warn us if they don't.
Michael Lentine03c64b02015-08-26 18:27:26 -0500552 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800553 return reinterpret_cast<PFN_vkVoidFunction>(
554 static_cast<PFN_vkGetDeviceProcAddr>(GetLayerDeviceProcAddr));
Michael Lentine03c64b02015-08-26 18:27:26 -0500555 }
556 if (strcmp(name, "vkCreateDevice") == 0) {
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800557 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
Michael Lentine03c64b02015-08-26 18:27:26 -0500558 }
Michael Lentine88594d72015-11-12 12:49:45 -0800559 // WSI extensions are not in the driver so return the loader functions
Michael Lentine88594d72015-11-12 12:49:45 -0800560 if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800561 return reinterpret_cast<PFN_vkVoidFunction>(
562 static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800563 }
564 if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800565 return reinterpret_cast<PFN_vkVoidFunction>(
566 static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800567 }
568 if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800569 return reinterpret_cast<PFN_vkVoidFunction>(
570 static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800571 }
572 if (strcmp(name, "vkAcquireNextImageKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800573 return reinterpret_cast<PFN_vkVoidFunction>(
574 static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800575 }
576 if (strcmp(name, "vkQueuePresentKHR") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800577 return reinterpret_cast<PFN_vkVoidFunction>(
578 static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR));
Michael Lentine88594d72015-11-12 12:49:45 -0800579 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500580 if (!device)
581 return GetGlobalDeviceProcAddr(name);
582 Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500583 return loader_device->instance->drv.GetDeviceProcAddr(device, name);
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500584}
585
Jesse Hall04f4f472015-08-16 19:51:04 -0700586// -----------------------------------------------------------------------------
587// "Bottom" functions. These are called at the end of the instance dispatch
588// chain.
589
Jesse Halle1b12782015-11-30 11:27:32 -0800590VKAPI_ATTR
Jesse Hall03b6fe12015-11-24 12:44:21 -0800591void DestroyInstanceBottom(VkInstance instance,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800592 const VkAllocationCallbacks* allocator) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700593 // These checks allow us to call DestroyInstanceBottom from any error path
594 // in CreateInstanceBottom, before the driver instance is fully initialized.
595 if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
596 instance->drv.vtbl.DestroyInstance) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800597 instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance,
598 allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700599 }
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500600 if (instance->message) {
601 PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500602 DebugDestroyMessageCallback =
603 reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
604 vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
Michael Lentinecd6cabf2015-09-14 17:32:59 -0500605 DebugDestroyMessageCallback(instance, instance->message);
606 }
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800607 for (auto it = instance->active_layers.begin();
608 it != instance->active_layers.end(); ++it) {
Michael Lentine1d1e65f2015-11-19 14:23:06 -0800609 DeactivateLayer(instance, it);
Michael Lentined1d5e5e2015-11-02 18:32:04 -0800610 }
Jesse Hall3fbc8562015-11-29 22:10:52 -0800611 const VkAllocationCallbacks* alloc = instance->alloc;
Jesse Hall04f4f472015-08-16 19:51:04 -0700612 instance->~VkInstance_T();
613 alloc->pfnFree(alloc->pUserData, instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700614}
615
Jesse Halle1b12782015-11-30 11:27:32 -0800616VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700617VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800618 const VkAllocationCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700619 VkInstance* instance_ptr) {
620 Instance* instance = *instance_ptr;
621 VkResult result;
622
Jesse Hall03b6fe12015-11-24 12:44:21 -0800623 result = g_hwdevice->CreateInstance(create_info, instance->alloc,
624 &instance->drv.vtbl.instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700625 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800626 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700627 return result;
628 }
629
Michael Lentine03c64b02015-08-26 18:27:26 -0500630 if (!LoadInstanceVtbl(
631 instance->drv.vtbl.instance, instance->drv.vtbl.instance,
632 g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800633 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700634 return VK_ERROR_INITIALIZATION_FAILED;
635 }
636
637 // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
638 // queryable from the Instance, and that the resulting function work for any
639 // VkDevice created from the instance.
640 instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
641 g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
642 "vkGetDeviceProcAddr"));
643 if (!instance->drv.GetDeviceProcAddr) {
644 ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
Jesse Hall03b6fe12015-11-24 12:44:21 -0800645 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700646 return VK_ERROR_INITIALIZATION_FAILED;
647 }
648
649 hwvulkan_dispatch_t* dispatch =
650 reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
651 if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
652 // Skip setting dispatch->vtbl on the driver instance handle, since we
653 // never intentionally call through it; we go through Instance::drv.vtbl
654 // instead.
655 } else {
656 ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
657 dispatch->magic);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800658 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700659 return VK_ERROR_INITIALIZATION_FAILED;
660 }
661
662 uint32_t num_physical_devices = 0;
663 result = instance->drv.vtbl.EnumeratePhysicalDevices(
664 instance->drv.vtbl.instance, &num_physical_devices, nullptr);
665 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -0800666 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700667 return VK_ERROR_INITIALIZATION_FAILED;
668 }
669 num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
670 result = instance->drv.vtbl.EnumeratePhysicalDevices(
671 instance->drv.vtbl.instance, &num_physical_devices,
672 instance->physical_devices);
673 if (result != VK_SUCCESS) {
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 for (uint32_t i = 0; i < num_physical_devices; i++) {
678 dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
679 instance->physical_devices[i]);
680 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
681 ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
682 dispatch->magic);
Jesse Hall03b6fe12015-11-24 12:44:21 -0800683 DestroyInstanceBottom(instance, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700684 return VK_ERROR_INITIALIZATION_FAILED;
685 }
686 dispatch->vtbl = instance->vtbl;
687 }
688 instance->drv.num_physical_devices = num_physical_devices;
689
690 instance->num_physical_devices = instance->drv.num_physical_devices;
691 return VK_SUCCESS;
692}
693
Jesse Halle1b12782015-11-30 11:27:32 -0800694VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700695VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
696 uint32_t* pdev_count,
697 VkPhysicalDevice* pdevs) {
698 uint32_t count = instance->num_physical_devices;
699 if (pdevs) {
700 count = std::min(count, *pdev_count);
701 std::copy(instance->physical_devices,
702 instance->physical_devices + count, pdevs);
703 }
704 *pdev_count = count;
705 return VK_SUCCESS;
706}
707
Jesse Halle1b12782015-11-30 11:27:32 -0800708VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800709void GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
710 VkPhysicalDeviceFeatures* features) {
711 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
Jesse Hall04f4f472015-08-16 19:51:04 -0700712}
713
Jesse Halle1b12782015-11-30 11:27:32 -0800714VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800715void GetPhysicalDeviceFormatPropertiesBottom(VkPhysicalDevice pdev,
716 VkFormat format,
717 VkFormatProperties* properties) {
718 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700719 pdev, format, properties);
720}
721
Jesse Halle1b12782015-11-30 11:27:32 -0800722VKAPI_ATTR
Jesse Halla9e57032015-11-30 01:03:10 -0800723VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700724 VkPhysicalDevice pdev,
725 VkFormat format,
726 VkImageType type,
727 VkImageTiling tiling,
728 VkImageUsageFlags usage,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700729 VkImageCreateFlags flags,
Jesse Hall04f4f472015-08-16 19:51:04 -0700730 VkImageFormatProperties* properties) {
Jesse Halla9e57032015-11-30 01:03:10 -0800731 return GetVtbl(pdev)
732 ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
733 pdev, format, type, tiling, usage, flags, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700734}
735
Jesse Halle1b12782015-11-30 11:27:32 -0800736VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800737void GetPhysicalDevicePropertiesBottom(VkPhysicalDevice pdev,
738 VkPhysicalDeviceProperties* properties) {
739 GetVtbl(pdev)
Jesse Hall04f4f472015-08-16 19:51:04 -0700740 ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
741}
742
Jesse Halle1b12782015-11-30 11:27:32 -0800743VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800744void GetPhysicalDeviceQueueFamilyPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700745 VkPhysicalDevice pdev,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700746 uint32_t* pCount,
747 VkQueueFamilyProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800748 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueFamilyProperties(
749 pdev, pCount, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700750}
751
Jesse Halle1b12782015-11-30 11:27:32 -0800752VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800753void GetPhysicalDeviceMemoryPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700754 VkPhysicalDevice pdev,
755 VkPhysicalDeviceMemoryProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800756 GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700757 pdev, properties);
758}
759
Jesse Halle1b12782015-11-30 11:27:32 -0800760VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700761VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
762 const VkDeviceCreateInfo* create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800763 const VkAllocationCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700764 VkDevice* out_device) {
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500765 Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700766 VkResult result;
767
Jesse Hall03b6fe12015-11-24 12:44:21 -0800768 if (!allocator) {
769 if (instance.alloc)
770 allocator = instance.alloc;
771 else
772 allocator = &kDefaultAllocCallbacks;
773 }
774
Jesse Hall3fbc8562015-11-29 22:10:52 -0800775 void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Device),
776 alignof(Device),
777 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
Jesse Hall04f4f472015-08-16 19:51:04 -0700778 if (!mem)
779 return VK_ERROR_OUT_OF_HOST_MEMORY;
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500780 Device* device = new (mem) Device(&instance);
Jesse Hall04f4f472015-08-16 19:51:04 -0700781
Jesse Hall9a16f972015-10-28 15:59:53 -0700782 result = ActivateAllLayers(create_info, &instance, device);
783 if (result != VK_SUCCESS) {
784 DestroyDevice(device);
785 return result;
786 }
787
Jesse Hall04f4f472015-08-16 19:51:04 -0700788 VkDevice drv_device;
Jesse Hall03b6fe12015-11-24 12:44:21 -0800789 result = instance.drv.vtbl.CreateDevice(pdev, create_info, allocator,
790 &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700791 if (result != VK_SUCCESS) {
792 DestroyDevice(device);
793 return result;
794 }
795
Jesse Hall04f4f472015-08-16 19:51:04 -0700796 hwvulkan_dispatch_t* dispatch =
797 reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
798 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
799 ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Michael Lentine03c64b02015-08-26 18:27:26 -0500800 PFN_vkDestroyDevice destroy_device =
801 reinterpret_cast<PFN_vkDestroyDevice>(
802 instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800803 destroy_device(drv_device, allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -0700804 DestroyDevice(device);
805 return VK_ERROR_INITIALIZATION_FAILED;
806 }
807 dispatch->vtbl = &device->vtbl_storage;
808
Michael Lentine03c64b02015-08-26 18:27:26 -0500809 void* base_object = static_cast<void*>(drv_device);
810 void* next_object = base_object;
811 VkLayerLinkedListElem* next_element;
812 PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
813 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500814 device->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -0500815 CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
816
817 for (size_t i = elem_list.size(); i > 0; i--) {
818 size_t idx = i - 1;
819 next_element = &elem_list[idx];
820 next_element->get_proc_addr =
821 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
822 next_element->base_object = base_object;
823 next_element->next_element = next_object;
824 next_object = static_cast<void*>(next_element);
825
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500826 auto& name = device->active_layers[idx]->first;
827 auto& handle = device->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -0500828 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500829 dlsym(handle, (name + "GetDeviceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -0500830 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500831 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500832 dlsym(handle, "vkGetDeviceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -0700833 if (!next_get_proc_addr) {
834 ALOGE("Cannot find vkGetDeviceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -0500835 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -0700836 next_object = next_element->next_element;
837 next_get_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
838 next_element->get_proc_addr);
839 }
Michael Lentine03c64b02015-08-26 18:27:26 -0500840 }
841 }
842
843 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
844 static_cast<VkDevice>(next_object), next_get_proc_addr,
845 device->vtbl_storage)) {
846 DestroyDevice(device);
847 return VK_ERROR_INITIALIZATION_FAILED;
848 }
849
850 PFN_vkCreateDevice layer_createDevice =
851 reinterpret_cast<PFN_vkCreateDevice>(
852 device->vtbl_storage.GetDeviceProcAddr(drv_device,
853 "vkCreateDevice"));
Jesse Hall03b6fe12015-11-24 12:44:21 -0800854 layer_createDevice(pdev, create_info, allocator, &drv_device);
Jesse Hall04f4f472015-08-16 19:51:04 -0700855
Michael Lentine88594d72015-11-12 12:49:45 -0800856 // TODO(mlentine) : This is needed to use WSI layer validation. Remove this
857 // when new version of layer initialization exits.
858 if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
859 static_cast<VkDevice>(next_object), next_get_proc_addr,
860 device->vtbl_storage)) {
861 DestroyDevice(device);
862 return VK_ERROR_INITIALIZATION_FAILED;
863 }
864
Jesse Hall04f4f472015-08-16 19:51:04 -0700865 *out_device = drv_device;
866 return VK_SUCCESS;
867}
868
Jesse Halle1b12782015-11-30 11:27:32 -0800869VKAPI_ATTR
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700870VkResult EnumerateDeviceExtensionPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700871 VkPhysicalDevice pdev,
872 const char* layer_name,
873 uint32_t* properties_count,
874 VkExtensionProperties* properties) {
875 // TODO: what are we supposed to do with layer_name here?
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700876 return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceExtensionProperties(
877 pdev, layer_name, properties_count, properties);
Jesse Hall04f4f472015-08-16 19:51:04 -0700878}
879
Jesse Halle1b12782015-11-30 11:27:32 -0800880VKAPI_ATTR
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700881VkResult EnumerateDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
882 uint32_t* properties_count,
883 VkLayerProperties* properties) {
884 return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceLayerProperties(
Jesse Hall04f4f472015-08-16 19:51:04 -0700885 pdev, properties_count, properties);
886}
887
Jesse Halle1b12782015-11-30 11:27:32 -0800888VKAPI_ATTR
Jesse Hall606a54e2015-11-19 22:17:28 -0800889void GetPhysicalDeviceSparseImageFormatPropertiesBottom(
Jesse Hall04f4f472015-08-16 19:51:04 -0700890 VkPhysicalDevice pdev,
891 VkFormat format,
892 VkImageType type,
Jesse Hall091ed9e2015-11-30 00:55:29 -0800893 VkSampleCountFlagBits samples,
Jesse Hall04f4f472015-08-16 19:51:04 -0700894 VkImageUsageFlags usage,
895 VkImageTiling tiling,
896 uint32_t* properties_count,
897 VkSparseImageFormatProperties* properties) {
Jesse Hall606a54e2015-11-19 22:17:28 -0800898 GetVtbl(pdev)
Jesse Hall04f4f472015-08-16 19:51:04 -0700899 ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
900 pdev, format, type, samples, usage, tiling, properties_count,
901 properties);
902}
903
Jesse Halle1b12782015-11-30 11:27:32 -0800904VKAPI_ATTR PFN_vkVoidFunction
905GetInstanceProcAddrBottom(VkInstance, const char*);
Jesse Hall04f4f472015-08-16 19:51:04 -0700906
907const InstanceVtbl kBottomInstanceFunctions = {
908 // clang-format off
909 .instance = nullptr,
Jesse Hallc838b082015-12-04 21:25:04 -0800910
Jesse Hall04f4f472015-08-16 19:51:04 -0700911 .CreateInstance = CreateInstanceBottom,
912 .DestroyInstance = DestroyInstanceBottom,
913 .GetInstanceProcAddr = GetInstanceProcAddrBottom,
914 .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
Jesse Hallc838b082015-12-04 21:25:04 -0800915
Jesse Hall04f4f472015-08-16 19:51:04 -0700916 .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
917 .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
918 .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700919 .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700920 .GetPhysicalDeviceQueueFamilyProperties = GetPhysicalDeviceQueueFamilyPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700921 .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
922 .CreateDevice = CreateDeviceBottom,
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700923 .EnumerateDeviceExtensionProperties = EnumerateDeviceExtensionPropertiesBottom,
924 .EnumerateDeviceLayerProperties = EnumerateDeviceLayerPropertiesBottom,
Jesse Hall04f4f472015-08-16 19:51:04 -0700925 .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
Jesse Hallc838b082015-12-04 21:25:04 -0800926
Jesse Hallb00daad2015-11-29 19:46:20 -0800927 .GetPhysicalDeviceSurfaceCapabilitiesKHR = GetPhysicalDeviceSurfaceCapabilitiesKHR,
928 .GetPhysicalDeviceSurfaceFormatsKHR = GetPhysicalDeviceSurfaceFormatsKHR,
929 .GetPhysicalDeviceSurfacePresentModesKHR = GetPhysicalDeviceSurfacePresentModesKHR,
Jesse Hallc838b082015-12-04 21:25:04 -0800930 .CreateAndroidSurfaceKHR = CreateAndroidSurfaceKHR,
931 .DestroySurfaceKHR = DestroySurfaceKHR,
932 .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
Jesse Hall04f4f472015-08-16 19:51:04 -0700933 // clang-format on
934};
935
Jesse Halle1b12782015-11-30 11:27:32 -0800936VKAPI_ATTR
Jesse Hall04f4f472015-08-16 19:51:04 -0700937PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
Michael Lentine03c64b02015-08-26 18:27:26 -0500938 // TODO: Possibly move this into the instance table
939 // TODO: Possibly register the callbacks in the loader
940 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
941 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
942 return reinterpret_cast<PFN_vkVoidFunction>(Noop);
943 }
944 if (strcmp(name, "vkCreateInstance") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -0800945 return reinterpret_cast<PFN_vkVoidFunction>(
946 static_cast<PFN_vkCreateInstance>(CreateInstanceBottom));
Michael Lentine03c64b02015-08-26 18:27:26 -0500947 }
Jesse Hall04f4f472015-08-16 19:51:04 -0700948 return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
949}
950
951} // namespace
952
953// -----------------------------------------------------------------------------
954// Global functions. These are called directly from the loader entry points,
955// without going through a dispatch table.
956
957namespace vulkan {
958
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700959VkResult EnumerateInstanceExtensionProperties(
960 const char* /*layer_name*/,
961 uint32_t* count,
962 VkExtensionProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700963 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700964 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700965
966 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700967 ALOGW("vkEnumerateInstanceExtensionProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700968
969 *count = 0;
970 return VK_SUCCESS;
971}
972
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700973VkResult EnumerateInstanceLayerProperties(uint32_t* count,
974 VkLayerProperties* /*properties*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -0700975 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700976 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700977
978 // TODO: not yet implemented
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700979 ALOGW("vkEnumerateInstanceLayerProperties not implemented");
Jesse Hall04f4f472015-08-16 19:51:04 -0700980
981 *count = 0;
982 return VK_SUCCESS;
983}
984
985VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
Jesse Hall3fbc8562015-11-29 22:10:52 -0800986 const VkAllocationCallbacks* allocator,
Jesse Hall04f4f472015-08-16 19:51:04 -0700987 VkInstance* out_instance) {
988 VkResult result;
989
990 if (!EnsureInitialized())
Jesse Hall5ae3abb2015-10-08 14:00:22 -0700991 return VK_ERROR_INITIALIZATION_FAILED;
Jesse Hall04f4f472015-08-16 19:51:04 -0700992
Jesse Hall03b6fe12015-11-24 12:44:21 -0800993 if (!allocator)
994 allocator = &kDefaultAllocCallbacks;
995
Jesse Hall04f4f472015-08-16 19:51:04 -0700996 VkInstanceCreateInfo local_create_info = *create_info;
Jesse Hall04f4f472015-08-16 19:51:04 -0700997 create_info = &local_create_info;
998
Jesse Hall3fbc8562015-11-29 22:10:52 -0800999 void* instance_mem = allocator->pfnAllocation(
1000 allocator->pUserData, sizeof(Instance), alignof(Instance),
1001 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
Jesse Hall04f4f472015-08-16 19:51:04 -07001002 if (!instance_mem)
1003 return VK_ERROR_OUT_OF_HOST_MEMORY;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001004 Instance* instance = new (instance_mem) Instance(allocator);
Jesse Hall04f4f472015-08-16 19:51:04 -07001005
1006 instance->vtbl_storage = kBottomInstanceFunctions;
1007 instance->vtbl_storage.instance = instance;
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001008 instance->message = VK_NULL_HANDLE;
Jesse Hall04f4f472015-08-16 19:51:04 -07001009
Michael Lentine03c64b02015-08-26 18:27:26 -05001010 // Scan layers
Michael Lentine03c64b02015-08-26 18:27:26 -05001011 CallbackAllocator<char> string_allocator(instance->alloc);
Jesse Hall21597662015-12-18 13:48:24 -08001012 String dir_name("/data/local/debug/vulkan/", string_allocator);
1013 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
1014 FindLayersInDirectory(*instance, dir_name);
Michael Lentine1c69b9e2015-09-14 13:26:59 -05001015 const std::string& path = LoaderData::GetInstance().layer_path;
1016 dir_name.assign(path.c_str(), path.size());
1017 dir_name.append("/");
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001018 FindLayersInDirectory(*instance, dir_name);
Jesse Hall04f4f472015-08-16 19:51:04 -07001019
Jesse Hall9a16f972015-10-28 15:59:53 -07001020 result = ActivateAllLayers(create_info, instance, instance);
1021 if (result != VK_SUCCESS) {
Jesse Hall03b6fe12015-11-24 12:44:21 -08001022 DestroyInstanceBottom(instance, allocator);
Jesse Hall9a16f972015-10-28 15:59:53 -07001023 return result;
1024 }
Michael Lentine03c64b02015-08-26 18:27:26 -05001025
1026 void* base_object = static_cast<void*>(instance);
1027 void* next_object = base_object;
1028 VkLayerLinkedListElem* next_element;
1029 PFN_vkGetInstanceProcAddr next_get_proc_addr =
1030 kBottomInstanceFunctions.GetInstanceProcAddr;
1031 Vector<VkLayerLinkedListElem> elem_list(
Michael Lentine1f0f5392015-09-11 14:54:34 -07001032 instance->active_layers.size(),
Michael Lentine03c64b02015-08-26 18:27:26 -05001033 CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
1034
1035 for (size_t i = elem_list.size(); i > 0; i--) {
1036 size_t idx = i - 1;
1037 next_element = &elem_list[idx];
1038 next_element->get_proc_addr =
1039 reinterpret_cast<PFN_vkGetProcAddr>(next_get_proc_addr);
1040 next_element->base_object = base_object;
1041 next_element->next_element = next_object;
1042 next_object = static_cast<void*>(next_element);
1043
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001044 auto& name = instance->active_layers[idx]->first;
1045 auto& handle = instance->active_layers[idx]->second.handle;
Michael Lentine03c64b02015-08-26 18:27:26 -05001046 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001047 dlsym(handle, (name + "GetInstanceProcAddr").c_str()));
Michael Lentine03c64b02015-08-26 18:27:26 -05001048 if (!next_get_proc_addr) {
Michael Lentine03c64b02015-08-26 18:27:26 -05001049 next_get_proc_addr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001050 dlsym(handle, "vkGetInstanceProcAddr"));
Michael Lentine1f0f5392015-09-11 14:54:34 -07001051 if (!next_get_proc_addr) {
1052 ALOGE("Cannot find vkGetInstanceProcAddr for %s, error is %s",
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001053 name.c_str(), dlerror());
Michael Lentine1f0f5392015-09-11 14:54:34 -07001054 next_object = next_element->next_element;
1055 next_get_proc_addr =
1056 reinterpret_cast<PFN_vkGetInstanceProcAddr>(
1057 next_element->get_proc_addr);
1058 }
Michael Lentine03c64b02015-08-26 18:27:26 -05001059 }
1060 }
1061
1062 if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
1063 static_cast<VkInstance>(next_object),
1064 next_get_proc_addr, instance->vtbl_storage)) {
Jesse Hall03b6fe12015-11-24 12:44:21 -08001065 DestroyInstanceBottom(instance, allocator);
Michael Lentine03c64b02015-08-26 18:27:26 -05001066 return VK_ERROR_INITIALIZATION_FAILED;
1067 }
1068
Michael Lentine950bb4f2015-09-14 13:26:30 -05001069 // Force enable callback extension if required
Jesse Hall21597662015-12-18 13:48:24 -08001070 bool enable_callback = false;
1071 bool enable_logging = false;
1072 if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
1073 enable_callback =
1074 property_get_bool("debug.vulkan.enable_callback", false);
1075 enable_logging = enable_callback;
1076 if (enable_callback) {
1077 enable_callback = AddExtensionToCreateInfo(
1078 local_create_info, "DEBUG_REPORT", instance->alloc);
1079 }
Michael Lentine950bb4f2015-09-14 13:26:30 -05001080 }
1081
Jesse Hall04f4f472015-08-16 19:51:04 -07001082 *out_instance = instance;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001083 result = instance->vtbl_storage.CreateInstance(create_info, allocator,
1084 out_instance);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001085 if (enable_callback)
1086 FreeAllocatedCreateInfo(local_create_info, instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001087 if (result <= 0) {
1088 // For every layer, including the loader top and bottom layers:
1089 // - If a call to the next CreateInstance fails, the layer must clean
1090 // up anything it has successfully done so far, and propagate the
1091 // error upwards.
1092 // - If a layer successfully calls the next layer's CreateInstance, and
1093 // afterwards must fail for some reason, it must call the next layer's
1094 // DestroyInstance before returning.
1095 // - The layer must not call the next layer's DestroyInstance if that
1096 // layer's CreateInstance wasn't called, or returned failure.
1097
1098 // On failure, CreateInstanceBottom frees the instance struct, so it's
1099 // already gone at this point. Nothing to do.
1100 }
1101
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001102 if (enable_logging) {
1103 PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001104 DebugCreateMessageCallback =
1105 reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
1106 vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
1107 DebugCreateMessageCallback(
1108 instance, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
1109 LogDebugMessageCallback, NULL, &instance->message);
Michael Lentinecd6cabf2015-09-14 17:32:59 -05001110 }
1111
Jesse Hall04f4f472015-08-16 19:51:04 -07001112 return result;
1113}
1114
1115PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
1116 if (!instance)
1117 return GetGlobalInstanceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001118 // TODO: Possibly move this into the instance table
1119 if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
1120 strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
1121 if (!instance->vtbl)
1122 return NULL;
1123 PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
1124 return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
1125 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001126 // For special-case functions we always return the loader entry
1127 if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
1128 strcmp(name, "vkGetDeviceProcAddr") == 0) {
1129 return GetGlobalInstanceProcAddr(name);
1130 }
1131 return GetSpecificInstanceProcAddr(instance->vtbl, name);
1132}
1133
1134PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
1135 if (!device)
1136 return GetGlobalDeviceProcAddr(name);
Michael Lentine03c64b02015-08-26 18:27:26 -05001137 if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001138 return reinterpret_cast<PFN_vkVoidFunction>(
1139 static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr));
Michael Lentine03c64b02015-08-26 18:27:26 -05001140 }
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001141 if (strcmp(name, "vkGetDeviceQueue") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001142 return reinterpret_cast<PFN_vkVoidFunction>(
1143 static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue));
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001144 }
Jesse Hall2ca1bd52015-12-02 15:40:12 -08001145 if (strcmp(name, "vkAllocateCommandBuffers") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001146 return reinterpret_cast<PFN_vkVoidFunction>(
1147 static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers));
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001148 }
1149 if (strcmp(name, "vkDestroyDevice") == 0) {
Jesse Hall06193802015-12-03 16:12:51 -08001150 return reinterpret_cast<PFN_vkVoidFunction>(
1151 static_cast<PFN_vkDestroyDevice>(DestroyDevice));
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001152 }
Jesse Hall04f4f472015-08-16 19:51:04 -07001153 return GetSpecificDeviceProcAddr(GetVtbl(device), name);
1154}
1155
Jesse Hall606a54e2015-11-19 22:17:28 -08001156void GetDeviceQueue(VkDevice drv_device,
1157 uint32_t family,
1158 uint32_t index,
1159 VkQueue* out_queue) {
Jesse Hall04f4f472015-08-16 19:51:04 -07001160 VkResult result;
1161 VkQueue queue;
1162 const DeviceVtbl* vtbl = GetVtbl(drv_device);
Jesse Hall606a54e2015-11-19 22:17:28 -08001163 vtbl->GetDeviceQueue(drv_device, family, index, &queue);
Jesse Hall04f4f472015-08-16 19:51:04 -07001164 hwvulkan_dispatch_t* dispatch =
1165 reinterpret_cast<hwvulkan_dispatch_t*>(queue);
Jesse Hall606a54e2015-11-19 22:17:28 -08001166 if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != vtbl)
Jesse Hall04f4f472015-08-16 19:51:04 -07001167 ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
Jesse Hall04f4f472015-08-16 19:51:04 -07001168 dispatch->vtbl = vtbl;
1169 *out_queue = queue;
Jesse Hall04f4f472015-08-16 19:51:04 -07001170}
1171
Jesse Hall2ca1bd52015-12-02 15:40:12 -08001172VkResult AllocateCommandBuffers(VkDevice device,
1173 const VkCommandBufferAllocateInfo* alloc_info,
1174 VkCommandBuffer* cmdbufs) {
Jesse Hallfbf97b02015-11-20 14:17:03 -08001175 const DeviceVtbl* vtbl = GetVtbl(device);
Jesse Hall3fbc8562015-11-29 22:10:52 -08001176 VkResult result = vtbl->AllocateCommandBuffers(device, alloc_info, cmdbufs);
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001177 if (result != VK_SUCCESS)
1178 return result;
Jesse Hall03b6fe12015-11-24 12:44:21 -08001179 for (uint32_t i = 0; i < alloc_info->bufferCount; i++) {
Jesse Hallfbf97b02015-11-20 14:17:03 -08001180 hwvulkan_dispatch_t* dispatch =
Jesse Hall3fbc8562015-11-29 22:10:52 -08001181 reinterpret_cast<hwvulkan_dispatch_t*>(cmdbufs[i]);
Jesse Hallfbf97b02015-11-20 14:17:03 -08001182 ALOGE_IF(dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001183 "invalid VkCommandBuffer dispatch magic: 0x%" PRIxPTR,
Jesse Hallfbf97b02015-11-20 14:17:03 -08001184 dispatch->magic);
1185 dispatch->vtbl = vtbl;
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001186 }
Jesse Hallc7a6eb52015-08-31 12:52:03 -07001187 return VK_SUCCESS;
1188}
1189
Jesse Hall06193802015-12-03 16:12:51 -08001190void DestroyDevice(VkDevice drv_device,
1191 const VkAllocationCallbacks* /*allocator*/) {
Jesse Hall04f4f472015-08-16 19:51:04 -07001192 const DeviceVtbl* vtbl = GetVtbl(drv_device);
1193 Device* device = static_cast<Device*>(vtbl->device);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001194 for (auto it = device->active_layers.begin();
1195 it != device->active_layers.end(); ++it) {
Michael Lentine1d1e65f2015-11-19 14:23:06 -08001196 DeactivateLayer(device->instance, it);
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001197 }
Jesse Hall03b6fe12015-11-24 12:44:21 -08001198 vtbl->DestroyDevice(drv_device, device->instance->alloc);
Jesse Hall04f4f472015-08-16 19:51:04 -07001199 DestroyDevice(device);
Jesse Hall04f4f472015-08-16 19:51:04 -07001200}
1201
Jesse Hall1356b0d2015-11-23 17:24:58 -08001202void* AllocMem(VkInstance instance,
1203 size_t size,
1204 size_t align,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001205 VkSystemAllocationScope scope) {
1206 const VkAllocationCallbacks* alloc_cb = instance->alloc;
1207 return alloc_cb->pfnAllocation(alloc_cb->pUserData, size, align, scope);
Jesse Hall1356b0d2015-11-23 17:24:58 -08001208}
1209
1210void FreeMem(VkInstance instance, void* ptr) {
Jesse Hall3fbc8562015-11-29 22:10:52 -08001211 const VkAllocationCallbacks* alloc_cb = instance->alloc;
Jesse Hall1356b0d2015-11-23 17:24:58 -08001212 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1213}
1214
1215void* AllocMem(VkDevice device,
1216 size_t size,
1217 size_t align,
Jesse Hall3fbc8562015-11-29 22:10:52 -08001218 VkSystemAllocationScope scope) {
1219 const VkAllocationCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001220 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Hall3fbc8562015-11-29 22:10:52 -08001221 return alloc_cb->pfnAllocation(alloc_cb->pUserData, size, align, scope);
Jesse Halld7b994a2015-09-07 14:17:37 -07001222}
1223
Jesse Hall1356b0d2015-11-23 17:24:58 -08001224void FreeMem(VkDevice device, void* ptr) {
Jesse Hall3fbc8562015-11-29 22:10:52 -08001225 const VkAllocationCallbacks* alloc_cb =
Michael Lentine9dbe67f2015-09-16 15:53:50 -05001226 static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
Jesse Halld7b994a2015-09-07 14:17:37 -07001227 alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
1228}
1229
1230const DeviceVtbl& GetDriverVtbl(VkDevice device) {
1231 // TODO(jessehall): This actually returns the API-level vtbl for the
1232 // device, not the driver entry points. Given the current use -- getting
1233 // the driver's private swapchain-related functions -- that works, but is
1234 // misleading and likely to cause bugs. Fix as part of separating the
1235 // loader->driver interface from the app->loader interface.
1236 return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
1237}
1238
1239const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
1240 // TODO(jessehall): This actually returns the API-level vtbl for the
1241 // device, not the driver entry points. Given the current use -- getting
1242 // the driver's private swapchain-related functions -- that works, but is
1243 // misleading and likely to cause bugs. Fix as part of separating the
1244 // loader->driver interface from the app->loader interface.
1245 return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
1246}
1247
Jesse Hall04f4f472015-08-16 19:51:04 -07001248} // namespace vulkan