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