From 19de6b1d1667c841e98c39cfc87b01928ca7c700 Mon Sep 17 00:00:00 2001 From: baldurk Date: Sun, 20 Sep 2015 00:04:17 +0200 Subject: [PATCH] Rename rdtrace.cpp -> vk_tracelayer.cpp, remove vk_hooks_*.cpp --- renderdoc/driver/vulkan/rdtrace.cpp | 256 --------------- .../driver/vulkan/renderdoc_vulkan.vcxproj | 9 +- .../vulkan/renderdoc_vulkan.vcxproj.filters | 4 +- renderdoc/driver/vulkan/vk_hooks_linux.cpp | 310 ------------------ renderdoc/driver/vulkan/vk_hooks_win32.cpp | 261 --------------- renderdoc/driver/vulkan/vk_tracelayer.cpp | 195 +++++++++++ 6 files changed, 197 insertions(+), 838 deletions(-) delete mode 100644 renderdoc/driver/vulkan/rdtrace.cpp delete mode 100644 renderdoc/driver/vulkan/vk_hooks_linux.cpp delete mode 100644 renderdoc/driver/vulkan/vk_hooks_win32.cpp create mode 100644 renderdoc/driver/vulkan/vk_tracelayer.cpp diff --git a/renderdoc/driver/vulkan/rdtrace.cpp b/renderdoc/driver/vulkan/rdtrace.cpp deleted file mode 100644 index d3bda64f7..000000000 --- a/renderdoc/driver/vulkan/rdtrace.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Vulkan - * - * Copyright (C) 2014 LunarG, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ -#include -#include -#include -#include "LoaderAndTools/loader/vk_loader_platform.h" -#include "LoaderAndTools/build/layers/vk_dispatch_table_helper.h" -#include "vk_layer.h" -#include "LoaderAndTools/layers/vk_layer_table.h" -#include "LoaderAndTools/layers/vk_layer_extension_utils.h" -// The following is #included again to catch certain OS-specific functions -// being used: -#include "LoaderAndTools/loader/vk_loader_platform.h" - -// Renderdoc Includes - -#include "driver/vulkan/vk_common.h" -#include "driver/vulkan/vk_core.h" -#include "driver/vulkan/vk_hookset_defs.h" - -#include "common/threading.h" -#include "serialise/string_utils.h" - -// don't want these definitions, the only place we'll use these is as parameter/variable names -#ifdef near -#undef near -#endif - -#ifdef far -#undef far -#endif - -#ifdef WIN32 -#undef VK_LAYER_EXPORT -#define VK_LAYER_EXPORT extern "C" __declspec(dllexport) -#endif - -// Renderdoc State - -WrappedVulkan *shadowVulkan = NULL; - -// Layer Intercepts - -static const VkLayerProperties rdt_physicaldevice_layers[] = { - { - "Renderdoc", - VK_API_VERSION, - VK_MAKE_VERSION(0, 1, 0), - "layer: implements Renderdoc tracing", - } -}; - -VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceLayerProperties( - VkPhysicalDevice physicalDevice, - uint32_t* pCount, - VkLayerProperties* pProperties) -{ - return util_GetLayerProperties(ARRAY_SIZE(rdt_physicaldevice_layers), rdt_physicaldevice_layers, - pCount, pProperties); -} - -static const VkExtensionProperties rdt_physicaldevice_extensions[] = { - { - DEBUG_MARKER_EXTENSION_NAME, - VK_MAKE_VERSION(0, 1, 0), - } -}; - -VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionProperties( - VkPhysicalDevice physicalDevice, - const char *pLayerName, - uint32_t *pCount, - VkExtensionProperties *pProperties) -{ - return util_GetExtensionProperties(ARRAY_SIZE(rdt_physicaldevice_extensions), rdt_physicaldevice_extensions, - pCount, pProperties); -} - -static const VkLayerProperties rdt_GlobalLayers[] = { - { - "Renderdoc", - VK_API_VERSION, - VK_MAKE_VERSION(0, 1, 0), - "Trace layer: Renderdoc", - } -}; - -VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalLayerProperties( - uint32_t *pCount, - VkLayerProperties* pProperties) -{ - return util_GetLayerProperties(ARRAY_SIZE(rdt_GlobalLayers), - rdt_GlobalLayers, - pCount, pProperties); -} - -#ifdef WIN32 -#undef VK_LAYER_EXPORT -#define VK_LAYER_EXPORT -#endif - -// Renderdoc Intercepts - -#define HookDefine0(ret, function) \ - VK_LAYER_EXPORT \ - ret VKAPI function() \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(); } -#define HookDefine1(ret, function, t1, p1) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1); } -#define HookDefine2(ret, function, t1, p1, t2, p2) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2); } -#define HookDefine3(ret, function, t1, p1, t2, p2, t3, p3) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3); } -#define HookDefine4(ret, function, t1, p1, t2, p2, t3, p3, t4, p4) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4); } -#define HookDefine5(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5); } -#define HookDefine6(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6); } -#define HookDefine7(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7); } -#define HookDefine8(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8); } -#define HookDefine9(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9); } -#define HookDefine10(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } -#define HookDefine11(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } -#define HookDefine12(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } -#define HookDefine13(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12, t13, p13) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } -#define HookDefine14(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12, t13, p13, t14, p14) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13, t14 p14) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } -#define HookDefine15(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12, t13, p13, t14, p14, t15, p15) \ - VK_LAYER_EXPORT \ - ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13, t14 p14, t15 p15) \ - { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } - -Threading::CriticalSection vkLock; - -DefineHooks(); - -#undef HookInit -#define HookInit(function) if (!strcmp(pName, STRINGIZE(function))) return (PFN_vkVoidFunction) function; - -#ifdef WIN32 -#undef VK_LAYER_EXPORT -#define VK_LAYER_EXPORT extern "C" __declspec(dllexport) -#endif - -// proc addr routines - -VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* pName) -{ - if (device == NULL) - return NULL; - - /* loader uses this to force layer initialization; device object is wrapped */ - if (!strcmp("vkGetDeviceProcAddr", pName)) { - initDeviceTable(renderdoc_device_table_map, (const VkBaseLayerObject *) device); - return (PFN_vkVoidFunction) vkGetDeviceProcAddr; - } - - HookInitVulkanDevice(); - - if (!strcmp("vkCreateDevice", pName)) - return (PFN_vkVoidFunction) vkCreateDevice; - if (!strcmp("vkDestroyDevice", pName)) - return (PFN_vkVoidFunction) vkDestroyDevice; - else - { - if (get_dispatch_table(renderdoc_device_table_map, device)->GetDeviceProcAddr == NULL) - return NULL; - return get_dispatch_table(renderdoc_device_table_map, device)->GetDeviceProcAddr(device, pName); - } -} - -VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* pName) -{ - if (instance == NULL) - return NULL; - - /* loader uses this to force layer initialization; instance object is wrapped */ - if (!strcmp("vkGetInstanceProcAddr", pName)) { - initInstanceTable(renderdoc_instance_table_map, (const VkBaseLayerObject *) instance); - if (shadowVulkan == NULL) { - shadowVulkan = new WrappedVulkan(""); - } - return (PFN_vkVoidFunction) vkGetInstanceProcAddr; - } - - HookInitVulkanInstance(); - - if (!strcmp("vkGetPhysicalDeviceLayerProperties", pName)) - return (PFN_vkVoidFunction) vkGetPhysicalDeviceLayerProperties; - if (!strcmp("vkGetPhysicalDeviceExtensionProperties", pName)) - return (PFN_vkVoidFunction) vkGetPhysicalDeviceExtensionProperties; - if (!strcmp("vkGetGlobalLayerProperties", pName)) - return (PFN_vkVoidFunction) vkGetGlobalLayerProperties; - - if (get_dispatch_table(renderdoc_instance_table_map, instance)->GetInstanceProcAddr == NULL) - return NULL; - return get_dispatch_table(renderdoc_instance_table_map, instance)->GetInstanceProcAddr(instance, pName); -} - diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj index 5dcb87505..2528152af 100644 --- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj +++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj @@ -21,17 +21,10 @@ - + - - true - - - true - true - diff --git a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters index eff2c2b58..3b689803e 100644 --- a/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters +++ b/renderdoc/driver/vulkan/renderdoc_vulkan.vcxproj.filters @@ -7,18 +7,16 @@ - - - ext ext + diff --git a/renderdoc/driver/vulkan/vk_hooks_linux.cpp b/renderdoc/driver/vulkan/vk_hooks_linux.cpp deleted file mode 100644 index 1717aacaa..000000000 --- a/renderdoc/driver/vulkan/vk_hooks_linux.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/****************************************************************************** - * The MIT License (MIT) - * - * Copyright (c) 2015 Baldur Karlsson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - ******************************************************************************/ - -#include -#include - -#include "hooks/hooks.h" - -#include "driver/vulkan/vk_common.h" -#include "driver/vulkan/vk_hookset.h" -#include "driver/vulkan/vk_core.h" - -#include "common/threading.h" -#include "serialise/string_utils.h" - -void *libvulkandlsymHandle = RTLD_NEXT; // default to RTLD_NEXT, but overwritten if app calls dlopen() on real libvulkan - -// don't want these definitions, the only place we'll use these is as parameter/variable names -#ifdef near -#undef near -#endif - -#ifdef far -#undef far -#endif - -// the _renderdoc_hooked variants are to make sure we always have a function symbol -// exported that we can return from GetProcAddr. If another library (or the app) -// creates a symbol called 'vkCreateImage' we'll return the address of that, and break -// badly. Instead we leave the 'naked' versions for applications trying to import those -// symbols, and declare the _renderdoc_hooked for returning as a func pointer. - -#define HookDefine0(ret, function) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function() \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(); } \ - ret CONCAT(function,_renderdoc_hooked)() \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(); } -#define HookDefine1(ret, function, t1, p1) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1); } -#define HookDefine2(ret, function, t1, p1, t2, p2) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2); } -#define HookDefine3(ret, function, t1, p1, t2, p2, t3, p3) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3); } -#define HookDefine4(ret, function, t1, p1, t2, p2, t3, p3, t4, p4) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4); } -#define HookDefine5(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5); } -#define HookDefine6(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6); } -#define HookDefine7(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7); } -#define HookDefine8(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8); } -#define HookDefine9(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9); } -#define HookDefine10(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } -#define HookDefine11(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } -#define HookDefine12(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } -#define HookDefine13(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12, t13, p13) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } -#define HookDefine14(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12, t13, p13, t14, p14) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13, t14 p14) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13, t14 p14) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); } -#define HookDefine15(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8, t9, p9, t10, p10, t11, p11, t12, p12, t13, p13, t14, p14, t15, p15) \ - extern "C" __attribute__ ((visibility ("default"))) \ - ret function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13, t14 p14, t15 p15) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } \ - ret CONCAT(function,_renderdoc_hooked)(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9, t10 p10, t11 p11, t12 p12, t13 p13, t14 p14, t15 p15) \ - { SCOPED_LOCK(vkLock); return VulkanHook::vkhooks.GetDriver()->function(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); } - -Threading::CriticalSection vkLock; - -class VulkanHook : LibraryHook -{ - public: - VulkanHook() - { - LibraryHooks::GetInstance().RegisterHook("libvulkan.so", this); - - RDCEraseEl(VK); - - GPA_Instance = (PFN_vkGetInstanceProcAddr)NULL; - GPA_Device = (PFN_vkGetDeviceProcAddr)NULL; - - m_Vulkan = NULL; - - m_EnabledHooks = true; - m_PopulatedHooks = false; - } - ~VulkanHook() - { - delete m_Vulkan; - } - - static void libHooked(void *realLib) - { - libvulkandlsymHandle = realLib; - VulkanHook::vkhooks.CreateHooks(NULL); - } - - bool CreateHooks(const char *libName) - { - if(!m_EnabledHooks) - return false; - - if(libName) - LinuxHookLibrary("libvulkan.so", &libHooked); - - bool success = SetupHooks(VK); - - if(!success) return false; - - m_HasHooks = true; - - return true; - } - - void EnableHooks(const char *libName, bool enable) - { - m_EnabledHooks = enable; - } - - static VulkanHook vkhooks; - - const VulkanFunctions &GetRealVKFunctions() - { - libvulkandlsymHandle = dlopen("libvulkan.so", RTLD_NOW); - SetupHooks(VK); - return VK; - } - - WrappedVulkan *GetDriver() - { - if(m_Vulkan == NULL) - m_Vulkan = new WrappedVulkan(VK, ""); - - return m_Vulkan; - } - - WrappedVulkan *m_Vulkan; - - VulkanFunctions VK; - - PFN_vkGetInstanceProcAddr GPA_Instance; - PFN_vkGetDeviceProcAddr GPA_Device; - - bool m_PopulatedHooks; - bool m_HasHooks; - bool m_EnabledHooks; - - bool SetupHooks(VulkanFunctions &VK); -}; - -DefineHooks(); - -void PopulateDeviceHooks(VkDevice d, VkInstance i) -{ -#define HACK_WSI(func) VulkanHook::vkhooks.VK.func = (CONCAT(PFN_, func))VulkanHook::vkhooks.GPA_Device(d, STRINGIZE(func)); - HACK_WSI(vkCreateSwapChainWSI) - HACK_WSI(vkDestroySwapChainWSI) - HACK_WSI(vkGetSwapChainInfoWSI) - HACK_WSI(vkGetSurfaceInfoWSI) - HACK_WSI(vkAcquireNextImageWSI) - HACK_WSI(vkQueuePresentWSI) -#undef HACK_WSI - -#define HACK_DBG(func) VulkanHook::vkhooks.VK.func = (CONCAT(PFN_, func))VulkanHook::vkhooks.GPA_Instance(i, STRINGIZE(func)); - HACK_DBG(vkDbgCreateMsgCallback) - HACK_DBG(vkDbgDestroyMsgCallback) -#undef HACK_DBG -} - -bool VulkanHook::SetupHooks(VulkanFunctions &VK) -{ - bool success = true; - -#undef HookInit -#define HookInit(function) if(VK.function == NULL) { VK.function = (CONCAT(PFN_, function))dlsym(libvulkandlsymHandle, STRINGIZE(function)); } - - HookInitVulkan(); - - if(GPA_Instance == NULL) GPA_Instance = (PFN_vkGetInstanceProcAddr)dlsym(libvulkandlsymHandle, "vkGetInstanceProcAddr"); - if(GPA_Device == NULL) GPA_Device = (PFN_vkGetDeviceProcAddr)dlsym(libvulkandlsymHandle, "vkGetDeviceProcAddr"); - - return success; -} - -extern "C" __attribute__ ((visibility ("default"))) -PFN_vkVoidFunction vkGetInstanceProcAddr( - VkInstance instance, - const char* pName) -{ - PFN_vkVoidFunction realFunc = VulkanHook::vkhooks.GPA_Instance(instance, pName); - -#undef HookInit -#define HookInit(function) if(!strcmp(pName, STRINGIZE(function))) { if(VulkanHook::vkhooks.VK.function == NULL) VulkanHook::vkhooks.VK.function = (CONCAT(PFN_, function))realFunc; return (PFN_vkVoidFunction)CONCAT(function, _renderdoc_hooked); } - - // VKTODOLOW do we want to care about the case where different instances have - // different function pointers? at the moment we assume they're all the - // same. - // Update - will be fixed by dispatch mechanism - HookInitVulkan(); - - RDCDEBUG("Instance GPA'd function '%s' is not hooked!", pName); - return realFunc; -} - -extern "C" __attribute__ ((visibility ("default"))) -PFN_vkVoidFunction vkGetDeviceProcAddr( - VkDevice device, - const char* pName) -{ - PFN_vkVoidFunction realFunc = VulkanHook::vkhooks.GPA_Device(device, pName); - -#undef HookInit -#define HookInit(function) if(!strcmp(pName, STRINGIZE(function))) { if(VulkanHook::vkhooks.VK.function == NULL) VulkanHook::vkhooks.VK.function = (CONCAT(PFN_, function))realFunc; return (PFN_vkVoidFunction)CONCAT(function, _renderdoc_hooked); } - - // VKTODOLOW do we want to care about the case where different devices have - // different function pointers? at the moment we assume they're all the - // same. - // Update - will be fixed by dispatch mechanism - HookInitVulkan(); - - RDCDEBUG("Device GPA'd function '%s' is not hooked!", pName); - return realFunc; -} - -VulkanHook VulkanHook::vkhooks; - -const VulkanFunctions &GetRealVKFunctions() { return VulkanHook::vkhooks.GetRealVKFunctions(); } diff --git a/renderdoc/driver/vulkan/vk_hooks_win32.cpp b/renderdoc/driver/vulkan/vk_hooks_win32.cpp deleted file mode 100644 index 679e3ea4c..000000000 --- a/renderdoc/driver/vulkan/vk_hooks_win32.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/****************************************************************************** - * The MIT License (MIT) - * - * Copyright (c) 2015 Baldur Karlsson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - ******************************************************************************/ - -#include "vk_common.h" -#include "vk_hookset.h" -#include "vk_core.h" -#include "hooks/hooks.h" - -#define DLL_NAME "vulkan.0.dll" - -Threading::CriticalSection vulkanLock; - -class VulkanHook : LibraryHook -{ - public: - VulkanHook() - { - LibraryHooks::GetInstance().RegisterHook(DLL_NAME, this); - - m_Driver = NULL; - - m_EnabledHooks = true; - m_PopulatedHooks = false; - } - ~VulkanHook() - { - delete m_Driver; - } - - bool CreateHooks(const char *dllName) - { - RDCEraseEl(VK); - - if(!m_EnabledHooks) - return false; - - bool success = SetupHooks(VK); - - if(!success) return false; - - m_HasHooks = true; - - return true; - } - - void EnableHooks(const char *dllName, bool enable) - { - m_EnabledHooks = enable; - } - - static VulkanHook vkhooks; - - const VulkanFunctions &GetRealVKFunctions() - { - LoadLibraryA("vulkan.0.dll"); - if(!m_PopulatedHooks) - { - PopulateHooks(); - m_PopulatedHooks = true; - } - return VK; - } - - void PopulateDeviceHooks(VkDevice d, VkInstance i) - { -#define HACK_WSI(func) VK.func = (CONCAT(PFN_, func))GPA_Device()(d, STRINGIZE(func)); - HACK_WSI(vkCreateSwapChainWSI) - HACK_WSI(vkDestroySwapChainWSI) - HACK_WSI(vkGetSwapChainInfoWSI) - HACK_WSI(vkGetSurfaceInfoWSI) - HACK_WSI(vkAcquireNextImageWSI) - HACK_WSI(vkQueuePresentWSI) -#undef HACK_WSI - -#define HACK_DBG(func) VK.func = (CONCAT(PFN_, func))GPA_Instance()(i, STRINGIZE(func)); - HACK_DBG(vkDbgCreateMsgCallback) - HACK_DBG(vkDbgDestroyMsgCallback) -#undef HACK_DBG - } - - private: - WrappedVulkan *GetDriver() - { - if(m_Driver == NULL) - m_Driver = new WrappedVulkan(VK, ""); - - GetRealVKFunctions(); - - return m_Driver; - } - - WrappedVulkan *m_Driver; - - VulkanFunctions VK; - - Hook GPA_Instance; - Hook GPA_Device; - - bool m_PopulatedHooks; - bool m_HasHooks; - bool m_EnabledHooks; - - bool PopulateHooks() - { -#undef HookInit -#define HookInit(funcname) \ - if(!VK.funcname) VK.funcname = (CONCAT(PFN_, funcname))Process::GetFunctionAddress(DLL_NAME, STRINGIZE(funcname)); - - HookInitVulkan() - - if(GPA_Instance() == NULL) GPA_Instance.SetFuncPtr(Process::GetFunctionAddress(DLL_NAME, "vkGetInstanceProcAddr")); - if(GPA_Device() == NULL) GPA_Device.SetFuncPtr(Process::GetFunctionAddress(DLL_NAME, "vkGetDeviceProcAddr")); - - return true; - } - - static PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr_hooked( - VkInstance instance, - const char* pName) - { - PFN_vkVoidFunction realFunc = VulkanHook::vkhooks.GPA_Instance()(instance, pName); - -#undef HookInit -#define HookInit(function) if(!strcmp(pName, STRINGIZE(function))) { if(vkhooks.VK.function == NULL) vkhooks.VK.function = (CONCAT(PFN_, function))realFunc; return (PFN_vkVoidFunction)CONCAT(hooked_, function); } - - // VKTODOLOW do we want to care about the case where different instances have - // different function pointers? at the moment we assume they're all the - // same. - // Update - will be fixed by dispatch mechanism - HookInitVulkan(); - - RDCDEBUG("Instance GPA'd function '%s' is not hooked!", pName); - return realFunc; - } - - static PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr_hooked( - VkDevice device, - const char* pName) - { - PFN_vkVoidFunction realFunc = VulkanHook::vkhooks.GPA_Device()(device, pName); - -#undef HookInit -#define HookInit(function) if(!strcmp(pName, STRINGIZE(function))) { if(vkhooks.VK.function == NULL) vkhooks.VK.function = (CONCAT(PFN_, function))realFunc; return (PFN_vkVoidFunction)CONCAT(hooked_, function); } - - // VKTODOLOW do we want to care about the case where different instances have - // different function pointers? at the moment we assume they're all the - // same. - // Update - will be fixed by dispatch mechanism - HookInitVulkan(); - - RDCDEBUG("Device GPA'd function '%s' is not hooked!", pName); - return realFunc; - } - - bool SetupHooks(VulkanFunctions &GL) - { - bool success = true; - -#undef HookInit -#define HookInit(funcname) \ - success &= CONCAT(hook_, funcname).Initialize(STRINGIZE(funcname), DLL_NAME, &CONCAT(hooked_, funcname)); \ - VK.funcname = CONCAT(hook_, funcname)(); - - HookInitVulkan() - - success &= GPA_Instance.Initialize("vkGetInstanceProcAddr", DLL_NAME, vkGetInstanceProcAddr_hooked); - success &= GPA_Device.Initialize("vkGetDeviceProcAddr", DLL_NAME, vkGetDeviceProcAddr_hooked); - - return success; - } - -// implement hooks -#undef HookDefine1 -#undef HookDefine2 -#undef HookDefine3 -#undef HookDefine4 -#undef HookDefine5 -#undef HookDefine6 -#undef HookDefine7 - -#define HookDefine1(ret, funcname, t0, p0) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0); \ - } -#define HookDefine2(ret, funcname, t0, p0, t1, p1) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1); \ - } -#define HookDefine3(ret, funcname, t0, p0, t1, p1, t2, p2) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1, t2 p2) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1, p2); \ - } -#define HookDefine4(ret, funcname, t0, p0, t1, p1, t2, p2, t3, p3) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1, t2 p2, t3 p3) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1, p2, p3); \ - } -#define HookDefine5(ret, funcname, t0, p0, t1, p1, t2, p2, t3, p3, t4, p4) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1, t2 p2, t3 p3, t4 p4) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1, p2, p3, p4); \ - } -#define HookDefine6(ret, funcname, t0, p0, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1, p2, p3, p4, p5); \ - } -#define HookDefine7(ret, funcname, t0, p0, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1, p2, p3, p4, p5, p6); \ - } -#define HookDefine8(ret, funcname, t0, p0, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7) \ - Hook CONCAT(hook_, funcname); \ - static ret VKAPI CONCAT(hooked_, funcname)(t0 p0, t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) \ - { \ - SCOPED_LOCK(vulkanLock); return vkhooks.GetDriver()->funcname(p0, p1, p2, p3, p4, p5, p6, p7); \ - } - - DefineHooks() -}; - -VulkanHook VulkanHook::vkhooks; - -void PopulateDeviceHooks(VkDevice d, VkInstance i) -{ - VulkanHook::vkhooks.PopulateDeviceHooks(d, i); -} - -const VulkanFunctions &GetRealVKFunctions() { return VulkanHook::vkhooks.GetRealVKFunctions(); } diff --git a/renderdoc/driver/vulkan/vk_tracelayer.cpp b/renderdoc/driver/vulkan/vk_tracelayer.cpp new file mode 100644 index 000000000..d13ee0545 --- /dev/null +++ b/renderdoc/driver/vulkan/vk_tracelayer.cpp @@ -0,0 +1,195 @@ +/* + * Vulkan + * + * Copyright (C) 2014 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "vk_layer.h" +#include "LoaderAndTools/layers/vk_layer_table.h" +#include "LoaderAndTools/layers/vk_layer_extension_utils.h" + +// RenderDoc Includes + +#include "driver/vulkan/vk_common.h" +#include "driver/vulkan/vk_core.h" +#include "driver/vulkan/vk_hookset_defs.h" + +#include "common/threading.h" + +// this should be in the vulkan definition header +#ifdef WIN32 +#undef VK_LAYER_EXPORT +#define VK_LAYER_EXPORT extern "C" __declspec(dllexport) +#endif + +// RenderDoc State + +WrappedVulkan *shadowVulkan = NULL; + +// RenderDoc Intercepts + +#define HookDefine0(ret, function) \ + ret VKAPI function() \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(); } +#define HookDefine1(ret, function, t1, p1) \ + ret VKAPI function(t1 p1) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1); } +#define HookDefine2(ret, function, t1, p1, t2, p2) \ + ret VKAPI function(t1 p1, t2 p2) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2); } +#define HookDefine3(ret, function, t1, p1, t2, p2, t3, p3) \ + ret VKAPI function(t1 p1, t2 p2, t3 p3) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3); } +#define HookDefine4(ret, function, t1, p1, t2, p2, t3, p3, t4, p4) \ + ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4); } +#define HookDefine5(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5) \ + ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5); } +#define HookDefine6(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6) \ + ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6); } +#define HookDefine7(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7) \ + ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7); } +#define HookDefine8(ret, function, t1, p1, t2, p2, t3, p3, t4, p4, t5, p5, t6, p6, t7, p7, t8, p8) \ + ret VKAPI function(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) \ + { SCOPED_LOCK(vkLock); return shadowVulkan->function(p1, p2, p3, p4, p5, p6, p7, p8); } + +Threading::CriticalSection vkLock; + +DefineHooks(); + +// Layer Intercepts + +static const VkLayerProperties rdt_physicaldevice_layers[] = { + { + "RenderDoc", + VK_API_VERSION, + VK_MAKE_VERSION(RENDERDOC_VERSION_MAJOR, RENDERDOC_VERSION_MINOR, 0), + "layer: implements RenderDoc tracing", + } +}; + +VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceLayerProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pCount, + VkLayerProperties* pProperties) +{ + return util_GetLayerProperties(ARRAY_SIZE(rdt_physicaldevice_layers), rdt_physicaldevice_layers, + pCount, pProperties); +} + +static const VkExtensionProperties rdt_physicaldevice_extensions[] = { + { + DEBUG_MARKER_EXTENSION_NAME, + VK_MAKE_VERSION(0, 1, 0), + } +}; + +VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionProperties( + VkPhysicalDevice physicalDevice, + const char *pLayerName, + uint32_t *pCount, + VkExtensionProperties *pProperties) +{ + return util_GetExtensionProperties(ARRAY_SIZE(rdt_physicaldevice_extensions), rdt_physicaldevice_extensions, + pCount, pProperties); +} + +static const VkLayerProperties rdt_GlobalLayers[] = { + { + "RenderDoc", + VK_API_VERSION, + VK_MAKE_VERSION(RENDERDOC_VERSION_MAJOR, RENDERDOC_VERSION_MINOR, 0), + "Debugging capture layer for RenderDoc", + } +}; + +VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalLayerProperties( + uint32_t *pCount, + VkLayerProperties* pProperties) +{ + return util_GetLayerProperties(ARRAY_SIZE(rdt_GlobalLayers), + rdt_GlobalLayers, + pCount, pProperties); +} + +#undef HookInit +#define HookInit(function) if (!strcmp(pName, STRINGIZE(function))) return (PFN_vkVoidFunction) function; + +// proc addr routines + +VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* pName) +{ + if (device == NULL) + return NULL; + + /* loader uses this to force layer initialization; device object is wrapped */ + if (!strcmp("vkGetDeviceProcAddr", pName)) { + initDeviceTable(renderdoc_device_table_map, (const VkBaseLayerObject *) device); + return (PFN_vkVoidFunction) vkGetDeviceProcAddr; + } + + HookInitVulkanDevice(); + + if (!strcmp("vkCreateDevice", pName)) + return (PFN_vkVoidFunction) vkCreateDevice; + if (!strcmp("vkDestroyDevice", pName)) + return (PFN_vkVoidFunction) vkDestroyDevice; + else + { + if (get_dispatch_table(renderdoc_device_table_map, device)->GetDeviceProcAddr == NULL) + return NULL; + return get_dispatch_table(renderdoc_device_table_map, device)->GetDeviceProcAddr(device, pName); + } +} + +VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* pName) +{ + if (instance == NULL) + return NULL; + + /* loader uses this to force layer initialization; instance object is wrapped */ + if (!strcmp("vkGetInstanceProcAddr", pName)) { + initInstanceTable(renderdoc_instance_table_map, (const VkBaseLayerObject *) instance); + if (shadowVulkan == NULL) { + shadowVulkan = new WrappedVulkan(""); + } + return (PFN_vkVoidFunction) vkGetInstanceProcAddr; + } + + HookInitVulkanInstance(); + + if (!strcmp("vkGetPhysicalDeviceLayerProperties", pName)) + return (PFN_vkVoidFunction) vkGetPhysicalDeviceLayerProperties; + if (!strcmp("vkGetPhysicalDeviceExtensionProperties", pName)) + return (PFN_vkVoidFunction) vkGetPhysicalDeviceExtensionProperties; + if (!strcmp("vkGetGlobalLayerProperties", pName)) + return (PFN_vkVoidFunction) vkGetGlobalLayerProperties; + + if (get_dispatch_table(renderdoc_instance_table_map, instance)->GetInstanceProcAddr == NULL) + return NULL; + return get_dispatch_table(renderdoc_instance_table_map, instance)->GetInstanceProcAddr(instance, pName); +} +