1 /* 2 * Copyright (C) 2017 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 <android/log.h> 18 #include <cstring> 19 #include <vulkan/vulkan.h> 20 #include "vk_layer_interface.h" 21 22 #define xstr(a) str(a) 23 #define str(a) #a 24 25 #define LOG_TAG "nullLayer" xstr(LAYERNAME) 26 27 #define ALOGI(msg, ...) \ 28 __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__) 29 30 31 // Announce if anything loads this layer. LAYERNAME is defined in Android.mk 32 class StaticLogMessage { 33 public: 34 StaticLogMessage(const char* msg) { 35 ALOGI("%s", msg); 36 } 37 }; 38 StaticLogMessage g_initMessage("nullLayer" xstr(LAYERNAME) " loaded"); 39 40 41 namespace { 42 43 44 // Minimal dispatch table for this simple layer 45 struct { 46 PFN_vkGetInstanceProcAddr GetInstanceProcAddr; 47 } g_VulkanDispatchTable; 48 49 50 template<class T> 51 VkResult getProperties(const uint32_t count, const T *properties, uint32_t *pCount, 52 T *pProperties) { 53 uint32_t copySize; 54 55 if (pProperties == NULL || properties == NULL) { 56 *pCount = count; 57 return VK_SUCCESS; 58 } 59 60 copySize = *pCount < count ? *pCount : count; 61 memcpy(pProperties, properties, copySize * sizeof(T)); 62 *pCount = copySize; 63 if (copySize < count) { 64 return VK_INCOMPLETE; 65 } 66 67 return VK_SUCCESS; 68 } 69 70 static const VkLayerProperties LAYER_PROPERTIES = { 71 "VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME), VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION), 1, "Layer: nullLayer" xstr(LAYERNAME), 72 }; 73 74 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { 75 return getProperties<VkLayerProperties>(1, &LAYER_PROPERTIES, pCount, pProperties); 76 } 77 78 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice /* physicalDevice */, uint32_t *pCount, 79 VkLayerProperties *pProperties) { 80 return getProperties<VkLayerProperties>(0, NULL, pCount, pProperties); 81 } 82 83 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char* /* pLayerName */, uint32_t *pCount, 84 VkExtensionProperties *pProperties) { 85 return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties); 86 } 87 88 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice /* physicalDevice */, const char* /* pLayerName */, 89 uint32_t *pCount, VkExtensionProperties *pProperties) { 90 return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties); 91 } 92 93 VKAPI_ATTR VkResult VKAPI_CALL nullCreateInstance(const VkInstanceCreateInfo* pCreateInfo, 94 const VkAllocationCallbacks* pAllocator, 95 VkInstance* pInstance) { 96 97 VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; 98 99 const char* msg = "nullCreateInstance called in nullLayer" xstr(LAYERNAME); 100 ALOGI("%s", msg); 101 102 // Step through the pNext chain until we get to the link function 103 while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || 104 layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) { 105 106 layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext; 107 } 108 109 if(layerCreateInfo == NULL) 110 return VK_ERROR_INITIALIZATION_FAILED; 111 112 // Grab GIPA for the next layer 113 PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; 114 115 // Track is in our dispatch table 116 g_VulkanDispatchTable.GetInstanceProcAddr = gpa; 117 118 // Advance the chain for next layer 119 layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext; 120 121 // Call the next layer 122 PFN_vkCreateInstance createFunc = (PFN_vkCreateInstance)gpa(VK_NULL_HANDLE, "vkCreateInstance"); 123 VkResult ret = createFunc(pCreateInfo, pAllocator, pInstance); 124 125 return ret; 126 } 127 128 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice /* dev */, const char* /* funcName */) { 129 return nullptr; 130 } 131 132 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) { 133 134 // Our simple layer only intercepts vkCreateInstance 135 const char* targetFunc = "vkCreateInstance"; 136 if (!strncmp(targetFunc, funcName, sizeof(&targetFunc))) 137 return (PFN_vkVoidFunction)nullCreateInstance; 138 139 return (PFN_vkVoidFunction)g_VulkanDispatchTable.GetInstanceProcAddr(instance, funcName); 140 } 141 142 } // namespace 143 144 // loader-layer interface v0, just wrappers since there is only a layer 145 146 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, 147 VkLayerProperties *pProperties) { 148 return EnumerateInstanceLayerProperties(pCount, pProperties); 149 } 150 151 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, 152 VkLayerProperties *pProperties) { 153 return EnumerateDeviceLayerProperties(physicalDevice, pCount, pProperties); 154 } 155 156 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, 157 VkExtensionProperties *pProperties) { 158 return EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); 159 } 160 161 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 162 const char *pLayerName, uint32_t *pCount, 163 VkExtensionProperties *pProperties) { 164 return EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties); 165 } 166 167 __attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { 168 return GetDeviceProcAddr(dev, funcName); 169 } 170 171 __attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { 172 return GetInstanceProcAddr(instance, funcName); 173 } 174