Home | History | Annotate | Download | only in libvulkan
      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 
     74     static const Hal& Get() { return hal_; }
     75     static const hwvulkan_device_t& Device() { return *Get().dev_; }
     76 
     77     int GetDebugReportIndex() const { return debug_report_index_; }
     78 
     79    private:
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    320 CreateInfoWrapper::~CreateInfoWrapper() {
    321     allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
    322     allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
    323 }
    324 
    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>&
    336 CreateInfoWrapper::GetHookExtensions() const {
    337     return hook_extensions_;
    338 }
    339 
    340 const std::bitset<ProcHook::EXTENSION_COUNT>&
    341 CreateInfoWrapper::GetHalExtensions() const {
    342     return hal_extensions_;
    343 }
    344 
    345 CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
    346     return &instance_info_;
    347 }
    348 
    349 CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
    350     return &dev_info_;
    351 }
    352 
    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 
    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 
    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 
    422 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 
    433 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 
    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 
    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 
    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 
    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 
    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 
    653 VKAPI_ATTR void DefaultFree(void*, void* ptr) {
    654     ALOGD_CALLSTACK("Free: %p", ptr);
    655     free(ptr);
    656 }
    657 
    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 
    668 void FreeInstanceData(InstanceData* data,
    669                       const VkAllocationCallbacks& allocator) {
    670     data->~InstanceData();
    671     allocator.pfnFree(allocator.pUserData, data);
    672 }
    673 
    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 
    686 void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
    687     data->~DeviceData();
    688     allocator.pfnFree(allocator.pUserData, data);
    689 }
    690 
    691 }  // anonymous namespace
    692 
    693 bool Debuggable() {
    694     return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
    695 }
    696 
    697 bool OpenHAL() {
    698     return Hal::Open();
    699 }
    700 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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 
   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
   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