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 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.
|
||||
///
|
||||
Application(VkDevice device, VkPhysicalDevice physicalDevice);
|
||||
Application(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
VkQueue graphicsQueue, VkQueue presentQueue);
|
||||
|
||||
///
|
||||
/// Add a swapchain to the application.
|
||||
|
|
@ -32,7 +34,6 @@ public:
|
|||
/// @param extent The extent of the 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.
|
||||
///
|
||||
void addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent,
|
||||
|
|
@ -46,28 +47,27 @@ public:
|
|||
/// @param semaphores The semaphores to wait on before presenting.
|
||||
/// @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.
|
||||
///
|
||||
void presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
||||
const std::vector<VkSemaphore>& semaphores, uint32_t idx);
|
||||
|
||||
|
||||
///
|
||||
/// Remove a swapchain from the application.
|
||||
///
|
||||
/// @param handle The Vulkan handle of the swapchain state to remove.
|
||||
/// @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);
|
||||
|
||||
|
||||
/// Get the Vulkan device.
|
||||
[[nodiscard]] VkDevice getDevice() const { return this->device; }
|
||||
/// Get the Vulkan physical device.
|
||||
[[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
|
||||
Application(const Application&) = delete;
|
||||
|
|
@ -81,6 +81,8 @@ private:
|
|||
// (non-owned resources)
|
||||
VkDevice device;
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkQueue graphicsQueue;
|
||||
VkQueue presentQueue;
|
||||
|
||||
// (owned resources)
|
||||
std::unordered_map<VkSwapchainKHR, SwapchainContext> swapchains;
|
||||
|
|
@ -95,16 +97,29 @@ public:
|
|||
///
|
||||
/// Create the swapchain context.
|
||||
///
|
||||
/// @param app The application context to use.
|
||||
/// @param swapchain The Vulkan swapchain handle.
|
||||
/// @param format The format of the swapchain images.
|
||||
/// @param extent The extent of 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.
|
||||
///
|
||||
SwapchainContext(VkSwapchainKHR swapchain, VkFormat format, VkExtent2D extent,
|
||||
const std::vector<VkImage>& images);
|
||||
SwapchainContext(const Application& app, VkSwapchainKHR swapchain,
|
||||
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.
|
||||
[[nodiscard]] VkSwapchainKHR handle() const { return this->swapchain; }
|
||||
|
|
|
|||
|
|
@ -4,62 +4,49 @@
|
|||
|
||||
#include <stdexcept>
|
||||
|
||||
Application::Application(VkDevice device, VkPhysicalDevice physicalDevice)
|
||||
: device(device), physicalDevice(physicalDevice) {
|
||||
if (device == VK_NULL_HANDLE || physicalDevice == VK_NULL_HANDLE)
|
||||
throw std::invalid_argument("Invalid Vulkan device or physical device");
|
||||
}
|
||||
Application::Application(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||
VkQueue graphicsQueue, VkQueue presentQueue)
|
||||
: device(device), physicalDevice(physicalDevice),
|
||||
graphicsQueue(graphicsQueue), presentQueue(presentQueue) {}
|
||||
|
||||
void Application::addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2D extent,
|
||||
const std::vector<VkImage>& images) {
|
||||
// add the swapchain handle
|
||||
auto it = this->swapchains.find(handle);
|
||||
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(handle, format, extent, images));
|
||||
this->swapchains.emplace(handle, SwapchainContext(*this, 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,
|
||||
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);
|
||||
if (it == this->swapchains.end())
|
||||
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 = {
|
||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
.pNext = nullptr,
|
||||
.waitSemaphoreCount = static_cast<uint32_t>(semaphores.size()),
|
||||
.pWaitSemaphores = semaphores.data(),
|
||||
.swapchainCount = 1,
|
||||
.pSwapchains = &handle,
|
||||
.pImageIndices = &idx,
|
||||
.pResults = nullptr // can be null if not needed
|
||||
.pSwapchains = &this->swapchain,
|
||||
.pImageIndices = &idx
|
||||
};
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
if (handle == VK_NULL_HANDLE)
|
||||
throw std::invalid_argument("Invalid swapchain handle");
|
||||
|
||||
// remove the swapchain context
|
||||
auto it = this->swapchains.find(handle);
|
||||
if (it == this->swapchains.end())
|
||||
return false; // already retired... hopefully
|
||||
|
|
|
|||
|
|
@ -21,6 +21,39 @@ namespace {
|
|||
VkDevice* 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
|
||||
if (application.has_value()) {
|
||||
Log::error("Application already initialized, are you trying to create a second device?");
|
||||
|
|
@ -28,7 +61,7 @@ namespace {
|
|||
}
|
||||
|
||||
try {
|
||||
application.emplace(*pDevice, physicalDevice);
|
||||
application.emplace(*pDevice, physicalDevice, graphicsQueue, presentQueue);
|
||||
Log::info("lsfg-vk(hooks): Application created successfully");
|
||||
} catch (const LSFG::vulkan_error& e) {
|
||||
Log::error("Encountered Vulkan error {:x} while creating application: {}",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue