mirror of
				https://github.com/PancakeTAS/lsfg-vk.git
				synced 2025-10-30 07:01:10 +00:00 
			
		
		
		
	move to vulkan layer
This commit is contained in:
		
							parent
							
								
									7dfcfe252f
								
							
						
					
					
						commit
						614457fab7
					
				
					 17 changed files with 876 additions and 605 deletions
				
			
		
							
								
								
									
										15
									
								
								VkLayer_LS_frame_generation.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								VkLayer_LS_frame_generation.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -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" | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -3,7 +3,9 @@ | ||||||
| 
 | 
 | ||||||
| #include <vulkan/vulkan_core.h> | #include <vulkan/vulkan_core.h> | ||||||
| 
 | 
 | ||||||
|  | #include <unordered_map> | ||||||
| #include <utility> | #include <utility> | ||||||
|  | #include <string> | ||||||
| 
 | 
 | ||||||
| namespace Hooks { | namespace Hooks { | ||||||
| 
 | 
 | ||||||
|  | @ -15,10 +17,8 @@ namespace Hooks { | ||||||
|         uint64_t frameGen; // amount of frames to generate
 |         uint64_t frameGen; // amount of frames to generate
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     ///
 |     /// Map of hooked Vulkan functions.
 | ||||||
|     /// Install overrides for hooked Vulkan functions.
 |     extern std::unordered_map<std::string, PFN_vkVoidFunction> hooks; | ||||||
|     ///
 |  | ||||||
|     void initialize(); |  | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										214
									
								
								include/layer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								include/layer.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,214 @@ | ||||||
|  | #ifndef LAYER_HPP | ||||||
|  | #define LAYER_HPP | ||||||
|  | 
 | ||||||
|  | #include <vulkan/vulkan_core.h> | ||||||
|  | 
 | ||||||
|  | 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
 | ||||||
|  | @ -1,133 +0,0 @@ | ||||||
| #ifndef DL_HPP |  | ||||||
| #define DL_HPP |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| #include <unordered_map> |  | ||||||
| 
 |  | ||||||
| //
 |  | ||||||
| // 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<std::string, void*>& 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<std::string, void*> 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
 |  | ||||||
|  | @ -1,58 +0,0 @@ | ||||||
| #ifndef VK_HPP |  | ||||||
| #define VK_HPP |  | ||||||
| 
 |  | ||||||
| #include <vulkan/vulkan.h> |  | ||||||
| 
 |  | ||||||
| #include <string> |  | ||||||
| 
 |  | ||||||
| //
 |  | ||||||
| // 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
 |  | ||||||
|  | @ -50,6 +50,16 @@ namespace Utils { | ||||||
|             VkPipelineStageFlags pre, VkPipelineStageFlags post, |             VkPipelineStageFlags pre, VkPipelineStageFlags post, | ||||||
|             bool makeSrcPresentable, bool makeDstPresentable); |             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
 | #endif // UTILS_HPP
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| #include "context.hpp" | #include "context.hpp" | ||||||
| #include "utils.hpp" | #include "layer.hpp" | ||||||
|  | #include "utils/utils.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -36,6 +37,10 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain, | ||||||
|             VK_IMAGE_ASPECT_COLOR_BIT, |             VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
|             &out_n_fds.at(i)); |             &out_n_fds.at(i)); | ||||||
| 
 | 
 | ||||||
|  |     Utils::storeLayerEnv(); | ||||||
|  |     LSFG::initialize(); | ||||||
|  |     Utils::restoreLayerEnv(); | ||||||
|  | 
 | ||||||
|     this->lsfgCtxId = std::shared_ptr<int32_t>( |     this->lsfgCtxId = std::shared_ptr<int32_t>( | ||||||
|         new int32_t(LSFG::createContext(extent.width, extent.height, |         new int32_t(LSFG::createContext(extent.width, extent.height, | ||||||
|             frame_0_fd, frame_1_fd, out_n_fds)), |             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
 |         // 3. acquire next swapchain image
 | ||||||
|         pass.acquireSemaphores.at(i) = Mini::Semaphore(info.device); |         pass.acquireSemaphores.at(i) = Mini::Semaphore(info.device); | ||||||
|         uint32_t imageIdx{}; |         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); |             pass.acquireSemaphores.at(i).handle(), VK_NULL_HANDLE, &imageIdx); | ||||||
|         if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) |         if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) | ||||||
|             throw LSFG::vulkan_error(res, "Failed to acquire next swapchain image"); |             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, |             .pSwapchains = &this->swapchain, | ||||||
|             .pImageIndices = &imageIdx, |             .pImageIndices = &imageIdx, | ||||||
|         }; |         }; | ||||||
|         res = vkQueuePresentKHR(queue, &presentInfo); |         res = Layer::ovkQueuePresentKHR(queue, &presentInfo); | ||||||
|         if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) |         if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) | ||||||
|             throw LSFG::vulkan_error(res, "Failed to present swapchain image"); |             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, |         .pSwapchains = &this->swapchain, | ||||||
|         .pImageIndices = &presentIdx, |         .pImageIndices = &presentIdx, | ||||||
|     }; |     }; | ||||||
|     auto res = vkQueuePresentKHR(queue, &presentInfo); |     auto res = Layer::ovkQueuePresentKHR(queue, &presentInfo); | ||||||
|     if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) |     if (res != VK_SUCCESS && res != VK_SUBOPTIMAL_KHR) | ||||||
|         throw LSFG::vulkan_error(res, "Failed to present swapchain image"); |         throw LSFG::vulkan_error(res, "Failed to present swapchain image"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,14 @@ | ||||||
| #include "loader/dl.hpp" |  | ||||||
| #include "loader/vk.hpp" |  | ||||||
| #include "context.hpp" |  | ||||||
| #include "hooks.hpp" | #include "hooks.hpp" | ||||||
| #include "log.hpp" | #include "context.hpp" | ||||||
| #include "utils.hpp" | #include "layer.hpp" | ||||||
|  | #include "utils/log.hpp" | ||||||
|  | #include "utils/utils.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
| #include <string> | #include <string> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
|  | #include <vulkan/vulkan_core.h> | ||||||
| 
 | 
 | ||||||
| using namespace Hooks; | using namespace Hooks; | ||||||
| 
 | 
 | ||||||
|  | @ -20,11 +20,6 @@ namespace { | ||||||
|             const VkInstanceCreateInfo* pCreateInfo, |             const VkInstanceCreateInfo* pCreateInfo, | ||||||
|             const VkAllocationCallbacks* pAllocator, |             const VkAllocationCallbacks* pAllocator, | ||||||
|             VkInstance* pInstance) { |             VkInstance* pInstance) { | ||||||
|         // create lsfg
 |  | ||||||
|         Loader::DL::disableHooks(); |  | ||||||
|         LSFG::initialize(); |  | ||||||
|         Loader::DL::enableHooks(); |  | ||||||
| 
 |  | ||||||
|         // add extensions
 |         // add extensions
 | ||||||
|         auto extensions = Utils::addExtensions(pCreateInfo->ppEnabledExtensionNames, |         auto extensions = Utils::addExtensions(pCreateInfo->ppEnabledExtensionNames, | ||||||
|             pCreateInfo->enabledExtensionCount, { |             pCreateInfo->enabledExtensionCount, { | ||||||
|  | @ -33,24 +28,26 @@ namespace { | ||||||
|                 "VK_KHR_external_semaphore_capabilities" |                 "VK_KHR_external_semaphore_capabilities" | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|  |         Log::info("lsfg-vk: Created Vulkan instance"); | ||||||
|         VkInstanceCreateInfo createInfo = *pCreateInfo; |         VkInstanceCreateInfo createInfo = *pCreateInfo; | ||||||
|         createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); |         createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); | ||||||
|         createInfo.ppEnabledExtensionNames = extensions.data(); |         createInfo.ppEnabledExtensionNames = extensions.data(); | ||||||
|         return vkCreateInstance(&createInfo, pAllocator, pInstance); |         return Layer::ovkCreateInstance(&createInfo, pAllocator, pInstance); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void myvkDestroyInstance( |     void myvkDestroyInstance( | ||||||
|             VkInstance instance, |             VkInstance instance, | ||||||
|             const VkAllocationCallbacks* pAllocator) { |             const VkAllocationCallbacks* pAllocator) { | ||||||
|         LSFG::finalize(); // destroy lsfg
 |         LSFG::finalize(); // destroy lsfg
 | ||||||
|         vkDestroyInstance(instance, pAllocator); |         Log::info("lsfg-vk: Destroyed Vulkan instance"); | ||||||
|  |         Layer::ovkDestroyInstance(instance, pAllocator); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // device hooks
 |     // device hooks
 | ||||||
| 
 | 
 | ||||||
|     std::unordered_map<VkDevice, DeviceInfo> devices; |     std::unordered_map<VkDevice, DeviceInfo> devices; | ||||||
| 
 | 
 | ||||||
|     VkResult myvkCreateDevice( |     VkResult myvkCreateDevicePre( | ||||||
|             VkPhysicalDevice physicalDevice, |             VkPhysicalDevice physicalDevice, | ||||||
|             const VkDeviceCreateInfo* pCreateInfo, |             const VkDeviceCreateInfo* pCreateInfo, | ||||||
|             const VkAllocationCallbacks* pAllocator, |             const VkAllocationCallbacks* pAllocator, | ||||||
|  | @ -67,8 +64,14 @@ namespace { | ||||||
|         VkDeviceCreateInfo createInfo = *pCreateInfo; |         VkDeviceCreateInfo createInfo = *pCreateInfo; | ||||||
|         createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); |         createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); | ||||||
|         createInfo.ppEnabledExtensionNames = extensions.data(); |         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
 |         // store device info
 | ||||||
|         try { |         try { | ||||||
|             const char* frameGen = std::getenv("LSFG_MULTIPLIER"); |             const char* frameGen = std::getenv("LSFG_MULTIPLIER"); | ||||||
|  | @ -76,7 +79,7 @@ namespace { | ||||||
|             devices.emplace(*pDevice, DeviceInfo { |             devices.emplace(*pDevice, DeviceInfo { | ||||||
|                 .device = *pDevice, |                 .device = *pDevice, | ||||||
|                 .physicalDevice = physicalDevice, |                 .physicalDevice = physicalDevice, | ||||||
|                 .queue = Utils::findQueue(*pDevice, physicalDevice, &createInfo, |                 .queue = Utils::findQueue(*pDevice, physicalDevice, pCreateInfo, | ||||||
|                     VK_QUEUE_GRAPHICS_BIT), |                     VK_QUEUE_GRAPHICS_BIT), | ||||||
|                 .frameGen = std::max<size_t>(1, std::stoul(frameGen) - 1) |                 .frameGen = std::max<size_t>(1, std::stoul(frameGen) - 1) | ||||||
|             }); |             }); | ||||||
|  | @ -84,12 +87,16 @@ namespace { | ||||||
|             Log::error("Failed to create device info: {}", e.what()); |             Log::error("Failed to create device info: {}", e.what()); | ||||||
|             return VK_ERROR_INITIALIZATION_FAILED; |             return VK_ERROR_INITIALIZATION_FAILED; | ||||||
|         } |         } | ||||||
|         return res; | 
 | ||||||
|  |         Log::info("lsfg-vk: Created Vulkan device"); | ||||||
|  |         return VK_SUCCESS; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void myvkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) { |     void myvkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) { | ||||||
|         devices.erase(device); // erase device info
 |         devices.erase(device); // erase device info
 | ||||||
|         vkDestroyDevice(device, pAllocator); | 
 | ||||||
|  |         Log::info("lsfg-vk: Destroyed Vulkan device"); | ||||||
|  |         Layer::ovkDestroyDevice(device, pAllocator); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // swapchain hooks
 |     // 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_DST_BIT; // allow copy from/to images
 | ||||||
|         createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; |         createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; | ||||||
|         createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; // force vsync
 |         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) { |         if (res != VK_SUCCESS) { | ||||||
|             Log::error("Failed to create swapchain: {:x}", static_cast<uint32_t>(res)); |             Log::error("Failed to create swapchain: {:x}", static_cast<uint32_t>(res)); | ||||||
|             return res; |             return res; | ||||||
|  | @ -119,12 +126,12 @@ namespace { | ||||||
|         try { |         try { | ||||||
|             // get swapchain images
 |             // get swapchain images
 | ||||||
|             uint32_t imageCount{}; |             uint32_t imageCount{}; | ||||||
|             res = vkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, nullptr); |             res = Layer::ovkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, nullptr); | ||||||
|             if (res != VK_SUCCESS || imageCount == 0) |             if (res != VK_SUCCESS || imageCount == 0) | ||||||
|                 throw LSFG::vulkan_error(res, "Failed to get swapchain images count"); |                 throw LSFG::vulkan_error(res, "Failed to get swapchain images count"); | ||||||
| 
 | 
 | ||||||
|             std::vector<VkImage> swapchainImages(imageCount); |             std::vector<VkImage> swapchainImages(imageCount); | ||||||
|             res = vkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, swapchainImages.data()); |             res = Layer::ovkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, swapchainImages.data()); | ||||||
|             if (res != VK_SUCCESS) |             if (res != VK_SUCCESS) | ||||||
|                 throw LSFG::vulkan_error(res, "Failed to get swapchain images"); |                 throw LSFG::vulkan_error(res, "Failed to get swapchain images"); | ||||||
| 
 | 
 | ||||||
|  | @ -135,7 +142,6 @@ namespace { | ||||||
|             )); |             )); | ||||||
| 
 | 
 | ||||||
|             swapchainToDeviceTable.emplace(*pSwapchain, device); |             swapchainToDeviceTable.emplace(*pSwapchain, device); | ||||||
|             Log::debug("Created swapchain with {} images", imageCount); |  | ||||||
|         } catch (const LSFG::vulkan_error& e) { |         } catch (const LSFG::vulkan_error& e) { | ||||||
|             Log::error("Encountered Vulkan error {:x} while creating swapchain: {}", |             Log::error("Encountered Vulkan error {:x} while creating swapchain: {}", | ||||||
|                 static_cast<uint32_t>(e.error()), e.what()); |                 static_cast<uint32_t>(e.error()), e.what()); | ||||||
|  | @ -145,6 +151,7 @@ namespace { | ||||||
|             return VK_ERROR_INITIALIZATION_FAILED; |             return VK_ERROR_INITIALIZATION_FAILED; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         Log::info("lsfg-vk: Created swapchain with {} images", pCreateInfo->minImageCount); | ||||||
|         return res; |         return res; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -177,41 +184,24 @@ namespace { | ||||||
|             const VkAllocationCallbacks* pAllocator) { |             const VkAllocationCallbacks* pAllocator) { | ||||||
|         swapchains.erase(swapchain); // erase swapchain context
 |         swapchains.erase(swapchain); // erase swapchain context
 | ||||||
|         swapchainToDeviceTable.erase(swapchain); |         swapchainToDeviceTable.erase(swapchain); | ||||||
|         vkDestroySwapchainKHR(device, swapchain, pAllocator); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     bool initialized{false}; |         Log::info("lsfg-vk: Destroyed swapchain"); | ||||||
|  |         Layer::ovkDestroySwapchainKHR(device, swapchain, pAllocator); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Hooks::initialize() { | std::unordered_map<std::string, PFN_vkVoidFunction> Hooks::hooks = { | ||||||
|     if (initialized) { |     // instance hooks
 | ||||||
|         Log::warn("Vulkan hooks already initialized, did you call it twice?"); |     {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(myvkCreateInstance)}, | ||||||
|         return; |     {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(myvkDestroyInstance)}, | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     // list of hooks to register
 |     // device hooks
 | ||||||
|     const std::vector<std::pair<std::string, void*>> hooks = { |     {"vkCreateDevicePre", reinterpret_cast<PFN_vkVoidFunction>(myvkCreateDevicePre)}, | ||||||
|         { "vkCreateInstance",      reinterpret_cast<void*>(myvkCreateInstance) }, |     {"vkCreateDevicePost", reinterpret_cast<PFN_vkVoidFunction>(myvkCreateDevicePost)}, | ||||||
|         { "vkDestroyInstance",     reinterpret_cast<void*>(myvkDestroyInstance) }, |     {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(myvkDestroyDevice)}, | ||||||
|         { "vkCreateDevice",        reinterpret_cast<void*>(myvkCreateDevice) }, |  | ||||||
|         { "vkDestroyDevice",       reinterpret_cast<void*>(myvkDestroyDevice) }, |  | ||||||
|         { "vkCreateSwapchainKHR",  reinterpret_cast<void*>(myvkCreateSwapchainKHR) }, |  | ||||||
|         { "vkQueuePresentKHR",     reinterpret_cast<void*>(myvkQueuePresentKHR) }, |  | ||||||
|         { "vkDestroySwapchainKHR", reinterpret_cast<void*>(myvkDestroySwapchainKHR) } |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     // register hooks to Vulkan loader
 |     // swapchain hooks
 | ||||||
|     for (const auto& hook : hooks) |     {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(myvkCreateSwapchainKHR)}, | ||||||
|         Loader::VK::registerSymbol(hook.first, hook.second); |     {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(myvkQueuePresentKHR)}, | ||||||
| 
 |     {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(myvkDestroySwapchainKHR)} | ||||||
|     // 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"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								src/init.cpp
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								src/init.cpp
									
										
									
									
									
								
							|  | @ -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); |  | ||||||
| } |  | ||||||
							
								
								
									
										527
									
								
								src/layer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										527
									
								
								src/layer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,527 @@ | ||||||
|  | #include "layer.hpp" | ||||||
|  | #include "hooks.hpp" | ||||||
|  | #include "utils/log.hpp" | ||||||
|  | 
 | ||||||
|  | #include <lsfg.hpp> | ||||||
|  | #include <vulkan/vk_layer.h> | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <vulkan/vulkan_core.h> | ||||||
|  | 
 | ||||||
|  | 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<VkLayerInstanceCreateInfo*>( | ||||||
|  |             reinterpret_cast<const VkLayerInstanceCreateInfo*>(pCreateInfo->pNext)); | ||||||
|  |         while (layerDesc && (layerDesc->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO | ||||||
|  |                 || layerDesc->function != VK_LAYER_LINK_INFO)) { | ||||||
|  |             layerDesc = const_cast<VkLayerInstanceCreateInfo*>( | ||||||
|  |                 reinterpret_cast<const VkLayerInstanceCreateInfo*>(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<PFN_vkCreateInstance>( | ||||||
|  |             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<PFN_vkCreateInstance>( | ||||||
|  |             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<uint32_t>(res)); | ||||||
|  |             return res; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // get relevant function pointers from the next layer
 | ||||||
|  |         next_vkDestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>( | ||||||
|  |             next_vkGetInstanceProcAddr(*pInstance, "vkDestroyInstance")); | ||||||
|  |         next_vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>( | ||||||
|  |             next_vkGetInstanceProcAddr(*pInstance, "vkGetInstanceProcAddr")); | ||||||
|  |         next_vkGetPhysicalDeviceQueueFamilyProperties = | ||||||
|  |             reinterpret_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>( | ||||||
|  |                 next_vkGetInstanceProcAddr(*pInstance, "vkGetPhysicalDeviceQueueFamilyProperties")); | ||||||
|  |         next_vkGetPhysicalDeviceMemoryProperties = | ||||||
|  |             reinterpret_cast<PFN_vkGetPhysicalDeviceMemoryProperties>( | ||||||
|  |                 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<VkLayerDeviceCreateInfo*>( | ||||||
|  |             reinterpret_cast<const VkLayerDeviceCreateInfo*>(pCreateInfo->pNext)); | ||||||
|  |         while (layerDesc && (layerDesc->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO | ||||||
|  |                 || layerDesc->function != VK_LAYER_LINK_INFO)) { | ||||||
|  |             layerDesc = const_cast<VkLayerDeviceCreateInfo*>( | ||||||
|  |                 reinterpret_cast<const VkLayerDeviceCreateInfo*>(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<PFN_vkCreateDevice>( | ||||||
|  |             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<PFN_vkCreateDevice>( | ||||||
|  |             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<uint32_t>(res)); | ||||||
|  |             return res; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // get relevant function pointers from the next layer
 | ||||||
|  |         next_vkDestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkDestroyDevice")); | ||||||
|  |         next_vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCreateSwapchainKHR")); | ||||||
|  |         next_vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkQueuePresentKHR")); | ||||||
|  |         next_vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkDestroySwapchainKHR")); | ||||||
|  |         next_vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkGetSwapchainImagesKHR")); | ||||||
|  |         next_vkAllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkAllocateCommandBuffers")); | ||||||
|  |         next_vkFreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkFreeCommandBuffers")); | ||||||
|  |         next_vkBeginCommandBuffer = reinterpret_cast<PFN_vkBeginCommandBuffer>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkBeginCommandBuffer")); | ||||||
|  |         next_vkEndCommandBuffer = reinterpret_cast<PFN_vkEndCommandBuffer>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkEndCommandBuffer")); | ||||||
|  |         next_vkCreateCommandPool = reinterpret_cast<PFN_vkCreateCommandPool>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCreateCommandPool")); | ||||||
|  |         next_vkDestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkDestroyCommandPool")); | ||||||
|  |         next_vkCreateImage = reinterpret_cast<PFN_vkCreateImage>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCreateImage")); | ||||||
|  |         next_vkDestroyImage = reinterpret_cast<PFN_vkDestroyImage>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkDestroyImage")); | ||||||
|  |         next_vkGetImageMemoryRequirements = reinterpret_cast<PFN_vkGetImageMemoryRequirements>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkGetImageMemoryRequirements")); | ||||||
|  |         next_vkBindImageMemory = reinterpret_cast<PFN_vkBindImageMemory>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkBindImageMemory")); | ||||||
|  |         next_vkGetMemoryFdKHR = reinterpret_cast<PFN_vkGetMemoryFdKHR>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkGetMemoryFdKHR")); | ||||||
|  |         next_vkAllocateMemory = reinterpret_cast<PFN_vkAllocateMemory>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkAllocateMemory")); | ||||||
|  |         next_vkFreeMemory = reinterpret_cast<PFN_vkFreeMemory>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkFreeMemory")); | ||||||
|  |         next_vkCreateSemaphore = reinterpret_cast<PFN_vkCreateSemaphore>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCreateSemaphore")); | ||||||
|  |         next_vkDestroySemaphore = reinterpret_cast<PFN_vkDestroySemaphore>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkDestroySemaphore")); | ||||||
|  |         next_vkGetSemaphoreFdKHR = reinterpret_cast<PFN_vkGetSemaphoreFdKHR>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkGetSemaphoreFdKHR")); | ||||||
|  |         next_vkGetDeviceQueue = reinterpret_cast<PFN_vkGetDeviceQueue>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkGetDeviceQueue")); | ||||||
|  |         next_vkQueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkQueueSubmit")); | ||||||
|  |         next_vkCmdPipelineBarrier = reinterpret_cast<PFN_vkCmdPipelineBarrier>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCmdPipelineBarrier")); | ||||||
|  |         next_vkCmdPipelineBarrier2 = reinterpret_cast<PFN_vkCmdPipelineBarrier2>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCmdPipelineBarrier2")); | ||||||
|  |         next_vkCmdCopyImage = reinterpret_cast<PFN_vkCmdCopyImage>( | ||||||
|  |             next_vkGetDeviceProcAddr(*pDevice, "vkCmdCopyImage")); | ||||||
|  |         next_vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>( | ||||||
|  |             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<PFN_vkCreateDevice>( | ||||||
|  |             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<uint32_t>(res)); | ||||||
|  |             return res; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Log::debug("lsfg-vk(layer): Successfully initialized lsfg-vk device layer"); | ||||||
|  |         return res; | ||||||
|  |     } // NOLINTEND
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const std::unordered_map<std::string, PFN_vkVoidFunction> layerFunctions = { | ||||||
|  |     { "vkCreateInstance", | ||||||
|  |         reinterpret_cast<PFN_vkVoidFunction>(&layer_vkCreateInstance) }, | ||||||
|  |     { "vkGetInstanceProcAddr", | ||||||
|  |         reinterpret_cast<PFN_vkVoidFunction>(&layer_vkGetInstanceProcAddr) }, | ||||||
|  |     { "vkGetDeviceProcAddr", | ||||||
|  |         reinterpret_cast<PFN_vkVoidFunction>(&layer_vkGetDeviceProcAddr) }, | ||||||
|  |     { "vkCreateDevice", | ||||||
|  |         reinterpret_cast<PFN_vkVoidFunction>(&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); | ||||||
|  | } | ||||||
|  | @ -1,182 +0,0 @@ | ||||||
| #include "loader/dl.hpp" |  | ||||||
| #include "log.hpp" |  | ||||||
| 
 |  | ||||||
| #include <vector> |  | ||||||
| 
 |  | ||||||
| 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<std::string, DL::File> overrides; |  | ||||||
|         return overrides; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // vector of loaded handles
 |  | ||||||
|     auto& handles() { |  | ||||||
|         static std::vector<void*> 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<dlopen_t> (dlvsym(-1, "dlopen",  "GLIBC_2.2.5")); |  | ||||||
|     dlsym_ptr   = reinterpret_cast<dlsym_t>  (dlvsym(-1, "dlsym",   "GLIBC_2.2.5")); |  | ||||||
|     dlclose_ptr = reinterpret_cast<dlclose_t>(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<void*>(&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); |  | ||||||
| } |  | ||||||
|  | @ -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<std::string, void*> 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<PFN_vkGetInstanceProcAddr>(DL::odlsym(handle, "vkGetInstanceProcAddr")); |  | ||||||
|     vkGetDeviceProcAddr_ptr = |  | ||||||
|         reinterpret_cast<PFN_vkGetDeviceProcAddr>  (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<void*>(myvkGetInstanceProcAddr)); |  | ||||||
|     vulkanLib.defineSymbol("vkGetDeviceProcAddr", |  | ||||||
|         reinterpret_cast<void*>(myvkGetDeviceProcAddr)); |  | ||||||
|     DL::registerFile(vulkanLib); |  | ||||||
| 
 |  | ||||||
|     DL::File vulkanLib2{"libvulkan.so"}; |  | ||||||
|     vulkanLib2.defineSymbol("vkGetInstanceProcAddr", |  | ||||||
|         reinterpret_cast<void*>(myvkGetInstanceProcAddr)); |  | ||||||
|     vulkanLib2.defineSymbol("vkGetDeviceProcAddr", |  | ||||||
|         reinterpret_cast<void*>(myvkGetDeviceProcAddr)); |  | ||||||
|     DL::registerFile(vulkanLib2); |  | ||||||
| 
 |  | ||||||
|     // register vulkan loader overrides
 |  | ||||||
|     VK::registerSymbol("vkGetInstanceProcAddr", reinterpret_cast<void*>(myvkGetInstanceProcAddr)); |  | ||||||
|     VK::registerSymbol("vkGetDeviceProcAddr", reinterpret_cast<void*>(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<PFN_vkVoidFunction>(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<PFN_vkVoidFunction>(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); |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include "mini/commandbuffer.hpp" | #include "mini/commandbuffer.hpp" | ||||||
|  | #include "layer.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -13,7 +14,7 @@ CommandBuffer::CommandBuffer(VkDevice device, const CommandPool& pool) { | ||||||
|         .commandBufferCount = 1 |         .commandBufferCount = 1 | ||||||
|     }; |     }; | ||||||
|     VkCommandBuffer commandBufferHandle{}; |     VkCommandBuffer commandBufferHandle{}; | ||||||
|     auto res = vkAllocateCommandBuffers(device, &desc, &commandBufferHandle); |     auto res = Layer::ovkAllocateCommandBuffers(device, &desc, &commandBufferHandle); | ||||||
|     if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE) |     if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to allocate command buffer"); |         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<VkCommandBuffer>( |     this->commandBuffer = std::shared_ptr<VkCommandBuffer>( | ||||||
|         new VkCommandBuffer(commandBufferHandle), |         new VkCommandBuffer(commandBufferHandle), | ||||||
|         [dev = device, pool = pool.handle()](VkCommandBuffer* cmdBuffer) { |         [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, |         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | ||||||
|         .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |         .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) |     if (res != VK_SUCCESS) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to begin command buffer"); |         throw LSFG::vulkan_error(res, "Unable to begin command buffer"); | ||||||
| 
 | 
 | ||||||
|  | @ -46,7 +47,7 @@ void CommandBuffer::end() { | ||||||
|     if (*this->state != CommandBufferState::Recording) |     if (*this->state != CommandBufferState::Recording) | ||||||
|         throw std::logic_error("Command buffer is not in Recording state"); |         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) |     if (res != VK_SUCCESS) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to end command buffer"); |         throw LSFG::vulkan_error(res, "Unable to end command buffer"); | ||||||
| 
 | 
 | ||||||
|  | @ -72,7 +73,7 @@ void CommandBuffer::submit(VkQueue queue, | ||||||
|         .signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()), |         .signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()), | ||||||
|         .pSignalSemaphores = signalSemaphores.data() |         .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) |     if (res != VK_SUCCESS) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to submit command buffer"); |         throw LSFG::vulkan_error(res, "Unable to submit command buffer"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include "mini/commandpool.hpp" | #include "mini/commandpool.hpp" | ||||||
|  | #include "layer.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -11,7 +12,7 @@ CommandPool::CommandPool(VkDevice device, uint32_t graphicsFamilyIdx) { | ||||||
|         .queueFamilyIndex = graphicsFamilyIdx |         .queueFamilyIndex = graphicsFamilyIdx | ||||||
|     }; |     }; | ||||||
|     VkCommandPool commandPoolHandle{}; |     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) |     if (res != VK_SUCCESS || commandPoolHandle == VK_NULL_HANDLE) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to create command pool"); |         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<VkCommandPool>( |     this->commandPool = std::shared_ptr<VkCommandPool>( | ||||||
|         new VkCommandPool(commandPoolHandle), |         new VkCommandPool(commandPoolHandle), | ||||||
|         [dev = device](VkCommandPool* commandPoolHandle) { |         [dev = device](VkCommandPool* commandPoolHandle) { | ||||||
|             vkDestroyCommandPool(dev, *commandPoolHandle, nullptr); |             Layer::ovkDestroyCommandPool(dev, *commandPoolHandle, nullptr); | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include "mini/image.hpp" | #include "mini/image.hpp" | ||||||
|  | #include "layer.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -32,16 +33,16 @@ Image::Image(VkDevice device, VkPhysicalDevice physicalDevice, | ||||||
|         .sharingMode = VK_SHARING_MODE_EXCLUSIVE |         .sharingMode = VK_SHARING_MODE_EXCLUSIVE | ||||||
|     }; |     }; | ||||||
|     VkImage imageHandle{}; |     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) |     if (res != VK_SUCCESS || imageHandle == VK_NULL_HANDLE) | ||||||
|         throw LSFG::vulkan_error(res, "Failed to create Vulkan image"); |         throw LSFG::vulkan_error(res, "Failed to create Vulkan image"); | ||||||
| 
 | 
 | ||||||
|     // find memory type
 |     // find memory type
 | ||||||
|     VkPhysicalDeviceMemoryProperties memProps; |     VkPhysicalDeviceMemoryProperties memProps; | ||||||
|     vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); |     Layer::ovkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); | ||||||
| 
 | 
 | ||||||
|     VkMemoryRequirements memReqs; |     VkMemoryRequirements memReqs; | ||||||
|     vkGetImageMemoryRequirements(device, imageHandle, &memReqs); |     Layer::ovkGetImageMemoryRequirements(device, imageHandle, &memReqs); | ||||||
| 
 | 
 | ||||||
| #pragma clang diagnostic push | #pragma clang diagnostic push | ||||||
| #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" | #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" | ||||||
|  | @ -74,24 +75,21 @@ Image::Image(VkDevice device, VkPhysicalDevice physicalDevice, | ||||||
|         .memoryTypeIndex = memType.value() |         .memoryTypeIndex = memType.value() | ||||||
|     }; |     }; | ||||||
|     VkDeviceMemory memoryHandle{}; |     VkDeviceMemory memoryHandle{}; | ||||||
|     res = vkAllocateMemory(device, &allocInfo, nullptr, &memoryHandle); |     res = Layer::ovkAllocateMemory(device, &allocInfo, nullptr, &memoryHandle); | ||||||
|     if (res != VK_SUCCESS || memoryHandle == VK_NULL_HANDLE) |     if (res != VK_SUCCESS || memoryHandle == VK_NULL_HANDLE) | ||||||
|         throw LSFG::vulkan_error(res, "Failed to allocate memory for Vulkan image"); |         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) |     if (res != VK_SUCCESS) | ||||||
|         throw LSFG::vulkan_error(res, "Failed to bind memory to Vulkan image"); |         throw LSFG::vulkan_error(res, "Failed to bind memory to Vulkan image"); | ||||||
| 
 | 
 | ||||||
|     // obtain the sharing fd
 |     // obtain the sharing fd
 | ||||||
|     auto vkGetMemoryFdKHR = |  | ||||||
|         reinterpret_cast<PFN_vkGetMemoryFdKHR>(vkGetDeviceProcAddr(device, "vkGetMemoryFdKHR")); |  | ||||||
| 
 |  | ||||||
|     const VkMemoryGetFdInfoKHR fdInfo{ |     const VkMemoryGetFdInfoKHR fdInfo{ | ||||||
|         .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, |         .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, | ||||||
|         .memory = memoryHandle, |         .memory = memoryHandle, | ||||||
|         .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR, |         .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) |     if (res != VK_SUCCESS || *fd < 0) | ||||||
|         throw LSFG::vulkan_error(res, "Failed to obtain sharing fd for Vulkan image"); |         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<VkImage>( |     this->image = std::shared_ptr<VkImage>( | ||||||
|         new VkImage(imageHandle), |         new VkImage(imageHandle), | ||||||
|         [dev = device](VkImage* img) { |         [dev = device](VkImage* img) { | ||||||
|             vkDestroyImage(dev, *img, nullptr); |             Layer::ovkDestroyImage(dev, *img, nullptr); | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|     this->memory = std::shared_ptr<VkDeviceMemory>( |     this->memory = std::shared_ptr<VkDeviceMemory>( | ||||||
|         new VkDeviceMemory(memoryHandle), |         new VkDeviceMemory(memoryHandle), | ||||||
|         [dev = device](VkDeviceMemory* mem) { |         [dev = device](VkDeviceMemory* mem) { | ||||||
|             vkFreeMemory(dev, *mem, nullptr); |             Layer::ovkFreeMemory(dev, *mem, nullptr); | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include "mini/semaphore.hpp" | #include "mini/semaphore.hpp" | ||||||
|  | #include "layer.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -10,7 +11,7 @@ Semaphore::Semaphore(VkDevice device) { | ||||||
|         .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO |         .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO | ||||||
|     }; |     }; | ||||||
|     VkSemaphore semaphoreHandle{}; |     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) |     if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to create semaphore"); |         throw LSFG::vulkan_error(res, "Unable to create semaphore"); | ||||||
| 
 | 
 | ||||||
|  | @ -18,7 +19,7 @@ Semaphore::Semaphore(VkDevice device) { | ||||||
|     this->semaphore = std::shared_ptr<VkSemaphore>( |     this->semaphore = std::shared_ptr<VkSemaphore>( | ||||||
|         new VkSemaphore(semaphoreHandle), |         new VkSemaphore(semaphoreHandle), | ||||||
|         [dev = device](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 |         .pNext = &exportInfo | ||||||
|     }; |     }; | ||||||
|     VkSemaphore semaphoreHandle{}; |     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) |     if (res != VK_SUCCESS || semaphoreHandle == VK_NULL_HANDLE) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to create semaphore"); |         throw LSFG::vulkan_error(res, "Unable to create semaphore"); | ||||||
| 
 | 
 | ||||||
|     // export semaphore to fd
 |     // export semaphore to fd
 | ||||||
|     auto vkGetSemaphoreFdKHR = reinterpret_cast<PFN_vkGetSemaphoreFdKHR>( |  | ||||||
|         vkGetDeviceProcAddr(device, "vkGetSemaphoreFdKHR")); |  | ||||||
| 
 |  | ||||||
|     const VkSemaphoreGetFdInfoKHR fdInfo{ |     const VkSemaphoreGetFdInfoKHR fdInfo{ | ||||||
|         .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, |         .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, | ||||||
|         .semaphore = semaphoreHandle, |         .semaphore = semaphoreHandle, | ||||||
|         .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |         .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) |     if (res != VK_SUCCESS || *fd < 0) | ||||||
|         throw LSFG::vulkan_error(res, "Unable to export semaphore to fd"); |         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<VkSemaphore>( |     this->semaphore = std::shared_ptr<VkSemaphore>( | ||||||
|         new VkSemaphore(semaphoreHandle), |         new VkSemaphore(semaphoreHandle), | ||||||
|         [dev = device](VkSemaphore* semaphoreHandle) { |         [dev = device](VkSemaphore* semaphoreHandle) { | ||||||
|             vkDestroySemaphore(dev, *semaphoreHandle, nullptr); |             Layer::ovkDestroySemaphore(dev, *semaphoreHandle, nullptr); | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,9 +1,11 @@ | ||||||
| #include "utils/utils.hpp" | #include "utils/utils.hpp" | ||||||
|  | #include "layer.hpp" | ||||||
| 
 | 
 | ||||||
| #include <lsfg.hpp> | #include <lsfg.hpp> | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <optional> | #include <optional> | ||||||
|  | #include <string> | ||||||
| 
 | 
 | ||||||
| using namespace Utils; | using namespace Utils; | ||||||
| 
 | 
 | ||||||
|  | @ -13,9 +15,9 @@ std::pair<uint32_t, VkQueue> Utils::findQueue(VkDevice device, VkPhysicalDevice | ||||||
|     std::copy_n(desc->pQueueCreateInfos, enabledQueues.size(), enabledQueues.data()); |     std::copy_n(desc->pQueueCreateInfos, enabledQueues.size(), enabledQueues.data()); | ||||||
| 
 | 
 | ||||||
|     uint32_t familyCount{}; |     uint32_t familyCount{}; | ||||||
|     vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, nullptr); |     Layer::ovkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, nullptr); | ||||||
|     std::vector<VkQueueFamilyProperties> families(familyCount); |     std::vector<VkQueueFamilyProperties> families(familyCount); | ||||||
|     vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, |     Layer::ovkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, | ||||||
|         families.data()); |         families.data()); | ||||||
| 
 | 
 | ||||||
|     std::optional<uint32_t> idx; |     std::optional<uint32_t> idx; | ||||||
|  | @ -30,7 +32,7 @@ std::pair<uint32_t, VkQueue> Utils::findQueue(VkDevice device, VkPhysicalDevice | ||||||
|         throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No suitable queue found"); |         throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED, "No suitable queue found"); | ||||||
| 
 | 
 | ||||||
|     VkQueue queue{}; |     VkQueue queue{}; | ||||||
|     vkGetDeviceQueue(device, *idx, 0, &queue); |     Layer::ovkGetDeviceQueue(device, *idx, 0, &queue); | ||||||
| 
 | 
 | ||||||
|     return { *idx, queue }; |     return { *idx, queue }; | ||||||
| } | } | ||||||
|  | @ -78,7 +80,7 @@ void Utils::copyImage(VkCommandBuffer buf, | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|     const std::vector<VkImageMemoryBarrier> barriers = { srcBarrier, dstBarrier }; |     const std::vector<VkImageMemoryBarrier> barriers = { srcBarrier, dstBarrier }; | ||||||
|     vkCmdPipelineBarrier(buf, |     Layer::ovkCmdPipelineBarrier(buf, | ||||||
|         pre, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, |         pre, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, | ||||||
|         0, nullptr, 0, nullptr, |         0, nullptr, 0, nullptr, | ||||||
|         static_cast<uint32_t>(barriers.size()), barriers.data()); |         static_cast<uint32_t>(barriers.size()), barriers.data()); | ||||||
|  | @ -98,7 +100,7 @@ void Utils::copyImage(VkCommandBuffer buf, | ||||||
|             .depth = 1 |             .depth = 1 | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|     vkCmdCopyImage(buf, |     Layer::ovkCmdCopyImage(buf, | ||||||
|         src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |         src, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, | ||||||
|         dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |         dst, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||||
|         1, &imageCopy); |         1, &imageCopy); | ||||||
|  | @ -115,7 +117,7 @@ void Utils::copyImage(VkCommandBuffer buf, | ||||||
|                 .layerCount = 1 |                 .layerCount = 1 | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         vkCmdPipelineBarrier(buf, |         Layer::ovkCmdPipelineBarrier(buf, | ||||||
|             VK_PIPELINE_STAGE_TRANSFER_BIT, post, 0, |             VK_PIPELINE_STAGE_TRANSFER_BIT, post, 0, | ||||||
|             0, nullptr, 0, nullptr, |             0, nullptr, 0, nullptr, | ||||||
|             1, &presentBarrier); |             1, &presentBarrier); | ||||||
|  | @ -135,10 +137,29 @@ void Utils::copyImage(VkCommandBuffer buf, | ||||||
|                 .layerCount = 1 |                 .layerCount = 1 | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         vkCmdPipelineBarrier(buf, |         Layer::ovkCmdPipelineBarrier(buf, | ||||||
|             VK_PIPELINE_STAGE_TRANSFER_BIT, post, 0, |             VK_PIPELINE_STAGE_TRANSFER_BIT, post, 0, | ||||||
|             0, nullptr, 0, nullptr, |             0, nullptr, 0, nullptr, | ||||||
|             1, &presentBarrier); |             1, &presentBarrier); | ||||||
|     } |     } | ||||||
| 
 | } | ||||||
|  | 
 | ||||||
|  | namespace { | ||||||
|  |     std::optional<std::string> 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"); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 PancakeTAS
						PancakeTAS