driver.cpp revision 319382517afe913285df5bbf76a8a484e6adfbd0
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 Hal {
50   public:
51    static bool Open();
52
53    static const Hal& Get() { return hal_; }
54    static const hwvulkan_device_t& Device() { return *Get().dev_; }
55
56    int GetDebugReportIndex() const { return debug_report_index_; }
57
58   private:
59    Hal() : dev_(nullptr), debug_report_index_(-1) {}
60    Hal(const Hal&) = delete;
61    Hal& operator=(const Hal&) = delete;
62
63    bool InitDebugReportIndex();
64
65    static Hal hal_;
66
67    const hwvulkan_device_t* dev_;
68    int debug_report_index_;
69};
70
71class CreateInfoWrapper {
72   public:
73    CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
74                      const VkAllocationCallbacks& allocator);
75    CreateInfoWrapper(VkPhysicalDevice physical_dev,
76                      const VkDeviceCreateInfo& create_info,
77                      const VkAllocationCallbacks& allocator);
78    ~CreateInfoWrapper();
79
80    VkResult Validate();
81
82    const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
83    const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
84
85    explicit operator const VkInstanceCreateInfo*() const;
86    explicit operator const VkDeviceCreateInfo*() const;
87
88   private:
89    struct ExtensionFilter {
90        VkExtensionProperties* exts;
91        uint32_t ext_count;
92
93        const char** names;
94        uint32_t name_count;
95    };
96
97    VkResult SanitizePNext();
98
99    VkResult SanitizeLayers();
100    VkResult SanitizeExtensions();
101
102    VkResult QueryExtensionCount(uint32_t& count) const;
103    VkResult EnumerateExtensions(uint32_t& count,
104                                 VkExtensionProperties* props) const;
105    VkResult InitExtensionFilter();
106    void FilterExtension(const char* name);
107
108    const bool is_instance_;
109    const VkAllocationCallbacks& allocator_;
110
111    VkPhysicalDevice physical_dev_;
112
113    union {
114        VkInstanceCreateInfo instance_info_;
115        VkDeviceCreateInfo dev_info_;
116    };
117
118    ExtensionFilter extension_filter_;
119
120    std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
121    std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
122};
123
124Hal Hal::hal_;
125
126bool Hal::Open() {
127    ALOG_ASSERT(!dev_, "OpenHAL called more than once");
128
129    // Use a stub device unless we successfully open a real HAL device.
130    hal_.dev_ = &stubhal::kDevice;
131
132    const hwvulkan_module_t* module;
133    int result =
134        hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
135    if (result != 0) {
136        ALOGI("no Vulkan HAL present, using stub HAL");
137        return true;
138    }
139
140    hwvulkan_device_t* device;
141    result =
142        module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
143                                     reinterpret_cast<hw_device_t**>(&device));
144    if (result != 0) {
145        // Any device with a Vulkan HAL should be able to open the device.
146        ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
147              result);
148        return false;
149    }
150
151    hal_.dev_ = device;
152
153    hal_.InitDebugReportIndex();
154
155    return true;
156}
157
158bool Hal::InitDebugReportIndex() {
159    uint32_t count;
160    if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
161        VK_SUCCESS) {
162        ALOGE("failed to get HAL instance extension count");
163        return false;
164    }
165
166    VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
167        malloc(sizeof(VkExtensionProperties) * count));
168    if (!exts) {
169        ALOGE("failed to allocate HAL instance extension array");
170        return false;
171    }
172
173    if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
174        VK_SUCCESS) {
175        ALOGE("failed to enumerate HAL instance extensions");
176        free(exts);
177        return false;
178    }
179
180    for (uint32_t i = 0; i < count; i++) {
181        if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
182            0) {
183            debug_report_index_ = static_cast<int>(i);
184            break;
185        }
186    }
187
188    free(exts);
189
190    return true;
191}
192
193CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
194                                     const VkAllocationCallbacks& allocator)
195    : is_instance_(true),
196      allocator_(allocator),
197      physical_dev_(VK_NULL_HANDLE),
198      instance_info_(create_info),
199      extension_filter_() {
200    hook_extensions_.set(ProcHook::EXTENSION_CORE);
201    hal_extensions_.set(ProcHook::EXTENSION_CORE);
202}
203
204CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
205                                     const VkDeviceCreateInfo& create_info,
206                                     const VkAllocationCallbacks& allocator)
207    : is_instance_(false),
208      allocator_(allocator),
209      physical_dev_(physical_dev),
210      dev_info_(create_info),
211      extension_filter_() {
212    hook_extensions_.set(ProcHook::EXTENSION_CORE);
213    hal_extensions_.set(ProcHook::EXTENSION_CORE);
214}
215
216CreateInfoWrapper::~CreateInfoWrapper() {
217    allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
218    allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
219}
220
221VkResult CreateInfoWrapper::Validate() {
222    VkResult result = SanitizePNext();
223    if (result == VK_SUCCESS)
224        result = SanitizeLayers();
225    if (result == VK_SUCCESS)
226        result = SanitizeExtensions();
227
228    return result;
229}
230
231const std::bitset<ProcHook::EXTENSION_COUNT>&
232CreateInfoWrapper::GetHookExtensions() const {
233    return hook_extensions_;
234}
235
236const std::bitset<ProcHook::EXTENSION_COUNT>&
237CreateInfoWrapper::GetHalExtensions() const {
238    return hal_extensions_;
239}
240
241CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
242    return &instance_info_;
243}
244
245CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
246    return &dev_info_;
247}
248
249VkResult CreateInfoWrapper::SanitizePNext() {
250    const struct StructHeader {
251        VkStructureType type;
252        const void* next;
253    } * header;
254
255    if (is_instance_) {
256        header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
257
258        // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
259        while (header &&
260               header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
261            header = reinterpret_cast<const StructHeader*>(header->next);
262
263        instance_info_.pNext = header;
264    } else {
265        header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
266
267        // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
268        while (header &&
269               header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
270            header = reinterpret_cast<const StructHeader*>(header->next);
271
272        dev_info_.pNext = header;
273    }
274
275    return VK_SUCCESS;
276}
277
278VkResult CreateInfoWrapper::SanitizeLayers() {
279    auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
280                                       : dev_info_.ppEnabledLayerNames;
281    auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
282                                       : dev_info_.enabledLayerCount;
283
284    // remove all layers
285    layer_names = nullptr;
286    layer_count = 0;
287
288    return VK_SUCCESS;
289}
290
291VkResult CreateInfoWrapper::SanitizeExtensions() {
292    auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
293                                     : dev_info_.ppEnabledExtensionNames;
294    auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
295                                     : dev_info_.enabledExtensionCount;
296    if (!ext_count)
297        return VK_SUCCESS;
298
299    VkResult result = InitExtensionFilter();
300    if (result != VK_SUCCESS)
301        return result;
302
303    for (uint32_t i = 0; i < ext_count; i++)
304        FilterExtension(ext_names[i]);
305
306    ext_names = extension_filter_.names;
307    ext_count = extension_filter_.name_count;
308
309    return VK_SUCCESS;
310}
311
312VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
313    if (is_instance_) {
314        return Hal::Device().EnumerateInstanceExtensionProperties(
315            nullptr, &count, nullptr);
316    } else {
317        const auto& driver = GetData(physical_dev_).driver;
318        return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
319                                                         &count, nullptr);
320    }
321}
322
323VkResult CreateInfoWrapper::EnumerateExtensions(
324    uint32_t& count,
325    VkExtensionProperties* props) const {
326    if (is_instance_) {
327        return Hal::Device().EnumerateInstanceExtensionProperties(
328            nullptr, &count, props);
329    } else {
330        const auto& driver = GetData(physical_dev_).driver;
331        return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
332                                                         &count, props);
333    }
334}
335
336VkResult CreateInfoWrapper::InitExtensionFilter() {
337    // query extension count
338    uint32_t count;
339    VkResult result = QueryExtensionCount(count);
340    if (result != VK_SUCCESS || count == 0)
341        return result;
342
343    auto& filter = extension_filter_;
344    filter.exts =
345        reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
346            allocator_.pUserData, sizeof(VkExtensionProperties) * count,
347            alignof(VkExtensionProperties),
348            VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
349    if (!filter.exts)
350        return VK_ERROR_OUT_OF_HOST_MEMORY;
351
352    // enumerate extensions
353    result = EnumerateExtensions(count, filter.exts);
354    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
355        return result;
356
357    if (!count)
358        return VK_SUCCESS;
359
360    filter.ext_count = count;
361
362    // allocate name array
363    uint32_t enabled_ext_count = (is_instance_)
364                                     ? instance_info_.enabledExtensionCount
365                                     : dev_info_.enabledExtensionCount;
366    count = std::min(filter.ext_count, enabled_ext_count);
367    filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
368        allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
369        VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
370    if (!filter.names)
371        return VK_ERROR_OUT_OF_HOST_MEMORY;
372
373    return VK_SUCCESS;
374}
375
376void CreateInfoWrapper::FilterExtension(const char* name) {
377    auto& filter = extension_filter_;
378
379    ProcHook::Extension ext_bit = GetProcHookExtension(name);
380    if (is_instance_) {
381        switch (ext_bit) {
382            case ProcHook::KHR_android_surface:
383            case ProcHook::KHR_surface:
384                hook_extensions_.set(ext_bit);
385                // return now as these extensions do not require HAL support
386                return;
387            case ProcHook::EXT_debug_report:
388                // both we and HAL can take part in
389                hook_extensions_.set(ext_bit);
390                break;
391            case ProcHook::EXTENSION_UNKNOWN:
392                // HAL's extensions
393                break;
394            default:
395                ALOGW("Ignored invalid instance extension %s", name);
396                return;
397        }
398    } else {
399        switch (ext_bit) {
400            case ProcHook::KHR_swapchain:
401                // map VK_KHR_swapchain to VK_ANDROID_native_buffer
402                name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
403                ext_bit = ProcHook::ANDROID_native_buffer;
404                break;
405            case ProcHook::EXTENSION_UNKNOWN:
406                // HAL's extensions
407                break;
408            default:
409                ALOGW("Ignored invalid device extension %s", name);
410                return;
411        }
412    }
413
414    for (uint32_t i = 0; i < filter.ext_count; i++) {
415        const VkExtensionProperties& props = filter.exts[i];
416        // ignore unknown extensions
417        if (strcmp(name, props.extensionName) != 0)
418            continue;
419
420        filter.names[filter.name_count++] = name;
421        if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
422            if (ext_bit == ProcHook::ANDROID_native_buffer)
423                hook_extensions_.set(ProcHook::KHR_swapchain);
424
425            hal_extensions_.set(ext_bit);
426        }
427
428        break;
429    }
430}
431
432VKAPI_ATTR void* DefaultAllocate(void*,
433                                 size_t size,
434                                 size_t alignment,
435                                 VkSystemAllocationScope) {
436    void* ptr = nullptr;
437    // Vulkan requires 'alignment' to be a power of two, but posix_memalign
438    // additionally requires that it be at least sizeof(void*).
439    int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
440    ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
441                    ret, ptr);
442    return ret == 0 ? ptr : nullptr;
443}
444
445VKAPI_ATTR void* DefaultReallocate(void*,
446                                   void* ptr,
447                                   size_t size,
448                                   size_t alignment,
449                                   VkSystemAllocationScope) {
450    if (size == 0) {
451        free(ptr);
452        return nullptr;
453    }
454
455    // TODO(jessehall): Right now we never shrink allocations; if the new
456    // request is smaller than the existing chunk, we just continue using it.
457    // Right now the loader never reallocs, so this doesn't matter. If that
458    // changes, or if this code is copied into some other project, this should
459    // probably have a heuristic to allocate-copy-free when doing so will save
460    // "enough" space.
461    size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
462    if (size <= old_size)
463        return ptr;
464
465    void* new_ptr = nullptr;
466    if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
467        return nullptr;
468    if (ptr) {
469        memcpy(new_ptr, ptr, std::min(old_size, size));
470        free(ptr);
471    }
472    return new_ptr;
473}
474
475VKAPI_ATTR void DefaultFree(void*, void* ptr) {
476    ALOGD_CALLSTACK("Free: %p", ptr);
477    free(ptr);
478}
479
480InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
481    void* data_mem = allocator.pfnAllocation(
482        allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
483        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
484    if (!data_mem)
485        return nullptr;
486
487    return new (data_mem) InstanceData(allocator);
488}
489
490void FreeInstanceData(InstanceData* data,
491                      const VkAllocationCallbacks& allocator) {
492    data->~InstanceData();
493    allocator.pfnFree(allocator.pUserData, data);
494}
495
496DeviceData* AllocateDeviceData(
497    const VkAllocationCallbacks& allocator,
498    const DebugReportCallbackList& debug_report_callbacks) {
499    void* data_mem = allocator.pfnAllocation(
500        allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
501        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
502    if (!data_mem)
503        return nullptr;
504
505    return new (data_mem) DeviceData(allocator, debug_report_callbacks);
506}
507
508void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
509    data->~DeviceData();
510    allocator.pfnFree(allocator.pUserData, data);
511}
512
513}  // anonymous namespace
514
515bool Debuggable() {
516    return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
517}
518
519bool OpenHAL() {
520    return Hal::Open();
521}
522
523const VkAllocationCallbacks& GetDefaultAllocator() {
524    static const VkAllocationCallbacks kDefaultAllocCallbacks = {
525        .pUserData = nullptr,
526        .pfnAllocation = DefaultAllocate,
527        .pfnReallocation = DefaultReallocate,
528        .pfnFree = DefaultFree,
529    };
530
531    return kDefaultAllocCallbacks;
532}
533
534PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
535    const ProcHook* hook = GetProcHook(pName);
536    if (!hook)
537        return Hal::Device().GetInstanceProcAddr(instance, pName);
538
539    if (!instance) {
540        if (hook->type == ProcHook::GLOBAL)
541            return hook->proc;
542
543        // v0 layers expect
544        //
545        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
546        //
547        // to work.
548        if (strcmp(pName, "vkCreateDevice") == 0)
549            return hook->proc;
550
551        ALOGE(
552            "internal vkGetInstanceProcAddr called for %s without an instance",
553            pName);
554
555        return nullptr;
556    }
557
558    PFN_vkVoidFunction proc;
559
560    switch (hook->type) {
561        case ProcHook::INSTANCE:
562            proc = (GetData(instance).hook_extensions[hook->extension])
563                       ? hook->proc
564                       : nullptr;
565            break;
566        case ProcHook::DEVICE:
567            proc = (hook->extension == ProcHook::EXTENSION_CORE)
568                       ? hook->proc
569                       : hook->checked_proc;
570            break;
571        default:
572            ALOGE(
573                "internal vkGetInstanceProcAddr called for %s with an instance",
574                pName);
575            proc = nullptr;
576            break;
577    }
578
579    return proc;
580}
581
582PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
583    const ProcHook* hook = GetProcHook(pName);
584    if (!hook)
585        return GetData(device).driver.GetDeviceProcAddr(device, pName);
586
587    if (hook->type != ProcHook::DEVICE) {
588        ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
589        return nullptr;
590    }
591
592    return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
593                                                              : nullptr;
594}
595
596VkResult EnumerateInstanceExtensionProperties(
597    const char* pLayerName,
598    uint32_t* pPropertyCount,
599    VkExtensionProperties* pProperties) {
600    static const std::array<VkExtensionProperties, 2> loader_extensions = {{
601        // WSI extensions
602        {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
603        {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
604         VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
605    }};
606    static const VkExtensionProperties loader_debug_report_extension = {
607        VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
608    };
609
610    // enumerate our extensions first
611    if (!pLayerName && pProperties) {
612        uint32_t count = std::min(
613            *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
614
615        std::copy_n(loader_extensions.begin(), count, pProperties);
616
617        if (count < loader_extensions.size()) {
618            *pPropertyCount = count;
619            return VK_INCOMPLETE;
620        }
621
622        pProperties += count;
623        *pPropertyCount -= count;
624
625        if (Hal::Get().GetDebugReportIndex() < 0) {
626            if (!*pPropertyCount) {
627                *pPropertyCount = count;
628                return VK_INCOMPLETE;
629            }
630
631            pProperties[0] = loader_debug_report_extension;
632            pProperties += 1;
633            *pPropertyCount -= 1;
634        }
635    }
636
637    VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
638        pLayerName, pPropertyCount, pProperties);
639
640    if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
641        int idx = Hal::Get().GetDebugReportIndex();
642        if (idx < 0) {
643            *pPropertyCount += 1;
644        } else if (pProperties &&
645                   static_cast<uint32_t>(idx) < *pPropertyCount) {
646            pProperties[idx].specVersion =
647                std::min(pProperties[idx].specVersion,
648                         loader_debug_report_extension.specVersion);
649        }
650
651        *pPropertyCount += loader_extensions.size();
652    }
653
654    return result;
655}
656
657VkResult EnumerateDeviceExtensionProperties(
658    VkPhysicalDevice physicalDevice,
659    const char* pLayerName,
660    uint32_t* pPropertyCount,
661    VkExtensionProperties* pProperties) {
662    const InstanceData& data = GetData(physicalDevice);
663
664    VkResult result = data.driver.EnumerateDeviceExtensionProperties(
665        physicalDevice, pLayerName, pPropertyCount, pProperties);
666    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
667        return result;
668
669    if (!pProperties)
670        return result;
671
672    // map VK_ANDROID_native_buffer to VK_KHR_swapchain
673    for (uint32_t i = 0; i < *pPropertyCount; i++) {
674        auto& prop = pProperties[i];
675
676        if (strcmp(prop.extensionName,
677                   VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
678            continue;
679
680        memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
681               sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
682        prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
683    }
684
685    return result;
686}
687
688VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
689                        const VkAllocationCallbacks* pAllocator,
690                        VkInstance* pInstance) {
691    const VkAllocationCallbacks& data_allocator =
692        (pAllocator) ? *pAllocator : GetDefaultAllocator();
693
694    CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
695    VkResult result = wrapper.Validate();
696    if (result != VK_SUCCESS)
697        return result;
698
699    InstanceData* data = AllocateInstanceData(data_allocator);
700    if (!data)
701        return VK_ERROR_OUT_OF_HOST_MEMORY;
702
703    data->hook_extensions |= wrapper.GetHookExtensions();
704
705    // call into the driver
706    VkInstance instance;
707    result = Hal::Device().CreateInstance(
708        static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
709        &instance);
710    if (result != VK_SUCCESS) {
711        FreeInstanceData(data, data_allocator);
712        return result;
713    }
714
715    // initialize InstanceDriverTable
716    if (!SetData(instance, *data) ||
717        !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
718                         wrapper.GetHalExtensions())) {
719        data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
720            Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
721        if (data->driver.DestroyInstance)
722            data->driver.DestroyInstance(instance, pAllocator);
723
724        FreeInstanceData(data, data_allocator);
725
726        return VK_ERROR_INCOMPATIBLE_DRIVER;
727    }
728
729    data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
730        Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
731    if (!data->get_device_proc_addr) {
732        data->driver.DestroyInstance(instance, pAllocator);
733        FreeInstanceData(data, data_allocator);
734
735        return VK_ERROR_INCOMPATIBLE_DRIVER;
736    }
737
738    *pInstance = instance;
739
740    return VK_SUCCESS;
741}
742
743void DestroyInstance(VkInstance instance,
744                     const VkAllocationCallbacks* pAllocator) {
745    InstanceData& data = GetData(instance);
746    data.driver.DestroyInstance(instance, pAllocator);
747
748    VkAllocationCallbacks local_allocator;
749    if (!pAllocator) {
750        local_allocator = data.allocator;
751        pAllocator = &local_allocator;
752    }
753
754    FreeInstanceData(&data, *pAllocator);
755}
756
757VkResult CreateDevice(VkPhysicalDevice physicalDevice,
758                      const VkDeviceCreateInfo* pCreateInfo,
759                      const VkAllocationCallbacks* pAllocator,
760                      VkDevice* pDevice) {
761    const InstanceData& instance_data = GetData(physicalDevice);
762    const VkAllocationCallbacks& data_allocator =
763        (pAllocator) ? *pAllocator : instance_data.allocator;
764
765    CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
766    VkResult result = wrapper.Validate();
767    if (result != VK_SUCCESS)
768        return result;
769
770    DeviceData* data = AllocateDeviceData(data_allocator,
771                                          instance_data.debug_report_callbacks);
772    if (!data)
773        return VK_ERROR_OUT_OF_HOST_MEMORY;
774
775    data->hook_extensions |= wrapper.GetHookExtensions();
776
777    // call into the driver
778    VkDevice dev;
779    result = instance_data.driver.CreateDevice(
780        physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
781        pAllocator, &dev);
782    if (result != VK_SUCCESS) {
783        FreeDeviceData(data, data_allocator);
784        return result;
785    }
786
787    // initialize DeviceDriverTable
788    if (!SetData(dev, *data) ||
789        !InitDriverTable(dev, instance_data.get_device_proc_addr,
790                         wrapper.GetHalExtensions())) {
791        data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
792            instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
793        if (data->driver.DestroyDevice)
794            data->driver.DestroyDevice(dev, pAllocator);
795
796        FreeDeviceData(data, data_allocator);
797
798        return VK_ERROR_INCOMPATIBLE_DRIVER;
799    }
800
801    *pDevice = dev;
802
803    return VK_SUCCESS;
804}
805
806void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
807    DeviceData& data = GetData(device);
808    data.driver.DestroyDevice(device, pAllocator);
809
810    VkAllocationCallbacks local_allocator;
811    if (!pAllocator) {
812        local_allocator = data.allocator;
813        pAllocator = &local_allocator;
814    }
815
816    FreeDeviceData(&data, *pAllocator);
817}
818
819VkResult EnumeratePhysicalDevices(VkInstance instance,
820                                  uint32_t* pPhysicalDeviceCount,
821                                  VkPhysicalDevice* pPhysicalDevices) {
822    const auto& data = GetData(instance);
823
824    VkResult result = data.driver.EnumeratePhysicalDevices(
825        instance, pPhysicalDeviceCount, pPhysicalDevices);
826    if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
827        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
828            SetData(pPhysicalDevices[i], data);
829    }
830
831    return result;
832}
833
834void GetDeviceQueue(VkDevice device,
835                    uint32_t queueFamilyIndex,
836                    uint32_t queueIndex,
837                    VkQueue* pQueue) {
838    const auto& data = GetData(device);
839
840    data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
841    SetData(*pQueue, data);
842}
843
844VKAPI_ATTR VkResult
845AllocateCommandBuffers(VkDevice device,
846                       const VkCommandBufferAllocateInfo* pAllocateInfo,
847                       VkCommandBuffer* pCommandBuffers) {
848    const auto& data = GetData(device);
849
850    VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
851                                                         pCommandBuffers);
852    if (result == VK_SUCCESS) {
853        for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
854            SetData(pCommandBuffers[i], data);
855    }
856
857    return result;
858}
859
860}  // namespace driver
861}  // namespace vulkan
862