mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
some reshuffling
This commit is contained in:
parent
13076e9fe3
commit
83dde594c6
3 changed files with 78 additions and 43 deletions
|
|
@ -18,11 +18,13 @@ public:
|
||||||
///
|
///
|
||||||
/// @param device Vulkan device
|
/// @param device Vulkan device
|
||||||
/// @param physicalDevice Vulkan physical device
|
/// @param physicalDevice Vulkan physical device
|
||||||
|
/// @param graphicsQueue Vulkan queue for graphics operations
|
||||||
|
/// @param presentQueue Vulkan queue for presentation operations
|
||||||
///
|
///
|
||||||
/// @throws std::invalid_argument if the device or physicalDevice is null.
|
|
||||||
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
||||||
///
|
///
|
||||||
Application(VkDevice device, VkPhysicalDevice physicalDevice);
|
Application(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||||
|
VkQueue graphicsQueue, VkQueue presentQueue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Add a swapchain to the application.
|
/// Add a swapchain to the application.
|
||||||
|
|
@ -32,7 +34,6 @@ public:
|
||||||
/// @param extent The extent of the images.
|
/// @param extent The extent of the images.
|
||||||
/// @param images The swapchain images.
|
/// @param images The swapchain images.
|
||||||
///
|
///
|
||||||
/// @throws std::invalid_argument if the handle is already added.
|
|
||||||
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
||||||
///
|
///
|
||||||
void addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent,
|
void addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent,
|
||||||
|
|
@ -46,28 +47,27 @@ public:
|
||||||
/// @param semaphores The semaphores to wait on before presenting.
|
/// @param semaphores The semaphores to wait on before presenting.
|
||||||
/// @param idx The index of the swapchain image to present.
|
/// @param idx The index of the swapchain image to present.
|
||||||
///
|
///
|
||||||
/// @throws std::invalid_argument if the handle is not found.
|
|
||||||
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
||||||
///
|
///
|
||||||
void presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
void presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
||||||
const std::vector<VkSemaphore>& semaphores, uint32_t idx);
|
const std::vector<VkSemaphore>& semaphores, uint32_t idx);
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Remove a swapchain from the application.
|
/// Remove a swapchain from the application.
|
||||||
///
|
///
|
||||||
/// @param handle The Vulkan handle of the swapchain state to remove.
|
/// @param handle The Vulkan handle of the swapchain state to remove.
|
||||||
/// @return true if the swapchain was removed, false if it was already retired.
|
/// @return true if the swapchain was removed, false if it was already retired.
|
||||||
///
|
///
|
||||||
/// @throws std::invalid_argument if the handle is null.
|
|
||||||
///
|
|
||||||
bool removeSwapchain(VkSwapchainKHR handle);
|
bool removeSwapchain(VkSwapchainKHR handle);
|
||||||
|
|
||||||
|
|
||||||
/// Get the Vulkan device.
|
/// Get the Vulkan device.
|
||||||
[[nodiscard]] VkDevice getDevice() const { return this->device; }
|
[[nodiscard]] VkDevice getDevice() const { return this->device; }
|
||||||
/// Get the Vulkan physical device.
|
/// Get the Vulkan physical device.
|
||||||
[[nodiscard]] VkPhysicalDevice getPhysicalDevice() const { return this->physicalDevice; }
|
[[nodiscard]] VkPhysicalDevice getPhysicalDevice() const { return this->physicalDevice; }
|
||||||
|
/// Get the Vulkan graphics queue.
|
||||||
|
[[nodiscard]] VkQueue getGraphicsQueue() const { return this->graphicsQueue; }
|
||||||
|
/// Get the Vulkan present queue.
|
||||||
|
[[nodiscard]] VkQueue getPresentQueue() const { return this->presentQueue; }
|
||||||
|
|
||||||
// Non-copyable and non-movable
|
// Non-copyable and non-movable
|
||||||
Application(const Application&) = delete;
|
Application(const Application&) = delete;
|
||||||
|
|
@ -81,6 +81,8 @@ private:
|
||||||
// (non-owned resources)
|
// (non-owned resources)
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkPhysicalDevice physicalDevice;
|
VkPhysicalDevice physicalDevice;
|
||||||
|
VkQueue graphicsQueue;
|
||||||
|
VkQueue presentQueue;
|
||||||
|
|
||||||
// (owned resources)
|
// (owned resources)
|
||||||
std::unordered_map<VkSwapchainKHR, SwapchainContext> swapchains;
|
std::unordered_map<VkSwapchainKHR, SwapchainContext> swapchains;
|
||||||
|
|
@ -95,16 +97,29 @@ public:
|
||||||
///
|
///
|
||||||
/// Create the swapchain context.
|
/// Create the swapchain context.
|
||||||
///
|
///
|
||||||
|
/// @param app The application context to use.
|
||||||
/// @param swapchain The Vulkan swapchain handle.
|
/// @param swapchain The Vulkan swapchain handle.
|
||||||
/// @param format The format of the swapchain images.
|
/// @param format The format of the swapchain images.
|
||||||
/// @param extent The extent of the swapchain images.
|
/// @param extent The extent of the swapchain images.
|
||||||
/// @param images The swapchain images.
|
/// @param images The swapchain images.
|
||||||
///
|
///
|
||||||
/// @throws std::invalid_argument if any parameter is null
|
|
||||||
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
||||||
///
|
///
|
||||||
SwapchainContext(VkSwapchainKHR swapchain, VkFormat format, VkExtent2D extent,
|
SwapchainContext(const Application& app, VkSwapchainKHR swapchain,
|
||||||
const std::vector<VkImage>& images);
|
VkFormat format, VkExtent2D extent, const std::vector<VkImage>& images);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Present the next frame
|
||||||
|
///
|
||||||
|
/// @param app The application context to use
|
||||||
|
/// @param queue The Vulkan queue to present the frame on.
|
||||||
|
/// @param semaphores The semaphores to wait on before presenting.
|
||||||
|
/// @param idx The index of the swapchain image to present.
|
||||||
|
///
|
||||||
|
/// @throws LSFG::vulkan_error if any Vulkan call fails.
|
||||||
|
///
|
||||||
|
void present(const Application& app, VkQueue queue,
|
||||||
|
const std::vector<VkSemaphore>& semaphores, uint32_t idx);
|
||||||
|
|
||||||
/// Get the Vulkan swapchain handle.
|
/// Get the Vulkan swapchain handle.
|
||||||
[[nodiscard]] VkSwapchainKHR handle() const { return this->swapchain; }
|
[[nodiscard]] VkSwapchainKHR handle() const { return this->swapchain; }
|
||||||
|
|
|
||||||
|
|
@ -4,62 +4,49 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
Application::Application(VkDevice device, VkPhysicalDevice physicalDevice)
|
Application::Application(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||||
: device(device), physicalDevice(physicalDevice) {
|
VkQueue graphicsQueue, VkQueue presentQueue)
|
||||||
if (device == VK_NULL_HANDLE || physicalDevice == VK_NULL_HANDLE)
|
: device(device), physicalDevice(physicalDevice),
|
||||||
throw std::invalid_argument("Invalid Vulkan device or physical device");
|
graphicsQueue(graphicsQueue), presentQueue(presentQueue) {}
|
||||||
}
|
|
||||||
|
|
||||||
void Application::addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent,
|
void Application::addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent,
|
||||||
const std::vector<VkImage>& images) {
|
const std::vector<VkImage>& images) {
|
||||||
// add the swapchain handle
|
|
||||||
auto it = this->swapchains.find(handle);
|
auto it = this->swapchains.find(handle);
|
||||||
if (it != this->swapchains.end())
|
if (it != this->swapchains.end())
|
||||||
throw std::invalid_argument("Swapchain handle already exists");
|
return; // already added
|
||||||
|
|
||||||
// initialize the swapchain context
|
this->swapchains.emplace(handle, SwapchainContext(*this, handle, format, extent, images));
|
||||||
this->swapchains.emplace(handle, SwapchainContext(handle, format, extent, images));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapchain,
|
||||||
|
VkFormat format, VkExtent2D extent, const std::vector<VkImage>& images)
|
||||||
|
: swapchain(swapchain), format(format), extent(extent), images(images) {}
|
||||||
|
|
||||||
void Application::presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
void Application::presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
||||||
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
||||||
if (handle == VK_NULL_HANDLE)
|
|
||||||
throw std::invalid_argument("Invalid swapchain handle");
|
|
||||||
|
|
||||||
// find the swapchain context
|
|
||||||
auto it = this->swapchains.find(handle);
|
auto it = this->swapchains.find(handle);
|
||||||
if (it == this->swapchains.end())
|
if (it == this->swapchains.end())
|
||||||
throw std::logic_error("Swapchain not found");
|
throw std::logic_error("Swapchain not found");
|
||||||
|
|
||||||
// TODO: present
|
it->second.present(*this, queue, semaphores, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SwapchainContext::present(const Application& app, VkQueue queue,
|
||||||
|
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
||||||
const VkPresentInfoKHR presentInfo = {
|
const VkPresentInfoKHR presentInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.pNext = nullptr,
|
|
||||||
.waitSemaphoreCount = static_cast<uint32_t>(semaphores.size()),
|
.waitSemaphoreCount = static_cast<uint32_t>(semaphores.size()),
|
||||||
.pWaitSemaphores = semaphores.data(),
|
.pWaitSemaphores = semaphores.data(),
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = &handle,
|
.pSwapchains = &this->swapchain,
|
||||||
.pImageIndices = &idx,
|
.pImageIndices = &idx
|
||||||
.pResults = nullptr // can be null if not needed
|
|
||||||
};
|
};
|
||||||
auto res = vkQueuePresentKHR(queue, &presentInfo);
|
auto res = vkQueuePresentKHR(queue, &presentInfo);
|
||||||
if (res != VK_SUCCESS) // do NOT check VK_SUBOPTIMAL_KHR
|
if (res != VK_SUCCESS) // FIXME: somehow return VK_SUBOPTIMAL_KHR
|
||||||
throw LSFG::vulkan_error(res, "Failed to present swapchain");
|
throw LSFG::vulkan_error(res, "Failed to present swapchain");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SwapchainContext::SwapchainContext(VkSwapchainKHR swapchain, VkFormat format, VkExtent2D extent,
|
|
||||||
const std::vector<VkImage>& images)
|
|
||||||
: swapchain(swapchain), format(format), extent(extent), images(images) {
|
|
||||||
if (swapchain == VK_NULL_HANDLE || format == VK_FORMAT_UNDEFINED)
|
|
||||||
throw std::invalid_argument("Invalid swapchain or images");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Application::removeSwapchain(VkSwapchainKHR handle) {
|
bool Application::removeSwapchain(VkSwapchainKHR handle) {
|
||||||
if (handle == VK_NULL_HANDLE)
|
|
||||||
throw std::invalid_argument("Invalid swapchain handle");
|
|
||||||
|
|
||||||
// remove the swapchain context
|
|
||||||
auto it = this->swapchains.find(handle);
|
auto it = this->swapchains.find(handle);
|
||||||
if (it == this->swapchains.end())
|
if (it == this->swapchains.end())
|
||||||
return false; // already retired... hopefully
|
return false; // already retired... hopefully
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,39 @@ namespace {
|
||||||
VkDevice* pDevice) {
|
VkDevice* pDevice) {
|
||||||
auto res = vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
|
auto res = vkCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
|
||||||
|
|
||||||
|
// extract graphics and present queues
|
||||||
|
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos(pCreateInfo->queueCreateInfoCount);
|
||||||
|
std::copy_n(pCreateInfo->pQueueCreateInfos, queueCreateInfos.size(), queueCreateInfos.data());
|
||||||
|
|
||||||
|
uint32_t familyCount{};
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, nullptr);
|
||||||
|
std::vector<VkQueueFamilyProperties> families(familyCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, families.data());
|
||||||
|
|
||||||
|
std::optional<uint32_t> graphicsFamilyIdx;
|
||||||
|
std::optional<uint32_t> presentFamilyIdx;
|
||||||
|
for (uint32_t i = 0; i < families.size(); ++i) {
|
||||||
|
auto it = std::ranges::find_if(queueCreateInfos,
|
||||||
|
[i](const VkDeviceQueueCreateInfo& info) {
|
||||||
|
return info.queueFamilyIndex == i;
|
||||||
|
}) ;
|
||||||
|
if (it == queueCreateInfos.end())
|
||||||
|
continue; // skip if this family is not used by the device
|
||||||
|
if (families.at(i).queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
graphicsFamilyIdx.emplace(i);
|
||||||
|
if (families.at(i).queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||||
|
presentFamilyIdx.emplace(i);
|
||||||
|
}
|
||||||
|
if (!graphicsFamilyIdx.has_value() || !presentFamilyIdx.has_value()) {
|
||||||
|
Log::error("No suitable queue family found for graphics or present");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkQueue graphicsQueue{};
|
||||||
|
vkGetDeviceQueue(*pDevice, *graphicsFamilyIdx, 0, &graphicsQueue);
|
||||||
|
VkQueue presentQueue{};
|
||||||
|
vkGetDeviceQueue(*pDevice, *presentFamilyIdx, 0, &presentQueue);
|
||||||
|
|
||||||
// create the main application
|
// create the main application
|
||||||
if (application.has_value()) {
|
if (application.has_value()) {
|
||||||
Log::error("Application already initialized, are you trying to create a second device?");
|
Log::error("Application already initialized, are you trying to create a second device?");
|
||||||
|
|
@ -28,7 +61,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
application.emplace(*pDevice, physicalDevice);
|
application.emplace(*pDevice, physicalDevice, graphicsQueue, presentQueue);
|
||||||
Log::info("lsfg-vk(hooks): Application created successfully");
|
Log::info("lsfg-vk(hooks): Application created successfully");
|
||||||
} catch (const LSFG::vulkan_error& e) {
|
} catch (const LSFG::vulkan_error& e) {
|
||||||
Log::error("Encountered Vulkan error {:x} while creating application: {}",
|
Log::error("Encountered Vulkan error {:x} while creating application: {}",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue