refactor(cleanup): base of new layer

This commit is contained in:
PancakeTAS 2025-12-11 20:20:00 +01:00
parent b70b403297
commit d8888a2caf
10 changed files with 383 additions and 782 deletions

View file

@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10)
project(lsfg-vk LANGUAGES CXX)
# === user facing options
option(LSFGVK_BUILD_VULKAN_LAYER
"Build the Vulkan layer" ON)
option(LSFGVK_BUILD_DEBUG_TOOL
"Build the debug tool for testing and debugging" OFF)
@ -25,6 +27,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
-Wno-c++98-compat-pedantic
-Wno-switch-default
-Wno-switch-enum
# allow global deconstructors
-Wno-exit-time-destructors
# disable noisy warnings
-Wno-missing-designated-field-initializers
-Wno-cast-function-type-strict
@ -40,6 +44,9 @@ endif()
add_subdirectory(lsfg-vk-common)
add_subdirectory(lsfg-vk-backend)
if(LSFGVK_BUILD_VULKAN_LAYER)
add_subdirectory(lsfg-vk-layer)
endif()
if(LSFGVK_BUILD_DEBUG_TOOL)
add_subdirectory(lsfg-vk-debug)
endif()

View file

@ -1,18 +0,0 @@
{
"file_format_version": "1.0.0",
"layer": {
"name": "VK_LAYER_LS_frame_generation",
"type": "GLOBAL",
"api_version": "1.4.313",
"library_path": "liblsfg-vk.so",
"implementation_version": "1",
"description": "Lossless Scaling frame generation layer",
"functions": {
"vkGetInstanceProcAddr": "layer_vkGetInstanceProcAddr",
"vkGetDeviceProcAddr": "layer_vkGetDeviceProcAddr"
},
"disable_environment": {
"DISABLE_LSFG": "1"
}
}
}

View file

@ -1,228 +0,0 @@
#pragma once
#include <vulkan/vulkan_core.h>
#include <cstdint>
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 vkSetDeviceLoaderData function.
VkResult ovkSetDeviceLoaderData(
VkDevice device,
void* object);
/// 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 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 vkGetPhysicalDeviceProperties function.
void ovkGetPhysicalDeviceProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties);
/// Call to the original vkGetPhysicalDeviceSurfaceCapabilitiesKHR function.
VkResult ovkGetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
/// 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 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 vkCmdBlitImage function.
void ovkCmdBlitImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit* pRegions,
VkFilter filter);
/// 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"
[[gnu::visibility("default")]]
PFN_vkVoidFunction layer_vkGetInstanceProcAddr(VkInstance instance, const char* pName);
/// Symbol definition for Vulkan device layer.
extern "C"
[[gnu::visibility("default")]]
PFN_vkVoidFunction layer_vkGetDeviceProcAddr(VkDevice device, const char* pName);

38
lsfg-vk-layer/.clang-tidy Normal file
View file

@ -0,0 +1,38 @@
Checks:
# enable basic checks
- "clang-analyzer-*"
# configure performance checks
- "performance-*"
- "-performance-enum-size"
# configure readability and bugprone checks
- "readability-*"
- "bugprone-*"
- "misc-*"
- "-readability-braces-around-statements"
- "-readability-function-cognitive-complexity"
- "-readability-identifier-length"
- "-readability-implicit-bool-conversion"
- "-readability-magic-numbers"
- "-readability-math-missing-parentheses"
- "-readability-named-parameter"
- "-bugprone-easily-swappable-parameters"
# configure modernization
- "modernize-*"
- "-modernize-use-trailing-return-type"
# configure cppcoreguidelines
- "cppcoreguidelines-*"
- "-cppcoreguidelines-avoid-magic-numbers"
- "-cppcoreguidelines-pro-type-reinterpret-cast"
- "-cppcoreguidelines-macro-usage"
- "-cppcoreguidelines-pro-type-union-access"
- "-cppcoreguidelines-avoid-non-const-global-variables"
# disable slow and pointless checks
- "-modernize-use-std-numbers"
- "-modernize-type-traits"
- "-cppcoreguidelines-owning-memory"
- "-cppcoreguidelines-macro-to-enum"
- "-readability-container-contains"
- "-bugprone-reserved-identifier"
- "-bugprone-stringview-nullptr"
- "-bugprone-standalone-empty"
- "-misc-unused-using-decls"

View file

@ -0,0 +1,12 @@
set(LAYER_SOURCES
"src/entrypoint.cpp"
"src/layer.cpp")
add_library(lsfg-vk-layer SHARED ${LAYER_SOURCES})
target_link_libraries(lsfg-vk-layer
PUBLIC lsfg-vk-common
PUBLIC lsfg-vk-backend)
set_target_properties(lsfg-vk-layer PROPERTIES
CXX_VISIBILITY_PRESET hidden)

View file

@ -0,0 +1,14 @@
{
"file_format_version": "1.1.0",
"layer": {
"name": "VK_LAYER_LS_frame_generation",
"description": "Lossless Scaling frame generation layer",
"implementation_version": "2",
"library_path": "liblsfg-vk-layer.so",
"type": "GLOBAL",
"api_version": "1.4.328",
"disable_environment": {
"DISABLE_LSFG": "1"
}
}
}

View file

@ -0,0 +1,257 @@
#include "layer.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan_core.h>
namespace {
/// reinterpret cast helper with const_cast
template<typename T, typename U>
T vcast(U ptr) {
return reinterpret_cast<T>(const_cast<void*>(ptr)); // NOLINT
}
/// helper function to add required extensions
std::vector<const char*> add_extensions(const char* const* existingExtensions, size_t count,
const std::vector<std::string>& requiredExtensions) {
std::vector<const char*> extensions(count);
std::copy_n(existingExtensions, count, extensions.data());
for (const auto& requiredExtension : requiredExtensions) {
auto it = std::ranges::find_if(extensions,
[requiredExtension](const char* extension) {
return std::string(extension) == requiredExtension;
});
if (it == extensions.end())
extensions.push_back(requiredExtension.c_str());
}
return extensions;
}
}
namespace {
PFN_vkGetInstanceProcAddr nxvkGetInstanceProcAddr{nullptr};
PFN_vkGetDeviceProcAddr nxvkGetDeviceProcAddr = nullptr;
VkInstance gInstance{VK_NULL_HANDLE}; // if there are multiple instances, we scream out loud, oke?
// create instance
VkResult myvkCreateInstance(
const VkInstanceCreateInfo* info,
const VkAllocationCallbacks* alloc,
VkInstance* instance) {
// apply layer chaining
auto* layerInfo = vcast<VkLayerInstanceCreateInfo*>(info->pNext);
while (layerInfo && (layerInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
|| layerInfo->function != VK_LAYER_LINK_INFO)) {
layerInfo = vcast<VkLayerInstanceCreateInfo*>(layerInfo->pNext);
}
if (!layerInfo) {
std::cerr << "lsfg-vk: no layer info found in pNext chain, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
auto* linkInfo = layerInfo->u.pLayerInfo;
if (!linkInfo) {
std::cerr << "lsfg-vk: link info is null, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
nxvkGetInstanceProcAddr = linkInfo->pfnNextGetInstanceProcAddr;
if (!nxvkGetInstanceProcAddr) {
std::cerr << "lsfg-vk: next layer's vkGetInstanceProcAddr is null, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
layerInfo->u.pLayerInfo = linkInfo->pNext; // advance for next layer
// create instance
auto* vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(
nxvkGetInstanceProcAddr(nullptr, "vkCreateInstance"));
if (!vkCreateInstance) {
std::cerr << "lsfg-vk: failed to get next layer's vkCreateInstance, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
auto requiredExtensions = lsfgvk::requiredInstanceExtensions();
auto extensions = add_extensions(
info->ppEnabledExtensionNames,
info->enabledExtensionCount,
requiredExtensions);
VkInstanceCreateInfo newInfo = *info;
newInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
newInfo.ppEnabledExtensionNames = extensions.data();
auto res = vkCreateInstance(&newInfo, alloc, instance);
if (res == VK_ERROR_EXTENSION_NOT_PRESENT)
std::cerr << "lsfg-vk: required Vulkan instance extensions are not present. "
"Your GPU driver is not supported.\n";
if (res != VK_SUCCESS)
return res;
gInstance = *instance;
return VK_SUCCESS;
}
// map of devices to layer instances
std::unordered_map<VkDevice, lsfgvk::LayerInstance>& device2InstanceMap() {
static std::unordered_map<VkDevice, lsfgvk::LayerInstance> map; // NOLINT
return map;
}
// create device
VkResult myvkCreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* info,
const VkAllocationCallbacks* alloc,
VkDevice* device) {
// apply layer chaining
auto* layerInfo = vcast<VkLayerDeviceCreateInfo*>(info->pNext);
while (layerInfo && (layerInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
|| layerInfo->function != VK_LAYER_LINK_INFO)) {
layerInfo = vcast<VkLayerDeviceCreateInfo*>(layerInfo->pNext);
}
if (!layerInfo) {
std::cerr << "lsfg-vk: no layer info found in pNext chain, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
auto* linkInfo = layerInfo->u.pLayerInfo;
if (!linkInfo) {
std::cerr << "lsfg-vk: link info is null, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
nxvkGetDeviceProcAddr = linkInfo->pfnNextGetDeviceProcAddr;
if (!nxvkGetDeviceProcAddr) {
std::cerr << "lsfg-vk: next layer's vkGetDeviceProcAddr is null, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
layerInfo->u.pLayerInfo = linkInfo->pNext; // advance for next layer
// fetch device loader functions
layerInfo = vcast<VkLayerDeviceCreateInfo*>(info->pNext);
while (layerInfo && (layerInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
|| layerInfo->function != VK_LOADER_DATA_CALLBACK)) {
layerInfo = vcast<VkLayerDeviceCreateInfo*>(layerInfo->pNext);
}
if (!layerInfo) {
std::cerr << "lsfg-vk: no layer loader data found in pNext chain.\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
auto* setLoaderData = layerInfo->u.pfnSetDeviceLoaderData;
if (!setLoaderData) {
std::cerr << "lsfg-vk: instance loader data function is null.\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
// create device
auto* vkCreateDevice = reinterpret_cast<PFN_vkCreateDevice>(
nxvkGetInstanceProcAddr(gInstance, "vkCreateDevice"));
if (!vkCreateDevice) {
std::cerr << "lsfg-vk: failed to get next layer's vkCreateDevice, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
}
auto requiredExtensions = lsfgvk::requiredDeviceExtensions();
auto extensions = add_extensions(
info->ppEnabledExtensionNames,
info->enabledExtensionCount,
requiredExtensions);
VkDeviceCreateInfo newInfo = *info;
newInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
newInfo.ppEnabledExtensionNames = extensions.data();
auto res = vkCreateDevice(physicalDevice, &newInfo, alloc, device);
if (res == VK_ERROR_EXTENSION_NOT_PRESENT)
std::cerr << "lsfg-vk: required Vulkan device extensions are not present. "
"Your GPU driver is not supported.\n";
if (res != VK_SUCCESS)
return res;
// create layer instance
try {
device2InstanceMap().emplace(*device,
lsfgvk::LayerInstance(gInstance, *device, setLoaderData));
} catch (const std::exception& e) {
std::cerr << "lsfg-vk: something went wrong during lsfg-vk initialization:\n";
std::cerr << "- " << e.what() << '\n';
}
return VK_SUCCESS;
}
PFN_vkVoidFunction getProcAddr(const std::string& name);
// get instance-level function pointers
PFN_vkVoidFunction myvkGetInstanceProcAddr(VkInstance instance, const char* pName) {
if (!pName) return nullptr;
auto func = getProcAddr(pName);
if (func) return func;
if (!nxvkGetInstanceProcAddr) return nullptr;
return nxvkGetInstanceProcAddr(instance, pName);
}
// get device-level function pointers
PFN_vkVoidFunction myvkGetDeviceProcAddr(VkDevice device, const char* pName) {
if (!pName) return nullptr;
auto func = getProcAddr(pName);
if (func) return func;
if (!nxvkGetDeviceProcAddr) return nullptr;
return nxvkGetDeviceProcAddr(device, pName);
}
// get optional function pointer override
PFN_vkVoidFunction getProcAddr(const std::string& name) {
if (name == "vkCreateInstance")
return reinterpret_cast<PFN_vkVoidFunction>(&myvkCreateInstance);
if (name == "vkCreateDevice")
return reinterpret_cast<PFN_vkVoidFunction>(&myvkCreateDevice);
return nullptr;
}
}
/// Vulkan layer entrypoint
__attribute__((visibility("default")))
VkResult vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* pVersionStruct) {
// ensure loader compatibility
if (!pVersionStruct
|| pVersionStruct->sType != LAYER_NEGOTIATE_INTERFACE_STRUCT
|| pVersionStruct->loaderLayerInterfaceVersion < 2)
return VK_ERROR_INITIALIZATION_FAILED;
// emplace function pointers/version
pVersionStruct->loaderLayerInterfaceVersion = 2;
pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
pVersionStruct->pfnGetDeviceProcAddr = myvkGetDeviceProcAddr;
pVersionStruct->pfnGetInstanceProcAddr = myvkGetInstanceProcAddr;
return VK_SUCCESS;
}

View file

@ -0,0 +1,25 @@
#include "layer.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan_core.h>
using namespace lsfgvk;
std::vector<std::string> lsfgvk::requiredInstanceExtensions() noexcept {
return {};
}
std::vector<std::string> lsfgvk::requiredDeviceExtensions() noexcept {
return {};
}
lsfgvk::LayerInstance::LayerInstance(VkInstance instance, VkDevice device,
PFN_vkSetDeviceLoaderData setLoaderData) {
std::cerr << "lsfg-vk: Hello, world!\n";
std::cerr << "lsfg-vk: instance=" << instance << ", device=" << device << '\n';
std::cerr << "lsfg-vk: setLoaderData=" << reinterpret_cast<void*>(setLoaderData) << '\n';
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <vector>
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan_core.h>
namespace lsfgvk {
/// required instance extensions
/// @return list of extension names
std::vector<std::string> requiredInstanceExtensions() noexcept;
/// required device extensions
/// @return list of extension names
std::vector<std::string> requiredDeviceExtensions() noexcept;
/// instance of the lsfg-vk layer on a VkInstance/VkDevice pair.
class LayerInstance {
public:
/// create a new layer instance
/// @param instance Vulkan instance
/// @param device Vulkan device
/// @param setLoaderData function to set device loader data
LayerInstance(VkInstance instance, VkDevice device,
PFN_vkSetDeviceLoaderData setLoaderData);
};
}

View file

@ -1,536 +0,0 @@
#include "layer.hpp"
#include "common/exception.hpp"
#include "config/config.hpp"
#include "hooks.hpp"
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan_core.h>
#include <unordered_map>
#include <exception>
#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <string>
namespace {
PFN_vkCreateInstance next_vkCreateInstance{};
PFN_vkDestroyInstance next_vkDestroyInstance{};
PFN_vkCreateDevice next_vkCreateDevice{};
PFN_vkDestroyDevice next_vkDestroyDevice{};
PFN_vkSetDeviceLoaderData next_vSetDeviceLoaderData{};
PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr{};
PFN_vkGetDeviceProcAddr next_vkGetDeviceProcAddr{};
PFN_vkGetPhysicalDeviceQueueFamilyProperties next_vkGetPhysicalDeviceQueueFamilyProperties{};
PFN_vkGetPhysicalDeviceMemoryProperties next_vkGetPhysicalDeviceMemoryProperties{};
PFN_vkGetPhysicalDeviceProperties next_vkGetPhysicalDeviceProperties{};
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR next_vkGetPhysicalDeviceSurfaceCapabilitiesKHR{};
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_vkGetDeviceQueue next_vkGetDeviceQueue{};
PFN_vkQueueSubmit next_vkQueueSubmit{};
PFN_vkCmdPipelineBarrier next_vkCmdPipelineBarrier{};
PFN_vkCmdBlitImage next_vkCmdBlitImage{};
PFN_vkAcquireNextImageKHR next_vkAcquireNextImageKHR{};
template<typename T>
bool initInstanceFunc(VkInstance instance, const char* name, T* func) {
*func = reinterpret_cast<T>(next_vkGetInstanceProcAddr(instance, name));
if (!*func) {
std::cerr << "(no function pointer for " << name << ")\n";
return false;
}
return true;
}
template<typename T>
bool initDeviceFunc(VkDevice device, const char* name, T* func) {
*func = reinterpret_cast<T>(next_vkGetDeviceProcAddr(device, name));
if (!*func) {
std::cerr << "(no function pointer for " << name << ")\n";
return false;
}
return true;
}
}
namespace {
VkResult layer_vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
try {
// prepare layer | NOLINTBEGIN
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)
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED,
"No layer creation info found in pNext chain");
next_vkGetInstanceProcAddr = layerDesc->u.pLayerInfo->pfnNextGetInstanceProcAddr;
layerDesc->u.pLayerInfo = layerDesc->u.pLayerInfo->pNext;
bool success = initInstanceFunc(nullptr, "vkCreateInstance", &next_vkCreateInstance);
if (!success)
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED,
"Failed to get instance function pointer for vkCreateInstance");
// NOLINTEND | skip initialization if the layer is disabled
if (!Config::currentConf.has_value() || std::getenv("LSFG_BENCHMARK")) {
auto res = next_vkCreateInstance(pCreateInfo, pAllocator, pInstance);
initInstanceFunc(*pInstance, "vkCreateDevice", &next_vkCreateDevice);
return res;
}
// create instance
try {
auto* createInstanceHook = reinterpret_cast<PFN_vkCreateInstance>(
Hooks::hooks["vkCreateInstance"]);
auto res = createInstanceHook(pCreateInfo, pAllocator, pInstance);
if (res != VK_SUCCESS)
throw LSFG::vulkan_error(res, "Unknown error");
} catch (const std::exception& e) {
throw LSFG::rethrowable_error("Failed to create Vulkan instance", e);
}
// get relevant function pointers from the next layer
success = true;
success &= initInstanceFunc(*pInstance,
"vkDestroyInstance", &next_vkDestroyInstance);
success &= initInstanceFunc(*pInstance,
"vkCreateDevice", &next_vkCreateDevice); // workaround mesa bug
success &= initInstanceFunc(*pInstance,
"vkGetPhysicalDeviceQueueFamilyProperties", &next_vkGetPhysicalDeviceQueueFamilyProperties);
success &= initInstanceFunc(*pInstance,
"vkGetPhysicalDeviceMemoryProperties", &next_vkGetPhysicalDeviceMemoryProperties);
success &= initInstanceFunc(*pInstance,
"vkGetPhysicalDeviceProperties", &next_vkGetPhysicalDeviceProperties);
success &= initInstanceFunc(*pInstance,
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", &next_vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
if (!success)
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED,
"Failed to get instance function pointers");
std::cerr << "lsfg-vk: Vulkan instance layer initialized successfully.\n";
} catch (const std::exception& e) {
std::cerr << "lsfg-vk: An error occurred while initializing the Vulkan instance layer:\n";
std::cerr << "- " << e.what() << '\n';
return VK_ERROR_INITIALIZATION_FAILED;
}
return VK_SUCCESS;
}
VkResult layer_vkCreateDevice( // NOLINTBEGIN
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice) {
try {
// prepare layer | NOLINTBEGIN
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)
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED,
"No layer creation info found in pNext chain");
next_vkGetDeviceProcAddr = layerDesc->u.pLayerInfo->pfnNextGetDeviceProcAddr;
layerDesc->u.pLayerInfo = layerDesc->u.pLayerInfo->pNext;
auto* layerDesc2 = const_cast<VkLayerDeviceCreateInfo*>(
reinterpret_cast<const VkLayerDeviceCreateInfo*>(pCreateInfo->pNext));
while (layerDesc2 && (layerDesc2->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
|| layerDesc2->function != VK_LOADER_DATA_CALLBACK)) {
layerDesc2 = const_cast<VkLayerDeviceCreateInfo*>(
reinterpret_cast<const VkLayerDeviceCreateInfo*>(layerDesc2->pNext));
}
if (!layerDesc2)
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED,
"No layer device loader data found in pNext chain");
next_vSetDeviceLoaderData = layerDesc2->u.pfnSetDeviceLoaderData;
// NOLINTEND | skip initialization if the layer is disabled
if (!Config::currentConf.has_value() || std::getenv("LSFG_BENCHMARK"))
return next_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
// create device
try {
auto* createDeviceHook = reinterpret_cast<PFN_vkCreateDevice>(
Hooks::hooks["vkCreateDevicePre"]);
auto res = createDeviceHook(physicalDevice, pCreateInfo, pAllocator, pDevice);
if (res != VK_SUCCESS)
throw LSFG::vulkan_error(res, "Unknown error");
} catch (const std::exception& e) {
throw LSFG::rethrowable_error("Failed to create Vulkan device", e);
}
// get relevant function pointers from the next layer
bool success = true;
success &= initDeviceFunc(*pDevice, "vkDestroyDevice", &next_vkDestroyDevice);
success &= initDeviceFunc(*pDevice, "vkCreateSwapchainKHR", &next_vkCreateSwapchainKHR);
success &= initDeviceFunc(*pDevice, "vkQueuePresentKHR", &next_vkQueuePresentKHR);
success &= initDeviceFunc(*pDevice, "vkDestroySwapchainKHR", &next_vkDestroySwapchainKHR);
success &= initDeviceFunc(*pDevice, "vkGetSwapchainImagesKHR", &next_vkGetSwapchainImagesKHR);
success &= initDeviceFunc(*pDevice, "vkAllocateCommandBuffers", &next_vkAllocateCommandBuffers);
success &= initDeviceFunc(*pDevice, "vkFreeCommandBuffers", &next_vkFreeCommandBuffers);
success &= initDeviceFunc(*pDevice, "vkBeginCommandBuffer", &next_vkBeginCommandBuffer);
success &= initDeviceFunc(*pDevice, "vkEndCommandBuffer", &next_vkEndCommandBuffer);
success &= initDeviceFunc(*pDevice, "vkCreateCommandPool", &next_vkCreateCommandPool);
success &= initDeviceFunc(*pDevice, "vkDestroyCommandPool", &next_vkDestroyCommandPool);
success &= initDeviceFunc(*pDevice, "vkCreateImage", &next_vkCreateImage);
success &= initDeviceFunc(*pDevice, "vkDestroyImage", &next_vkDestroyImage);
success &= initDeviceFunc(*pDevice, "vkGetImageMemoryRequirements", &next_vkGetImageMemoryRequirements);
success &= initDeviceFunc(*pDevice, "vkBindImageMemory", &next_vkBindImageMemory);
success &= initDeviceFunc(*pDevice, "vkGetMemoryFdKHR", &next_vkGetMemoryFdKHR);
success &= initDeviceFunc(*pDevice, "vkAllocateMemory", &next_vkAllocateMemory);
success &= initDeviceFunc(*pDevice, "vkFreeMemory", &next_vkFreeMemory);
success &= initDeviceFunc(*pDevice, "vkCreateSemaphore", &next_vkCreateSemaphore);
success &= initDeviceFunc(*pDevice, "vkDestroySemaphore", &next_vkDestroySemaphore);
success &= initDeviceFunc(*pDevice, "vkGetSemaphoreFdKHR", &next_vkGetSemaphoreFdKHR);
success &= initDeviceFunc(*pDevice, "vkGetDeviceQueue", &next_vkGetDeviceQueue);
success &= initDeviceFunc(*pDevice, "vkQueueSubmit", &next_vkQueueSubmit);
success &= initDeviceFunc(*pDevice, "vkCmdPipelineBarrier", &next_vkCmdPipelineBarrier);
success &= initDeviceFunc(*pDevice, "vkCmdBlitImage", &next_vkCmdBlitImage);
success &= initDeviceFunc(*pDevice, "vkAcquireNextImageKHR", &next_vkAcquireNextImageKHR);
if (!success)
throw LSFG::vulkan_error(VK_ERROR_INITIALIZATION_FAILED,
"Failed to get device function pointers");
auto postCreateDeviceHook = reinterpret_cast<PFN_vkCreateDevice>(
Hooks::hooks["vkCreateDevicePost"]);
auto res = postCreateDeviceHook(physicalDevice, pCreateInfo, pAllocator, pDevice);
if (res != VK_SUCCESS)
throw LSFG::vulkan_error(res, "Unknown error");
std::cerr << "lsfg-vk: Vulkan device layer initialized successfully.\n";
} catch (const std::exception& e) {
std::cerr << "lsfg-vk: An error occurred while initializing the Vulkan device layer:\n";
std::cerr << "- " << e.what() << '\n';
return VK_ERROR_INITIALIZATION_FAILED;
}
return VK_SUCCESS;
} // NOLINTEND
}
const std::unordered_map<std::string, PFN_vkVoidFunction> layerFunctions = {
{ "vkCreateInstance",
reinterpret_cast<PFN_vkVoidFunction>(&layer_vkCreateInstance) },
{ "vkCreateDevice",
reinterpret_cast<PFN_vkVoidFunction>(&layer_vkCreateDevice) },
{ "vkGetInstanceProcAddr",
reinterpret_cast<PFN_vkVoidFunction>(&layer_vkGetInstanceProcAddr) },
{ "vkGetDeviceProcAddr",
reinterpret_cast<PFN_vkVoidFunction>(&layer_vkGetDeviceProcAddr) },
};
PFN_vkVoidFunction layer_vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
const std::string name(pName);
auto it = layerFunctions.find(name);
if (it != layerFunctions.end())
return it->second;
it = Hooks::hooks.find(name);
if (it != Hooks::hooks.end() && (Config::currentConf.has_value() && !std::getenv("LSFG_BENCHMARK")))
return it->second;
return next_vkGetInstanceProcAddr(instance, pName);
}
PFN_vkVoidFunction layer_vkGetDeviceProcAddr(VkDevice device, const char* pName) {
const std::string name(pName);
auto it = layerFunctions.find(name);
if (it != layerFunctions.end())
return it->second;
it = Hooks::hooks.find(name);
if (it != Hooks::hooks.end() && (Config::currentConf.has_value() && !std::getenv("LSFG_BENCHMARK")))
return it->second;
return next_vkGetDeviceProcAddr(device, pName);
}
// original functions
namespace Layer {
VkResult ovkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
return next_vkCreateInstance(pCreateInfo, pAllocator, pInstance);
}
void ovkDestroyInstance(
VkInstance instance,
const VkAllocationCallbacks* pAllocator) {
next_vkDestroyInstance(instance, pAllocator);
}
VkResult ovkCreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice) {
return next_vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
}
void ovkDestroyDevice(
VkDevice device,
const VkAllocationCallbacks* pAllocator) {
next_vkDestroyDevice(device, pAllocator);
}
VkResult ovkSetDeviceLoaderData(VkDevice device, void* object) {
return next_vSetDeviceLoaderData(device, object);
}
PFN_vkVoidFunction ovkGetInstanceProcAddr(
VkInstance instance,
const char* pName) {
return next_vkGetInstanceProcAddr(instance, pName);
}
PFN_vkVoidFunction ovkGetDeviceProcAddr(
VkDevice device,
const char* pName) {
return next_vkGetDeviceProcAddr(device, pName);
}
void ovkGetPhysicalDeviceQueueFamilyProperties(
VkPhysicalDevice physicalDevice,
uint32_t* pQueueFamilyPropertyCount,
VkQueueFamilyProperties* pQueueFamilyProperties) {
next_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
}
void ovkGetPhysicalDeviceMemoryProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
next_vkGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
}
void ovkGetPhysicalDeviceProperties(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties) {
next_vkGetPhysicalDeviceProperties(physicalDevice, pProperties);
}
VkResult ovkGetPhysicalDeviceSurfaceCapabilitiesKHR(
VkPhysicalDevice physicalDevice,
VkSurfaceKHR surface,
VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
return next_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
}
VkResult ovkCreateSwapchainKHR(
VkDevice device,
const VkSwapchainCreateInfoKHR* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSwapchainKHR* pSwapchain) {
return next_vkCreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
}
VkResult ovkQueuePresentKHR(
VkQueue queue,
const VkPresentInfoKHR* pPresentInfo) {
return next_vkQueuePresentKHR(queue, pPresentInfo);
}
void ovkDestroySwapchainKHR(
VkDevice device,
VkSwapchainKHR swapchain,
const VkAllocationCallbacks* pAllocator) {
next_vkDestroySwapchainKHR(device, swapchain, pAllocator);
}
VkResult ovkGetSwapchainImagesKHR(
VkDevice device,
VkSwapchainKHR swapchain,
uint32_t* pSwapchainImageCount,
VkImage* pSwapchainImages) {
return next_vkGetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
}
VkResult ovkAllocateCommandBuffers(
VkDevice device,
const VkCommandBufferAllocateInfo* pAllocateInfo,
VkCommandBuffer* pCommandBuffers) {
return next_vkAllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
}
void ovkFreeCommandBuffers(
VkDevice device,
VkCommandPool commandPool,
uint32_t commandBufferCount,
const VkCommandBuffer* pCommandBuffers) {
next_vkFreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
}
VkResult ovkBeginCommandBuffer(
VkCommandBuffer commandBuffer,
const VkCommandBufferBeginInfo* pBeginInfo) {
return next_vkBeginCommandBuffer(commandBuffer, pBeginInfo);
}
VkResult ovkEndCommandBuffer(
VkCommandBuffer commandBuffer) {
return next_vkEndCommandBuffer(commandBuffer);
}
VkResult ovkCreateCommandPool(
VkDevice device,
const VkCommandPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkCommandPool* pCommandPool) {
return next_vkCreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
}
void ovkDestroyCommandPool(
VkDevice device,
VkCommandPool commandPool,
const VkAllocationCallbacks* pAllocator) {
next_vkDestroyCommandPool(device, commandPool, pAllocator);
}
VkResult ovkCreateImage(
VkDevice device,
const VkImageCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkImage* pImage) {
return next_vkCreateImage(device, pCreateInfo, pAllocator, pImage);
}
void ovkDestroyImage(
VkDevice device,
VkImage image,
const VkAllocationCallbacks* pAllocator) {
next_vkDestroyImage(device, image, pAllocator);
}
void ovkGetImageMemoryRequirements(
VkDevice device,
VkImage image,
VkMemoryRequirements* pMemoryRequirements) {
next_vkGetImageMemoryRequirements(device, image, pMemoryRequirements);
}
VkResult ovkBindImageMemory(
VkDevice device,
VkImage image,
VkDeviceMemory memory,
VkDeviceSize memoryOffset) {
return next_vkBindImageMemory(device, image, memory, memoryOffset);
}
VkResult ovkAllocateMemory(
VkDevice device,
const VkMemoryAllocateInfo* pAllocateInfo,
const VkAllocationCallbacks* pAllocator,
VkDeviceMemory* pMemory) {
return next_vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
}
void ovkFreeMemory(
VkDevice device,
VkDeviceMemory memory,
const VkAllocationCallbacks* pAllocator) {
next_vkFreeMemory(device, memory, pAllocator);
}
VkResult ovkCreateSemaphore(
VkDevice device,
const VkSemaphoreCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSemaphore* pSemaphore) {
return next_vkCreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
}
void ovkDestroySemaphore(
VkDevice device,
VkSemaphore semaphore,
const VkAllocationCallbacks* pAllocator) {
next_vkDestroySemaphore(device, semaphore, pAllocator);
}
VkResult ovkGetMemoryFdKHR(
VkDevice device,
const VkMemoryGetFdInfoKHR* pGetFdInfo,
int* pFd) {
return next_vkGetMemoryFdKHR(device, pGetFdInfo, pFd);
}
VkResult ovkGetSemaphoreFdKHR(
VkDevice device,
const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
int* pFd) {
return next_vkGetSemaphoreFdKHR(device, pGetFdInfo, pFd);
}
void ovkGetDeviceQueue(
VkDevice device,
uint32_t queueFamilyIndex,
uint32_t queueIndex,
VkQueue* pQueue) {
next_vkGetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
}
VkResult ovkQueueSubmit(
VkQueue queue,
uint32_t submitCount,
const VkSubmitInfo* pSubmits,
VkFence fence) {
return next_vkQueueSubmit(queue, submitCount, pSubmits, fence);
}
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) {
next_vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
memoryBarrierCount, pMemoryBarriers,
bufferMemoryBarrierCount, pBufferMemoryBarriers,
imageMemoryBarrierCount, pImageMemoryBarriers);
}
void ovkCmdBlitImage(
VkCommandBuffer commandBuffer,
VkImage srcImage,
VkImageLayout srcImageLayout,
VkImage dstImage,
VkImageLayout dstImageLayout,
uint32_t regionCount,
const VkImageBlit* pRegions,
VkFilter filter) {
next_vkCmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
}
VkResult ovkAcquireNextImageKHR(
VkDevice device,
VkSwapchainKHR swapchain,
uint64_t timeout,
VkSemaphore semaphore,
VkFence fence,
uint32_t* pImageIndex) {
return next_vkAcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
}
}