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