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