From 614457fab7c509cbce19a520e71c83d002a19fcc Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Sat, 5 Jul 2025 16:03:00 +0200 Subject: [PATCH] move to vulkan layer --- VkLayer_LS_frame_generation.json | 15 + include/hooks.hpp | 8 +- include/layer.hpp | 214 +++++++++++++ include/loader/dl.hpp | 133 -------- include/loader/vk.hpp | 58 ---- include/utils/utils.hpp | 10 + src/context.cpp | 13 +- src/hooks.cpp | 98 +++--- src/init.cpp | 27 -- src/layer.cpp | 527 +++++++++++++++++++++++++++++++ src/loader/dl.cpp | 182 ----------- src/loader/vk.cpp | 109 ------- src/mini/commandbuffer.cpp | 11 +- src/mini/commandpool.cpp | 5 +- src/mini/image.cpp | 20 +- src/mini/semaphore.cpp | 14 +- src/utils/utils.cpp | 37 ++- 17 files changed, 876 insertions(+), 605 deletions(-) create mode 100644 VkLayer_LS_frame_generation.json create mode 100644 include/layer.hpp delete mode 100644 include/loader/dl.hpp delete mode 100644 include/loader/vk.hpp delete mode 100644 src/init.cpp create mode 100644 src/layer.cpp delete mode 100644 src/loader/dl.cpp delete mode 100644 src/loader/vk.cpp diff --git a/VkLayer_LS_frame_generation.json b/VkLayer_LS_frame_generation.json new file mode 100644 index 0000000..e7040ff --- /dev/null +++ b/VkLayer_LS_frame_generation.json @@ -0,0 +1,15 @@ +{ + "file_format_version": "1.0.0", + "layer": { + "name": "VK_LAYER_LS_frame_generation", + "type": "GLOBAL", + "api_version": "1.4.313", + "library_path": "./build/liblsfg-vk.so", + "implementation_version": "1", + "description": "Lossless Scaling frame generation layer", + "functions": { + "vkGetInstanceProcAddr": "layer_vkGetInstanceProcAddr", + "vkGetDeviceProcAddr": "layer_vkGetDeviceProcAddr" + } + } +} diff --git a/include/hooks.hpp b/include/hooks.hpp index 0758e21..8e66dc5 100644 --- a/include/hooks.hpp +++ b/include/hooks.hpp @@ -3,7 +3,9 @@ #include +#include #include +#include namespace Hooks { @@ -15,10 +17,8 @@ namespace Hooks { uint64_t frameGen; // amount of frames to generate }; - /// - /// Install overrides for hooked Vulkan functions. - /// - void initialize(); + /// Map of hooked Vulkan functions. + extern std::unordered_map hooks; } diff --git a/include/layer.hpp b/include/layer.hpp new file mode 100644 index 0000000..e43b265 --- /dev/null +++ b/include/layer.hpp @@ -0,0 +1,214 @@ +#ifndef LAYER_HPP +#define LAYER_HPP + +#include + +namespace Layer { + /// Call to the original vkCreateInstance function. + VkResult ovkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance); + /// Call to the original vkDestroyInstance function. + void ovkDestroyInstance( + VkInstance instance, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkCreateDevice function. + VkResult ovkCreateDevice( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice); + /// Call to the original vkDestroyDevice function. + void ovkDestroyDevice( + VkDevice device, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkGetInstanceProcAddr function. + PFN_vkVoidFunction ovkGetInstanceProcAddr( + VkInstance instance, + const char* pName); + /// Call to the original vkGetDeviceProcAddr function. + PFN_vkVoidFunction ovkGetDeviceProcAddr( + VkDevice device, + const char* pName); + + /// Call to the original vkCreateSwapchainKHR function. + VkResult ovkCreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain); + /// Call to the original vkQueuePresentKHR function. + VkResult ovkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo); + /// Call to the original vkDestroySwapchainKHR function. + void ovkDestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkGetSwapchainImagesKHR function. + VkResult ovkGetSwapchainImagesKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pSwapchainImageCount, + VkImage* pSwapchainImages); + + /// Call to the original vkAllocateCommandBuffers function. + VkResult ovkAllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers); + /// Call to the original vkFreeCommandBuffers function. + void ovkFreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers); + + /// Call to the original vkBeginCommandBuffer function. + VkResult ovkBeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo); + /// Call to the original vkEndCommandBuffer function. + VkResult ovkEndCommandBuffer( + VkCommandBuffer commandBuffer); + + /// Call to the original vkCreateCommandPool function. + VkResult ovkCreateCommandPool( + VkDevice device, + const VkCommandPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCommandPool* pCommandPool); + /// Call to the original vkDestroyCommandPool function. + void ovkDestroyCommandPool( + VkDevice device, + VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkCreateImage function. + VkResult ovkCreateImage( + VkDevice device, + const VkImageCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImage* pImage); + /// Call to the original vkDestroyImage function. + void ovkDestroyImage( + VkDevice device, + VkImage image, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkGetImageMemoryRequirements function. + void ovkGetImageMemoryRequirements( + VkDevice device, + VkImage image, + VkMemoryRequirements* pMemoryRequirements); + /// Call to the original vkBindImageMemory function. + VkResult ovkBindImageMemory( + VkDevice device, + VkImage image, + VkDeviceMemory memory, + VkDeviceSize memoryOffset); + /// Call to the original vkAllocateMemory function. + VkResult ovkAllocateMemory( + VkDevice device, + const VkMemoryAllocateInfo* pAllocateInfo, + const VkAllocationCallbacks* pAllocator, + VkDeviceMemory* pMemory); + /// Call to the original vkFreeMemory function. + void ovkFreeMemory( + VkDevice device, + VkDeviceMemory memory, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkCreateSemaphore function. + VkResult ovkCreateSemaphore( + VkDevice device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSemaphore* pSemaphore); + /// Call to the original vkDestroySemaphore function. + void ovkDestroySemaphore( + VkDevice device, + VkSemaphore semaphore, + const VkAllocationCallbacks* pAllocator); + + /// Call to the original vkGetMemoryFdKHR function. + VkResult ovkGetMemoryFdKHR( + VkDevice device, + const VkMemoryGetFdInfoKHR* pGetFdInfo, + int* pFd); + /// Call to the original vkGetSemaphoreFdKHR function. + VkResult ovkGetSemaphoreFdKHR( + VkDevice device, + const VkSemaphoreGetFdInfoKHR* pGetFdInfo, + int* pFd); + + /// Call to the original vkGetPhysicalDeviceQueueFamilyProperties function. + void ovkGetPhysicalDeviceQueueFamilyProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties* pQueueFamilyProperties); + /// Call to the original vkGetPhysicalDeviceMemoryProperties function. + void ovkGetPhysicalDeviceMemoryProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties* pMemoryProperties); + + /// Call to the original vkGetDeviceQueue function. + void ovkGetDeviceQueue( + VkDevice device, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue* pQueue); + /// Call to the original vkQueueSubmit function. + VkResult ovkQueueSubmit( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence); + + /// Call to the original vkCmdPipelineBarrier function. + void ovkCmdPipelineBarrier( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers); + /// Call to the original vkCmdPipelineBarrier2 function. + void ovkCmdPipelineBarrier2( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo); + /// Call to the original vkCmdCopyImage function. + void ovkCmdCopyImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions); + + /// Call to the original vkAcquireNextImageKHR function. + VkResult ovkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex); +} + +/// Symbol definition for Vulkan instance layer. +extern "C" PFN_vkVoidFunction layer_vkGetInstanceProcAddr(VkInstance instance, const char* pName); +/// Symbol definition for Vulkan device layer. +extern "C" PFN_vkVoidFunction layer_vkGetDeviceProcAddr(VkDevice device, const char* pName); + +#endif // LAYER_HPP diff --git a/include/loader/dl.hpp b/include/loader/dl.hpp deleted file mode 100644 index 6ceb44d..0000000 --- a/include/loader/dl.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef DL_HPP -#define DL_HPP - -#include -#include - -// -// This dynamic loader replaces the standard dlopen, dlsym, and dlclose functions. -// On initialize, the original functions are obtained via dlvsym (glibc exclusive) -// and made available under functions with the "o" prefix. -// -// Any call to regular dlopen, dlsym or dlclose is intercepted and may be -// overriden by registering a File override via `Loader::DL::registerFile`. -// - -namespace Loader::DL { - - /// Dynamic loader override structure. - class File { - public: - /// - /// Create a dynamic loader override for a specific file. - /// - /// @param filename The name of the file to override. - /// - File(std::string filename) - : filename(std::move(filename)) {} - - /// - /// Append a symbol to the dynamic loader override. - /// - /// @param symbol The name of the symbol to add. - /// @param address The address of the symbol. - /// - void defineSymbol(const std::string& symbol, void* address) { - symbols[symbol] = address; - } - - /// Get the filename - [[nodiscard]] const std::string& getFilename() const { return filename; } - /// Get all overriden symbols - [[nodiscard]] const std::unordered_map& getSymbols() const { return symbols; } - - // Find a specific symbol - [[nodiscard]] void* findSymbol(const std::string& symbol) const { - auto it = symbols.find(symbol); - return (it != symbols.end()) ? it->second : nullptr; - } - - /// Get the fake handle - [[nodiscard]] void* getHandle() const { return handle; } - /// Get the real handle - [[nodiscard]] void* getOriginalHandle() const { return handle_orig; } - - /// Set the fake handle - void setHandle(void* new_handle) { handle = new_handle; } - /// Set the real handle - void setOriginalHandle(void* new_handle) { handle_orig = new_handle; } - - /// Copyable, moveable, default destructor - File(const File&) = default; - File(File&&) = default; - File& operator=(const File&) = default; - File& operator=(File&&) = default; - ~File() = default; - private: - std::string filename; - std::unordered_map symbols; - - void* handle = nullptr; - void* handle_orig = nullptr; - }; - - /// - /// Initialize the dynamic loader - /// - void initialize(); - - /// - /// Register a file with the dynamic loader. - /// - /// @param file The file to register. - /// - void registerFile(const File& file); - - /// - /// Disable hooks temporarily. This may be useful - /// when loading third-party libraries you wish not - /// to hook. - /// - void disableHooks(); - - /// - /// Re-enable hooks after they were disabled. - /// - void enableHooks(); - - /// - /// Call the original dlopen function. - /// - /// @param filename The name of the file to open. - /// @param flag The flags to use when opening the file. - /// @return A handle to the opened file, or NULL on failure. - /// - void* odlopen(const char* filename, int flag); - - /// - /// Call the original dlsym function. - /// - /// @param handle The handle to the opened file. - /// @param symbol The name of the symbol to look up. - /// @return A pointer to the symbol, or NULL on failure. - /// - void* odlsym(void* handle, const char* symbol); - - /// - /// Call the original dlclose function. - /// - /// @param handle The handle to the opened file. - /// @return 0 on success, or -1 on failure. - /// - int odlclose(void* handle); - -} - -/// Modified version of the dlopen function. -extern "C" void* dlopen(const char* filename, int flag) noexcept; -/// Modified version of the dlsym function. -extern "C" void* dlsym(void* handle, const char* symbol) noexcept; -/// Modified version of the dlclose function. -extern "C" int dlclose(void* handle) noexcept; - -#endif // DL_HPP diff --git a/include/loader/vk.hpp b/include/loader/vk.hpp deleted file mode 100644 index 38d6338..0000000 --- a/include/loader/vk.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef VK_HPP -#define VK_HPP - -#include - -#include - -// -// Similar to the dynamic loader, the Vulkan loader replaces the standard -// vkGetInstanceProcAddr and vkGetDeviceProcAddr functions. -// -// One thing that should be noted, is that not every application uses the -// Vulkan loader for every method. On Linux it's not unusual to see dlsym -// being used for vulkan functions, so make sure to register the same -// symbol on both loaders. -// - -namespace Loader::VK { - - /// - /// Initialize the Vulkan loader. - /// - void initialize(); - - /// - /// Register a symbol to the Vulkan loader. - /// - /// @param symbol The name of the Vulkan function to override. - /// @param address The address of the Vulkan function. - /// - void registerSymbol(const std::string& symbol, void* address); - - /// - /// Call the original vkGetInstanceProcAddr function. - /// - /// @param instance The (optional) Vulkan instance. - /// @param pName The name of the function to retrieve. - /// @return The address of the function, or nullptr if not found. - /// - PFN_vkVoidFunction ovkGetInstanceProcAddr(VkInstance instance, const char* pName); - - /// - /// Call the original vkGetDeviceProcAddr function. - /// - /// @param device The Vulkan device. - /// @param pName The name of the function to retrieve. - /// @return The address of the function, or nullptr if not found. - /// - PFN_vkVoidFunction ovkGetDeviceProcAddr(VkDevice device, const char* pName); - -} - -/// Modified version of the vkGetInstanceProcAddr function. -extern "C" PFN_vkVoidFunction myvkGetInstanceProcAddr(VkInstance instance, const char* pName); -/// Modified version of the vkGetDeviceProcAddr function. -extern "C" PFN_vkVoidFunction myvkGetDeviceProcAddr(VkDevice device, const char* pName); - -#endif // VK_HPP diff --git a/include/utils/utils.hpp b/include/utils/utils.hpp index 0989e2d..fb6d8b1 100644 --- a/include/utils/utils.hpp +++ b/include/utils/utils.hpp @@ -50,6 +50,16 @@ namespace Utils { VkPipelineStageFlags pre, VkPipelineStageFlags post, bool makeSrcPresentable, bool makeDstPresentable); + /// + /// Store the current layer environment. + /// + void storeLayerEnv(); + + /// + /// Restore the layer environment to the previously stored value. + /// + void restoreLayerEnv(); + } #endif // UTILS_HPP diff --git a/src/context.cpp b/src/context.cpp index d4b2c39..2070bb9 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1,5 +1,6 @@ #include "context.hpp" -#include "utils.hpp" +#include "layer.hpp" +#include "utils/utils.hpp" #include @@ -36,6 +37,10 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain, VK_IMAGE_ASPECT_COLOR_BIT, &out_n_fds.at(i)); + Utils::storeLayerEnv(); + LSFG::initialize(); + Utils::restoreLayerEnv(); + this->lsfgCtxId = std::shared_ptr( new int32_t(LSFG::createContext(extent.width, extent.height, frame_0_fd, frame_1_fd, out_n_fds)), @@ -98,7 +103,7 @@ VkResult LsContext::present(const Hooks::DeviceInfo& info, const void* pNext, Vk // 3. acquire next swapchain image pass.acquireSemaphores.at(i) = Mini::Semaphore(info.device); uint32_t imageIdx{}; - auto res = vkAcquireNextImageKHR(info.device, this->swapchain, UINT64_MAX, + auto res = Layer::ovkAcquireNextImageKHR(info.device, this->swapchain, UINT64_MAX, pass.acquireSemaphores.at(i).handle(), VK_NULL_HANDLE, &imageIdx); if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) throw LSFG::vulkan_error(res, "Failed to acquire next swapchain image"); @@ -136,7 +141,7 @@ VkResult LsContext::present(const Hooks::DeviceInfo& info, const void* pNext, Vk .pSwapchains = &this->swapchain, .pImageIndices = &imageIdx, }; - res = vkQueuePresentKHR(queue, &presentInfo); + res = Layer::ovkQueuePresentKHR(queue, &presentInfo); if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) throw LSFG::vulkan_error(res, "Failed to present swapchain image"); } @@ -152,7 +157,7 @@ VkResult LsContext::present(const Hooks::DeviceInfo& info, const void* pNext, Vk .pSwapchains = &this->swapchain, .pImageIndices = &presentIdx, }; - auto res = vkQueuePresentKHR(queue, &presentInfo); + auto res = Layer::ovkQueuePresentKHR(queue, &presentInfo); if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) throw LSFG::vulkan_error(res, "Failed to present swapchain image"); diff --git a/src/hooks.cpp b/src/hooks.cpp index f7530c0..9831175 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -1,14 +1,14 @@ -#include "loader/dl.hpp" -#include "loader/vk.hpp" -#include "context.hpp" #include "hooks.hpp" -#include "log.hpp" -#include "utils.hpp" +#include "context.hpp" +#include "layer.hpp" +#include "utils/log.hpp" +#include "utils/utils.hpp" #include #include #include +#include using namespace Hooks; @@ -20,11 +20,6 @@ namespace { const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) { - // create lsfg - Loader::DL::disableHooks(); - LSFG::initialize(); - Loader::DL::enableHooks(); - // add extensions auto extensions = Utils::addExtensions(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount, { @@ -33,24 +28,26 @@ namespace { "VK_KHR_external_semaphore_capabilities" }); + Log::info("lsfg-vk: Created Vulkan instance"); VkInstanceCreateInfo createInfo = *pCreateInfo; createInfo.enabledExtensionCount = static_cast(extensions.size()); createInfo.ppEnabledExtensionNames = extensions.data(); - return vkCreateInstance(&createInfo, pAllocator, pInstance); + return Layer::ovkCreateInstance(&createInfo, pAllocator, pInstance); } void myvkDestroyInstance( VkInstance instance, const VkAllocationCallbacks* pAllocator) { LSFG::finalize(); // destroy lsfg - vkDestroyInstance(instance, pAllocator); + Log::info("lsfg-vk: Destroyed Vulkan instance"); + Layer::ovkDestroyInstance(instance, pAllocator); } // device hooks std::unordered_map devices; - VkResult myvkCreateDevice( + VkResult myvkCreateDevicePre( VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, @@ -67,8 +64,14 @@ namespace { VkDeviceCreateInfo createInfo = *pCreateInfo; createInfo.enabledExtensionCount = static_cast(extensions.size()); createInfo.ppEnabledExtensionNames = extensions.data(); - auto res = vkCreateDevice(physicalDevice, &createInfo, pAllocator, pDevice); + return Layer::ovkCreateDevice(physicalDevice, &createInfo, pAllocator, pDevice); + } + VkResult myvkCreateDevicePost( + VkPhysicalDevice physicalDevice, + VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice) { // store device info try { const char* frameGen = std::getenv("LSFG_MULTIPLIER"); @@ -76,7 +79,7 @@ namespace { devices.emplace(*pDevice, DeviceInfo { .device = *pDevice, .physicalDevice = physicalDevice, - .queue = Utils::findQueue(*pDevice, physicalDevice, &createInfo, + .queue = Utils::findQueue(*pDevice, physicalDevice, pCreateInfo, VK_QUEUE_GRAPHICS_BIT), .frameGen = std::max(1, std::stoul(frameGen) - 1) }); @@ -84,12 +87,16 @@ namespace { Log::error("Failed to create device info: {}", e.what()); return VK_ERROR_INITIALIZATION_FAILED; } - return res; + + Log::info("lsfg-vk: Created Vulkan device"); + return VK_SUCCESS; } void myvkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) { devices.erase(device); // erase device info - vkDestroyDevice(device, pAllocator); + + Log::info("lsfg-vk: Destroyed Vulkan device"); + Layer::ovkDestroyDevice(device, pAllocator); } // swapchain hooks @@ -110,7 +117,7 @@ namespace { createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; // allow copy from/to images createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; // force vsync - auto res = vkCreateSwapchainKHR(device, &createInfo, pAllocator, pSwapchain); + auto res = Layer::ovkCreateSwapchainKHR(device, &createInfo, pAllocator, pSwapchain); if (res != VK_SUCCESS) { Log::error("Failed to create swapchain: {:x}", static_cast(res)); return res; @@ -119,12 +126,12 @@ namespace { try { // get swapchain images uint32_t imageCount{}; - res = vkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, nullptr); + res = Layer::ovkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, nullptr); if (res != VK_SUCCESS || imageCount == 0) throw LSFG::vulkan_error(res, "Failed to get swapchain images count"); std::vector swapchainImages(imageCount); - res = vkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, swapchainImages.data()); + res = Layer::ovkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, swapchainImages.data()); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Failed to get swapchain images"); @@ -135,7 +142,6 @@ namespace { )); swapchainToDeviceTable.emplace(*pSwapchain, device); - Log::debug("Created swapchain with {} images", imageCount); } catch (const LSFG::vulkan_error& e) { Log::error("Encountered Vulkan error {:x} while creating swapchain: {}", static_cast(e.error()), e.what()); @@ -145,6 +151,7 @@ namespace { return VK_ERROR_INITIALIZATION_FAILED; } + Log::info("lsfg-vk: Created swapchain with {} images", pCreateInfo->minImageCount); return res; } @@ -177,41 +184,24 @@ namespace { const VkAllocationCallbacks* pAllocator) { swapchains.erase(swapchain); // erase swapchain context swapchainToDeviceTable.erase(swapchain); - vkDestroySwapchainKHR(device, swapchain, pAllocator); - } - bool initialized{false}; + Log::info("lsfg-vk: Destroyed swapchain"); + Layer::ovkDestroySwapchainKHR(device, swapchain, pAllocator); + } } -void Hooks::initialize() { - if (initialized) { - Log::warn("Vulkan hooks already initialized, did you call it twice?"); - return; - } +std::unordered_map Hooks::hooks = { + // instance hooks + {"vkCreateInstance", reinterpret_cast(myvkCreateInstance)}, + {"vkDestroyInstance", reinterpret_cast(myvkDestroyInstance)}, - // list of hooks to register - const std::vector> hooks = { - { "vkCreateInstance", reinterpret_cast(myvkCreateInstance) }, - { "vkDestroyInstance", reinterpret_cast(myvkDestroyInstance) }, - { "vkCreateDevice", reinterpret_cast(myvkCreateDevice) }, - { "vkDestroyDevice", reinterpret_cast(myvkDestroyDevice) }, - { "vkCreateSwapchainKHR", reinterpret_cast(myvkCreateSwapchainKHR) }, - { "vkQueuePresentKHR", reinterpret_cast(myvkQueuePresentKHR) }, - { "vkDestroySwapchainKHR", reinterpret_cast(myvkDestroySwapchainKHR) } - }; + // device hooks + {"vkCreateDevicePre", reinterpret_cast(myvkCreateDevicePre)}, + {"vkCreateDevicePost", reinterpret_cast(myvkCreateDevicePost)}, + {"vkDestroyDevice", reinterpret_cast(myvkDestroyDevice)}, - // register hooks to Vulkan loader - for (const auto& hook : hooks) - Loader::VK::registerSymbol(hook.first, hook.second); - - // register hooks to dynamic loader under libvulkan.so.1 and libvulkan.so - for (const char* libName : {"libvulkan.so.1", "libvulkan.so"}) { - Loader::DL::File vkLib(libName); - for (const auto& hook : hooks) - vkLib.defineSymbol(hook.first, hook.second); - Loader::DL::registerFile(vkLib); - } - - initialized = true; - Log::info("Vulkan hooks initialized successfully"); -} + // swapchain hooks + {"vkCreateSwapchainKHR", reinterpret_cast(myvkCreateSwapchainKHR)}, + {"vkQueuePresentKHR", reinterpret_cast(myvkQueuePresentKHR)}, + {"vkDestroySwapchainKHR", reinterpret_cast(myvkDestroySwapchainKHR)} +}; diff --git a/src/init.cpp b/src/init.cpp deleted file mode 100644 index 3127d86..0000000 --- a/src/init.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "loader/dl.hpp" -#include "loader/vk.hpp" -#include "hooks.hpp" -#include "log.hpp" - -extern "C" void __attribute__((constructor)) init(); -extern "C" [[noreturn]] void __attribute__((destructor)) deinit(); - -void init() { - Log::info("lsfg-vk: init() called"); - - // hook loaders - Loader::DL::initialize(); - Loader::VK::initialize(); - - // setup hooks - Hooks::initialize(); - - Log::info("lsfg-vk: init() completed successfully"); -} - -void deinit() { - Log::debug("lsfg-vk: deinit() called, exiting"); - // for some reason some applications unload the library despite it containing - // the dl functions. this will lead to a segmentation fault, so we exit early. - exit(EXIT_SUCCESS); -} diff --git a/src/layer.cpp b/src/layer.cpp new file mode 100644 index 0000000..6f3d361 --- /dev/null +++ b/src/layer.cpp @@ -0,0 +1,527 @@ +#include "layer.hpp" +#include "hooks.hpp" +#include "utils/log.hpp" + +#include +#include + +#include +#include +#include + +namespace { + PFN_vkCreateInstance next_vkCreateInstance{}; + PFN_vkDestroyInstance next_vkDestroyInstance{}; + + PFN_vkCreateDevice next_vkCreateDevice{}; + PFN_vkDestroyDevice next_vkDestroyDevice{}; + + PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr{}; + PFN_vkGetDeviceProcAddr next_vkGetDeviceProcAddr{}; + + PFN_vkCreateSwapchainKHR next_vkCreateSwapchainKHR{}; + PFN_vkQueuePresentKHR next_vkQueuePresentKHR{}; + PFN_vkDestroySwapchainKHR next_vkDestroySwapchainKHR{}; + PFN_vkGetSwapchainImagesKHR next_vkGetSwapchainImagesKHR{}; + PFN_vkAllocateCommandBuffers next_vkAllocateCommandBuffers{}; + PFN_vkFreeCommandBuffers next_vkFreeCommandBuffers{}; + PFN_vkBeginCommandBuffer next_vkBeginCommandBuffer{}; + PFN_vkEndCommandBuffer next_vkEndCommandBuffer{}; + PFN_vkCreateCommandPool next_vkCreateCommandPool{}; + PFN_vkDestroyCommandPool next_vkDestroyCommandPool{}; + PFN_vkCreateImage next_vkCreateImage{}; + PFN_vkDestroyImage next_vkDestroyImage{}; + PFN_vkGetImageMemoryRequirements next_vkGetImageMemoryRequirements{}; + PFN_vkBindImageMemory next_vkBindImageMemory{}; + PFN_vkAllocateMemory next_vkAllocateMemory{}; + PFN_vkFreeMemory next_vkFreeMemory{}; + PFN_vkCreateSemaphore next_vkCreateSemaphore{}; + PFN_vkDestroySemaphore next_vkDestroySemaphore{}; + PFN_vkGetMemoryFdKHR next_vkGetMemoryFdKHR{}; + PFN_vkGetSemaphoreFdKHR next_vkGetSemaphoreFdKHR{}; + PFN_vkGetPhysicalDeviceQueueFamilyProperties next_vkGetPhysicalDeviceQueueFamilyProperties{}; + PFN_vkGetPhysicalDeviceMemoryProperties next_vkGetPhysicalDeviceMemoryProperties{}; + PFN_vkGetDeviceQueue next_vkGetDeviceQueue{}; + PFN_vkQueueSubmit next_vkQueueSubmit{}; + PFN_vkCmdPipelineBarrier next_vkCmdPipelineBarrier{}; + PFN_vkCmdPipelineBarrier2 next_vkCmdPipelineBarrier2{}; + PFN_vkCmdCopyImage next_vkCmdCopyImage{}; + PFN_vkAcquireNextImageKHR next_vkAcquireNextImageKHR{}; +} + +namespace { + VkResult layer_vkCreateInstance( // NOLINTBEGIN + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance) { + Log::debug("lsfg-vk(layer): Initializing lsfg-vk instance layer"); + + // find layer creation info + auto* layerDesc = const_cast( + reinterpret_cast(pCreateInfo->pNext)); + while (layerDesc && (layerDesc->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO + || layerDesc->function != VK_LAYER_LINK_INFO)) { + layerDesc = const_cast( + reinterpret_cast(layerDesc->pNext)); + } + if (!layerDesc) { + Log::error("lsfg-vk(layer): No layer creation info found in pNext chain"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + // advance link info (i don't really know what this does) + next_vkGetInstanceProcAddr = layerDesc->u.pLayerInfo->pfnNextGetInstanceProcAddr; + layerDesc->u.pLayerInfo = layerDesc->u.pLayerInfo->pNext; + + // create instance + next_vkCreateInstance = reinterpret_cast( + next_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance")); + if (!next_vkCreateInstance) { + Log::error("lsfg-vk(layer): Failed to get vkCreateInstance function pointer"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + auto* layer_vkCreateInstance2 = reinterpret_cast( + Hooks::hooks["vkCreateInstance"]); + auto res = layer_vkCreateInstance2(pCreateInfo, pAllocator, pInstance); + if (res != VK_SUCCESS) { + Log::error("lsfg-vk(layer): Failed to create Vulkan instance: {:x}", + static_cast(res)); + return res; + } + + // get relevant function pointers from the next layer + next_vkDestroyInstance = reinterpret_cast( + next_vkGetInstanceProcAddr(*pInstance, "vkDestroyInstance")); + next_vkGetInstanceProcAddr = reinterpret_cast( + next_vkGetInstanceProcAddr(*pInstance, "vkGetInstanceProcAddr")); + next_vkGetPhysicalDeviceQueueFamilyProperties = + reinterpret_cast( + next_vkGetInstanceProcAddr(*pInstance, "vkGetPhysicalDeviceQueueFamilyProperties")); + next_vkGetPhysicalDeviceMemoryProperties = + reinterpret_cast( + next_vkGetInstanceProcAddr(*pInstance, "vkGetPhysicalDeviceMemoryProperties")); + if (!next_vkDestroyInstance || !next_vkGetInstanceProcAddr || + !next_vkGetPhysicalDeviceQueueFamilyProperties || + !next_vkGetPhysicalDeviceMemoryProperties) { + Log::error("lsfg-vk(layer): Failed to get instance function pointers"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + Log::debug("lsfg-vk(layer): Successfully initialized lsfg-vk instance layer"); + return res; + } // NOLINTEND + + VkResult layer_vkCreateDevice( // NOLINTBEGIN + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice) { + Log::debug("lsfg-vk(layer): Initializing lsfg-vk device layer"); + + // find layer creation info + auto* layerDesc = const_cast( + reinterpret_cast(pCreateInfo->pNext)); + while (layerDesc && (layerDesc->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO + || layerDesc->function != VK_LAYER_LINK_INFO)) { + layerDesc = const_cast( + reinterpret_cast(layerDesc->pNext)); + } + if (!layerDesc) { + Log::error("lsfg-vk(layer): No layer creation info found in pNext chain"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + // advance link info (i don't really know what this does) + next_vkGetDeviceProcAddr = layerDesc->u.pLayerInfo->pfnNextGetDeviceProcAddr; + layerDesc->u.pLayerInfo = layerDesc->u.pLayerInfo->pNext; + + // create device + next_vkCreateDevice = reinterpret_cast( + next_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice")); + if (!next_vkCreateDevice) { + Log::error("lsfg-vk(layer): Failed to get vkCreateDevice function pointer"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + auto* layer_vkCreateDevice2 = reinterpret_cast( + Hooks::hooks["vkCreateDevicePre"]); + auto res = layer_vkCreateDevice2(physicalDevice, pCreateInfo, pAllocator, pDevice); + if (res != VK_SUCCESS) { + Log::error("lsfg-vk(layer): Failed to create Vulkan device: {:x}", + static_cast(res)); + return res; + } + + // get relevant function pointers from the next layer + next_vkDestroyDevice = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkDestroyDevice")); + next_vkCreateSwapchainKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCreateSwapchainKHR")); + next_vkQueuePresentKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkQueuePresentKHR")); + next_vkDestroySwapchainKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkDestroySwapchainKHR")); + next_vkGetSwapchainImagesKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkGetSwapchainImagesKHR")); + next_vkAllocateCommandBuffers = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkAllocateCommandBuffers")); + next_vkFreeCommandBuffers = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkFreeCommandBuffers")); + next_vkBeginCommandBuffer = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkBeginCommandBuffer")); + next_vkEndCommandBuffer = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkEndCommandBuffer")); + next_vkCreateCommandPool = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCreateCommandPool")); + next_vkDestroyCommandPool = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkDestroyCommandPool")); + next_vkCreateImage = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCreateImage")); + next_vkDestroyImage = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkDestroyImage")); + next_vkGetImageMemoryRequirements = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkGetImageMemoryRequirements")); + next_vkBindImageMemory = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkBindImageMemory")); + next_vkGetMemoryFdKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkGetMemoryFdKHR")); + next_vkAllocateMemory = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkAllocateMemory")); + next_vkFreeMemory = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkFreeMemory")); + next_vkCreateSemaphore = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCreateSemaphore")); + next_vkDestroySemaphore = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkDestroySemaphore")); + next_vkGetSemaphoreFdKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkGetSemaphoreFdKHR")); + next_vkGetDeviceQueue = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkGetDeviceQueue")); + next_vkQueueSubmit = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkQueueSubmit")); + next_vkCmdPipelineBarrier = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCmdPipelineBarrier")); + next_vkCmdPipelineBarrier2 = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCmdPipelineBarrier2")); + next_vkCmdCopyImage = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkCmdCopyImage")); + next_vkAcquireNextImageKHR = reinterpret_cast( + next_vkGetDeviceProcAddr(*pDevice, "vkAcquireNextImageKHR")); + if (!next_vkDestroyDevice || !next_vkCreateSwapchainKHR || + !next_vkQueuePresentKHR || !next_vkDestroySwapchainKHR || + !next_vkGetSwapchainImagesKHR || !next_vkAllocateCommandBuffers || + !next_vkFreeCommandBuffers || !next_vkBeginCommandBuffer || + !next_vkEndCommandBuffer || !next_vkCreateCommandPool || + !next_vkDestroyCommandPool || !next_vkCreateImage || + !next_vkDestroyImage || !next_vkGetImageMemoryRequirements || + !next_vkBindImageMemory || !next_vkGetMemoryFdKHR || + !next_vkAllocateMemory || !next_vkFreeMemory || + !next_vkCreateSemaphore || !next_vkDestroySemaphore || + !next_vkGetSemaphoreFdKHR || !next_vkGetDeviceQueue || + !next_vkQueueSubmit || !next_vkCmdPipelineBarrier || + !next_vkCmdPipelineBarrier2 || !next_vkCmdCopyImage || + !next_vkAcquireNextImageKHR) { + Log::error("lsfg-vk(layer): Failed to get device function pointers"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + layer_vkCreateDevice2 = reinterpret_cast( + Hooks::hooks["vkCreateDevicePost"]); + res = layer_vkCreateDevice2(physicalDevice, pCreateInfo, pAllocator, pDevice); + if (res != VK_SUCCESS) { + Log::error("lsfg-vk(layer): Failed to create Vulkan device: {:x}", + static_cast(res)); + return res; + } + + Log::debug("lsfg-vk(layer): Successfully initialized lsfg-vk device layer"); + return res; + } // NOLINTEND +} + +const std::unordered_map layerFunctions = { + { "vkCreateInstance", + reinterpret_cast(&layer_vkCreateInstance) }, + { "vkGetInstanceProcAddr", + reinterpret_cast(&layer_vkGetInstanceProcAddr) }, + { "vkGetDeviceProcAddr", + reinterpret_cast(&layer_vkGetDeviceProcAddr) }, + { "vkCreateDevice", + reinterpret_cast(&layer_vkCreateDevice) }, +}; + +PFN_vkVoidFunction layer_vkGetInstanceProcAddr(VkInstance instance, const char* pName) { + std::string name(pName); + auto it = layerFunctions.find(name); + if (it != layerFunctions.end()) { + Log::debug("lsfg-vk(layer): Inserted layer function for {}", name); + return it->second; + } + + it = Hooks::hooks.find(name); + if (it != Hooks::hooks.end()) { + Log::debug("lsfg-vk(layer): Inserted hook function for {}", name); + return it->second; + } + + return next_vkGetInstanceProcAddr(instance, pName); +} + +PFN_vkVoidFunction layer_vkGetDeviceProcAddr(VkDevice device, const char* pName) { + std::string name(pName); + auto it = layerFunctions.find(name); + if (it != layerFunctions.end()) { + Log::debug("lsfg-vk(layer): Inserted layer function for {}", name); + return it->second; + } + + it = Hooks::hooks.find(name); + if (it != Hooks::hooks.end()) { + Log::debug("lsfg-vk(layer): Inserted hook function for {}", name); + return it->second; + } + + return next_vkGetDeviceProcAddr(device, pName); +} + +// original functions + +VkResult Layer::ovkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkInstance* pInstance) { + return next_vkCreateInstance(pCreateInfo, pAllocator, pInstance); +} +void Layer::ovkDestroyInstance( + VkInstance instance, + const VkAllocationCallbacks* pAllocator) { + next_vkDestroyInstance(instance, pAllocator); +} + +VkResult Layer::ovkCreateDevice( + VkPhysicalDevice physicalDevice, + const VkDeviceCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDevice* pDevice) { + return next_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice); +} +void Layer::ovkDestroyDevice( + VkDevice device, + const VkAllocationCallbacks* pAllocator) { + next_vkDestroyDevice(device, pAllocator); +} + +PFN_vkVoidFunction Layer::ovkGetInstanceProcAddr( + VkInstance instance, + const char* pName) { + return next_vkGetInstanceProcAddr(instance, pName); +} +PFN_vkVoidFunction Layer::ovkGetDeviceProcAddr( + VkDevice device, + const char* pName) { + return next_vkGetDeviceProcAddr(device, pName); +} + +VkResult Layer::ovkCreateSwapchainKHR( + VkDevice device, + const VkSwapchainCreateInfoKHR* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSwapchainKHR* pSwapchain) { + return next_vkCreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); +} +VkResult Layer::ovkQueuePresentKHR( + VkQueue queue, + const VkPresentInfoKHR* pPresentInfo) { + return next_vkQueuePresentKHR(queue, pPresentInfo); +} +void Layer::ovkDestroySwapchainKHR( + VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks* pAllocator) { + next_vkDestroySwapchainKHR(device, swapchain, pAllocator); +} + +VkResult Layer::ovkGetSwapchainImagesKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint32_t* pSwapchainImageCount, + VkImage* pSwapchainImages) { + return next_vkGetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages); +} + +VkResult Layer::ovkAllocateCommandBuffers( + VkDevice device, + const VkCommandBufferAllocateInfo* pAllocateInfo, + VkCommandBuffer* pCommandBuffers) { + return next_vkAllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers); +} +void Layer::ovkFreeCommandBuffers( + VkDevice device, + VkCommandPool commandPool, + uint32_t commandBufferCount, + const VkCommandBuffer* pCommandBuffers) { + next_vkFreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers); +} + +VkResult Layer::ovkBeginCommandBuffer( + VkCommandBuffer commandBuffer, + const VkCommandBufferBeginInfo* pBeginInfo) { + return next_vkBeginCommandBuffer(commandBuffer, pBeginInfo); +} +VkResult Layer::ovkEndCommandBuffer( + VkCommandBuffer commandBuffer) { + return next_vkEndCommandBuffer(commandBuffer); +} + +VkResult Layer::ovkCreateCommandPool( + VkDevice device, + const VkCommandPoolCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCommandPool* pCommandPool) { + return next_vkCreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool); +} +void Layer::ovkDestroyCommandPool( + VkDevice device, + VkCommandPool commandPool, + const VkAllocationCallbacks* pAllocator) { + next_vkDestroyCommandPool(device, commandPool, pAllocator); +} + +VkResult Layer::ovkCreateImage( + VkDevice device, + const VkImageCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkImage* pImage) { + return next_vkCreateImage(device, pCreateInfo, pAllocator, pImage); +} +void Layer::ovkDestroyImage( + VkDevice device, + VkImage image, + const VkAllocationCallbacks* pAllocator) { + next_vkDestroyImage(device, image, pAllocator); +} + +void Layer::ovkGetImageMemoryRequirements( + VkDevice device, + VkImage image, + VkMemoryRequirements* pMemoryRequirements) { + next_vkGetImageMemoryRequirements(device, image, pMemoryRequirements); +} +VkResult Layer::ovkBindImageMemory( + VkDevice device, + VkImage image, + VkDeviceMemory memory, + VkDeviceSize memoryOffset) { + return next_vkBindImageMemory(device, image, memory, memoryOffset); +} + +VkResult Layer::ovkAllocateMemory( + VkDevice device, + const VkMemoryAllocateInfo* pAllocateInfo, + const VkAllocationCallbacks* pAllocator, + VkDeviceMemory* pMemory) { + return next_vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory); +} +void Layer::ovkFreeMemory( + VkDevice device, + VkDeviceMemory memory, + const VkAllocationCallbacks* pAllocator) { + next_vkFreeMemory(device, memory, pAllocator); +} + +VkResult Layer::ovkCreateSemaphore( + VkDevice device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSemaphore* pSemaphore) { + return next_vkCreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); +} +void Layer::ovkDestroySemaphore( + VkDevice device, + VkSemaphore semaphore, + const VkAllocationCallbacks* pAllocator) { + next_vkDestroySemaphore(device, semaphore, pAllocator); +} + +VkResult Layer::ovkGetMemoryFdKHR( + VkDevice device, + const VkMemoryGetFdInfoKHR* pGetFdInfo, + int* pFd) { + return next_vkGetMemoryFdKHR(device, pGetFdInfo, pFd); +} +VkResult Layer::ovkGetSemaphoreFdKHR( + VkDevice device, + const VkSemaphoreGetFdInfoKHR* pGetFdInfo, + int* pFd) { + return next_vkGetSemaphoreFdKHR(device, pGetFdInfo, pFd); +} + +void Layer::ovkGetPhysicalDeviceQueueFamilyProperties( + VkPhysicalDevice physicalDevice, + uint32_t* pQueueFamilyPropertyCount, + VkQueueFamilyProperties* pQueueFamilyProperties) { + next_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties); +} +void Layer::ovkGetPhysicalDeviceMemoryProperties( + VkPhysicalDevice physicalDevice, + VkPhysicalDeviceMemoryProperties* pMemoryProperties) { + next_vkGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties); +} + +void Layer::ovkGetDeviceQueue( + VkDevice device, + uint32_t queueFamilyIndex, + uint32_t queueIndex, + VkQueue* pQueue) { + next_vkGetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue); +} +VkResult Layer::ovkQueueSubmit( + VkQueue queue, + uint32_t submitCount, + const VkSubmitInfo* pSubmits, + VkFence fence) { + return next_vkQueueSubmit(queue, submitCount, pSubmits, fence); +} + +void Layer::ovkCmdPipelineBarrier( + VkCommandBuffer commandBuffer, + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers) { + next_vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, + memoryBarrierCount, pMemoryBarriers, + bufferMemoryBarrierCount, pBufferMemoryBarriers, + imageMemoryBarrierCount, pImageMemoryBarriers); +} +void Layer::ovkCmdPipelineBarrier2( + VkCommandBuffer commandBuffer, + const VkDependencyInfo* pDependencyInfo) { + next_vkCmdPipelineBarrier2(commandBuffer, pDependencyInfo); +} +void Layer::ovkCmdCopyImage( + VkCommandBuffer commandBuffer, + VkImage srcImage, + VkImageLayout srcImageLayout, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkImageCopy* pRegions) { + next_vkCmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions); +} + +VkResult Layer::ovkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex) { + return next_vkAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); +} diff --git a/src/loader/dl.cpp b/src/loader/dl.cpp deleted file mode 100644 index da25349..0000000 --- a/src/loader/dl.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include "loader/dl.hpp" -#include "log.hpp" - -#include - -using namespace Loader; - -using dlopen_t = void* (*)(const char*, int); -using dlsym_t = void* (*)(void*, const char*); -using dlclose_t = int (*)(void*); - -// glibc exclusive function to get versioned symbols -extern "C" void* dlvsym(long, const char*, const char*); - -namespace { - // original function pointers - dlopen_t dlopen_ptr; - dlsym_t dlsym_ptr; - dlclose_t dlclose_ptr; - - // map of all registered overrides - auto& overrides() { - // this has to be a function rather than a static variable - // because of weird initialization order issues. - static std::unordered_map overrides; - return overrides; - } - - // vector of loaded handles - auto& handles() { - static std::vector handles; - return handles; - } - - bool enable_hooks{true}; -} - -void DL::initialize() { - if (dlopen_ptr || dlsym_ptr || dlclose_ptr) { - Log::warn("lsfg-vk(dl): Dynamic loader already initialized, did you call it twice?"); - return; - } - - dlopen_ptr = reinterpret_cast (dlvsym(-1, "dlopen", "GLIBC_2.2.5")); - dlsym_ptr = reinterpret_cast (dlvsym(-1, "dlsym", "GLIBC_2.2.5")); - dlclose_ptr = reinterpret_cast(dlvsym(-1, "dlclose", "GLIBC_2.2.5")); - if (!dlopen_ptr || !dlsym_ptr || !dlclose_ptr) { - Log::error("lsfg-vk(dl): Failed to initialize dynamic loader, missing symbols"); - exit(EXIT_FAILURE); - } - - Log::debug("lsfg-vk(dl): Initialized dynamic loader with original functions"); -} - -void DL::registerFile(const File& file) { - auto& files = overrides(); - - auto it = files.find(file.getFilename()); - if (it == files.end()) { - // simply register if the file hasn't been registered yet - files.emplace(file.getFilename(), file); - return; - } - - // merge the new file's symbols into the previously registered one - auto& existing_file = it->second; - for (const auto& [symbol, func] : file.getSymbols()) - if (existing_file.findSymbol(symbol) == nullptr) - existing_file.defineSymbol(symbol, func); - else - Log::warn("lsfg-vk(dl): Tried registering symbol {}::{}, but it is already defined", - existing_file.getFilename(), symbol); -} - -void DL::disableHooks() { enable_hooks = false; } -void DL::enableHooks() { enable_hooks = true; } - -void* dlopen(const char* filename, int flag) noexcept { - auto& files = overrides(); - auto& loaded = handles(); - - // ALWAYS load the library and ensure it's tracked - auto* handle = dlopen_ptr(filename, flag); - if (handle && std::ranges::find(loaded, handle) == loaded.end()) - loaded.push_back(handle); - - // no need to check for overrides if hooks are disabled - if (!enable_hooks || !filename) - return handle; - - // try to find an override for this filename - const std::string filename_str(filename); - auto it = files.find(filename_str); - if (it == files.end()) - return handle; - - auto& file = it->second; - file.setOriginalHandle(handle); - file.setHandle(reinterpret_cast(&file)); - - Log::debug("lsfg-vk(dl): Intercepted module load for {}", file.getFilename()); - return file.getHandle(); -} - -void* dlsym(void* handle, const char* symbol) noexcept { - const auto& files = overrides(); - - if (!enable_hooks || !handle || !symbol) - return dlsym_ptr(handle, symbol); - - // see if handle is a fake one - const auto it = std::ranges::find_if(files, [handle](const auto& pair) { - return pair.second.getHandle() == handle; - }); - if (it == files.end()) - return dlsym_ptr(handle, symbol); - const auto& file = it->second; - - // find a symbol override - const std::string symbol_str(symbol); - auto* func = file.findSymbol(symbol_str); - if (func == nullptr) - return dlsym_ptr(file.getOriginalHandle(), symbol); - - Log::debug("lsfg-vk(dl): Intercepted symbol {}::{}", file.getFilename(), symbol_str); - return func; -} - -int dlclose(void* handle) noexcept { - auto& files = overrides(); - auto& loaded = handles(); - - // no handle, let the original dlclose handle it - if (!handle) - return dlclose_ptr(handle); - - // see if the handle is a fake one - auto it = std::ranges::find_if(files, [handle](const auto& pair) { - return pair.second.getHandle() == handle; - }); - if (it == files.end()) { - // if the handle is not fake, check if it's still loaded. - // this is necessary to avoid double closing when - // one handle was acquired while hooks were disabled - auto l_it = std::ranges::find(loaded, handle); - if (l_it == loaded.end()) - return 0; - loaded.erase(l_it); - return dlclose_ptr(handle); - } - - auto& file = it->second; - handle = file.getOriginalHandle(); - file.setHandle(nullptr); - file.setOriginalHandle(nullptr); - - // similarly, if it is fake, check if it's still loaded - // before unloading it again. - auto l_it = std::ranges::find(loaded, handle); - if (l_it == loaded.end()) { - Log::debug("lsfg-vk(dl): Skipping unload for {} (already unloaded)", file.getFilename()); - return 0; - } - loaded.erase(l_it); - - Log::debug("lsfg-vk(dl): Unloaded {}", file.getFilename()); - return dlclose_ptr(handle); -} - -// original function calls - -void* DL::odlopen(const char* filename, int flag) { - return dlopen_ptr(filename, flag); -} - -void* DL::odlsym(void* handle, const char* symbol) { - return dlsym_ptr(handle, symbol); -} - -int DL::odlclose(void* handle) { - return dlclose_ptr(handle); -} diff --git a/src/loader/vk.cpp b/src/loader/vk.cpp deleted file mode 100644 index 4628fab..0000000 --- a/src/loader/vk.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "loader/vk.hpp" -#include "loader/dl.hpp" -#include "log.hpp" - -using namespace Loader; - -namespace { - // original function pointers - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr_ptr{}; - PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr_ptr{}; - - // map of all overridden symbols - auto& symbols() { - static std::unordered_map symbols; - return symbols; - } -} - -void VK::initialize() { - if (vkGetInstanceProcAddr_ptr || vkGetDeviceProcAddr_ptr) { - Log::warn("lsfg-vk(vk): Vulkan loader already initialized, did you call it twice?"); - return; - } - - // get original function pointers - auto* handle = DL::odlopen("libvulkan.so.1", 0x2); - vkGetInstanceProcAddr_ptr = - reinterpret_cast(DL::odlsym(handle, "vkGetInstanceProcAddr")); - vkGetDeviceProcAddr_ptr = - reinterpret_cast (DL::odlsym(handle, "vkGetDeviceProcAddr")); - if (!vkGetInstanceProcAddr_ptr || !vkGetDeviceProcAddr_ptr) { - Log::error("lsfg-vk(vk): Failed to initialize Vulkan loader, missing symbols"); - exit(EXIT_FAILURE); - } - - // register dynamic loader overrides - DL::File vulkanLib{"libvulkan.so.1"}; - vulkanLib.defineSymbol("vkGetInstanceProcAddr", - reinterpret_cast(myvkGetInstanceProcAddr)); - vulkanLib.defineSymbol("vkGetDeviceProcAddr", - reinterpret_cast(myvkGetDeviceProcAddr)); - DL::registerFile(vulkanLib); - - DL::File vulkanLib2{"libvulkan.so"}; - vulkanLib2.defineSymbol("vkGetInstanceProcAddr", - reinterpret_cast(myvkGetInstanceProcAddr)); - vulkanLib2.defineSymbol("vkGetDeviceProcAddr", - reinterpret_cast(myvkGetDeviceProcAddr)); - DL::registerFile(vulkanLib2); - - // register vulkan loader overrides - VK::registerSymbol("vkGetInstanceProcAddr", reinterpret_cast(myvkGetInstanceProcAddr)); - VK::registerSymbol("vkGetDeviceProcAddr", reinterpret_cast(myvkGetDeviceProcAddr)); - - Log::debug("lsfg-vk(vk): Initialized Vulkan loader with original functions"); -} - -void VK::registerSymbol(const std::string& symbol, void* address) { - auto& syms = symbols(); - - const auto it = syms.find(symbol); - if (it != syms.end()) { - Log::warn("lsfg-vk(vk): Tried registering symbol {}, but it is already defined", symbol); - return; - } - - syms.emplace(symbol, address); -} - -PFN_vkVoidFunction myvkGetInstanceProcAddr(VkInstance instance, const char* pName) { - const auto& syms = symbols(); - - if (!pName) - return vkGetInstanceProcAddr_ptr(instance, pName); - - // try to find an override - const std::string pName_str(pName); - const auto it = syms.find(pName_str); - if (it == syms.end()) - return vkGetInstanceProcAddr_ptr(instance, pName); - - Log::debug("lsfg-vk(vk): Intercepted Vulkan symbol {}", pName_str); - return reinterpret_cast(it->second); -} - -PFN_vkVoidFunction myvkGetDeviceProcAddr(VkDevice device, const char* pName) { - const auto& syms = symbols(); - - if (!pName) - return vkGetDeviceProcAddr_ptr(device, pName); - - const std::string pName_str(pName); - auto it = syms.find(pName_str); - if (it == syms.end()) - return vkGetDeviceProcAddr_ptr(device, pName); - - Log::debug("lsfg-vk(vk): Intercepted Vulkan symbol {}", pName_str); - return reinterpret_cast(it->second); -} - -// original function calls - -PFN_vkVoidFunction VK::ovkGetInstanceProcAddr(VkInstance instance, const char* pName) { - return vkGetInstanceProcAddr_ptr(instance, pName); -} - -PFN_vkVoidFunction VK::ovkGetDeviceProcAddr(VkDevice device, const char* pName) { - return vkGetDeviceProcAddr_ptr(device, pName); -} diff --git a/src/mini/commandbuffer.cpp b/src/mini/commandbuffer.cpp index 8a8ac32..5887f65 100644 --- a/src/mini/commandbuffer.cpp +++ b/src/mini/commandbuffer.cpp @@ -1,4 +1,5 @@ #include "mini/commandbuffer.hpp" +#include "layer.hpp" #include @@ -13,7 +14,7 @@ CommandBuffer::CommandBuffer(VkDevice device, const CommandPool& pool) { .commandBufferCount = 1 }; VkCommandBuffer commandBufferHandle{}; - auto res = vkAllocateCommandBuffers(device, &desc, &commandBufferHandle); + auto res = Layer::ovkAllocateCommandBuffers(device, &desc, &commandBufferHandle); if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Unable to allocate command buffer"); @@ -22,7 +23,7 @@ CommandBuffer::CommandBuffer(VkDevice device, const CommandPool& pool) { this->commandBuffer = std::shared_ptr( new VkCommandBuffer(commandBufferHandle), [dev = device, pool = pool.handle()](VkCommandBuffer* cmdBuffer) { - vkFreeCommandBuffers(dev, pool, 1, cmdBuffer); + Layer::ovkFreeCommandBuffers(dev, pool, 1, cmdBuffer); } ); } @@ -35,7 +36,7 @@ void CommandBuffer::begin() { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }; - auto res = vkBeginCommandBuffer(*this->commandBuffer, &beginInfo); + auto res = Layer::ovkBeginCommandBuffer(*this->commandBuffer, &beginInfo); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Unable to begin command buffer"); @@ -46,7 +47,7 @@ void CommandBuffer::end() { if (*this->state != CommandBufferState::Recording) throw std::logic_error("Command buffer is not in Recording state"); - auto res = vkEndCommandBuffer(*this->commandBuffer); + auto res = Layer::ovkEndCommandBuffer(*this->commandBuffer); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Unable to end command buffer"); @@ -72,7 +73,7 @@ void CommandBuffer::submit(VkQueue queue, .signalSemaphoreCount = static_cast(signalSemaphores.size()), .pSignalSemaphores = signalSemaphores.data() }; - auto res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); + auto res = Layer::ovkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Unable to submit command buffer"); diff --git a/src/mini/commandpool.cpp b/src/mini/commandpool.cpp index 3407410..a624a59 100644 --- a/src/mini/commandpool.cpp +++ b/src/mini/commandpool.cpp @@ -1,4 +1,5 @@ #include "mini/commandpool.hpp" +#include "layer.hpp" #include @@ -11,7 +12,7 @@ CommandPool::CommandPool(VkDevice device, uint32_t graphicsFamilyIdx) { .queueFamilyIndex = graphicsFamilyIdx }; VkCommandPool commandPoolHandle{}; - auto res = vkCreateCommandPool(device, &desc, nullptr, &commandPoolHandle); + auto res = Layer::ovkCreateCommandPool(device, &desc, nullptr, &commandPoolHandle); if (res != VK_SUCCESS || commandPoolHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Unable to create command pool"); @@ -19,7 +20,7 @@ CommandPool::CommandPool(VkDevice device, uint32_t graphicsFamilyIdx) { this->commandPool = std::shared_ptr( new VkCommandPool(commandPoolHandle), [dev = device](VkCommandPool* commandPoolHandle) { - vkDestroyCommandPool(dev, *commandPoolHandle, nullptr); + Layer::ovkDestroyCommandPool(dev, *commandPoolHandle, nullptr); } ); } diff --git a/src/mini/image.cpp b/src/mini/image.cpp index 4fc8dcc..714c9cb 100644 --- a/src/mini/image.cpp +++ b/src/mini/image.cpp @@ -1,4 +1,5 @@ #include "mini/image.hpp" +#include "layer.hpp" #include @@ -32,16 +33,16 @@ Image::Image(VkDevice device, VkPhysicalDevice physicalDevice, .sharingMode = VK_SHARING_MODE_EXCLUSIVE }; VkImage imageHandle{}; - auto res = vkCreateImage(device, &desc, nullptr, &imageHandle); + auto res = Layer::ovkCreateImage(device, &desc, nullptr, &imageHandle); if (res != VK_SUCCESS || imageHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Failed to create Vulkan image"); // find memory type VkPhysicalDeviceMemoryProperties memProps; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); + Layer::ovkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); VkMemoryRequirements memReqs; - vkGetImageMemoryRequirements(device, imageHandle, &memReqs); + Layer::ovkGetImageMemoryRequirements(device, imageHandle, &memReqs); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" @@ -74,24 +75,21 @@ Image::Image(VkDevice device, VkPhysicalDevice physicalDevice, .memoryTypeIndex = memType.value() }; VkDeviceMemory memoryHandle{}; - res = vkAllocateMemory(device, &allocInfo, nullptr, &memoryHandle); + res = Layer::ovkAllocateMemory(device, &allocInfo, nullptr, &memoryHandle); if (res != VK_SUCCESS || memoryHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Failed to allocate memory for Vulkan image"); - res = vkBindImageMemory(device, imageHandle, memoryHandle, 0); + res = Layer::ovkBindImageMemory(device, imageHandle, memoryHandle, 0); if (res != VK_SUCCESS) throw LSFG::vulkan_error(res, "Failed to bind memory to Vulkan image"); // obtain the sharing fd - auto vkGetMemoryFdKHR = - reinterpret_cast(vkGetDeviceProcAddr(device, "vkGetMemoryFdKHR")); - const VkMemoryGetFdInfoKHR fdInfo{ .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, .memory = memoryHandle, .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, }; - res = vkGetMemoryFdKHR(device, &fdInfo, fd); + res = Layer::ovkGetMemoryFdKHR(device, &fdInfo, fd); if (res != VK_SUCCESS || *fd < 0) throw LSFG::vulkan_error(res, "Failed to obtain sharing fd for Vulkan image"); @@ -99,13 +97,13 @@ Image::Image(VkDevice device, VkPhysicalDevice physicalDevice, this->image = std::shared_ptr( new VkImage(imageHandle), [dev = device](VkImage* img) { - vkDestroyImage(dev, *img, nullptr); + Layer::ovkDestroyImage(dev, *img, nullptr); } ); this->memory = std::shared_ptr( new VkDeviceMemory(memoryHandle), [dev = device](VkDeviceMemory* mem) { - vkFreeMemory(dev, *mem, nullptr); + Layer::ovkFreeMemory(dev, *mem, nullptr); } ); } diff --git a/src/mini/semaphore.cpp b/src/mini/semaphore.cpp index f4b2225..b54c776 100644 --- a/src/mini/semaphore.cpp +++ b/src/mini/semaphore.cpp @@ -1,4 +1,5 @@ #include "mini/semaphore.hpp" +#include "layer.hpp" #include @@ -10,7 +11,7 @@ Semaphore::Semaphore(VkDevice device) { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; VkSemaphore semaphoreHandle{}; - auto res = vkCreateSemaphore(device, &desc, nullptr, &semaphoreHandle); + auto res = Layer::ovkCreateSemaphore(device, &desc, nullptr, &semaphoreHandle); if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Unable to create semaphore"); @@ -18,7 +19,7 @@ Semaphore::Semaphore(VkDevice device) { this->semaphore = std::shared_ptr( new VkSemaphore(semaphoreHandle), [dev = device](VkSemaphore* semaphoreHandle) { - vkDestroySemaphore(dev, *semaphoreHandle, nullptr); + Layer::ovkDestroySemaphore(dev, *semaphoreHandle, nullptr); } ); } @@ -34,20 +35,17 @@ Semaphore::Semaphore(VkDevice device, int* fd) { .pNext = &exportInfo }; VkSemaphore semaphoreHandle{}; - auto res = vkCreateSemaphore(device, &desc, nullptr, &semaphoreHandle); + auto res = Layer::ovkCreateSemaphore(device, &desc, nullptr, &semaphoreHandle); if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE) throw LSFG::vulkan_error(res, "Unable to create semaphore"); // export semaphore to fd - auto vkGetSemaphoreFdKHR = reinterpret_cast( - vkGetDeviceProcAddr(device, "vkGetSemaphoreFdKHR")); - const VkSemaphoreGetFdInfoKHR fdInfo{ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, .semaphore = semaphoreHandle, .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT }; - res = vkGetSemaphoreFdKHR(device, &fdInfo, fd); + res = Layer::ovkGetSemaphoreFdKHR(device, &fdInfo, fd); if (res != VK_SUCCESS || *fd < 0) throw LSFG::vulkan_error(res, "Unable to export semaphore to fd"); @@ -55,7 +53,7 @@ Semaphore::Semaphore(VkDevice device, int* fd) { this->semaphore = std::shared_ptr( new VkSemaphore(semaphoreHandle), [dev = device](VkSemaphore* semaphoreHandle) { - vkDestroySemaphore(dev, *semaphoreHandle, nullptr); + Layer::ovkDestroySemaphore(dev, *semaphoreHandle, nullptr); } ); } diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index ed5acad..b32e0e6 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -1,9 +1,11 @@ #include "utils/utils.hpp" +#include "layer.hpp" #include #include #include +#include using namespace Utils; @@ -13,9 +15,9 @@ std::pair Utils::findQueue(VkDevice device, VkPhysicalDevice std::copy_n(desc->pQueueCreateInfos, enabledQueues.size(), enabledQueues.data()); uint32_t familyCount{}; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, nullptr); + Layer::ovkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, nullptr); std::vector families(familyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, + Layer::ovkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, families.data()); std::optional idx; @@ -30,7 +32,7 @@ std::pair Utils::findQueue(VkDevice device, VkPhysicalDevice throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No suitable queue found"); VkQueue queue{}; - vkGetDeviceQueue(device, *idx, 0, &queue); + Layer::ovkGetDeviceQueue(device, *idx, 0, &queue); return { *idx, queue }; } @@ -78,7 +80,7 @@ void Utils::copyImage(VkCommandBuffer buf, } }; const std::vector barriers = { srcBarrier, dstBarrier }; - vkCmdPipelineBarrier(buf, + Layer::ovkCmdPipelineBarrier(buf, pre, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, static_cast(barriers.size()), barriers.data()); @@ -98,7 +100,7 @@ void Utils::copyImage(VkCommandBuffer buf, .depth = 1 } }; - vkCmdCopyImage(buf, + Layer::ovkCmdCopyImage(buf, src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy); @@ -115,7 +117,7 @@ void Utils::copyImage(VkCommandBuffer buf, .layerCount = 1 } }; - vkCmdPipelineBarrier(buf, + Layer::ovkCmdPipelineBarrier(buf, VK_PIPELINE_STAGE_TRANSFER_BIT, post, 0, 0, nullptr, 0, nullptr, 1, &presentBarrier); @@ -135,10 +137,29 @@ void Utils::copyImage(VkCommandBuffer buf, .layerCount = 1 } }; - vkCmdPipelineBarrier(buf, + Layer::ovkCmdPipelineBarrier(buf, VK_PIPELINE_STAGE_TRANSFER_BIT, post, 0, 0, nullptr, 0, nullptr, 1, &presentBarrier); } - +} + +namespace { + std::optional layersEnvironment; +} + +void Utils::storeLayerEnv() { + const char* env = std::getenv("VK_INSTANCE_LAYERS"); + if (env) + layersEnvironment = env; + else + layersEnvironment.reset(); + unsetenv("VK_INSTANCE_LAYERS"); +} + +void Utils::restoreLayerEnv() { + if (layersEnvironment.has_value()) + setenv("VK_INSTANCE_LAYERS", layersEnvironment->c_str(), 1); + else + unsetenv("VK_INSTANCE_LAYERS"); }