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 <cstring>
18 #include <string>
19 
20 #include "vk_layer_interface.h"
21 #include <android/log.h>
22 #include <vulkan/vulkan.h>
23 
24 #define xstr(a) str(a)
25 #define str(a) #a
26 
27 #define LAYER_FULL_NAME "VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME)
28 #define LOG_TAG LAYER_FULL_NAME
29 
30 #define ALOGI(msg, ...) \
31     __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
32 
33 #ifdef DEBUGUTILSPECVERSION
34 const VkExtensionProperties debug_utils_extension = {
35     "VK_EXT_debug_utils",
36     static_cast<uint32_t>(std::atoi(xstr(DEBUGUTILSPECVERSION))),
37 };
38 #endif
39 
40 // Announce if anything loads this layer.  LAYERNAME is defined in Android.mk
41 class StaticLogMessage {
42     public:
StaticLogMessage(const char * msg)43         StaticLogMessage(const char* msg) {
44             ALOGI("%s", msg);
45     }
46 };
47 StaticLogMessage
48     g_initMessage("VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME) " loaded");
49 
50 namespace {
51 
52 
53 // Minimal dispatch table for this simple layer
54 struct {
55     PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
56     PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
57 } g_VulkanDispatchTable;
58 
59 template<class T>
getProperties(const uint32_t count,const T * properties,uint32_t * pCount,T * pProperties)60 VkResult getProperties(const uint32_t count, const T *properties, uint32_t *pCount,
61                             T *pProperties) {
62     uint32_t copySize;
63 
64     if (pProperties == NULL || properties == NULL) {
65         *pCount = count;
66         return VK_SUCCESS;
67     }
68 
69     copySize = *pCount < count ? *pCount : count;
70     memcpy(pProperties, properties, copySize * sizeof(T));
71     *pCount = copySize;
72     if (copySize < count) {
73         return VK_INCOMPLETE;
74     }
75 
76     return VK_SUCCESS;
77 }
78 
79 static const VkLayerProperties LAYER_PROPERTIES = {
80     LAYER_FULL_NAME,
81     VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION),
82     1,
83     "Layer: nullLayer" xstr(LAYERNAME),
84 };
85 
EnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)86 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
87     return getProperties<VkLayerProperties>(1, &LAYER_PROPERTIES, pCount, pProperties);
88 }
89 
EnumerateDeviceLayerProperties(VkPhysicalDevice,uint32_t * pCount,VkLayerProperties * pProperties)90 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice /* physicalDevice */, uint32_t *pCount,
91                                                               VkLayerProperties *pProperties) {
92     return getProperties<VkLayerProperties>(0, NULL, pCount, pProperties);
93 }
94 
EnumerateInstanceExtensionProperties(const char *,uint32_t * pCount,VkExtensionProperties * pProperties)95 VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char* /* pLayerName */, uint32_t *pCount,
96                                                                     VkExtensionProperties *pProperties) {
97 #ifdef DEBUGUTILSPECVERSION
98   return getProperties<VkExtensionProperties>(1, &debug_utils_extension, pCount,
99                                               pProperties);
100 #else
101   return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
102 #endif
103 }
104 
EnumerateDeviceExtensionProperties(VkPhysicalDevice,const char *,uint32_t * pCount,VkExtensionProperties * pProperties)105 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice /* physicalDevice */, const char* /* pLayerName */,
106                                                                   uint32_t *pCount, VkExtensionProperties *pProperties) {
107     return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
108 }
109 
nullCreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)110 VKAPI_ATTR VkResult VKAPI_CALL nullCreateDevice(VkPhysicalDevice physicalDevice,
111                                                 const VkDeviceCreateInfo* pCreateInfo,
112                                                 const VkAllocationCallbacks* pAllocator,
113                                                 VkDevice* pDevice) {
114     VkLayerDeviceCreateInfo *layerCreateInfo = (VkLayerDeviceCreateInfo*)pCreateInfo->pNext;
115     const char *msg = "nullCreateDevice called in " LAYER_FULL_NAME;
116     ALOGI("%s", msg);
117 
118     // Step through the pNext chain until we get to the link function
119     while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO ||
120                               layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) {
121       layerCreateInfo = (VkLayerDeviceCreateInfo *)layerCreateInfo->pNext;
122     }
123 
124     if(layerCreateInfo == NULL)
125       return VK_ERROR_INITIALIZATION_FAILED;
126 
127     // Grab GDPA and GIPA for the next layer
128     PFN_vkGetDeviceProcAddr gdpa = layerCreateInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr;
129     PFN_vkGetInstanceProcAddr gipa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
130 
131     // Track them in our dispatch table
132     g_VulkanDispatchTable.GetDeviceProcAddr = gdpa;
133     g_VulkanDispatchTable.GetInstanceProcAddr = gipa;
134 
135     // Advance the chain for next layer
136     layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext;
137 
138     // Call the next layer
139     PFN_vkCreateDevice createFunc = (PFN_vkCreateDevice)gipa(VK_NULL_HANDLE, "vkCreateDevice");
140     VkResult ret = createFunc(physicalDevice, pCreateInfo, pAllocator, pDevice);
141 
142     return ret;
143 }
144 
nullCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)145 VKAPI_ATTR VkResult VKAPI_CALL nullCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
146                                                   const VkAllocationCallbacks* pAllocator,
147                                                   VkInstance* pInstance) {
148     VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
149     const char *msg = "nullCreateInstance called in " LAYER_FULL_NAME;
150     ALOGI("%s", msg);
151 
152     // Step through the pNext chain until we get to the link function
153     while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
154                               layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) {
155       layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext;
156     }
157 
158     if(layerCreateInfo == NULL)
159       return VK_ERROR_INITIALIZATION_FAILED;
160 
161     // Grab GIPA for the next layer
162     PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
163 
164     // Track it in our dispatch table
165     g_VulkanDispatchTable.GetInstanceProcAddr = gpa;
166 
167     // Advance the chain for next layer
168     layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext;
169 
170     // Call the next layer
171     PFN_vkCreateInstance createFunc = (PFN_vkCreateInstance)gpa(VK_NULL_HANDLE, "vkCreateInstance");
172     VkResult ret = createFunc(pCreateInfo, pAllocator, pInstance);
173 
174     return ret;
175 }
176 
GetDeviceProcAddr(VkDevice dev,const char * funcName)177 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char* funcName) {
178 
179     const char* targetFunc = "vkCreateDevice";
180     if (!strncmp(targetFunc, funcName, sizeof("vkCreateDevice"))) {
181         return (PFN_vkVoidFunction)nullCreateDevice;
182     }
183 
184     return (PFN_vkVoidFunction)g_VulkanDispatchTable.GetDeviceProcAddr(dev, funcName);
185 }
186 
GetInstanceProcAddr(VkInstance instance,const char * funcName)187 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) {
188 
189     const char* targetFunc = "vkCreateInstance";
190     if (!strncmp(targetFunc, funcName, sizeof("vkCreateInstance"))) {
191         return (PFN_vkVoidFunction)nullCreateInstance;
192     }
193 
194     return (PFN_vkVoidFunction)g_VulkanDispatchTable.GetInstanceProcAddr(instance, funcName);
195 }
196 
197 }  // namespace
198 
199 // loader-layer interface v0, just wrappers since there is only a layer
200 
vkEnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)201 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
202                                                                   VkLayerProperties *pProperties) {
203     return EnumerateInstanceLayerProperties(pCount, pProperties);
204 }
205 
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pCount,VkLayerProperties * pProperties)206 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
207                                                                 VkLayerProperties *pProperties) {
208     return EnumerateDeviceLayerProperties(physicalDevice, pCount, pProperties);
209 }
210 
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)211 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
212                                                                       VkExtensionProperties *pProperties) {
213     return EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
214 }
215 
vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)216 __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
217                                                                     const char *pLayerName, uint32_t *pCount,
218                                                                     VkExtensionProperties *pProperties) {
219     return EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
220 }
221 
vkGetDeviceProcAddr(VkDevice dev,const char * funcName)222 __attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
223     return GetDeviceProcAddr(dev, funcName);
224 }
225 
vkGetInstanceProcAddr(VkInstance instance,const char * funcName)226 __attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
227     return GetInstanceProcAddr(instance, funcName);
228 }
229