blob: 9dbdcc21a63e8821e6d2ea1f48c3eef78ccf7b51 [file] [log] [blame]
Chia-I Wu9d518162016-03-24 14:55:27 +08001/*
2 * Copyright 2016 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
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080017#include <stdlib.h>
18#include <string.h>
19#include <algorithm>
Chia-I Wuff4a6c72016-03-24 16:05:56 +080020#include <array>
Chia-I Wu4901db72016-03-24 16:38:58 +080021#include <new>
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080022#include <malloc.h>
Chia-I Wu9d518162016-03-24 14:55:27 +080023#include <sys/prctl.h>
24
25#include "driver.h"
26
Chia-I Wudbb7e9c2016-03-24 15:09:38 +080027// #define ENABLE_ALLOC_CALLSTACKS 1
28#if ENABLE_ALLOC_CALLSTACKS
29#include <utils/CallStack.h>
30#define ALOGD_CALLSTACK(...) \
31 do { \
32 ALOGD(__VA_ARGS__); \
33 android::CallStack callstack; \
34 callstack.update(); \
35 callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, " "); \
36 } while (false)
37#else
38#define ALOGD_CALLSTACK(...) \
39 do { \
40 } while (false)
41#endif
42
Chia-I Wu9d518162016-03-24 14:55:27 +080043namespace vulkan {
44namespace driver {
45
Chia-I Wu136b8eb2016-03-24 15:01:52 +080046namespace {
47
Chia-I Wu4901db72016-03-24 16:38:58 +080048class CreateInfoWrapper {
49 public:
Chia-I Wuff4a6c72016-03-24 16:05:56 +080050 CreateInfoWrapper(hwvulkan_device_t* hw_dev,
51 const VkInstanceCreateInfo& create_info,
52 const VkAllocationCallbacks& allocator);
Chia-I Wu4901db72016-03-24 16:38:58 +080053 CreateInfoWrapper(VkPhysicalDevice physical_dev,
54 const VkDeviceCreateInfo& create_info,
55 const VkAllocationCallbacks& allocator);
56 ~CreateInfoWrapper();
57
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080058 VkResult Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +080059
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080060 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
61 const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080062
Chia-I Wuff4a6c72016-03-24 16:05:56 +080063 explicit operator const VkInstanceCreateInfo*() const;
Chia-I Wu4901db72016-03-24 16:38:58 +080064 explicit operator const VkDeviceCreateInfo*() const;
65
66 private:
67 struct ExtensionFilter {
68 VkExtensionProperties* exts;
69 uint32_t ext_count;
70
71 const char** names;
72 uint32_t name_count;
73 };
74
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080075 VkResult SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +080076
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080077 VkResult SanitizeLayers();
78 VkResult SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +080079
Chia-I Wu3e6c2d62016-04-11 13:55:56 +080080 VkResult QueryExtensionCount(uint32_t& count) const;
81 VkResult EnumerateExtensions(uint32_t& count,
82 VkExtensionProperties* props) const;
83 VkResult InitExtensionFilter();
84 void FilterExtension(const char* name);
Chia-I Wu4901db72016-03-24 16:38:58 +080085
86 const bool is_instance_;
87 const VkAllocationCallbacks& allocator_;
88
89 union {
90 hwvulkan_device_t* hw_dev_;
91 VkPhysicalDevice physical_dev_;
92 };
93
94 union {
95 VkInstanceCreateInfo instance_info_;
96 VkDeviceCreateInfo dev_info_;
97 };
98
99 ExtensionFilter extension_filter_;
100
101 std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
102 std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
103};
104
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800105CreateInfoWrapper::CreateInfoWrapper(hwvulkan_device_t* hw_dev,
106 const VkInstanceCreateInfo& create_info,
107 const VkAllocationCallbacks& allocator)
108 : is_instance_(true),
109 allocator_(allocator),
110 hw_dev_(hw_dev),
111 instance_info_(create_info),
112 extension_filter_() {
113 hook_extensions_.set(ProcHook::EXTENSION_CORE);
114 hal_extensions_.set(ProcHook::EXTENSION_CORE);
115}
116
Chia-I Wu4901db72016-03-24 16:38:58 +0800117CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
118 const VkDeviceCreateInfo& create_info,
119 const VkAllocationCallbacks& allocator)
120 : is_instance_(false),
121 allocator_(allocator),
122 physical_dev_(physical_dev),
123 dev_info_(create_info),
124 extension_filter_() {
125 hook_extensions_.set(ProcHook::EXTENSION_CORE);
126 hal_extensions_.set(ProcHook::EXTENSION_CORE);
127}
128
129CreateInfoWrapper::~CreateInfoWrapper() {
130 allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
131 allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
132}
133
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800134VkResult CreateInfoWrapper::Validate() {
135 VkResult result = SanitizePNext();
Chia-I Wu4901db72016-03-24 16:38:58 +0800136 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800137 result = SanitizeLayers();
Chia-I Wu4901db72016-03-24 16:38:58 +0800138 if (result == VK_SUCCESS)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800139 result = SanitizeExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800140
141 return result;
142}
143
144const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800145CreateInfoWrapper::GetHookExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800146 return hook_extensions_;
147}
148
149const std::bitset<ProcHook::EXTENSION_COUNT>&
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800150CreateInfoWrapper::GetHalExtensions() const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800151 return hal_extensions_;
152}
153
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800154CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
155 return &instance_info_;
156}
157
Chia-I Wu4901db72016-03-24 16:38:58 +0800158CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
159 return &dev_info_;
160}
161
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800162VkResult CreateInfoWrapper::SanitizePNext() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800163 const struct StructHeader {
164 VkStructureType type;
165 const void* next;
166 } * header;
167
168 if (is_instance_) {
169 header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
170
171 // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
172 while (header &&
173 header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
174 header = reinterpret_cast<const StructHeader*>(header->next);
175
176 instance_info_.pNext = header;
177 } else {
178 header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
179
180 // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
181 while (header &&
182 header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
183 header = reinterpret_cast<const StructHeader*>(header->next);
184
185 dev_info_.pNext = header;
186 }
187
188 return VK_SUCCESS;
189}
190
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800191VkResult CreateInfoWrapper::SanitizeLayers() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800192 auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
193 : dev_info_.ppEnabledLayerNames;
194 auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
195 : dev_info_.enabledLayerCount;
196
197 // remove all layers
198 layer_names = nullptr;
199 layer_count = 0;
200
201 return VK_SUCCESS;
202}
203
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800204VkResult CreateInfoWrapper::SanitizeExtensions() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800205 auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
206 : dev_info_.ppEnabledExtensionNames;
207 auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
208 : dev_info_.enabledExtensionCount;
209 if (!ext_count)
210 return VK_SUCCESS;
211
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800212 VkResult result = InitExtensionFilter();
Chia-I Wu4901db72016-03-24 16:38:58 +0800213 if (result != VK_SUCCESS)
214 return result;
215
216 for (uint32_t i = 0; i < ext_count; i++)
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800217 FilterExtension(ext_names[i]);
Chia-I Wu4901db72016-03-24 16:38:58 +0800218
219 ext_names = extension_filter_.names;
220 ext_count = extension_filter_.name_count;
221
222 return VK_SUCCESS;
223}
224
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800225VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
Chia-I Wu4901db72016-03-24 16:38:58 +0800226 if (is_instance_) {
227 return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
228 nullptr);
229 } else {
230 const auto& driver = GetData(physical_dev_).driver;
231 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
232 &count, nullptr);
233 }
234}
235
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800236VkResult CreateInfoWrapper::EnumerateExtensions(
Chia-I Wu4901db72016-03-24 16:38:58 +0800237 uint32_t& count,
238 VkExtensionProperties* props) const {
239 if (is_instance_) {
240 return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
241 props);
242 } else {
243 const auto& driver = GetData(physical_dev_).driver;
244 return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
245 &count, props);
246 }
247}
248
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800249VkResult CreateInfoWrapper::InitExtensionFilter() {
Chia-I Wu4901db72016-03-24 16:38:58 +0800250 // query extension count
251 uint32_t count;
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800252 VkResult result = QueryExtensionCount(count);
Chia-I Wu4901db72016-03-24 16:38:58 +0800253 if (result != VK_SUCCESS || count == 0)
254 return result;
255
256 auto& filter = extension_filter_;
257 filter.exts =
258 reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
259 allocator_.pUserData, sizeof(VkExtensionProperties) * count,
260 alignof(VkExtensionProperties),
261 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
262 if (!filter.exts)
263 return VK_ERROR_OUT_OF_HOST_MEMORY;
264
265 // enumerate extensions
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800266 result = EnumerateExtensions(count, filter.exts);
Chia-I Wu4901db72016-03-24 16:38:58 +0800267 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
268 return result;
269
270 if (!count)
271 return VK_SUCCESS;
272
273 filter.ext_count = count;
274
275 // allocate name array
276 uint32_t enabled_ext_count = (is_instance_)
277 ? instance_info_.enabledExtensionCount
278 : dev_info_.enabledExtensionCount;
279 count = std::min(filter.ext_count, enabled_ext_count);
280 filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
281 allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
282 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
283 if (!filter.names)
284 return VK_ERROR_OUT_OF_HOST_MEMORY;
285
286 return VK_SUCCESS;
287}
288
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800289void CreateInfoWrapper::FilterExtension(const char* name) {
Chia-I Wu4901db72016-03-24 16:38:58 +0800290 auto& filter = extension_filter_;
291
292 ProcHook::Extension ext_bit = GetProcHookExtension(name);
293 if (is_instance_) {
294 switch (ext_bit) {
295 case ProcHook::KHR_android_surface:
296 case ProcHook::KHR_surface:
297 hook_extensions_.set(ext_bit);
298 // return now as these extensions do not require HAL support
299 return;
300 case ProcHook::EXT_debug_report:
301 // both we and HAL can take part in
302 hook_extensions_.set(ext_bit);
303 break;
304 case ProcHook::EXTENSION_UNKNOWN:
305 // HAL's extensions
306 break;
307 default:
308 ALOGW("Ignored invalid instance extension %s", name);
309 return;
310 }
311 } else {
312 switch (ext_bit) {
313 case ProcHook::KHR_swapchain:
314 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
315 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
316 ext_bit = ProcHook::ANDROID_native_buffer;
317 break;
318 case ProcHook::EXTENSION_UNKNOWN:
319 // HAL's extensions
320 break;
321 default:
322 ALOGW("Ignored invalid device extension %s", name);
323 return;
324 }
325 }
326
327 for (uint32_t i = 0; i < filter.ext_count; i++) {
328 const VkExtensionProperties& props = filter.exts[i];
329 // ignore unknown extensions
330 if (strcmp(name, props.extensionName) != 0)
331 continue;
332
333 if (ext_bit == ProcHook::ANDROID_native_buffer)
334 hook_extensions_.set(ProcHook::KHR_swapchain);
335
336 filter.names[filter.name_count++] = name;
337 hal_extensions_.set(ext_bit);
338
339 break;
340 }
341}
342
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800343hwvulkan_device_t* g_hwdevice = nullptr;
344
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800345VKAPI_ATTR void* DefaultAllocate(void*,
346 size_t size,
347 size_t alignment,
348 VkSystemAllocationScope) {
349 void* ptr = nullptr;
350 // Vulkan requires 'alignment' to be a power of two, but posix_memalign
351 // additionally requires that it be at least sizeof(void*).
352 int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
353 ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
354 ret, ptr);
355 return ret == 0 ? ptr : nullptr;
356}
357
358VKAPI_ATTR void* DefaultReallocate(void*,
359 void* ptr,
360 size_t size,
361 size_t alignment,
362 VkSystemAllocationScope) {
363 if (size == 0) {
364 free(ptr);
365 return nullptr;
366 }
367
368 // TODO(jessehall): Right now we never shrink allocations; if the new
369 // request is smaller than the existing chunk, we just continue using it.
370 // Right now the loader never reallocs, so this doesn't matter. If that
371 // changes, or if this code is copied into some other project, this should
372 // probably have a heuristic to allocate-copy-free when doing so will save
373 // "enough" space.
374 size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
375 if (size <= old_size)
376 return ptr;
377
378 void* new_ptr = nullptr;
379 if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
380 return nullptr;
381 if (ptr) {
382 memcpy(new_ptr, ptr, std::min(old_size, size));
383 free(ptr);
384 }
385 return new_ptr;
386}
387
388VKAPI_ATTR void DefaultFree(void*, void* ptr) {
389 ALOGD_CALLSTACK("Free: %p", ptr);
390 free(ptr);
391}
392
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800393InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
394 void* data_mem = allocator.pfnAllocation(
395 allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
396 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
397 if (!data_mem)
398 return nullptr;
399
400 return new (data_mem) InstanceData(allocator);
401}
402
403void FreeInstanceData(InstanceData* data,
404 const VkAllocationCallbacks& allocator) {
405 data->~InstanceData();
406 allocator.pfnFree(allocator.pUserData, data);
407}
408
Chia-I Wu4901db72016-03-24 16:38:58 +0800409DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
410 void* data_mem = allocator.pfnAllocation(
411 allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
412 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
413 if (!data_mem)
414 return nullptr;
415
416 return new (data_mem) DeviceData(allocator);
417}
418
419void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
420 data->~DeviceData();
421 allocator.pfnFree(allocator.pUserData, data);
422}
423
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800424} // anonymous namespace
425
Chia-I Wu9d518162016-03-24 14:55:27 +0800426bool Debuggable() {
427 return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
428}
429
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800430bool OpenHAL() {
431 if (g_hwdevice)
432 return true;
433
434 const hwvulkan_module_t* module;
435 int result =
436 hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
437 if (result != 0) {
438 ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result), result);
439 return false;
440 }
441
442 hwvulkan_device_t* device;
443 result =
444 module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
445 reinterpret_cast<hw_device_t**>(&device));
446 if (result != 0) {
447 ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
448 result);
449 return false;
450 }
451
Chia-I Wu136b8eb2016-03-24 15:01:52 +0800452 g_hwdevice = device;
453
454 return true;
455}
456
Chia-I Wudbb7e9c2016-03-24 15:09:38 +0800457const VkAllocationCallbacks& GetDefaultAllocator() {
458 static const VkAllocationCallbacks kDefaultAllocCallbacks = {
459 .pUserData = nullptr,
460 .pfnAllocation = DefaultAllocate,
461 .pfnReallocation = DefaultReallocate,
462 .pfnFree = DefaultFree,
463 };
464
465 return kDefaultAllocCallbacks;
466}
467
Chia-I Wueb7db122016-03-24 09:11:06 +0800468PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
469 const ProcHook* hook = GetProcHook(pName);
470 if (!hook)
471 return g_hwdevice->GetInstanceProcAddr(instance, pName);
472
473 if (!instance) {
474 if (hook->type == ProcHook::GLOBAL)
475 return hook->proc;
476
477 ALOGE(
478 "Invalid use of vkGetInstanceProcAddr to query %s without an "
479 "instance",
480 pName);
481
482 // Some naughty layers expect
483 //
484 // vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
485 //
486 // to work.
487 return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
488 }
489
490 PFN_vkVoidFunction proc;
491
492 switch (hook->type) {
493 case ProcHook::INSTANCE:
494 proc = (GetData(instance).hook_extensions[hook->extension])
495 ? hook->proc
496 : hook->disabled_proc;
497 break;
498 case ProcHook::DEVICE:
499 proc = (hook->extension == ProcHook::EXTENSION_CORE)
500 ? hook->proc
501 : hook->checked_proc;
502 break;
503 default:
504 ALOGE(
505 "Invalid use of vkGetInstanceProcAddr to query %s with an "
506 "instance",
507 pName);
508 proc = nullptr;
509 break;
510 }
511
512 return proc;
513}
514
515PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
516 const ProcHook* hook = GetProcHook(pName);
517 if (!hook)
Chia-I Wucc5e2762016-03-24 13:01:16 +0800518 return GetData(device).driver.GetDeviceProcAddr(device, pName);
Chia-I Wueb7db122016-03-24 09:11:06 +0800519
520 if (hook->type != ProcHook::DEVICE) {
521 ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
522 return nullptr;
523 }
524
525 return (GetData(device).hook_extensions[hook->extension])
526 ? hook->proc
527 : hook->disabled_proc;
528}
529
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800530VkResult EnumerateInstanceExtensionProperties(
531 const char* pLayerName,
532 uint32_t* pPropertyCount,
533 VkExtensionProperties* pProperties) {
534 static const std::array<VkExtensionProperties, 2> loader_extensions = {{
535 // WSI extensions
536 {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
537 {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
538 VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
539 }};
540
541 // enumerate our extensions first
542 if (!pLayerName && pProperties) {
543 uint32_t count = std::min(
544 *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
545
546 std::copy_n(loader_extensions.begin(), count, pProperties);
547
548 if (count < loader_extensions.size()) {
549 *pPropertyCount = count;
550 return VK_INCOMPLETE;
551 }
552
553 pProperties += count;
554 *pPropertyCount -= count;
555 }
556
557 VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
558 pLayerName, pPropertyCount, pProperties);
559
560 if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
561 *pPropertyCount += loader_extensions.size();
562
563 return result;
564}
565
Chia-I Wu01cf3052016-03-24 16:16:21 +0800566VkResult EnumerateDeviceExtensionProperties(
567 VkPhysicalDevice physicalDevice,
568 const char* pLayerName,
569 uint32_t* pPropertyCount,
570 VkExtensionProperties* pProperties) {
571 const InstanceData& data = GetData(physicalDevice);
572
573 VkResult result = data.driver.EnumerateDeviceExtensionProperties(
574 physicalDevice, pLayerName, pPropertyCount, pProperties);
575 if (result != VK_SUCCESS && result != VK_INCOMPLETE)
576 return result;
577
578 if (!pProperties)
579 return result;
580
581 // map VK_ANDROID_native_buffer to VK_KHR_swapchain
582 for (uint32_t i = 0; i < *pPropertyCount; i++) {
583 auto& prop = pProperties[i];
584
585 if (strcmp(prop.extensionName,
586 VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
587 continue;
588
589 memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
590 sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
591 prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
592 }
593
594 return result;
595}
596
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800597VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
598 const VkAllocationCallbacks* pAllocator,
599 VkInstance* pInstance) {
600 const VkAllocationCallbacks& data_allocator =
601 (pAllocator) ? *pAllocator : GetDefaultAllocator();
602
603 CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800604 VkResult result = wrapper.Validate();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800605 if (result != VK_SUCCESS)
606 return result;
607
608 InstanceData* data = AllocateInstanceData(data_allocator);
609 if (!data)
610 return VK_ERROR_OUT_OF_HOST_MEMORY;
611
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800612 data->hook_extensions |= wrapper.GetHookExtensions();
613 data->hal_extensions |= wrapper.GetHalExtensions();
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800614
615 // call into the driver
616 VkInstance instance;
617 result = g_hwdevice->CreateInstance(
618 static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
619 &instance);
620 if (result != VK_SUCCESS) {
621 FreeInstanceData(data, data_allocator);
622 return result;
623 }
624
625 // initialize InstanceDriverTable
626 if (!SetData(instance, *data) ||
627 !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr)) {
628 data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
629 g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
630 if (data->driver.DestroyInstance)
631 data->driver.DestroyInstance(instance, pAllocator);
632
633 FreeInstanceData(data, data_allocator);
634
635 return VK_ERROR_INCOMPATIBLE_DRIVER;
636 }
637
638 data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
639 g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
640 if (!data->get_device_proc_addr) {
641 data->driver.DestroyInstance(instance, pAllocator);
642 FreeInstanceData(data, data_allocator);
643
644 return VK_ERROR_INCOMPATIBLE_DRIVER;
645 }
646
647 *pInstance = instance;
648
649 return VK_SUCCESS;
650}
651
652void DestroyInstance(VkInstance instance,
653 const VkAllocationCallbacks* pAllocator) {
654 InstanceData& data = GetData(instance);
655 data.driver.DestroyInstance(instance, pAllocator);
656
657 VkAllocationCallbacks local_allocator;
658 if (!pAllocator) {
659 local_allocator = data.allocator;
660 pAllocator = &local_allocator;
661 }
662
663 FreeInstanceData(&data, *pAllocator);
664}
665
Chia-I Wu4901db72016-03-24 16:38:58 +0800666VkResult CreateDevice(VkPhysicalDevice physicalDevice,
667 const VkDeviceCreateInfo* pCreateInfo,
668 const VkAllocationCallbacks* pAllocator,
669 VkDevice* pDevice) {
670 const InstanceData& instance_data = GetData(physicalDevice);
671 const VkAllocationCallbacks& data_allocator =
672 (pAllocator) ? *pAllocator : instance_data.allocator;
673
674 CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800675 VkResult result = wrapper.Validate();
Chia-I Wu4901db72016-03-24 16:38:58 +0800676 if (result != VK_SUCCESS)
677 return result;
678
679 DeviceData* data = AllocateDeviceData(data_allocator);
680 if (!data)
681 return VK_ERROR_OUT_OF_HOST_MEMORY;
682
Chia-I Wu3e6c2d62016-04-11 13:55:56 +0800683 data->hook_extensions |= wrapper.GetHookExtensions();
684 data->hal_extensions |= wrapper.GetHalExtensions();
Chia-I Wu4901db72016-03-24 16:38:58 +0800685
686 // call into the driver
687 VkDevice dev;
688 result = instance_data.driver.CreateDevice(
689 physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
690 pAllocator, &dev);
691 if (result != VK_SUCCESS) {
692 FreeDeviceData(data, data_allocator);
693 return result;
694 }
695
696 // initialize DeviceDriverTable
697 if (!SetData(dev, *data) ||
698 !InitDriverTable(dev, instance_data.get_device_proc_addr)) {
699 data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
700 instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
701 if (data->driver.DestroyDevice)
702 data->driver.DestroyDevice(dev, pAllocator);
703
704 FreeDeviceData(data, data_allocator);
705
706 return VK_ERROR_INCOMPATIBLE_DRIVER;
707 }
708
709 *pDevice = dev;
710
711 return VK_SUCCESS;
712}
713
714void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
715 DeviceData& data = GetData(device);
716 data.driver.DestroyDevice(device, pAllocator);
717
718 VkAllocationCallbacks local_allocator;
719 if (!pAllocator) {
720 local_allocator = data.allocator;
721 pAllocator = &local_allocator;
722 }
723
724 FreeDeviceData(&data, *pAllocator);
725}
726
Chia-I Wuff4a6c72016-03-24 16:05:56 +0800727VkResult EnumeratePhysicalDevices(VkInstance instance,
728 uint32_t* pPhysicalDeviceCount,
729 VkPhysicalDevice* pPhysicalDevices) {
730 const auto& data = GetData(instance);
731
732 VkResult result = data.driver.EnumeratePhysicalDevices(
733 instance, pPhysicalDeviceCount, pPhysicalDevices);
734 if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
735 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
736 SetData(pPhysicalDevices[i], data);
737 }
738
739 return result;
740}
741
Chia-I Wuba0be412016-03-24 16:24:40 +0800742void GetDeviceQueue(VkDevice device,
743 uint32_t queueFamilyIndex,
744 uint32_t queueIndex,
745 VkQueue* pQueue) {
746 const auto& data = GetData(device);
747
748 data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
749 SetData(*pQueue, data);
750}
751
Chia-I Wu6a58a8a2016-03-24 16:29:51 +0800752VKAPI_ATTR VkResult
753AllocateCommandBuffers(VkDevice device,
754 const VkCommandBufferAllocateInfo* pAllocateInfo,
755 VkCommandBuffer* pCommandBuffers) {
756 const auto& data = GetData(device);
757
758 VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
759 pCommandBuffers);
760 if (result == VK_SUCCESS) {
761 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
762 SetData(pCommandBuffers[i], data);
763 }
764
765 return result;
766}
767
Chia-I Wu9d518162016-03-24 14:55:27 +0800768} // namespace driver
769} // namespace vulkan