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 /* NOTE:
     18  * This stub HAL is only used internally by the loader when a real HAL
     19  * implementation is not present, in order to avoid needing "null HAL" checks
     20  * throughout the loader. It does not enumerate any physical devices, and is
     21  * only as conformant to the Vulkan and Android HAL interfaces as the loader
     22  * needs it to be. Do not use it as an example of a correct implementation; the
     23  * code in ../null_driver is better for that.
     24  */
     25 
     26 #undef LOG_TAG
     27 #define LOG_TAG "vkstub"
     28 
     29 #include <array>
     30 #include <bitset>
     31 #include <mutex>
     32 
     33 #include <log/log.h>
     34 #include <hardware/hwvulkan.h>
     35 
     36 #include "stubhal.h"
     37 
     38 namespace vulkan {
     39 namespace stubhal {
     40 
     41 namespace {
     42 
     43 const size_t kMaxInstances = 32;
     44 static std::mutex g_instance_mutex;
     45 static std::bitset<kMaxInstances> g_instance_used(false);
     46 static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
     47 
     48 [[noreturn]] VKAPI_ATTR void NoOp() {
     49     LOG_ALWAYS_FATAL("invalid stub function called");
     50 }
     51 
     52 VKAPI_ATTR VkResult
     53 EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
     54                                      uint32_t* count,
     55                                      VkExtensionProperties* /*properties*/) {
     56     *count = 0;
     57     return VK_SUCCESS;
     58 }
     59 
     60 VKAPI_ATTR VkResult
     61 EnumerateInstanceLayerProperties(uint32_t* count,
     62                                  VkLayerProperties* /*properties*/) {
     63     *count = 0;
     64     return VK_SUCCESS;
     65 }
     66 
     67 VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
     68                                    const VkAllocationCallbacks* /*allocator*/,
     69                                    VkInstance* instance) {
     70     std::lock_guard<std::mutex> lock(g_instance_mutex);
     71     for (size_t i = 0; i < kMaxInstances; i++) {
     72         if (!g_instance_used[i]) {
     73             g_instance_used[i] = true;
     74             g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
     75             *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
     76             return VK_SUCCESS;
     77         }
     78     }
     79     ALOGE("no more instances available (max=%zu)", kMaxInstances);
     80     return VK_ERROR_INITIALIZATION_FAILED;
     81 }
     82 
     83 VKAPI_ATTR void DestroyInstance(VkInstance instance,
     84                                 const VkAllocationCallbacks* /*allocator*/) {
     85     std::lock_guard<std::mutex> lock(g_instance_mutex);
     86     ssize_t idx =
     87         reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
     88     ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
     89                 "DestroyInstance: invalid instance handle");
     90     g_instance_used[static_cast<size_t>(idx)] = false;
     91 }
     92 
     93 VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
     94                                              uint32_t* count,
     95                                              VkPhysicalDevice* /*gpus*/) {
     96     *count = 0;
     97     return VK_SUCCESS;
     98 }
     99 
    100 VKAPI_ATTR VkResult
    101 EnumeratePhysicalDeviceGroups(VkInstance /*instance*/,
    102                               uint32_t* count,
    103                               VkPhysicalDeviceGroupProperties* /*properties*/) {
    104     *count = 0;
    105     return VK_SUCCESS;
    106 }
    107 
    108 VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
    109                                                   const char* name) {
    110     if (strcmp(name, "vkCreateInstance") == 0)
    111         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
    112     if (strcmp(name, "vkDestroyInstance") == 0)
    113         return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
    114     if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
    115         return reinterpret_cast<PFN_vkVoidFunction>(
    116             EnumerateInstanceExtensionProperties);
    117     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
    118         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
    119     if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
    120         return reinterpret_cast<PFN_vkVoidFunction>(
    121             EnumeratePhysicalDeviceGroups);
    122     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
    123         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
    124     // Per the spec, return NULL if instance is NULL.
    125     if (!instance)
    126         return nullptr;
    127     // None of the other Vulkan functions should ever be called, as they all
    128     // take a VkPhysicalDevice or other object obtained from a physical device.
    129     return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
    130 }
    131 
    132 }  // anonymous namespace
    133 
    134 const hwvulkan_device_t kDevice = {
    135     .common =
    136         {
    137             .tag = HARDWARE_DEVICE_TAG,
    138             .version = HWVULKAN_DEVICE_API_VERSION_0_1,
    139             .module = nullptr,
    140             .close = nullptr,
    141         },
    142     .EnumerateInstanceExtensionProperties =
    143         EnumerateInstanceExtensionProperties,
    144     .CreateInstance = CreateInstance,
    145     .GetInstanceProcAddr = GetInstanceProcAddr,
    146 };
    147 
    148 }  // namespace stubhal
    149 }  // namespace vulkan
    150