driver.cpp revision cbe07ef239121dc99a31a19b9593d76d76abb08b
1/*
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
17#include <stdlib.h>
18#include <string.h>
19#include <algorithm>
20#include <array>
21#include <new>
22#include <malloc.h>
23#include <sys/prctl.h>
24
25#include "driver.h"
26#include "stubhal.h"
27
28// #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
44namespace vulkan {
45namespace driver {
46
47namespace {
48
49class CreateInfoWrapper {
50   public:
51    CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
52                      const VkInstanceCreateInfo& create_info,
53                      const VkAllocationCallbacks& allocator);
54    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>& GetHookExtensions() const;
62    const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
63
64    explicit operator const VkInstanceCreateInfo*() const;
65    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 SanitizePNext();
77
78    VkResult SanitizeLayers();
79    VkResult SanitizeExtensions();
80
81    VkResult QueryExtensionCount(uint32_t& count) const;
82    VkResult EnumerateExtensions(uint32_t& count,
83                                 VkExtensionProperties* props) const;
84    VkResult InitExtensionFilter();
85    void FilterExtension(const char* name);
86
87    const bool is_instance_;
88    const VkAllocationCallbacks& allocator_;
89
90    union {
91        const 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
106CreateInfoWrapper::CreateInfoWrapper(const 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
118CreateInfoWrapper::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 = SanitizePNext();
137    if (result == VK_SUCCESS)
138        result = SanitizeLayers();
139    if (result == VK_SUCCESS)
140        result = SanitizeExtensions();
141
142    return result;
143}
144
145const std::bitset<ProcHook::EXTENSION_COUNT>&
146CreateInfoWrapper::GetHookExtensions() const {
147    return hook_extensions_;
148}
149
150const std::bitset<ProcHook::EXTENSION_COUNT>&
151CreateInfoWrapper::GetHalExtensions() const {
152    return hal_extensions_;
153}
154
155CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
156    return &instance_info_;
157}
158
159CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
160    return &dev_info_;
161}
162
163VkResult CreateInfoWrapper::SanitizePNext() {
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::SanitizeLayers() {
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::SanitizeExtensions() {
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 = InitExtensionFilter();
214    if (result != VK_SUCCESS)
215        return result;
216
217    for (uint32_t i = 0; i < ext_count; i++)
218        FilterExtension(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::QueryExtensionCount(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::EnumerateExtensions(
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::InitExtensionFilter() {
251    // query extension count
252    uint32_t count;
253    VkResult result = QueryExtensionCount(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 = EnumerateExtensions(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::FilterExtension(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        filter.names[filter.name_count++] = name;
335        if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
336            if (ext_bit == ProcHook::ANDROID_native_buffer)
337                hook_extensions_.set(ProcHook::KHR_swapchain);
338
339            hal_extensions_.set(ext_bit);
340        }
341
342        break;
343    }
344}
345
346const hwvulkan_device_t* g_hwdevice = nullptr;
347
348VKAPI_ATTR void* DefaultAllocate(void*,
349                                 size_t size,
350                                 size_t alignment,
351                                 VkSystemAllocationScope) {
352    void* ptr = nullptr;
353    // Vulkan requires 'alignment' to be a power of two, but posix_memalign
354    // additionally requires that it be at least sizeof(void*).
355    int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
356    ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
357                    ret, ptr);
358    return ret == 0 ? ptr : nullptr;
359}
360
361VKAPI_ATTR void* DefaultReallocate(void*,
362                                   void* ptr,
363                                   size_t size,
364                                   size_t alignment,
365                                   VkSystemAllocationScope) {
366    if (size == 0) {
367        free(ptr);
368        return nullptr;
369    }
370
371    // TODO(jessehall): Right now we never shrink allocations; if the new
372    // request is smaller than the existing chunk, we just continue using it.
373    // Right now the loader never reallocs, so this doesn't matter. If that
374    // changes, or if this code is copied into some other project, this should
375    // probably have a heuristic to allocate-copy-free when doing so will save
376    // "enough" space.
377    size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
378    if (size <= old_size)
379        return ptr;
380
381    void* new_ptr = nullptr;
382    if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
383        return nullptr;
384    if (ptr) {
385        memcpy(new_ptr, ptr, std::min(old_size, size));
386        free(ptr);
387    }
388    return new_ptr;
389}
390
391VKAPI_ATTR void DefaultFree(void*, void* ptr) {
392    ALOGD_CALLSTACK("Free: %p", ptr);
393    free(ptr);
394}
395
396InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
397    void* data_mem = allocator.pfnAllocation(
398        allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
399        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
400    if (!data_mem)
401        return nullptr;
402
403    return new (data_mem) InstanceData(allocator);
404}
405
406void FreeInstanceData(InstanceData* data,
407                      const VkAllocationCallbacks& allocator) {
408    data->~InstanceData();
409    allocator.pfnFree(allocator.pUserData, data);
410}
411
412DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
413    void* data_mem = allocator.pfnAllocation(
414        allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
415        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
416    if (!data_mem)
417        return nullptr;
418
419    return new (data_mem) DeviceData(allocator);
420}
421
422void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
423    data->~DeviceData();
424    allocator.pfnFree(allocator.pUserData, data);
425}
426
427}  // anonymous namespace
428
429bool Debuggable() {
430    return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
431}
432
433bool OpenHAL() {
434    ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
435
436    // Use a stub device unless we successfully open a real HAL device.
437    g_hwdevice = &stubhal::kDevice;
438
439    const hwvulkan_module_t* module;
440    int result =
441        hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
442    if (result != 0) {
443        ALOGV("no Vulkan HAL present, using stub HAL");
444        return true;
445    }
446
447    hwvulkan_device_t* device;
448    result =
449        module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
450                                     reinterpret_cast<hw_device_t**>(&device));
451    if (result != 0) {
452        // Any device with a Vulkan HAL should be able to open the device.
453        ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
454              result);
455        return false;
456    }
457
458    g_hwdevice = device;
459
460    return true;
461}
462
463const VkAllocationCallbacks& GetDefaultAllocator() {
464    static const VkAllocationCallbacks kDefaultAllocCallbacks = {
465        .pUserData = nullptr,
466        .pfnAllocation = DefaultAllocate,
467        .pfnReallocation = DefaultReallocate,
468        .pfnFree = DefaultFree,
469    };
470
471    return kDefaultAllocCallbacks;
472}
473
474PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
475    const ProcHook* hook = GetProcHook(pName);
476    if (!hook)
477        return g_hwdevice->GetInstanceProcAddr(instance, pName);
478
479    if (!instance) {
480        if (hook->type == ProcHook::GLOBAL)
481            return hook->proc;
482
483        ALOGE(
484            "Invalid use of vkGetInstanceProcAddr to query %s without an "
485            "instance",
486            pName);
487
488        // Some naughty layers expect
489        //
490        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
491        //
492        // to work.
493        return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
494    }
495
496    PFN_vkVoidFunction proc;
497
498    switch (hook->type) {
499        case ProcHook::INSTANCE:
500            proc = (GetData(instance).hook_extensions[hook->extension])
501                       ? hook->proc
502                       : hook->disabled_proc;
503            break;
504        case ProcHook::DEVICE:
505            proc = (hook->extension == ProcHook::EXTENSION_CORE)
506                       ? hook->proc
507                       : hook->checked_proc;
508            break;
509        default:
510            ALOGE(
511                "Invalid use of vkGetInstanceProcAddr to query %s with an "
512                "instance",
513                pName);
514            proc = nullptr;
515            break;
516    }
517
518    return proc;
519}
520
521PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
522    const ProcHook* hook = GetProcHook(pName);
523    if (!hook)
524        return GetData(device).driver.GetDeviceProcAddr(device, pName);
525
526    if (hook->type != ProcHook::DEVICE) {
527        ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
528        return nullptr;
529    }
530
531    return (GetData(device).hook_extensions[hook->extension])
532               ? hook->proc
533               : hook->disabled_proc;
534}
535
536VkResult EnumerateInstanceExtensionProperties(
537    const char* pLayerName,
538    uint32_t* pPropertyCount,
539    VkExtensionProperties* pProperties) {
540    static const std::array<VkExtensionProperties, 2> loader_extensions = {{
541        // WSI extensions
542        {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
543        {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
544         VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
545    }};
546
547    // enumerate our extensions first
548    if (!pLayerName && pProperties) {
549        uint32_t count = std::min(
550            *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
551
552        std::copy_n(loader_extensions.begin(), count, pProperties);
553
554        if (count < loader_extensions.size()) {
555            *pPropertyCount = count;
556            return VK_INCOMPLETE;
557        }
558
559        pProperties += count;
560        *pPropertyCount -= count;
561    }
562
563    VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
564        pLayerName, pPropertyCount, pProperties);
565
566    if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
567        *pPropertyCount += loader_extensions.size();
568
569    return result;
570}
571
572VkResult EnumerateDeviceExtensionProperties(
573    VkPhysicalDevice physicalDevice,
574    const char* pLayerName,
575    uint32_t* pPropertyCount,
576    VkExtensionProperties* pProperties) {
577    const InstanceData& data = GetData(physicalDevice);
578
579    VkResult result = data.driver.EnumerateDeviceExtensionProperties(
580        physicalDevice, pLayerName, pPropertyCount, pProperties);
581    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
582        return result;
583
584    if (!pProperties)
585        return result;
586
587    // map VK_ANDROID_native_buffer to VK_KHR_swapchain
588    for (uint32_t i = 0; i < *pPropertyCount; i++) {
589        auto& prop = pProperties[i];
590
591        if (strcmp(prop.extensionName,
592                   VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
593            continue;
594
595        memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
596               sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
597        prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
598    }
599
600    return result;
601}
602
603VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
604                        const VkAllocationCallbacks* pAllocator,
605                        VkInstance* pInstance) {
606    const VkAllocationCallbacks& data_allocator =
607        (pAllocator) ? *pAllocator : GetDefaultAllocator();
608
609    CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
610    VkResult result = wrapper.Validate();
611    if (result != VK_SUCCESS)
612        return result;
613
614    InstanceData* data = AllocateInstanceData(data_allocator);
615    if (!data)
616        return VK_ERROR_OUT_OF_HOST_MEMORY;
617
618    data->hook_extensions |= wrapper.GetHookExtensions();
619
620    // call into the driver
621    VkInstance instance;
622    result = g_hwdevice->CreateInstance(
623        static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
624        &instance);
625    if (result != VK_SUCCESS) {
626        FreeInstanceData(data, data_allocator);
627        return result;
628    }
629
630    // initialize InstanceDriverTable
631    if (!SetData(instance, *data) ||
632        !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr,
633                         wrapper.GetHalExtensions())) {
634        data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
635            g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
636        if (data->driver.DestroyInstance)
637            data->driver.DestroyInstance(instance, pAllocator);
638
639        FreeInstanceData(data, data_allocator);
640
641        return VK_ERROR_INCOMPATIBLE_DRIVER;
642    }
643
644    data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
645        g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
646    if (!data->get_device_proc_addr) {
647        data->driver.DestroyInstance(instance, pAllocator);
648        FreeInstanceData(data, data_allocator);
649
650        return VK_ERROR_INCOMPATIBLE_DRIVER;
651    }
652
653    *pInstance = instance;
654
655    return VK_SUCCESS;
656}
657
658void DestroyInstance(VkInstance instance,
659                     const VkAllocationCallbacks* pAllocator) {
660    InstanceData& data = GetData(instance);
661    data.driver.DestroyInstance(instance, pAllocator);
662
663    VkAllocationCallbacks local_allocator;
664    if (!pAllocator) {
665        local_allocator = data.allocator;
666        pAllocator = &local_allocator;
667    }
668
669    FreeInstanceData(&data, *pAllocator);
670}
671
672VkResult CreateDevice(VkPhysicalDevice physicalDevice,
673                      const VkDeviceCreateInfo* pCreateInfo,
674                      const VkAllocationCallbacks* pAllocator,
675                      VkDevice* pDevice) {
676    const InstanceData& instance_data = GetData(physicalDevice);
677    const VkAllocationCallbacks& data_allocator =
678        (pAllocator) ? *pAllocator : instance_data.allocator;
679
680    CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
681    VkResult result = wrapper.Validate();
682    if (result != VK_SUCCESS)
683        return result;
684
685    DeviceData* data = AllocateDeviceData(data_allocator);
686    if (!data)
687        return VK_ERROR_OUT_OF_HOST_MEMORY;
688
689    data->hook_extensions |= wrapper.GetHookExtensions();
690
691    // call into the driver
692    VkDevice dev;
693    result = instance_data.driver.CreateDevice(
694        physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
695        pAllocator, &dev);
696    if (result != VK_SUCCESS) {
697        FreeDeviceData(data, data_allocator);
698        return result;
699    }
700
701    // initialize DeviceDriverTable
702    if (!SetData(dev, *data) ||
703        !InitDriverTable(dev, instance_data.get_device_proc_addr,
704                         wrapper.GetHalExtensions())) {
705        data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
706            instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
707        if (data->driver.DestroyDevice)
708            data->driver.DestroyDevice(dev, pAllocator);
709
710        FreeDeviceData(data, data_allocator);
711
712        return VK_ERROR_INCOMPATIBLE_DRIVER;
713    }
714
715    *pDevice = dev;
716
717    return VK_SUCCESS;
718}
719
720void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
721    DeviceData& data = GetData(device);
722    data.driver.DestroyDevice(device, pAllocator);
723
724    VkAllocationCallbacks local_allocator;
725    if (!pAllocator) {
726        local_allocator = data.allocator;
727        pAllocator = &local_allocator;
728    }
729
730    FreeDeviceData(&data, *pAllocator);
731}
732
733VkResult EnumeratePhysicalDevices(VkInstance instance,
734                                  uint32_t* pPhysicalDeviceCount,
735                                  VkPhysicalDevice* pPhysicalDevices) {
736    const auto& data = GetData(instance);
737
738    VkResult result = data.driver.EnumeratePhysicalDevices(
739        instance, pPhysicalDeviceCount, pPhysicalDevices);
740    if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
741        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
742            SetData(pPhysicalDevices[i], data);
743    }
744
745    return result;
746}
747
748void GetDeviceQueue(VkDevice device,
749                    uint32_t queueFamilyIndex,
750                    uint32_t queueIndex,
751                    VkQueue* pQueue) {
752    const auto& data = GetData(device);
753
754    data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
755    SetData(*pQueue, data);
756}
757
758VKAPI_ATTR VkResult
759AllocateCommandBuffers(VkDevice device,
760                       const VkCommandBufferAllocateInfo* pAllocateInfo,
761                       VkCommandBuffer* pCommandBuffers) {
762    const auto& data = GetData(device);
763
764    VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
765                                                         pCommandBuffers);
766    if (result == VK_SUCCESS) {
767        for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
768            SetData(pCommandBuffers[i], data);
769    }
770
771    return result;
772}
773
774}  // namespace driver
775}  // namespace vulkan
776