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