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 
44 namespace vulkan {
45 namespace driver {
46 
47 namespace {
48 
49 class Hal {
50    public:
51     static bool Open();
52 
Get()53     static const Hal& Get() { return hal_; }
Device()54     static const hwvulkan_device_t& Device() { return *Get().dev_; }
55 
GetDebugReportIndex() const56     int GetDebugReportIndex() const { return debug_report_index_; }
57 
58    private:
Hal()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 
71 class 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 
124 Hal Hal::hal_;
125 
Open()126 bool Hal::Open() {
127     ALOG_ASSERT(!hal_.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 
InitDebugReportIndex()158 bool 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 
CreateInfoWrapper(const VkInstanceCreateInfo & create_info,const VkAllocationCallbacks & allocator)193 CreateInfoWrapper::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 
CreateInfoWrapper(VkPhysicalDevice physical_dev,const VkDeviceCreateInfo & create_info,const VkAllocationCallbacks & allocator)204 CreateInfoWrapper::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 
~CreateInfoWrapper()216 CreateInfoWrapper::~CreateInfoWrapper() {
217     allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
218     allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
219 }
220 
Validate()221 VkResult 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 
231 const std::bitset<ProcHook::EXTENSION_COUNT>&
GetHookExtensions() const232 CreateInfoWrapper::GetHookExtensions() const {
233     return hook_extensions_;
234 }
235 
236 const std::bitset<ProcHook::EXTENSION_COUNT>&
GetHalExtensions() const237 CreateInfoWrapper::GetHalExtensions() const {
238     return hal_extensions_;
239 }
240 
operator const VkInstanceCreateInfo*() const241 CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
242     return &instance_info_;
243 }
244 
operator const VkDeviceCreateInfo*() const245 CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
246     return &dev_info_;
247 }
248 
SanitizePNext()249 VkResult 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 
SanitizeLayers()278 VkResult 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 
SanitizeExtensions()291 VkResult 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 
QueryExtensionCount(uint32_t & count) const312 VkResult 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 
EnumerateExtensions(uint32_t & count,VkExtensionProperties * props) const323 VkResult 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 
InitExtensionFilter()336 VkResult 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 
FilterExtension(const char * name)376 void 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 
DefaultAllocate(void *,size_t size,size_t alignment,VkSystemAllocationScope)432 VKAPI_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 
DefaultReallocate(void *,void * ptr,size_t size,size_t alignment,VkSystemAllocationScope)445 VKAPI_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 
DefaultFree(void *,void * ptr)475 VKAPI_ATTR void DefaultFree(void*, void* ptr) {
476     ALOGD_CALLSTACK("Free: %p", ptr);
477     free(ptr);
478 }
479 
AllocateInstanceData(const VkAllocationCallbacks & allocator)480 InstanceData* 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 
FreeInstanceData(InstanceData * data,const VkAllocationCallbacks & allocator)490 void FreeInstanceData(InstanceData* data,
491                       const VkAllocationCallbacks& allocator) {
492     data->~InstanceData();
493     allocator.pfnFree(allocator.pUserData, data);
494 }
495 
AllocateDeviceData(const VkAllocationCallbacks & allocator,const DebugReportCallbackList & debug_report_callbacks)496 DeviceData* 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 
FreeDeviceData(DeviceData * data,const VkAllocationCallbacks & allocator)508 void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
509     data->~DeviceData();
510     allocator.pfnFree(allocator.pUserData, data);
511 }
512 
513 }  // anonymous namespace
514 
Debuggable()515 bool Debuggable() {
516     return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
517 }
518 
OpenHAL()519 bool OpenHAL() {
520     return Hal::Open();
521 }
522 
GetDefaultAllocator()523 const 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 
GetInstanceProcAddr(VkInstance instance,const char * pName)534 PFN_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 
GetDeviceProcAddr(VkDevice device,const char * pName)582 PFN_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 
EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)596 VkResult 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 
EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)657 VkResult 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 
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)688 VkResult 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 
DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)743 void 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 
CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)757 VkResult 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     data->driver_device = dev;
801 
802     *pDevice = dev;
803 
804     return VK_SUCCESS;
805 }
806 
DestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)807 void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
808     DeviceData& data = GetData(device);
809     data.driver.DestroyDevice(device, pAllocator);
810 
811     VkAllocationCallbacks local_allocator;
812     if (!pAllocator) {
813         local_allocator = data.allocator;
814         pAllocator = &local_allocator;
815     }
816 
817     FreeDeviceData(&data, *pAllocator);
818 }
819 
EnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)820 VkResult EnumeratePhysicalDevices(VkInstance instance,
821                                   uint32_t* pPhysicalDeviceCount,
822                                   VkPhysicalDevice* pPhysicalDevices) {
823     const auto& data = GetData(instance);
824 
825     VkResult result = data.driver.EnumeratePhysicalDevices(
826         instance, pPhysicalDeviceCount, pPhysicalDevices);
827     if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
828         for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
829             SetData(pPhysicalDevices[i], data);
830     }
831 
832     return result;
833 }
834 
GetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)835 void GetDeviceQueue(VkDevice device,
836                     uint32_t queueFamilyIndex,
837                     uint32_t queueIndex,
838                     VkQueue* pQueue) {
839     const auto& data = GetData(device);
840 
841     data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
842     SetData(*pQueue, data);
843 }
844 
845 VKAPI_ATTR VkResult
AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)846 AllocateCommandBuffers(VkDevice device,
847                        const VkCommandBufferAllocateInfo* pAllocateInfo,
848                        VkCommandBuffer* pCommandBuffers) {
849     const auto& data = GetData(device);
850 
851     VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
852                                                          pCommandBuffers);
853     if (result == VK_SUCCESS) {
854         for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
855             SetData(pCommandBuffers[i], data);
856     }
857 
858     return result;
859 }
860 
861 }  // namespace driver
862 }  // namespace vulkan
863