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 PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
    101                                                   const char* name) {
    102     if (strcmp(name, "vkCreateInstance") == 0)
    103         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
    104     if (strcmp(name, "vkDestroyInstance") == 0)
    105         return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
    106     if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
    107         return reinterpret_cast<PFN_vkVoidFunction>(
    108             EnumerateInstanceExtensionProperties);
    109     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
    110         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
    111     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
    112         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
    113 
    114     // None of the other Vulkan functions should ever be called, as they all
    115     // take a VkPhysicalDevice or other object obtained from a physical device.
    116     return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
    117 }
    118 
    119 }  // anonymous namespace
    120 
    121 const hwvulkan_device_t kDevice = {
    122     .common =
    123         {
    124             .tag = HARDWARE_DEVICE_TAG,
    125             .version = HWVULKAN_DEVICE_API_VERSION_0_1,
    126             .module = nullptr,
    127             .close = nullptr,
    128         },
    129     .EnumerateInstanceExtensionProperties =
    130         EnumerateInstanceExtensionProperties,
    131     .CreateInstance = CreateInstance,
    132     .GetInstanceProcAddr = GetInstanceProcAddr,
    133 };
    134 
    135 }  // namespace stubhal
    136 }  // namespace vulkan
    137