refactor(cleanup): remove global constructors and initialize vk funcs

This commit is contained in:
PancakeTAS 2025-12-15 14:06:07 +01:00
parent 5bc7555744
commit 0b387b2b37
7 changed files with 167 additions and 148 deletions

View file

@ -29,8 +29,6 @@ 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

View file

@ -26,6 +26,11 @@ namespace vk {
PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
};
/// initialize vulkan instance function pointers
/// @param instance vulkan instance handle
/// @param mpa function to get instance proc addresses
VulkanInstanceFuncs initVulkanInstanceFuncs(VkInstance instance, PFN_vkGetInstanceProcAddr mpa);
using PhysicalDeviceSelector = const std::function<
VkPhysicalDevice(
const VulkanInstanceFuncs&,
@ -94,6 +99,11 @@ namespace vk {
PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR;
};
/// initialize vulkan device function pointers
/// @param fi instance function pointers
/// @param device logical device handle
VulkanDeviceFuncs initVulkanDeviceFuncs(const VulkanInstanceFuncs& fi, VkDevice device);
/// vulkan version wrapper
class version {
public:

View file

@ -91,30 +91,6 @@ namespace {
);
}
/// initialize vulkan instance function pointers
VulkanInstanceFuncs initVulkanInstanceFuncs(VkInstance i) {
const auto& mpa = get_mpa();
return {
.DestroyInstance = ipa<PFN_vkDestroyInstance>(mpa, i, "vkDestroyInstance"),
.EnumeratePhysicalDevices = ipa<PFN_vkEnumeratePhysicalDevices>(mpa, i,
"vkEnumeratePhysicalDevices"),
.EnumerateDeviceExtensionProperties = ipa<PFN_vkEnumerateDeviceExtensionProperties>(mpa, i,
"vkEnumerateDeviceExtensionProperties"),
.GetPhysicalDeviceProperties2 = ipa<PFN_vkGetPhysicalDeviceProperties2>(mpa, i,
"vkGetPhysicalDeviceProperties2"),
.GetPhysicalDeviceQueueFamilyProperties =
ipa<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(mpa, i,
"vkGetPhysicalDeviceQueueFamilyProperties"),
.GetPhysicalDeviceFeatures2 = ipa<PFN_vkGetPhysicalDeviceFeatures2>(mpa, i,
"vkGetPhysicalDeviceFeatures2"),
.GetPhysicalDeviceMemoryProperties = ipa<PFN_vkGetPhysicalDeviceMemoryProperties>(mpa, i,
"vkGetPhysicalDeviceMemoryProperties"),
.CreateDevice = ipa<PFN_vkCreateDevice>(mpa, i, "vkCreateDevice"),
.GetDeviceProcAddr = ipa<PFN_vkGetDeviceProcAddr>(mpa, i, "vkGetDeviceProcAddr"),
};
}
/// filter for a physical device
VkPhysicalDevice findPhysicalDevice(const VulkanInstanceFuncs& fi,
VkInstance instance,
@ -222,75 +198,6 @@ namespace {
);
}
/// initialize vulkan device function pointers
VulkanDeviceFuncs initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevice d) {
return {
.GetDeviceQueue = dpa<PFN_vkGetDeviceQueue>(f, d, "vkGetDeviceQueue"),
.DeviceWaitIdle = dpa<PFN_vkDeviceWaitIdle>(f, d, "vkDeviceWaitIdle"),
.CreateCommandPool = dpa<PFN_vkCreateCommandPool>(f, d, "vkCreateCommandPool"),
.DestroyCommandPool = dpa<PFN_vkDestroyCommandPool>(f, d, "vkDestroyCommandPool"),
.CreateDescriptorPool = dpa<PFN_vkCreateDescriptorPool>(f, d, "vkCreateDescriptorPool"),
.DestroyDescriptorPool = dpa<PFN_vkDestroyDescriptorPool>(f, d, "vkDestroyDescriptorPool"),
.CreateBuffer = dpa<PFN_vkCreateBuffer>(f, d, "vkCreateBuffer"),
.DestroyBuffer = dpa<PFN_vkDestroyBuffer>(f, d, "vkDestroyBuffer"),
.GetBufferMemoryRequirements = dpa<PFN_vkGetBufferMemoryRequirements>(f, d,
"vkGetBufferMemoryRequirements"),
.AllocateMemory = dpa<PFN_vkAllocateMemory>(f, d, "vkAllocateMemory"),
.FreeMemory = dpa<PFN_vkFreeMemory>(f, d, "vkFreeMemory"),
.BindBufferMemory = dpa<PFN_vkBindBufferMemory>(f, d, "vkBindBufferMemory"),
.MapMemory = dpa<PFN_vkMapMemory>(f, d, "vkMapMemory"),
.UnmapMemory = dpa<PFN_vkUnmapMemory>(f, d, "vkUnmapMemory"),
.AllocateCommandBuffers = dpa<PFN_vkAllocateCommandBuffers>(f, d,
"vkAllocateCommandBuffers"),
.FreeCommandBuffers = dpa<PFN_vkFreeCommandBuffers>(f, d, "vkFreeCommandBuffers"),
.BeginCommandBuffer = dpa<PFN_vkBeginCommandBuffer>(f, d, "vkBeginCommandBuffer"),
.EndCommandBuffer = dpa<PFN_vkEndCommandBuffer>(f, d, "vkEndCommandBuffer"),
.CmdPipelineBarrier = dpa<PFN_vkCmdPipelineBarrier>(f, d, "vkCmdPipelineBarrier"),
.CmdClearColorImage = dpa<PFN_vkCmdClearColorImage>(f, d, "vkCmdClearColorImage"),
.CmdBindPipeline = dpa<PFN_vkCmdBindPipeline>(f, d, "vkCmdBindPipeline"),
.CmdBindDescriptorSets = dpa<PFN_vkCmdBindDescriptorSets>(f, d, "vkCmdBindDescriptorSets"),
.CmdDispatch = dpa<PFN_vkCmdDispatch>(f, d, "vkCmdDispatch"),
.CmdCopyBufferToImage = dpa<PFN_vkCmdCopyBufferToImage>(f, d, "vkCmdCopyBufferToImage"),
.QueueSubmit = dpa<PFN_vkQueueSubmit>(f, d, "vkQueueSubmit"),
.AllocateDescriptorSets = dpa<PFN_vkAllocateDescriptorSets>(f, d,
"vkAllocateDescriptorSets"),
.FreeDescriptorSets = dpa<PFN_vkFreeDescriptorSets>(f, d, "vkFreeDescriptorSets"),
.UpdateDescriptorSets = dpa<PFN_vkUpdateDescriptorSets>(f, d, "vkUpdateDescriptorSets"),
.CreateFence = dpa<PFN_vkCreateFence>(f, d, "vkCreateFence"),
.DestroyFence = dpa<PFN_vkDestroyFence>(f, d, "vkDestroyFence"),
.ResetFences = dpa<PFN_vkResetFences>(f, d, "vkResetFences"),
.WaitForFences = dpa<PFN_vkWaitForFences>(f, d, "vkWaitForFences"),
.CreateImage = dpa<PFN_vkCreateImage>(f, d, "vkCreateImage"),
.DestroyImage = dpa<PFN_vkDestroyImage>(f, d, "vkDestroyImage"),
.GetImageMemoryRequirements = dpa<PFN_vkGetImageMemoryRequirements>(f, d,
"vkGetImageMemoryRequirements"),
.BindImageMemory = dpa<PFN_vkBindImageMemory>(f, d, "vkBindImageMemory"),
.CreateImageView = dpa<PFN_vkCreateImageView>(f, d, "vkCreateImageView"),
.DestroyImageView = dpa<PFN_vkDestroyImageView>(f, d, "vkDestroyImageView"),
.CreateSampler = dpa<PFN_vkCreateSampler>(f, d, "vkCreateSampler"),
.DestroySampler = dpa<PFN_vkDestroySampler>(f, d, "vkDestroySampler"),
.CreateSemaphore = dpa<PFN_vkCreateSemaphore>(f, d, "vkCreateSemaphore"),
.DestroySemaphore = dpa<PFN_vkDestroySemaphore>(f, d, "vkDestroySemaphore"),
.CreateShaderModule = dpa<PFN_vkCreateShaderModule>(f, d, "vkCreateShaderModule"),
.DestroyShaderModule = dpa<PFN_vkDestroyShaderModule>(f, d, "vkDestroyShaderModule"),
.CreateDescriptorSetLayout = dpa<PFN_vkCreateDescriptorSetLayout>(f, d,
"vkCreateDescriptorSetLayout"),
.DestroyDescriptorSetLayout = dpa<PFN_vkDestroyDescriptorSetLayout>(f, d,
"vkDestroyDescriptorSetLayout"),
.CreatePipelineLayout = dpa<PFN_vkCreatePipelineLayout>(f, d, "vkCreatePipelineLayout"),
.DestroyPipelineLayout = dpa<PFN_vkDestroyPipelineLayout>(f, d, "vkDestroyPipelineLayout"),
.CreateComputePipelines = dpa<PFN_vkCreateComputePipelines>(f, d,
"vkCreateComputePipelines"),
.DestroyPipeline = dpa<PFN_vkDestroyPipeline>(f, d, "vkDestroyPipeline"),
.SignalSemaphore = dpa<PFN_vkSignalSemaphore>(f, d, "vkSignalSemaphore"),
.WaitSemaphores = dpa<PFN_vkWaitSemaphores>(f, d, "vkWaitSemaphores"),
.GetMemoryFdKHR = dpa<PFN_vkGetMemoryFdKHR>(f, d, "vkGetMemoryFdKHR"),
.ImportSemaphoreFdKHR = dpa<PFN_vkImportSemaphoreFdKHR>(f, d, "vkImportSemaphoreFdKHR"),
.GetSemaphoreFdKHR = dpa<PFN_vkGetSemaphoreFdKHR>(f, d, "vkGetSemaphoreFdKHR"),
};
}
/// get a queue from the logical device
VkQueue getQueue(const VulkanDeviceFuncs& fd,
VkDevice device, uint32_t cfi) {
@ -352,6 +259,97 @@ namespace {
}
}
/// initialize vulkan instance function pointers
VulkanInstanceFuncs vk::initVulkanInstanceFuncs(VkInstance i, PFN_vkGetInstanceProcAddr mpa) {
return {
.DestroyInstance = ipa<PFN_vkDestroyInstance>(mpa, i, "vkDestroyInstance"),
.EnumeratePhysicalDevices = ipa<PFN_vkEnumeratePhysicalDevices>(mpa, i,
"vkEnumeratePhysicalDevices"),
.EnumerateDeviceExtensionProperties = ipa<PFN_vkEnumerateDeviceExtensionProperties>(mpa, i,
"vkEnumerateDeviceExtensionProperties"),
.GetPhysicalDeviceProperties2 = ipa<PFN_vkGetPhysicalDeviceProperties2>(mpa, i,
"vkGetPhysicalDeviceProperties2"),
.GetPhysicalDeviceQueueFamilyProperties =
ipa<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(mpa, i,
"vkGetPhysicalDeviceQueueFamilyProperties"),
.GetPhysicalDeviceFeatures2 = ipa<PFN_vkGetPhysicalDeviceFeatures2>(mpa, i,
"vkGetPhysicalDeviceFeatures2"),
.GetPhysicalDeviceMemoryProperties = ipa<PFN_vkGetPhysicalDeviceMemoryProperties>(mpa, i,
"vkGetPhysicalDeviceMemoryProperties"),
.CreateDevice = ipa<PFN_vkCreateDevice>(mpa, i, "vkCreateDevice"),
.GetDeviceProcAddr = ipa<PFN_vkGetDeviceProcAddr>(mpa, i, "vkGetDeviceProcAddr"),
};
}
/// initialize vulkan device function pointers
VulkanDeviceFuncs vk::initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevice d) {
return {
.GetDeviceQueue = dpa<PFN_vkGetDeviceQueue>(f, d, "vkGetDeviceQueue"),
.DeviceWaitIdle = dpa<PFN_vkDeviceWaitIdle>(f, d, "vkDeviceWaitIdle"),
.CreateCommandPool = dpa<PFN_vkCreateCommandPool>(f, d, "vkCreateCommandPool"),
.DestroyCommandPool = dpa<PFN_vkDestroyCommandPool>(f, d, "vkDestroyCommandPool"),
.CreateDescriptorPool = dpa<PFN_vkCreateDescriptorPool>(f, d, "vkCreateDescriptorPool"),
.DestroyDescriptorPool = dpa<PFN_vkDestroyDescriptorPool>(f, d, "vkDestroyDescriptorPool"),
.CreateBuffer = dpa<PFN_vkCreateBuffer>(f, d, "vkCreateBuffer"),
.DestroyBuffer = dpa<PFN_vkDestroyBuffer>(f, d, "vkDestroyBuffer"),
.GetBufferMemoryRequirements = dpa<PFN_vkGetBufferMemoryRequirements>(f, d,
"vkGetBufferMemoryRequirements"),
.AllocateMemory = dpa<PFN_vkAllocateMemory>(f, d, "vkAllocateMemory"),
.FreeMemory = dpa<PFN_vkFreeMemory>(f, d, "vkFreeMemory"),
.BindBufferMemory = dpa<PFN_vkBindBufferMemory>(f, d, "vkBindBufferMemory"),
.MapMemory = dpa<PFN_vkMapMemory>(f, d, "vkMapMemory"),
.UnmapMemory = dpa<PFN_vkUnmapMemory>(f, d, "vkUnmapMemory"),
.AllocateCommandBuffers = dpa<PFN_vkAllocateCommandBuffers>(f, d,
"vkAllocateCommandBuffers"),
.FreeCommandBuffers = dpa<PFN_vkFreeCommandBuffers>(f, d, "vkFreeCommandBuffers"),
.BeginCommandBuffer = dpa<PFN_vkBeginCommandBuffer>(f, d, "vkBeginCommandBuffer"),
.EndCommandBuffer = dpa<PFN_vkEndCommandBuffer>(f, d, "vkEndCommandBuffer"),
.CmdPipelineBarrier = dpa<PFN_vkCmdPipelineBarrier>(f, d, "vkCmdPipelineBarrier"),
.CmdClearColorImage = dpa<PFN_vkCmdClearColorImage>(f, d, "vkCmdClearColorImage"),
.CmdBindPipeline = dpa<PFN_vkCmdBindPipeline>(f, d, "vkCmdBindPipeline"),
.CmdBindDescriptorSets = dpa<PFN_vkCmdBindDescriptorSets>(f, d, "vkCmdBindDescriptorSets"),
.CmdDispatch = dpa<PFN_vkCmdDispatch>(f, d, "vkCmdDispatch"),
.CmdCopyBufferToImage = dpa<PFN_vkCmdCopyBufferToImage>(f, d, "vkCmdCopyBufferToImage"),
.QueueSubmit = dpa<PFN_vkQueueSubmit>(f, d, "vkQueueSubmit"),
.AllocateDescriptorSets = dpa<PFN_vkAllocateDescriptorSets>(f, d,
"vkAllocateDescriptorSets"),
.FreeDescriptorSets = dpa<PFN_vkFreeDescriptorSets>(f, d, "vkFreeDescriptorSets"),
.UpdateDescriptorSets = dpa<PFN_vkUpdateDescriptorSets>(f, d, "vkUpdateDescriptorSets"),
.CreateFence = dpa<PFN_vkCreateFence>(f, d, "vkCreateFence"),
.DestroyFence = dpa<PFN_vkDestroyFence>(f, d, "vkDestroyFence"),
.ResetFences = dpa<PFN_vkResetFences>(f, d, "vkResetFences"),
.WaitForFences = dpa<PFN_vkWaitForFences>(f, d, "vkWaitForFences"),
.CreateImage = dpa<PFN_vkCreateImage>(f, d, "vkCreateImage"),
.DestroyImage = dpa<PFN_vkDestroyImage>(f, d, "vkDestroyImage"),
.GetImageMemoryRequirements = dpa<PFN_vkGetImageMemoryRequirements>(f, d,
"vkGetImageMemoryRequirements"),
.BindImageMemory = dpa<PFN_vkBindImageMemory>(f, d, "vkBindImageMemory"),
.CreateImageView = dpa<PFN_vkCreateImageView>(f, d, "vkCreateImageView"),
.DestroyImageView = dpa<PFN_vkDestroyImageView>(f, d, "vkDestroyImageView"),
.CreateSampler = dpa<PFN_vkCreateSampler>(f, d, "vkCreateSampler"),
.DestroySampler = dpa<PFN_vkDestroySampler>(f, d, "vkDestroySampler"),
.CreateSemaphore = dpa<PFN_vkCreateSemaphore>(f, d, "vkCreateSemaphore"),
.DestroySemaphore = dpa<PFN_vkDestroySemaphore>(f, d, "vkDestroySemaphore"),
.CreateShaderModule = dpa<PFN_vkCreateShaderModule>(f, d, "vkCreateShaderModule"),
.DestroyShaderModule = dpa<PFN_vkDestroyShaderModule>(f, d, "vkDestroyShaderModule"),
.CreateDescriptorSetLayout = dpa<PFN_vkCreateDescriptorSetLayout>(f, d,
"vkCreateDescriptorSetLayout"),
.DestroyDescriptorSetLayout = dpa<PFN_vkDestroyDescriptorSetLayout>(f, d,
"vkDestroyDescriptorSetLayout"),
.CreatePipelineLayout = dpa<PFN_vkCreatePipelineLayout>(f, d, "vkCreatePipelineLayout"),
.DestroyPipelineLayout = dpa<PFN_vkDestroyPipelineLayout>(f, d, "vkDestroyPipelineLayout"),
.CreateComputePipelines = dpa<PFN_vkCreateComputePipelines>(f, d,
"vkCreateComputePipelines"),
.DestroyPipeline = dpa<PFN_vkDestroyPipeline>(f, d, "vkDestroyPipeline"),
.SignalSemaphore = dpa<PFN_vkSignalSemaphore>(f, d, "vkSignalSemaphore"),
.WaitSemaphores = dpa<PFN_vkWaitSemaphores>(f, d, "vkWaitSemaphores"),
.GetMemoryFdKHR = dpa<PFN_vkGetMemoryFdKHR>(f, d, "vkGetMemoryFdKHR"),
.ImportSemaphoreFdKHR = dpa<PFN_vkImportSemaphoreFdKHR>(f, d, "vkImportSemaphoreFdKHR"),
.GetSemaphoreFdKHR = dpa<PFN_vkGetSemaphoreFdKHR>(f, d, "vkGetSemaphoreFdKHR"),
};
}
Vulkan::Vulkan(const std::string& appName, version appVersion,
const std::string& engineName, version engineVersion,
PhysicalDeviceSelector selectPhysicalDevice) :
@ -359,7 +357,7 @@ Vulkan::Vulkan(const std::string& appName, version appVersion,
appName, appVersion,
engineName, engineVersion
)),
instance_funcs(initVulkanInstanceFuncs(*this->instance)),
instance_funcs(initVulkanInstanceFuncs(*this->instance, get_mpa())),
physdev(findPhysicalDevice(this->instance_funcs,
*this->instance,
selectPhysicalDevice

View file

@ -26,6 +26,7 @@ Checks:
- "-cppcoreguidelines-macro-usage"
- "-cppcoreguidelines-pro-type-union-access"
- "-cppcoreguidelines-avoid-non-const-global-variables"
- "-cppcoreguidelines-pro-type-const-cast"
# disable slow and pointless checks
- "-modernize-use-std-numbers"
- "-modernize-type-traits"

View file

@ -1,11 +1,11 @@
#include "layer.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <iostream>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
@ -33,28 +33,36 @@ namespace {
return extensions;
}
/// struct containing various helper globals
struct Globals {
layer::Layer layer;
VkInstance instance{VK_NULL_HANDLE}; // if there are multiple instances, we scream
vk::VulkanInstanceFuncs fi{};
std::unordered_map<std::string, PFN_vkVoidFunction> procAddrMap; // all overriden pointers
std::unordered_map<VkDevice, layer::LayerInstance> device2InstanceMap;
};
}
namespace {
PFN_vkGetInstanceProcAddr nxvkGetInstanceProcAddr{nullptr};
PFN_vkGetDeviceProcAddr nxvkGetDeviceProcAddr = nullptr;
auto& layer() {
static std::optional<layer::Layer> instance; // NOLINT
return instance;
}
VkInstance gInstance{VK_NULL_HANDLE}; // if there are multiple instances, we scream out loud, oke?
Globals* global{nullptr};
void populateProcAddrMap();
// create instance
PFN_vkGetInstanceProcAddr nxvkGetInstanceProcAddr{nullptr};
VkResult myvkCreateInstance(
const VkInstanceCreateInfo* info,
const VkAllocationCallbacks* alloc,
VkInstance* instance) {
// try to load lsfg-vk layer
try {
if (!layer().has_value())
layer().emplace();
if (!global) { // cleanup in vkDestroyInstance
global = new Globals();
populateProcAddrMap();
}
} catch (const std::exception& e) {
std::cerr << "lsfg-vk: something went wrong during lsfg-vk layer initialization:\n";
std::cerr << "- " << e.what() << '\n';
@ -97,14 +105,14 @@ namespace {
return VK_ERROR_INITIALIZATION_FAILED;
}
const auto& l = layer();
if (!l.has_value() || !l->active()) // skip inactive
const auto& l = global;
if (!l || !l->layer.active()) // skip inactive
return vkCreateInstance(info, alloc, instance);
auto extensions = add_extensions(
info->ppEnabledExtensionNames,
info->enabledExtensionCount,
l->instanceExtensions());
l->layer.instanceExtensions());
VkInstanceCreateInfo newInfo = *info;
newInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
@ -118,17 +126,13 @@ namespace {
if (res != VK_SUCCESS)
return res;
gInstance = *instance;
l->instance = *instance;
l->fi = vk::initVulkanInstanceFuncs(l->instance, nxvkGetInstanceProcAddr);
return VK_SUCCESS;
}
// map of devices to layer instances
std::unordered_map<VkDevice, layer::LayerInstance>& device2InstanceMap() {
static std::unordered_map<VkDevice, layer::LayerInstance> map; // NOLINT
return map;
}
// create device
PFN_vkGetDeviceProcAddr nxvkGetDeviceProcAddr{nullptr};
VkResult myvkCreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* info,
@ -153,8 +157,9 @@ namespace {
return VK_ERROR_INITIALIZATION_FAILED;
}
global->fi.GetDeviceProcAddr = linkInfo->pfnNextGetDeviceProcAddr;
nxvkGetDeviceProcAddr = linkInfo->pfnNextGetDeviceProcAddr;
if (!nxvkGetDeviceProcAddr) {
if (!linkInfo->pfnNextGetDeviceProcAddr) {
std::cerr << "lsfg-vk: next layer's vkGetDeviceProcAddr is null, "
"the previous layer does not follow spec\n";
return VK_ERROR_INITIALIZATION_FAILED;
@ -180,28 +185,16 @@ namespace {
}
// 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;
}
const auto& l = layer();
if (!l.has_value() || !l->active()) // skip inactive
return vkCreateDevice(physicalDevice, info, alloc, device);
auto extensions = add_extensions(
info->ppEnabledExtensionNames,
info->enabledExtensionCount,
l->deviceExtensions());
global->layer.deviceExtensions());
VkDeviceCreateInfo newInfo = *info;
newInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
newInfo.ppEnabledExtensionNames = extensions.data();
auto res = vkCreateDevice(physicalDevice, &newInfo, alloc, device);
auto res = global->fi.CreateDevice(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";
@ -211,8 +204,14 @@ namespace {
// create layer instance
try {
device2InstanceMap().emplace(*device,
layer::LayerInstance(*l, gInstance, *device, setLoaderData));
global->device2InstanceMap.emplace(
*device,
layer::LayerInstance(
global->layer, vk::initVulkanDeviceFuncs(global->fi, *device),
global->instance, *device,
setLoaderData
)
);
} catch (const std::exception& e) {
std::cerr << "lsfg-vk: something went wrong during lsfg-vk initialization:\n";
std::cerr << "- " << e.what() << '\n';
@ -221,12 +220,32 @@ namespace {
return VK_SUCCESS;
}
PFN_vkVoidFunction getProcAddr(const std::string& name);
// populate function pointer override map
void populateProcAddrMap() {
#define VKPTR(name) reinterpret_cast<PFN_vkVoidFunction>(name)
global->procAddrMap = {
{ "vkCreateInstance", VKPTR(myvkCreateInstance) },
{ "vkCreateDevice", VKPTR(myvkCreateDevice) },
};
#undef VKPTR
}
// get optional function pointer override
PFN_vkVoidFunction getProcAddr(const std::string& name) {
if (!global) return nullptr;
auto it = global->procAddrMap.find(name);
if (it != global->procAddrMap.end())
return it->second;
return nullptr;
}
// get instance-level function pointers
PFN_vkVoidFunction myvkGetInstanceProcAddr(VkInstance instance, const char* pName) {
if (!pName) return nullptr;
if (std::string(pName) == "vkCreateInstance") // pre-instance function
return reinterpret_cast<PFN_vkVoidFunction>(myvkCreateInstance);
auto func = getProcAddr(pName);
if (func) return func;
@ -245,15 +264,6 @@ namespace {
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

View file

@ -1,5 +1,6 @@
#include "layer.hpp"
#include "detection.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <iostream>
#include <string>
@ -72,7 +73,7 @@ std::vector<const char*> Layer::deviceExtensions() const {
};
}
layer::LayerInstance::LayerInstance(const Layer& layer,
layer::LayerInstance::LayerInstance(const Layer& layer, vk::VulkanDeviceFuncs df,
VkInstance instance, VkDevice device,
PFN_vkSetDeviceLoaderData setLoaderData) {
std::cerr << "lsfg-vk: Hello, world!\n";

View file

@ -2,9 +2,9 @@
#include "config.hpp"
#include "detection.hpp"
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <optional>
#include <string>
#include <vector>
#include <vulkan/vk_layer.h>
@ -48,10 +48,11 @@ namespace lsfgvk::layer {
public:
/// create a new layer instance
/// @param layer parent layer
/// @param df Vulkan device function pointers
/// @param instance Vulkan instance
/// @param device Vulkan device
/// @param setLoaderData function to set device loader data
LayerInstance(const Layer& layer,
LayerInstance(const Layer& layer, vk::VulkanDeviceFuncs df,
VkInstance instance, VkDevice device,
PFN_vkSetDeviceLoaderData setLoaderData);
private: