refactor(cleanup): pass vulkan instance to layer

This commit is contained in:
PancakeTAS 2025-12-15 14:46:06 +01:00
parent 0b387b2b37
commit bf1d8a8a09
9 changed files with 80 additions and 114 deletions

View file

@ -1,42 +0,0 @@
#pragma once
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <memory>
namespace Mini {
///
/// C++ wrapper class for a Vulkan command pool.
///
/// This class manages the lifetime of a Vulkan command pool.
///
class CommandPool {
public:
CommandPool() noexcept = default;
///
/// Create the command pool.
///
/// @param device Vulkan device
/// @param graphicsFamilyIdx Index of the graphics queue family
///
/// @throws LSFG::vulkan_error if object creation fails.
///
CommandPool(VkDevice device, uint32_t graphicsFamilyIdx);
/// Get the Vulkan handle.
[[nodiscard]] auto handle() const { return *this->commandPool; }
/// Trivially copyable, moveable and destructible
CommandPool(const CommandPool&) noexcept = default;
CommandPool& operator=(const CommandPool&) noexcept = default;
CommandPool(CommandPool&&) noexcept = default;
CommandPool& operator=(CommandPool&&) noexcept = default;
~CommandPool() = default;
private:
std::shared_ptr<VkCommandPool> commandPool;
};
}

View file

@ -57,6 +57,11 @@ namespace ls {
/// default constructor
owned_ptr() = default;
/// construct from raw pointer without deleter
/// @param ptr raw pointer to own, must be valid for object lifetime
explicit owned_ptr(T* ptr)
: ptr(ptr) {}
/// construct from raw pointer
/// @param ptr raw pointer to own, must be valid for object lifetime
/// @param deleter custom deleter function, called only on owned instances
@ -97,8 +102,8 @@ namespace ls {
// destructor
~owned_ptr() {
if (ptr && deleter) {
deleter(*ptr);
if (ptr) {
if (deleter) deleter(*ptr);
delete ptr;
}
}

View file

@ -90,10 +90,11 @@ namespace vk {
PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
PFN_vkCreateComputePipelines CreateComputePipelines;
PFN_vkDestroyPipeline DestroyPipeline;
PFN_vkSignalSemaphore SignalSemaphore;
PFN_vkWaitSemaphores WaitSemaphores;
// extension functions
PFN_vkSignalSemaphoreKHR SignalSemaphoreKHR;
PFN_vkWaitSemaphoresKHR WaitSemaphoresKHR;
PFN_vkGetMemoryFdKHR GetMemoryFdKHR;
PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR;
PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR;
@ -130,10 +131,26 @@ namespace vk {
/// @param engineName name of the engine
/// @param engineVersion version of the engine
/// @param selectPhysicalDevice function to select the physical device
/// @param isGraphical whether the device is graphical (rather than compute)
/// @throws ls::vulkan_error on failure
Vulkan(const std::string& appName, version appVersion,
const std::string& engineName, version engineVersion,
PhysicalDeviceSelector selectPhysicalDevice);
PhysicalDeviceSelector selectPhysicalDevice,
bool isGraphical = false);
/// create based on an existing externally managed vulkan instance.
/// @param instance vulkan instance handle
/// @param device logical device handle
/// @param physdev physical device handle
/// @param instanceFuncs instance function pointers
/// @param deviceFuncs device function pointers
/// @param isGraphical whether the device is graphical (rather than compute)
/// @throws ls::vulkan_error on failure
Vulkan(VkInstance instance, VkDevice device,
VkPhysicalDevice physdev,
VulkanInstanceFuncs instanceFuncs,
VulkanDeviceFuncs deviceFuncs,
bool isGraphical = true);
/// find a memory type index
/// @param validTypes bitset of valid memory types
@ -170,7 +187,7 @@ namespace vk {
VulkanInstanceFuncs instance_funcs;
VkPhysicalDevice physdev;
uint32_t computeFamilyIdx;
uint32_t queueFamilyIdx;
bool fp16;
ls::owned_ptr<VkDevice> device;

View file

@ -81,7 +81,7 @@ void TimelineSemaphore::signal(const vk::Vulkan& vk, uint64_t value) const {
.semaphore = *this->semaphore,
.value = value
};
auto res = vk.df().SignalSemaphore(vk.dev(), &signalInfo);
auto res = vk.df().SignalSemaphoreKHR(vk.dev(), &signalInfo);
if (res != VK_SUCCESS)
throw ls::vulkan_error(res, "vkSignalSemaphore() failed");
}
@ -94,7 +94,7 @@ bool TimelineSemaphore::wait(const vk::Vulkan& vk, uint64_t value, uint64_t time
.pSemaphores = &semaphore,
.pValues = &value
};
auto res = vk.df().WaitSemaphores(vk.dev(), &waitInfo, timeout);
auto res = vk.df().WaitSemaphoresKHR(vk.dev(), &waitInfo, timeout);
if (res != VK_SUCCESS && res != VK_TIMEOUT)
throw ls::vulkan_error(res, "vkWaitSemaphores() failed");

View file

@ -341,9 +341,9 @@ VulkanDeviceFuncs vk::initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevi
.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"),
.SignalSemaphoreKHR = dpa<PFN_vkSignalSemaphoreKHR>(f, d, "vkSignalSemaphoreKHR"),
.WaitSemaphoresKHR = dpa<PFN_vkWaitSemaphoresKHR>(f, d, "vkWaitSemaphoresKHR"),
.GetMemoryFdKHR = dpa<PFN_vkGetMemoryFdKHR>(f, d, "vkGetMemoryFdKHR"),
.ImportSemaphoreFdKHR = dpa<PFN_vkImportSemaphoreFdKHR>(f, d, "vkImportSemaphoreFdKHR"),
.GetSemaphoreFdKHR = dpa<PFN_vkGetSemaphoreFdKHR>(f, d, "vkGetSemaphoreFdKHR"),
@ -352,7 +352,8 @@ VulkanDeviceFuncs vk::initVulkanDeviceFuncs(const VulkanInstanceFuncs& f, VkDevi
Vulkan::Vulkan(const std::string& appName, version appVersion,
const std::string& engineName, version engineVersion,
PhysicalDeviceSelector selectPhysicalDevice) :
PhysicalDeviceSelector selectPhysicalDevice,
bool isGraphical) :
instance(createInstance(
appName, appVersion,
engineName, engineVersion
@ -362,21 +363,45 @@ Vulkan::Vulkan(const std::string& appName, version appVersion,
*this->instance,
selectPhysicalDevice
)),
computeFamilyIdx(findQFI(this->instance_funcs, this->physdev, VK_QUEUE_COMPUTE_BIT)),
queueFamilyIdx(findQFI(this->instance_funcs, this->physdev,
isGraphical ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_COMPUTE_BIT)),
fp16(checkFP16(this->instance_funcs, this->physdev)),
device(createLogicalDevice(this->instance_funcs,
this->physdev,
this->computeFamilyIdx,
this->queueFamilyIdx,
this->fp16
)),
device_funcs(initVulkanDeviceFuncs(
this->instance_funcs,
*this->device
)),
computeQueue(getQueue(this->device_funcs, *this->device, this->computeFamilyIdx)),
computeQueue(getQueue(this->device_funcs, *this->device, this->queueFamilyIdx)),
cmdPool(createCommandPool(this->device_funcs,
*this->device,
this->computeFamilyIdx
this->queueFamilyIdx
)),
descPool(createDescriptorPool(this->device_funcs,
*this->device
)) {
}
Vulkan::Vulkan(VkInstance instance, VkDevice device,
VkPhysicalDevice physdev,
VulkanInstanceFuncs instanceFuncs,
VulkanDeviceFuncs deviceFuncs,
bool isGraphical) :
instance(new VkInstance(instance)),
instance_funcs(instanceFuncs),
physdev(physdev),
queueFamilyIdx(findQFI(this->instance_funcs, this->physdev,
isGraphical ? VK_QUEUE_GRAPHICS_BIT : VK_QUEUE_COMPUTE_BIT)),
fp16(false),
device(new VkDevice(device)),
device_funcs(deviceFuncs),
computeQueue(getQueue(this->device_funcs, *this->device, this->queueFamilyIdx)),
cmdPool(createCommandPool(this->device_funcs,
*this->device,
this->queueFamilyIdx
)),
descPool(createDescriptorPool(this->device_funcs,
*this->device

View file

@ -134,7 +134,7 @@ namespace {
// create device
PFN_vkGetDeviceProcAddr nxvkGetDeviceProcAddr{nullptr};
VkResult myvkCreateDevice(
VkPhysicalDevice physicalDevice,
VkPhysicalDevice physdev,
const VkDeviceCreateInfo* info,
const VkAllocationCallbacks* alloc,
VkDevice* device) {
@ -194,7 +194,7 @@ namespace {
newInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
newInfo.ppEnabledExtensionNames = extensions.data();
auto res = global->fi.CreateDevice(physicalDevice, &newInfo, alloc, device);
auto res = global->fi.CreateDevice(physdev, &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";
@ -207,9 +207,13 @@ namespace {
global->device2InstanceMap.emplace(
*device,
layer::LayerInstance(
global->layer, vk::initVulkanDeviceFuncs(global->fi, *device),
global->instance, *device,
setLoaderData
global->layer,
vk::Vulkan(
global->instance, *device,
physdev,
global->fi,
vk::initVulkanDeviceFuncs(global->fi, *device)
)
)
);
} catch (const std::exception& e) {

View file

@ -3,12 +3,9 @@
#include "lsfg-vk-common/vulkan/vulkan.hpp"
#include <iostream>
#include <string>
#include <utility>
#include <vector>
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan_core.h>
using namespace lsfgvk;
using namespace lsfgvk::layer;
@ -69,14 +66,12 @@ std::vector<const char*> Layer::deviceExtensions() const {
"VK_KHR_external_memory",
"VK_KHR_external_memory_fd",
"VK_KHR_external_semaphore",
"VK_KHR_external_semaphore_fd"
"VK_KHR_external_semaphore_fd",
"VK_KHR_timeline_semaphore"
};
}
layer::LayerInstance::LayerInstance(const Layer& layer, vk::VulkanDeviceFuncs df,
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';
layer::LayerInstance::LayerInstance(const Layer& layer, vk::Vulkan vk)
: vk(std::move(vk)) {
}

View file

@ -7,9 +7,6 @@
#include <optional>
#include <vector>
#include <vulkan/vk_layer.h>
#include <vulkan/vulkan_core.h>
namespace lsfgvk::layer {
/// lsfg-vk layer
@ -48,15 +45,10 @@ 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, vk::VulkanDeviceFuncs df,
VkInstance instance, VkDevice device,
PFN_vkSetDeviceLoaderData setLoaderData);
/// @param vk vulkan instance
LayerInstance(const Layer& layer, vk::Vulkan vk);
private:
Configuration config;
vk::Vulkan vk;
};
}

View file

@ -1,30 +0,0 @@
#include "mini/commandpool.hpp"
#include "common/exception.hpp"
#include "layer.hpp"
#include <vulkan/vulkan_core.h>
#include <cstdint>
#include <memory>
using namespace Mini;
CommandPool::CommandPool(VkDevice device, uint32_t graphicsFamilyIdx) {
// create command pool
const VkCommandPoolCreateInfo desc{
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.queueFamilyIndex = graphicsFamilyIdx
};
VkCommandPool commandPoolHandle{};
auto res = Layer::ovkCreateCommandPool(device, &desc, nullptr, &commandPoolHandle);
if (res != VK_SUCCESS || commandPoolHandle == VK_NULL_HANDLE)
throw LSFG::vulkan_error(res, "Unable to create command pool");
// store command pool in shared ptr
this->commandPool = std::shared_ptr<VkCommandPool>(
new VkCommandPool(commandPoolHandle),
[dev = device](VkCommandPool* commandPoolHandle) {
Layer::ovkDestroyCommandPool(dev, *commandPoolHandle, nullptr);
}
);
}