• 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 <malloc.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/prctl.h>
21 
22 #include <dlfcn.h>
23 #include <algorithm>
24 #include <array>
25 #include <new>
26 
27 #include <log/log.h>
28 
29 #include <android/dlext.h>
30 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
31 #include <configstore/Utils.h>
32 #include <cutils/properties.h>
33 #include <graphicsenv/GraphicsEnv.h>
34 #include <utils/Vector.h>
35 
36 #include "android-base/properties.h"
37 
38 #include "driver.h"
39 #include "stubhal.h"
40 
41 using namespace android::hardware::configstore;
42 using namespace android::hardware::configstore::V1_0;
43 
44 // TODO(b/37049319) Get this from a header once one exists
45 extern "C" {
46 android_namespace_t* android_get_exported_namespace(const char*);
47 }
48 
49 // #define ENABLE_ALLOC_CALLSTACKS 1
50 #if ENABLE_ALLOC_CALLSTACKS
51 #include <utils/CallStack.h>
52 #define ALOGD_CALLSTACK(...)                             \
53     do {                                                 \
54         ALOGD(__VA_ARGS__);                              \
55         android::CallStack callstack;                    \
56         callstack.update();                              \
57         callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, "  "); \
58     } while (false)
59 #else
60 #define ALOGD_CALLSTACK(...) \
61     do {                     \
62     } while (false)
63 #endif
64 
65 namespace vulkan {
66 namespace driver {
67 
68 namespace {
69 
70 class Hal {
71    public:
72     static bool Open();
73 
Get()74     static const Hal& Get() { return hal_; }
Device()75     static const hwvulkan_device_t& Device() { return *Get().dev_; }
76 
GetDebugReportIndex() const77     int GetDebugReportIndex() const { return debug_report_index_; }
78 
79    private:
Hal()80     Hal() : dev_(nullptr), debug_report_index_(-1) {}
81     Hal(const Hal&) = delete;
82     Hal& operator=(const Hal&) = delete;
83 
84     bool InitDebugReportIndex();
85 
86     static Hal hal_;
87 
88     const hwvulkan_device_t* dev_;
89     int debug_report_index_;
90 };
91 
92 class CreateInfoWrapper {
93    public:
94     CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
95                       const VkAllocationCallbacks& allocator);
96     CreateInfoWrapper(VkPhysicalDevice physical_dev,
97                       const VkDeviceCreateInfo& create_info,
98                       const VkAllocationCallbacks& allocator);
99     ~CreateInfoWrapper();
100 
101     VkResult Validate();
102     void DowngradeApiVersion();
103 
104     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
105     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
106 
107     explicit operator const VkInstanceCreateInfo*() const;
108     explicit operator const VkDeviceCreateInfo*() const;
109 
110    private:
111     struct ExtensionFilter {
112         VkExtensionProperties* exts;
113         uint32_t ext_count;
114 
115         const char** names;
116         uint32_t name_count;
117     };
118 
119     VkResult SanitizePNext();
120 
121     VkResult SanitizeLayers();
122     VkResult SanitizeExtensions();
123 
124     VkResult QueryExtensionCount(uint32_t& count) const;
125     VkResult EnumerateExtensions(uint32_t& count,
126                                  VkExtensionProperties* props) const;
127     VkResult InitExtensionFilter();
128     void FilterExtension(const char* name);
129 
130     const bool is_instance_;
131     const VkAllocationCallbacks& allocator_;
132 
133     VkPhysicalDevice physical_dev_;
134 
135     union {
136         VkInstanceCreateInfo instance_info_;
137         VkDeviceCreateInfo dev_info_;
138     };
139 
140     VkApplicationInfo application_info_;
141 
142     ExtensionFilter extension_filter_;
143 
144     std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
145     std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
146 };
147 
148 Hal Hal::hal_;
149 
LoadLibrary(const android_dlextinfo & dlextinfo,const char * subname,int subname_len)150 void* LoadLibrary(const android_dlextinfo& dlextinfo,
151                   const char* subname,
152                   int subname_len) {
153     const char kLibFormat[] = "vulkan.%*s.so";
154     char* name = static_cast<char*>(
155         alloca(sizeof(kLibFormat) + static_cast<size_t>(subname_len)));
156     sprintf(name, kLibFormat, subname_len, subname);
157     return android_dlopen_ext(name, RTLD_LOCAL | RTLD_NOW, &dlextinfo);
158 }
159 
160 const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
161     "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
162     "ro.board.platform",
163 }};
164 
LoadDriver(android_namespace_t * library_namespace,const hwvulkan_module_t ** module)165 int LoadDriver(android_namespace_t* library_namespace,
166                const hwvulkan_module_t** module) {
167     const android_dlextinfo dlextinfo = {
168         .flags = ANDROID_DLEXT_USE_NAMESPACE,
169         .library_namespace = library_namespace,
170     };
171     void* so = nullptr;
172     char prop[PROPERTY_VALUE_MAX];
173     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
174         int prop_len = property_get(key, prop, nullptr);
175         if (prop_len > 0) {
176             so = LoadLibrary(dlextinfo, prop, prop_len);
177             if (so)
178                 break;
179         }
180     }
181     if (!so)
182         return -ENOENT;
183 
184     auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
185     if (!hmi) {
186         ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
187         dlclose(so);
188         return -EINVAL;
189     }
190     if (strcmp(hmi->id, HWVULKAN_HARDWARE_MODULE_ID) != 0) {
191         ALOGE("HAL id '%s' != '%s'", hmi->id, HWVULKAN_HARDWARE_MODULE_ID);
192         dlclose(so);
193         return -EINVAL;
194     }
195     hmi->dso = so;
196     *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
197     return 0;
198 }
199 
LoadBuiltinDriver(const hwvulkan_module_t ** module)200 int LoadBuiltinDriver(const hwvulkan_module_t** module) {
201     auto ns = android_get_exported_namespace("sphal");
202     if (!ns)
203         return -ENOENT;
204     return LoadDriver(ns, module);
205 }
206 
LoadUpdatedDriver(const hwvulkan_module_t ** module)207 int LoadUpdatedDriver(const hwvulkan_module_t** module) {
208     auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
209     if (!ns)
210         return -ENOENT;
211     return LoadDriver(ns, module);
212 }
213 
Open()214 bool Hal::Open() {
215     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
216 
217     // Use a stub device unless we successfully open a real HAL device.
218     hal_.dev_ = &stubhal::kDevice;
219 
220     int result;
221     const hwvulkan_module_t* module = nullptr;
222 
223     result = LoadUpdatedDriver(&module);
224     if (result == -ENOENT) {
225         result = LoadBuiltinDriver(&module);
226         if (result != 0) {
227             // -ENOENT means the sphal namespace doesn't exist, not that there
228             // is a problem with the driver.
229             ALOGW_IF(
230                 result != -ENOENT,
231                 "Failed to load Vulkan driver into sphal namespace. This "
232                 "usually means the driver has forbidden library dependencies."
233                 "Please fix, this will soon stop working.");
234             result =
235                 hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
236                               reinterpret_cast<const hw_module_t**>(&module));
237         }
238     }
239     if (result != 0) {
240         ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
241         return true;
242     }
243 
244     hwvulkan_device_t* device;
245     result =
246         module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
247                                      reinterpret_cast<hw_device_t**>(&device));
248     if (result != 0) {
249         // Any device with a Vulkan HAL should be able to open the device.
250         ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
251               result);
252         return false;
253     }
254 
255     hal_.dev_ = device;
256 
257     hal_.InitDebugReportIndex();
258 
259     return true;
260 }
261 
InitDebugReportIndex()262 bool Hal::InitDebugReportIndex() {
263     uint32_t count;
264     if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, nullptr) !=
265         VK_SUCCESS) {
266         ALOGE("failed to get HAL instance extension count");
267         return false;
268     }
269 
270     VkExtensionProperties* exts = reinterpret_cast<VkExtensionProperties*>(
271         malloc(sizeof(VkExtensionProperties) * count));
272     if (!exts) {
273         ALOGE("failed to allocate HAL instance extension array");
274         return false;
275     }
276 
277     if (dev_->EnumerateInstanceExtensionProperties(nullptr, &count, exts) !=
278         VK_SUCCESS) {
279         ALOGE("failed to enumerate HAL instance extensions");
280         free(exts);
281         return false;
282     }
283 
284     for (uint32_t i = 0; i < count; i++) {
285         if (strcmp(exts[i].extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) ==
286             0) {
287             debug_report_index_ = static_cast<int>(i);
288             break;
289         }
290     }
291 
292     free(exts);
293 
294     return true;
295 }
296 
CreateInfoWrapper(const VkInstanceCreateInfo & create_info,const VkAllocationCallbacks & allocator)297 CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info,
298                                      const VkAllocationCallbacks& allocator)
299     : is_instance_(true),
300       allocator_(allocator),
301       physical_dev_(VK_NULL_HANDLE),
302       instance_info_(create_info),
303       extension_filter_() {
304     hook_extensions_.set(ProcHook::EXTENSION_CORE);
305     hal_extensions_.set(ProcHook::EXTENSION_CORE);
306 }
307 
CreateInfoWrapper(VkPhysicalDevice physical_dev,const VkDeviceCreateInfo & create_info,const VkAllocationCallbacks & allocator)308 CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
309                                      const VkDeviceCreateInfo& create_info,
310                                      const VkAllocationCallbacks& allocator)
311     : is_instance_(false),
312       allocator_(allocator),
313       physical_dev_(physical_dev),
314       dev_info_(create_info),
315       extension_filter_() {
316     hook_extensions_.set(ProcHook::EXTENSION_CORE);
317     hal_extensions_.set(ProcHook::EXTENSION_CORE);
318 }
319 
~CreateInfoWrapper()320 CreateInfoWrapper::~CreateInfoWrapper() {
321     allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
322     allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
323 }
324 
Validate()325 VkResult CreateInfoWrapper::Validate() {
326     VkResult result = SanitizePNext();
327     if (result == VK_SUCCESS)
328         result = SanitizeLayers();
329     if (result == VK_SUCCESS)
330         result = SanitizeExtensions();
331 
332     return result;
333 }
334 
335 const std::bitset<ProcHook::EXTENSION_COUNT>&
GetHookExtensions() const336 CreateInfoWrapper::GetHookExtensions() const {
337     return hook_extensions_;
338 }
339 
340 const std::bitset<ProcHook::EXTENSION_COUNT>&
GetHalExtensions() const341 CreateInfoWrapper::GetHalExtensions() const {
342     return hal_extensions_;
343 }
344 
operator const VkInstanceCreateInfo*() const345 CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
346     return &instance_info_;
347 }
348 
operator const VkDeviceCreateInfo*() const349 CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
350     return &dev_info_;
351 }
352 
SanitizePNext()353 VkResult CreateInfoWrapper::SanitizePNext() {
354     const struct StructHeader {
355         VkStructureType type;
356         const void* next;
357     } * header;
358 
359     if (is_instance_) {
360         header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
361 
362         // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
363         while (header &&
364                header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
365             header = reinterpret_cast<const StructHeader*>(header->next);
366 
367         instance_info_.pNext = header;
368     } else {
369         header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
370 
371         // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
372         while (header &&
373                header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
374             header = reinterpret_cast<const StructHeader*>(header->next);
375 
376         dev_info_.pNext = header;
377     }
378 
379     return VK_SUCCESS;
380 }
381 
SanitizeLayers()382 VkResult CreateInfoWrapper::SanitizeLayers() {
383     auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
384                                        : dev_info_.ppEnabledLayerNames;
385     auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
386                                        : dev_info_.enabledLayerCount;
387 
388     // remove all layers
389     layer_names = nullptr;
390     layer_count = 0;
391 
392     return VK_SUCCESS;
393 }
394 
SanitizeExtensions()395 VkResult CreateInfoWrapper::SanitizeExtensions() {
396     auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
397                                      : dev_info_.ppEnabledExtensionNames;
398     auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
399                                      : dev_info_.enabledExtensionCount;
400     if (!ext_count)
401         return VK_SUCCESS;
402 
403     VkResult result = InitExtensionFilter();
404     if (result != VK_SUCCESS)
405         return result;
406 
407     for (uint32_t i = 0; i < ext_count; i++)
408         FilterExtension(ext_names[i]);
409 
410     // Enable device extensions that contain physical-device commands, so that
411     // vkGetInstanceProcAddr will return those physical-device commands.
412     if (is_instance_) {
413         hook_extensions_.set(ProcHook::KHR_swapchain);
414     }
415 
416     ext_names = extension_filter_.names;
417     ext_count = extension_filter_.name_count;
418 
419     return VK_SUCCESS;
420 }
421 
QueryExtensionCount(uint32_t & count) const422 VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
423     if (is_instance_) {
424         return Hal::Device().EnumerateInstanceExtensionProperties(
425             nullptr, &count, nullptr);
426     } else {
427         const auto& driver = GetData(physical_dev_).driver;
428         return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
429                                                          &count, nullptr);
430     }
431 }
432 
EnumerateExtensions(uint32_t & count,VkExtensionProperties * props) const433 VkResult CreateInfoWrapper::EnumerateExtensions(
434     uint32_t& count,
435     VkExtensionProperties* props) const {
436     if (is_instance_) {
437         return Hal::Device().EnumerateInstanceExtensionProperties(
438             nullptr, &count, props);
439     } else {
440         const auto& driver = GetData(physical_dev_).driver;
441         return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
442                                                          &count, props);
443     }
444 }
445 
InitExtensionFilter()446 VkResult CreateInfoWrapper::InitExtensionFilter() {
447     // query extension count
448     uint32_t count;
449     VkResult result = QueryExtensionCount(count);
450     if (result != VK_SUCCESS || count == 0)
451         return result;
452 
453     auto& filter = extension_filter_;
454     filter.exts =
455         reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
456             allocator_.pUserData, sizeof(VkExtensionProperties) * count,
457             alignof(VkExtensionProperties),
458             VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
459     if (!filter.exts)
460         return VK_ERROR_OUT_OF_HOST_MEMORY;
461 
462     // enumerate extensions
463     result = EnumerateExtensions(count, filter.exts);
464     if (result != VK_SUCCESS && result != VK_INCOMPLETE)
465         return result;
466 
467     if (!count)
468         return VK_SUCCESS;
469 
470     filter.ext_count = count;
471 
472     // allocate name array
473     uint32_t enabled_ext_count = (is_instance_)
474                                      ? instance_info_.enabledExtensionCount
475                                      : dev_info_.enabledExtensionCount;
476     count = std::min(filter.ext_count, enabled_ext_count);
477     filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
478         allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
479         VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
480     if (!filter.names)
481         return VK_ERROR_OUT_OF_HOST_MEMORY;
482 
483     return VK_SUCCESS;
484 }
485 
FilterExtension(const char * name)486 void CreateInfoWrapper::FilterExtension(const char* name) {
487     auto& filter = extension_filter_;
488 
489     ProcHook::Extension ext_bit = GetProcHookExtension(name);
490     if (is_instance_) {
491         switch (ext_bit) {
492             case ProcHook::KHR_android_surface:
493             case ProcHook::KHR_surface:
494             case ProcHook::EXT_swapchain_colorspace:
495             case ProcHook::KHR_get_surface_capabilities2:
496                 hook_extensions_.set(ext_bit);
497                 // return now as these extensions do not require HAL support
498                 return;
499             case ProcHook::EXT_debug_report:
500                 // both we and HAL can take part in
501                 hook_extensions_.set(ext_bit);
502                 break;
503             case ProcHook::KHR_get_physical_device_properties2:
504             case ProcHook::EXTENSION_UNKNOWN:
505                 // Extensions we don't need to do anything about at this level
506                 break;
507 
508             case ProcHook::KHR_incremental_present:
509             case ProcHook::KHR_shared_presentable_image:
510             case ProcHook::KHR_swapchain:
511             case ProcHook::EXT_hdr_metadata:
512             case ProcHook::ANDROID_external_memory_android_hardware_buffer:
513             case ProcHook::ANDROID_native_buffer:
514             case ProcHook::GOOGLE_display_timing:
515             case ProcHook::EXTENSION_CORE:
516             case ProcHook::EXTENSION_COUNT:
517                 // Device and meta extensions. If we ever get here it's a bug in
518                 // our code. But enumerating them lets us avoid having a default
519                 // case, and default hides other bugs.
520                 ALOGE(
521                     "CreateInfoWrapper::FilterExtension: invalid instance "
522                     "extension '%s'. FIX ME",
523                     name);
524                 return;
525 
526             // Don't use a default case. Without it, -Wswitch will tell us
527             // at compile time if someone adds a new ProcHook extension but
528             // doesn't handle it above. That's a real bug that has
529             // not-immediately-obvious effects.
530             //
531             // default:
532             //     break;
533         }
534     } else {
535         switch (ext_bit) {
536             case ProcHook::KHR_swapchain:
537                 // map VK_KHR_swapchain to VK_ANDROID_native_buffer
538                 name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
539                 ext_bit = ProcHook::ANDROID_native_buffer;
540                 break;
541             case ProcHook::KHR_incremental_present:
542             case ProcHook::GOOGLE_display_timing:
543             case ProcHook::KHR_shared_presentable_image:
544                 hook_extensions_.set(ext_bit);
545                 // return now as these extensions do not require HAL support
546                 return;
547             case ProcHook::EXT_hdr_metadata:
548                 hook_extensions_.set(ext_bit);
549                 break;
550             case ProcHook::ANDROID_external_memory_android_hardware_buffer:
551             case ProcHook::EXTENSION_UNKNOWN:
552                 // Extensions we don't need to do anything about at this level
553                 break;
554 
555             case ProcHook::KHR_android_surface:
556             case ProcHook::KHR_get_physical_device_properties2:
557             case ProcHook::KHR_get_surface_capabilities2:
558             case ProcHook::KHR_surface:
559             case ProcHook::EXT_debug_report:
560             case ProcHook::EXT_swapchain_colorspace:
561             case ProcHook::ANDROID_native_buffer:
562             case ProcHook::EXTENSION_CORE:
563             case ProcHook::EXTENSION_COUNT:
564                 // Instance and meta extensions. If we ever get here it's a bug
565                 // in our code. But enumerating them lets us avoid having a
566                 // default case, and default hides other bugs.
567                 ALOGE(
568                     "CreateInfoWrapper::FilterExtension: invalid device "
569                     "extension '%s'. FIX ME",
570                     name);
571                 return;
572 
573             // Don't use a default case. Without it, -Wswitch will tell us
574             // at compile time if someone adds a new ProcHook extension but
575             // doesn't handle it above. That's a real bug that has
576             // not-immediately-obvious effects.
577             //
578             // default:
579             //     break;
580         }
581     }
582 
583     for (uint32_t i = 0; i < filter.ext_count; i++) {
584         const VkExtensionProperties& props = filter.exts[i];
585         // ignore unknown extensions
586         if (strcmp(name, props.extensionName) != 0)
587             continue;
588 
589         filter.names[filter.name_count++] = name;
590         if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
591             if (ext_bit == ProcHook::ANDROID_native_buffer)
592                 hook_extensions_.set(ProcHook::KHR_swapchain);
593 
594             hal_extensions_.set(ext_bit);
595         }
596 
597         break;
598     }
599 }
600 
DowngradeApiVersion()601 void CreateInfoWrapper::DowngradeApiVersion() {
602     // If pApplicationInfo is NULL, apiVersion is assumed to be 1.0:
603     if (instance_info_.pApplicationInfo) {
604         application_info_ = *instance_info_.pApplicationInfo;
605         instance_info_.pApplicationInfo = &application_info_;
606         application_info_.apiVersion = VK_API_VERSION_1_0;
607     }
608 }
609 
DefaultAllocate(void *,size_t size,size_t alignment,VkSystemAllocationScope)610 VKAPI_ATTR void* DefaultAllocate(void*,
611                                  size_t size,
612                                  size_t alignment,
613                                  VkSystemAllocationScope) {
614     void* ptr = nullptr;
615     // Vulkan requires 'alignment' to be a power of two, but posix_memalign
616     // additionally requires that it be at least sizeof(void*).
617     int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
618     ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
619                     ret, ptr);
620     return ret == 0 ? ptr : nullptr;
621 }
622 
DefaultReallocate(void *,void * ptr,size_t size,size_t alignment,VkSystemAllocationScope)623 VKAPI_ATTR void* DefaultReallocate(void*,
624                                    void* ptr,
625                                    size_t size,
626                                    size_t alignment,
627                                    VkSystemAllocationScope) {
628     if (size == 0) {
629         free(ptr);
630         return nullptr;
631     }
632 
633     // TODO(jessehall): Right now we never shrink allocations; if the new
634     // request is smaller than the existing chunk, we just continue using it.
635     // Right now the loader never reallocs, so this doesn't matter. If that
636     // changes, or if this code is copied into some other project, this should
637     // probably have a heuristic to allocate-copy-free when doing so will save
638     // "enough" space.
639     size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
640     if (size <= old_size)
641         return ptr;
642 
643     void* new_ptr = nullptr;
644     if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
645         return nullptr;
646     if (ptr) {
647         memcpy(new_ptr, ptr, std::min(old_size, size));
648         free(ptr);
649     }
650     return new_ptr;
651 }
652 
DefaultFree(void *,void * ptr)653 VKAPI_ATTR void DefaultFree(void*, void* ptr) {
654     ALOGD_CALLSTACK("Free: %p", ptr);
655     free(ptr);
656 }
657 
AllocateInstanceData(const VkAllocationCallbacks & allocator)658 InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
659     void* data_mem = allocator.pfnAllocation(
660         allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
661         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
662     if (!data_mem)
663         return nullptr;
664 
665     return new (data_mem) InstanceData(allocator);
666 }
667 
FreeInstanceData(InstanceData * data,const VkAllocationCallbacks & allocator)668 void FreeInstanceData(InstanceData* data,
669                       const VkAllocationCallbacks& allocator) {
670     data->~InstanceData();
671     allocator.pfnFree(allocator.pUserData, data);
672 }
673 
AllocateDeviceData(const VkAllocationCallbacks & allocator,const DebugReportCallbackList & debug_report_callbacks)674 DeviceData* AllocateDeviceData(
675     const VkAllocationCallbacks& allocator,
676     const DebugReportCallbackList& debug_report_callbacks) {
677     void* data_mem = allocator.pfnAllocation(
678         allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
679         VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
680     if (!data_mem)
681         return nullptr;
682 
683     return new (data_mem) DeviceData(allocator, debug_report_callbacks);
684 }
685 
FreeDeviceData(DeviceData * data,const VkAllocationCallbacks & allocator)686 void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
687     data->~DeviceData();
688     allocator.pfnFree(allocator.pUserData, data);
689 }
690 
691 }  // anonymous namespace
692 
Debuggable()693 bool Debuggable() {
694     return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
695 }
696 
OpenHAL()697 bool OpenHAL() {
698     return Hal::Open();
699 }
700 
GetDefaultAllocator()701 const VkAllocationCallbacks& GetDefaultAllocator() {
702     static const VkAllocationCallbacks kDefaultAllocCallbacks = {
703         .pUserData = nullptr,
704         .pfnAllocation = DefaultAllocate,
705         .pfnReallocation = DefaultReallocate,
706         .pfnFree = DefaultFree,
707     };
708 
709     return kDefaultAllocCallbacks;
710 }
711 
GetInstanceProcAddr(VkInstance instance,const char * pName)712 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
713     const ProcHook* hook = GetProcHook(pName);
714     if (!hook)
715         return Hal::Device().GetInstanceProcAddr(instance, pName);
716 
717     if (!instance) {
718         if (hook->type == ProcHook::GLOBAL)
719             return hook->proc;
720 
721         // v0 layers expect
722         //
723         //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
724         //
725         // to work.
726         if (strcmp(pName, "vkCreateDevice") == 0)
727             return hook->proc;
728 
729         ALOGE(
730             "internal vkGetInstanceProcAddr called for %s without an instance",
731             pName);
732 
733         return nullptr;
734     }
735 
736     PFN_vkVoidFunction proc;
737 
738     switch (hook->type) {
739         case ProcHook::INSTANCE:
740             proc = (GetData(instance).hook_extensions[hook->extension])
741                        ? hook->proc
742                        : nullptr;
743             break;
744         case ProcHook::DEVICE:
745             proc = (hook->extension == ProcHook::EXTENSION_CORE)
746                        ? hook->proc
747                        : hook->checked_proc;
748             break;
749         default:
750             ALOGE(
751                 "internal vkGetInstanceProcAddr called for %s with an instance",
752                 pName);
753             proc = nullptr;
754             break;
755     }
756 
757     return proc;
758 }
759 
GetDeviceProcAddr(VkDevice device,const char * pName)760 PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
761     const ProcHook* hook = GetProcHook(pName);
762     if (!hook)
763         return GetData(device).driver.GetDeviceProcAddr(device, pName);
764 
765     if (hook->type != ProcHook::DEVICE) {
766         ALOGE("internal vkGetDeviceProcAddr called for %s", pName);
767         return nullptr;
768     }
769 
770     return (GetData(device).hook_extensions[hook->extension]) ? hook->proc
771                                                               : nullptr;
772 }
773 
EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)774 VkResult EnumerateInstanceExtensionProperties(
775     const char* pLayerName,
776     uint32_t* pPropertyCount,
777     VkExtensionProperties* pProperties) {
778 
779     android::Vector<VkExtensionProperties> loader_extensions;
780     loader_extensions.push_back({
781         VK_KHR_SURFACE_EXTENSION_NAME,
782         VK_KHR_SURFACE_SPEC_VERSION});
783     loader_extensions.push_back({
784         VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
785         VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
786     loader_extensions.push_back({
787         VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
788         VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION});
789     loader_extensions.push_back({
790         VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
791         VK_KHR_GET_SURFACE_CAPABILITIES_2_SPEC_VERSION});
792 
793     static const VkExtensionProperties loader_debug_report_extension = {
794         VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION,
795     };
796 
797     // enumerate our extensions first
798     if (!pLayerName && pProperties) {
799         uint32_t count = std::min(
800             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
801 
802         std::copy_n(loader_extensions.begin(), count, pProperties);
803 
804         if (count < loader_extensions.size()) {
805             *pPropertyCount = count;
806             return VK_INCOMPLETE;
807         }
808 
809         pProperties += count;
810         *pPropertyCount -= count;
811 
812         if (Hal::Get().GetDebugReportIndex() < 0) {
813             if (!*pPropertyCount) {
814                 *pPropertyCount = count;
815                 return VK_INCOMPLETE;
816             }
817 
818             pProperties[0] = loader_debug_report_extension;
819             pProperties += 1;
820             *pPropertyCount -= 1;
821         }
822     }
823 
824     VkResult result = Hal::Device().EnumerateInstanceExtensionProperties(
825         pLayerName, pPropertyCount, pProperties);
826 
827     if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
828         int idx = Hal::Get().GetDebugReportIndex();
829         if (idx < 0) {
830             *pPropertyCount += 1;
831         } else if (pProperties &&
832                    static_cast<uint32_t>(idx) < *pPropertyCount) {
833             pProperties[idx].specVersion =
834                 std::min(pProperties[idx].specVersion,
835                          loader_debug_report_extension.specVersion);
836         }
837 
838         *pPropertyCount += loader_extensions.size();
839     }
840 
841     return result;
842 }
843 
QueryPresentationProperties(VkPhysicalDevice physicalDevice,VkPhysicalDevicePresentationPropertiesANDROID * presentation_properties)844 bool QueryPresentationProperties(
845     VkPhysicalDevice physicalDevice,
846     VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties)
847 {
848     const InstanceData& data = GetData(physicalDevice);
849 
850     // GPDP2 must be present and enabled on the instance.
851     if (!data.driver.GetPhysicalDeviceProperties2KHR &&
852         !data.driver.GetPhysicalDeviceProperties2)
853         return false;
854 
855     // Request the android-specific presentation properties via GPDP2
856     VkPhysicalDeviceProperties2KHR properties = {
857         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
858         presentation_properties,
859         {}
860     };
861 
862 #pragma clang diagnostic push
863 #pragma clang diagnostic ignored "-Wold-style-cast"
864     presentation_properties->sType =
865         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID;
866 #pragma clang diagnostic pop
867     presentation_properties->pNext = nullptr;
868     presentation_properties->sharedImage = VK_FALSE;
869 
870     if (data.driver.GetPhysicalDeviceProperties2KHR) {
871         data.driver.GetPhysicalDeviceProperties2KHR(physicalDevice,
872                                                     &properties);
873     } else {
874         data.driver.GetPhysicalDeviceProperties2(physicalDevice, &properties);
875     }
876 
877     return true;
878 }
879 
EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)880 VkResult EnumerateDeviceExtensionProperties(
881     VkPhysicalDevice physicalDevice,
882     const char* pLayerName,
883     uint32_t* pPropertyCount,
884     VkExtensionProperties* pProperties) {
885     const InstanceData& data = GetData(physicalDevice);
886     // extensions that are unconditionally exposed by the loader
887     android::Vector<VkExtensionProperties> loader_extensions;
888     loader_extensions.push_back({
889         VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
890         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
891 
892     bool hdrBoardConfig =
893         getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(
894             false);
895     if (hdrBoardConfig) {
896         loader_extensions.push_back({VK_EXT_HDR_METADATA_EXTENSION_NAME,
897                                      VK_EXT_HDR_METADATA_SPEC_VERSION});
898     }
899 
900     VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
901     if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
902         presentation_properties.sharedImage) {
903         loader_extensions.push_back({
904             VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
905             VK_KHR_SHARED_PRESENTABLE_IMAGE_SPEC_VERSION});
906     }
907 
908     // conditionally add VK_GOOGLE_display_timing if present timestamps are
909     // supported by the driver:
910     const std::string timestamp_property("service.sf.present_timestamp");
911     android::base::WaitForPropertyCreation(timestamp_property);
912     if (android::base::GetBoolProperty(timestamp_property, true)) {
913         loader_extensions.push_back({
914                 VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
915                 VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
916     }
917 
918     // enumerate our extensions first
919     if (!pLayerName && pProperties) {
920         uint32_t count = std::min(
921             *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
922 
923         std::copy_n(loader_extensions.begin(), count, pProperties);
924 
925         if (count < loader_extensions.size()) {
926             *pPropertyCount = count;
927             return VK_INCOMPLETE;
928         }
929 
930         pProperties += count;
931         *pPropertyCount -= count;
932     }
933 
934     VkResult result = data.driver.EnumerateDeviceExtensionProperties(
935         physicalDevice, pLayerName, pPropertyCount, pProperties);
936 
937     if (pProperties) {
938         // map VK_ANDROID_native_buffer to VK_KHR_swapchain
939         for (uint32_t i = 0; i < *pPropertyCount; i++) {
940             auto& prop = pProperties[i];
941 
942             if (strcmp(prop.extensionName,
943                        VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
944                 continue;
945 
946             memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
947                    sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
948             prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
949         }
950     }
951 
952     // restore loader extension count
953     if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
954         *pPropertyCount += loader_extensions.size();
955     }
956 
957     return result;
958 }
959 
CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)960 VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
961                         const VkAllocationCallbacks* pAllocator,
962                         VkInstance* pInstance) {
963     const VkAllocationCallbacks& data_allocator =
964         (pAllocator) ? *pAllocator : GetDefaultAllocator();
965 
966     CreateInfoWrapper wrapper(*pCreateInfo, data_allocator);
967     VkResult result = wrapper.Validate();
968     if (result != VK_SUCCESS)
969         return result;
970 
971     InstanceData* data = AllocateInstanceData(data_allocator);
972     if (!data)
973         return VK_ERROR_OUT_OF_HOST_MEMORY;
974 
975     data->hook_extensions |= wrapper.GetHookExtensions();
976 
977 #pragma clang diagnostic push
978 #pragma clang diagnostic ignored "-Wold-style-cast"
979     uint32_t api_version = ((pCreateInfo->pApplicationInfo)
980                                 ? pCreateInfo->pApplicationInfo->apiVersion
981                                 : VK_API_VERSION_1_0);
982     uint32_t api_major_version = VK_VERSION_MAJOR(api_version);
983     uint32_t api_minor_version = VK_VERSION_MINOR(api_version);
984     uint32_t icd_api_version;
985     PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version =
986         reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
987             Hal::Device().GetInstanceProcAddr(NULL,
988                                               "vkEnumerateInstanceVersion"));
989     if (!pfn_enumerate_instance_version) {
990         icd_api_version = VK_API_VERSION_1_0;
991     } else {
992         result = (*pfn_enumerate_instance_version)(&icd_api_version);
993     }
994     uint32_t icd_api_major_version = VK_VERSION_MAJOR(icd_api_version);
995     uint32_t icd_api_minor_version = VK_VERSION_MINOR(icd_api_version);
996 
997     if ((icd_api_major_version == 1) && (icd_api_minor_version == 0) &&
998         ((api_major_version > 1) || (api_minor_version > 0))) {
999         api_version = VK_API_VERSION_1_0;
1000         wrapper.DowngradeApiVersion();
1001     }
1002 #pragma clang diagnostic pop
1003 
1004     // call into the driver
1005     VkInstance instance;
1006     result = Hal::Device().CreateInstance(
1007         static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
1008         &instance);
1009     if (result != VK_SUCCESS) {
1010         FreeInstanceData(data, data_allocator);
1011         return result;
1012     }
1013 
1014     // initialize InstanceDriverTable
1015     if (!SetData(instance, *data) ||
1016         !InitDriverTable(instance, Hal::Device().GetInstanceProcAddr,
1017                          wrapper.GetHalExtensions())) {
1018         data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
1019             Hal::Device().GetInstanceProcAddr(instance, "vkDestroyInstance"));
1020         if (data->driver.DestroyInstance)
1021             data->driver.DestroyInstance(instance, pAllocator);
1022 
1023         FreeInstanceData(data, data_allocator);
1024 
1025         return VK_ERROR_INCOMPATIBLE_DRIVER;
1026     }
1027 
1028     data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
1029         Hal::Device().GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
1030     if (!data->get_device_proc_addr) {
1031         data->driver.DestroyInstance(instance, pAllocator);
1032         FreeInstanceData(data, data_allocator);
1033 
1034         return VK_ERROR_INCOMPATIBLE_DRIVER;
1035     }
1036 
1037     *pInstance = instance;
1038 
1039     return VK_SUCCESS;
1040 }
1041 
DestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)1042 void DestroyInstance(VkInstance instance,
1043                      const VkAllocationCallbacks* pAllocator) {
1044     InstanceData& data = GetData(instance);
1045     data.driver.DestroyInstance(instance, pAllocator);
1046 
1047     VkAllocationCallbacks local_allocator;
1048     if (!pAllocator) {
1049         local_allocator = data.allocator;
1050         pAllocator = &local_allocator;
1051     }
1052 
1053     FreeInstanceData(&data, *pAllocator);
1054 }
1055 
CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1056 VkResult CreateDevice(VkPhysicalDevice physicalDevice,
1057                       const VkDeviceCreateInfo* pCreateInfo,
1058                       const VkAllocationCallbacks* pAllocator,
1059                       VkDevice* pDevice) {
1060     const InstanceData& instance_data = GetData(physicalDevice);
1061     const VkAllocationCallbacks& data_allocator =
1062         (pAllocator) ? *pAllocator : instance_data.allocator;
1063 
1064     CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
1065     VkResult result = wrapper.Validate();
1066     if (result != VK_SUCCESS)
1067         return result;
1068 
1069     DeviceData* data = AllocateDeviceData(data_allocator,
1070                                           instance_data.debug_report_callbacks);
1071     if (!data)
1072         return VK_ERROR_OUT_OF_HOST_MEMORY;
1073 
1074     data->hook_extensions |= wrapper.GetHookExtensions();
1075 
1076     // call into the driver
1077     VkDevice dev;
1078     result = instance_data.driver.CreateDevice(
1079         physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
1080         pAllocator, &dev);
1081     if (result != VK_SUCCESS) {
1082         FreeDeviceData(data, data_allocator);
1083         return result;
1084     }
1085 
1086     // initialize DeviceDriverTable
1087     if (!SetData(dev, *data) ||
1088         !InitDriverTable(dev, instance_data.get_device_proc_addr,
1089                          wrapper.GetHalExtensions())) {
1090         data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
1091             instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
1092         if (data->driver.DestroyDevice)
1093             data->driver.DestroyDevice(dev, pAllocator);
1094 
1095         FreeDeviceData(data, data_allocator);
1096 
1097         return VK_ERROR_INCOMPATIBLE_DRIVER;
1098     }
1099 
1100     // sanity check ANDROID_native_buffer implementation, whose set of
1101     // entrypoints varies according to the spec version.
1102     if ((wrapper.GetHalExtensions()[ProcHook::ANDROID_native_buffer]) &&
1103         !data->driver.GetSwapchainGrallocUsageANDROID &&
1104         !data->driver.GetSwapchainGrallocUsage2ANDROID) {
1105         ALOGE("Driver's implementation of ANDROID_native_buffer is broken;"
1106               " must expose at least one of "
1107               "vkGetSwapchainGrallocUsageANDROID or "
1108               "vkGetSwapchainGrallocUsage2ANDROID");
1109 
1110         data->driver.DestroyDevice(dev, pAllocator);
1111         FreeDeviceData(data, data_allocator);
1112 
1113         return VK_ERROR_INCOMPATIBLE_DRIVER;
1114     }
1115 
1116     VkPhysicalDeviceProperties properties;
1117     instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
1118                                                      &properties);
1119 
1120     data->driver_device = dev;
1121     data->driver_version = properties.driverVersion;
1122 
1123     *pDevice = dev;
1124 
1125     return VK_SUCCESS;
1126 }
1127 
DestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)1128 void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
1129     DeviceData& data = GetData(device);
1130     data.driver.DestroyDevice(device, pAllocator);
1131 
1132     VkAllocationCallbacks local_allocator;
1133     if (!pAllocator) {
1134         local_allocator = data.allocator;
1135         pAllocator = &local_allocator;
1136     }
1137 
1138     FreeDeviceData(&data, *pAllocator);
1139 }
1140 
EnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)1141 VkResult EnumeratePhysicalDevices(VkInstance instance,
1142                                   uint32_t* pPhysicalDeviceCount,
1143                                   VkPhysicalDevice* pPhysicalDevices) {
1144     const auto& data = GetData(instance);
1145 
1146     VkResult result = data.driver.EnumeratePhysicalDevices(
1147         instance, pPhysicalDeviceCount, pPhysicalDevices);
1148     if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
1149         for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
1150             SetData(pPhysicalDevices[i], data);
1151     }
1152 
1153     return result;
1154 }
1155 
EnumeratePhysicalDeviceGroups(VkInstance instance,uint32_t * pPhysicalDeviceGroupCount,VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties)1156 VkResult EnumeratePhysicalDeviceGroups(
1157     VkInstance instance,
1158     uint32_t* pPhysicalDeviceGroupCount,
1159     VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
1160     VkResult result = VK_SUCCESS;
1161     const auto& data = GetData(instance);
1162 
1163     if (!data.driver.EnumeratePhysicalDeviceGroups) {
1164         uint32_t device_count = 0;
1165         result = EnumeratePhysicalDevices(instance, &device_count, nullptr);
1166         if (result < 0)
1167             return result;
1168         if (!pPhysicalDeviceGroupProperties) {
1169             *pPhysicalDeviceGroupCount = device_count;
1170             return result;
1171         }
1172 
1173         device_count = std::min(device_count, *pPhysicalDeviceGroupCount);
1174         if (!device_count) {
1175             *pPhysicalDeviceGroupCount = 0;
1176             return result;
1177         }
1178 
1179         android::Vector<VkPhysicalDevice> devices;
1180         devices.resize(device_count);
1181 
1182         result = EnumeratePhysicalDevices(instance, &device_count,
1183                                           devices.editArray());
1184         if (result < 0)
1185             return result;
1186 
1187         devices.resize(device_count);
1188         *pPhysicalDeviceGroupCount = device_count;
1189         for (uint32_t i = 0; i < device_count; ++i) {
1190             pPhysicalDeviceGroupProperties[i].physicalDeviceCount = 1;
1191             pPhysicalDeviceGroupProperties[i].physicalDevices[0] = devices[i];
1192             pPhysicalDeviceGroupProperties[i].subsetAllocation = 0;
1193         }
1194     } else {
1195         result = data.driver.EnumeratePhysicalDeviceGroups(
1196             instance, pPhysicalDeviceGroupCount,
1197             pPhysicalDeviceGroupProperties);
1198         if ((result == VK_SUCCESS || result == VK_INCOMPLETE) &&
1199             *pPhysicalDeviceGroupCount && pPhysicalDeviceGroupProperties) {
1200             for (uint32_t i = 0; i < *pPhysicalDeviceGroupCount; i++) {
1201                 for (uint32_t j = 0;
1202                      j < pPhysicalDeviceGroupProperties[i].physicalDeviceCount;
1203                      j++) {
1204                     SetData(
1205                         pPhysicalDeviceGroupProperties[i].physicalDevices[j],
1206                         data);
1207                 }
1208             }
1209         }
1210     }
1211 
1212     return result;
1213 }
1214 
GetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)1215 void GetDeviceQueue(VkDevice device,
1216                     uint32_t queueFamilyIndex,
1217                     uint32_t queueIndex,
1218                     VkQueue* pQueue) {
1219     const auto& data = GetData(device);
1220 
1221     data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
1222     SetData(*pQueue, data);
1223 }
1224 
GetDeviceQueue2(VkDevice device,const VkDeviceQueueInfo2 * pQueueInfo,VkQueue * pQueue)1225 void GetDeviceQueue2(VkDevice device,
1226                      const VkDeviceQueueInfo2* pQueueInfo,
1227                      VkQueue* pQueue) {
1228     const auto& data = GetData(device);
1229 
1230     data.driver.GetDeviceQueue2(device, pQueueInfo, pQueue);
1231     if (*pQueue != VK_NULL_HANDLE) SetData(*pQueue, data);
1232 }
1233 
1234 VKAPI_ATTR VkResult
AllocateCommandBuffers(VkDevice device,const VkCommandBufferAllocateInfo * pAllocateInfo,VkCommandBuffer * pCommandBuffers)1235 AllocateCommandBuffers(VkDevice device,
1236                        const VkCommandBufferAllocateInfo* pAllocateInfo,
1237                        VkCommandBuffer* pCommandBuffers) {
1238     const auto& data = GetData(device);
1239 
1240     VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
1241                                                          pCommandBuffers);
1242     if (result == VK_SUCCESS) {
1243         for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
1244             SetData(pCommandBuffers[i], data);
1245     }
1246 
1247     return result;
1248 }
1249 
1250 }  // namespace driver
1251 }  // namespace vulkan
1252