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 #include <hardware/hwvulkan.h>
     33 #include <log/log.h>
     34 #include "stubhal.h"
     35 
     36 namespace vulkan {
     37 namespace stubhal {
     38 
     39 namespace {
     40 
     41 const size_t kMaxInstances = 32;
     42 static std::mutex g_instance_mutex;
     43 static std::bitset<kMaxInstances> g_instance_used(false);
     44 static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
     45 
     46 [[noreturn]] void NoOp() {
     47     LOG_ALWAYS_FATAL("invalid stub function called");
     48 }
     49 
     50 VKAPI_ATTR VkResult
     51 EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
     52                                      uint32_t* count,
     53                                      VkExtensionProperties* /*properties*/) {
     54     *count = 0;
     55     return VK_SUCCESS;
     56 }
     57 
     58 VKAPI_ATTR VkResult
     59 EnumerateInstanceLayerProperties(uint32_t* count,
     60                                  VkLayerProperties* /*properties*/) {
     61     *count = 0;
     62     return VK_SUCCESS;
     63 }
     64 
     65 VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
     66                                    const VkAllocationCallbacks* /*allocator*/,
     67                                    VkInstance* instance) {
     68     std::lock_guard<std::mutex> lock(g_instance_mutex);
     69     for (size_t i = 0; i < kMaxInstances; i++) {
     70         if (!g_instance_used[i]) {
     71             g_instance_used[i] = true;
     72             g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
     73             *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
     74             return VK_SUCCESS;
     75         }
     76     }
     77     ALOGE("no more instances available (max=%zu)", kMaxInstances);
     78     return VK_ERROR_INITIALIZATION_FAILED;
     79 }
     80 
     81 VKAPI_ATTR void DestroyInstance(VkInstance instance,
     82                                 const VkAllocationCallbacks* /*allocator*/) {
     83     std::lock_guard<std::mutex> lock(g_instance_mutex);
     84     ssize_t idx =
     85         reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
     86     ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
     87                 "DestroyInstance: invalid instance handle");
     88     g_instance_used[static_cast<size_t>(idx)] = false;
     89 }
     90 
     91 VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
     92                                              uint32_t* count,
     93                                              VkPhysicalDevice* /*gpus*/) {
     94     *count = 0;
     95     return VK_SUCCESS;
     96 }
     97 
     98 VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
     99                                                   const char* name) {
    100     if (strcmp(name, "vkCreateInstance") == 0)
    101         return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
    102     if (strcmp(name, "vkDestroyInstance") == 0)
    103         return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
    104     if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
    105         return reinterpret_cast<PFN_vkVoidFunction>(
    106             EnumerateInstanceExtensionProperties);
    107     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
    108         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
    109     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
    110         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
    111 
    112     // None of the other Vulkan functions should ever be called, as they all
    113     // take a VkPhysicalDevice or other object obtained from a physical device.
    114     return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
    115 }
    116 
    117 }  // anonymous namespace
    118 
    119 const hwvulkan_device_t kDevice = {
    120     .common =
    121         {
    122             .tag = HARDWARE_DEVICE_TAG,
    123             .version = HWVULKAN_DEVICE_API_VERSION_0_1,
    124             .module = nullptr,
    125             .close = nullptr,
    126         },
    127     .EnumerateInstanceExtensionProperties =
    128         EnumerateInstanceExtensionProperties,
    129     .CreateInstance = CreateInstance,
    130     .GetInstanceProcAddr = GetInstanceProcAddr,
    131 };
    132 
    133 }  // namespace stubhal
    134 }  // namespace vulkan
    135