/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include "vk_layer_interface.h" #include #include #define xstr(a) str(a) #define str(a) #a #define LAYER_FULL_NAME "VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME) #define LOG_TAG LAYER_FULL_NAME #define ALOGI(msg, ...) \ __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__) #ifdef DEBUGUTILSPECVERSION const VkExtensionProperties debug_utils_extension = { "VK_EXT_debug_utils", static_cast(std::atoi(xstr(DEBUGUTILSPECVERSION))), }; #endif // Announce if anything loads this layer. LAYERNAME is defined in Android.mk class StaticLogMessage { public: StaticLogMessage(const char* msg) { ALOGI("%s", msg); } }; StaticLogMessage g_initMessage("VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME) " loaded"); namespace { // Minimal dispatch table for this simple layer struct { PFN_vkGetDeviceProcAddr GetDeviceProcAddr; PFN_vkGetInstanceProcAddr GetInstanceProcAddr; } g_VulkanDispatchTable; template VkResult getProperties(const uint32_t count, const T *properties, uint32_t *pCount, T *pProperties) { uint32_t copySize; if (pProperties == NULL || properties == NULL) { *pCount = count; return VK_SUCCESS; } copySize = *pCount < count ? *pCount : count; memcpy(pProperties, properties, copySize * sizeof(T)); *pCount = copySize; if (copySize < count) { return VK_INCOMPLETE; } return VK_SUCCESS; } static const VkLayerProperties LAYER_PROPERTIES = { LAYER_FULL_NAME, VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION), 1, "Layer: nullLayer" xstr(LAYERNAME), }; VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { return getProperties(1, &LAYER_PROPERTIES, pCount, pProperties); } VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice /* physicalDevice */, uint32_t *pCount, VkLayerProperties *pProperties) { return getProperties(0, NULL, pCount, pProperties); } VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char* /* pLayerName */, uint32_t *pCount, VkExtensionProperties *pProperties) { #ifdef DEBUGUTILSPECVERSION return getProperties(1, &debug_utils_extension, pCount, pProperties); #else return getProperties(0, NULL, pCount, pProperties); #endif } VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice /* physicalDevice */, const char* /* pLayerName */, uint32_t *pCount, VkExtensionProperties *pProperties) { return getProperties(0, NULL, pCount, pProperties); } VKAPI_ATTR VkResult VKAPI_CALL nullCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) { VkLayerDeviceCreateInfo *layerCreateInfo = (VkLayerDeviceCreateInfo*)pCreateInfo->pNext; const char *msg = "nullCreateDevice called in " LAYER_FULL_NAME; ALOGI("%s", msg); // Step through the pNext chain until we get to the link function while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO || layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) { layerCreateInfo = (VkLayerDeviceCreateInfo *)layerCreateInfo->pNext; } if(layerCreateInfo == NULL) return VK_ERROR_INITIALIZATION_FAILED; // Grab GDPA and GIPA for the next layer PFN_vkGetDeviceProcAddr gdpa = layerCreateInfo->u.pLayerInfo->pfnNextGetDeviceProcAddr; PFN_vkGetInstanceProcAddr gipa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; // Track them in our dispatch table g_VulkanDispatchTable.GetDeviceProcAddr = gdpa; g_VulkanDispatchTable.GetInstanceProcAddr = gipa; // Advance the chain for next layer layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext; // Call the next layer PFN_vkCreateDevice createFunc = (PFN_vkCreateDevice)gipa(VK_NULL_HANDLE, "vkCreateDevice"); VkResult ret = createFunc(physicalDevice, pCreateInfo, pAllocator, pDevice); return ret; } VKAPI_ATTR VkResult VKAPI_CALL nullCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) { VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext; const char *msg = "nullCreateInstance called in " LAYER_FULL_NAME; ALOGI("%s", msg); // Step through the pNext chain until we get to the link function while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) { layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext; } if(layerCreateInfo == NULL) return VK_ERROR_INITIALIZATION_FAILED; // Grab GIPA for the next layer PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr; // Track it in our dispatch table g_VulkanDispatchTable.GetInstanceProcAddr = gpa; // Advance the chain for next layer layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext; // Call the next layer PFN_vkCreateInstance createFunc = (PFN_vkCreateInstance)gpa(VK_NULL_HANDLE, "vkCreateInstance"); VkResult ret = createFunc(pCreateInfo, pAllocator, pInstance); return ret; } VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice dev, const char* funcName) { const char* targetFunc = "vkCreateDevice"; if (!strncmp(targetFunc, funcName, sizeof("vkCreateDevice"))) { return (PFN_vkVoidFunction)nullCreateDevice; } return (PFN_vkVoidFunction)g_VulkanDispatchTable.GetDeviceProcAddr(dev, funcName); } VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) { const char* targetFunc = "vkCreateInstance"; if (!strncmp(targetFunc, funcName, sizeof("vkCreateInstance"))) { return (PFN_vkVoidFunction)nullCreateInstance; } return (PFN_vkVoidFunction)g_VulkanDispatchTable.GetInstanceProcAddr(instance, funcName); } } // namespace // loader-layer interface v0, just wrappers since there is only a layer __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { return EnumerateInstanceLayerProperties(pCount, pProperties); } __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { return EnumerateDeviceLayerProperties(physicalDevice, pCount, pProperties); } __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { return EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } __attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { return EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties); } __attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) { return GetDeviceProcAddr(dev, funcName); } __attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { return GetInstanceProcAddr(instance, funcName); }