mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2025-10-30 07:01:10 +00:00
some progress on rendering
This commit is contained in:
parent
70bf51fa72
commit
ad0fd6eb77
9 changed files with 300 additions and 17 deletions
|
|
@ -1,7 +1,10 @@
|
||||||
#ifndef APPLICATION_HPP
|
#ifndef APPLICATION_HPP
|
||||||
#define APPLICATION_HPP
|
#define APPLICATION_HPP
|
||||||
|
|
||||||
|
#include "mini/commandpool.hpp"
|
||||||
#include "mini/image.hpp"
|
#include "mini/image.hpp"
|
||||||
|
#include "mini/semaphore.hpp"
|
||||||
|
#include <array>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -20,12 +23,12 @@ 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 graphicsQueue Vulkan queue for graphics operations
|
||||||
/// @param presentQueue Vulkan queue for presentation operations
|
/// @param graphicsQueueFamilyIndex The family index of the graphics queue
|
||||||
///
|
///
|
||||||
/// @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);
|
VkQueue graphicsQueue, uint32_t graphicsQueueFamilyIndex);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Add a swapchain to the application.
|
/// Add a swapchain to the application.
|
||||||
|
|
@ -67,8 +70,8 @@ public:
|
||||||
[[nodiscard]] VkPhysicalDevice getPhysicalDevice() const { return this->physicalDevice; }
|
[[nodiscard]] VkPhysicalDevice getPhysicalDevice() const { return this->physicalDevice; }
|
||||||
/// Get the Vulkan graphics queue.
|
/// Get the Vulkan graphics queue.
|
||||||
[[nodiscard]] VkQueue getGraphicsQueue() const { return this->graphicsQueue; }
|
[[nodiscard]] VkQueue getGraphicsQueue() const { return this->graphicsQueue; }
|
||||||
/// Get the Vulkan present queue.
|
/// Get the graphics queue family index.
|
||||||
[[nodiscard]] VkQueue getPresentQueue() const { return this->presentQueue; }
|
[[nodiscard]] uint32_t getGraphicsQueueFamilyIndex() const { return this->graphicsQueueFamilyIndex; }
|
||||||
|
|
||||||
// Non-copyable and non-movable
|
// Non-copyable and non-movable
|
||||||
Application(const Application&) = delete;
|
Application(const Application&) = delete;
|
||||||
|
|
@ -83,7 +86,7 @@ private:
|
||||||
VkDevice device;
|
VkDevice device;
|
||||||
VkPhysicalDevice physicalDevice;
|
VkPhysicalDevice physicalDevice;
|
||||||
VkQueue graphicsQueue;
|
VkQueue graphicsQueue;
|
||||||
VkQueue presentQueue;
|
uint32_t graphicsQueueFamilyIndex;
|
||||||
|
|
||||||
// (owned resources)
|
// (owned resources)
|
||||||
std::unordered_map<VkSwapchainKHR, SwapchainContext> swapchains;
|
std::unordered_map<VkSwapchainKHR, SwapchainContext> swapchains;
|
||||||
|
|
@ -144,8 +147,15 @@ private:
|
||||||
std::vector<VkImage> images;
|
std::vector<VkImage> images;
|
||||||
|
|
||||||
// (owned resources)
|
// (owned resources)
|
||||||
|
Mini::CommandPool cmdPool;
|
||||||
|
std::array<Mini::Semaphore, 8> copySemaphores; // copy current swap to frame
|
||||||
|
std::array<Mini::Semaphore, 8> acquireSemaphores; // acquire new swapchain image
|
||||||
|
std::array<Mini::Semaphore, 8> renderSemaphores; // fg is done
|
||||||
|
std::array<Mini::Semaphore, 8> presentSemaphores; // copy is done, ready to present
|
||||||
|
|
||||||
Mini::Image frame_0, frame_1;
|
Mini::Image frame_0, frame_1;
|
||||||
std::shared_ptr<int32_t> lsfgId;
|
std::shared_ptr<int32_t> lsfgId;
|
||||||
|
uint64_t frameIdx{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPLICATION_HPP
|
#endif // APPLICATION_HPP
|
||||||
|
|
|
||||||
95
include/mini/commandbuffer.hpp
Normal file
95
include/mini/commandbuffer.hpp
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
#ifndef COMMANDBUFFER_HPP
|
||||||
|
#define COMMANDBUFFER_HPP
|
||||||
|
|
||||||
|
#include "mini/commandpool.hpp"
|
||||||
|
#include "mini/semaphore.hpp"
|
||||||
|
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Mini {
|
||||||
|
|
||||||
|
/// State of the command buffer.
|
||||||
|
enum class CommandBufferState {
|
||||||
|
/// Command buffer is not initialized or has been destroyed.
|
||||||
|
Invalid,
|
||||||
|
/// Command buffer has been created.
|
||||||
|
Empty,
|
||||||
|
/// Command buffer recording has started.
|
||||||
|
Recording,
|
||||||
|
/// Command buffer recording has ended.
|
||||||
|
Full,
|
||||||
|
/// Command buffer has been submitted to a queue.
|
||||||
|
Submitted
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// C++ wrapper class for a Vulkan command buffer.
|
||||||
|
///
|
||||||
|
/// This class manages the lifetime of a Vulkan command buffer.
|
||||||
|
///
|
||||||
|
class CommandBuffer {
|
||||||
|
public:
|
||||||
|
CommandBuffer() noexcept = default;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Create the command buffer.
|
||||||
|
///
|
||||||
|
/// @param device Vulkan device
|
||||||
|
/// @param pool Vulkan command pool
|
||||||
|
///
|
||||||
|
/// @throws LSFG::vulkan_error if object creation fails.
|
||||||
|
///
|
||||||
|
CommandBuffer(VkDevice device, const CommandPool& pool);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Begin recording commands in the command buffer.
|
||||||
|
///
|
||||||
|
/// @throws std::logic_error if the command buffer is in Empty state
|
||||||
|
/// @throws LSFG::vulkan_error if beginning the command buffer fails.
|
||||||
|
///
|
||||||
|
void begin();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// End recording commands in the command buffer.
|
||||||
|
///
|
||||||
|
/// @throws std::logic_error if the command buffer is not in Recording state
|
||||||
|
/// @throws LSFG::vulkan_error if ending the command buffer fails.
|
||||||
|
///
|
||||||
|
void end();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Submit the command buffer to a queue.
|
||||||
|
///
|
||||||
|
/// @param queue Vulkan queue to submit to
|
||||||
|
/// @param waitSemaphores Semaphores to wait on before executing the command buffer
|
||||||
|
/// @param signalSemaphores Semaphores to signal after executing the command buffer
|
||||||
|
///
|
||||||
|
/// @throws std::logic_error if the command buffer is not in Full state.
|
||||||
|
/// @throws LSFG::vulkan_error if submission fails.
|
||||||
|
///
|
||||||
|
void submit(VkQueue queue,
|
||||||
|
const std::vector<Semaphore>& waitSemaphores = {},
|
||||||
|
const std::vector<Semaphore>& signalSemaphores = {});
|
||||||
|
|
||||||
|
/// Get the state of the command buffer.
|
||||||
|
[[nodiscard]] CommandBufferState getState() const { return *this->state; }
|
||||||
|
/// Get the Vulkan handle.
|
||||||
|
[[nodiscard]] auto handle() const { return *this->commandBuffer; }
|
||||||
|
|
||||||
|
/// Trivially copyable, moveable and destructible
|
||||||
|
CommandBuffer(const CommandBuffer&) noexcept = default;
|
||||||
|
CommandBuffer& operator=(const CommandBuffer&) noexcept = default;
|
||||||
|
CommandBuffer(CommandBuffer&&) noexcept = default;
|
||||||
|
CommandBuffer& operator=(CommandBuffer&&) noexcept = default;
|
||||||
|
~CommandBuffer() = default;
|
||||||
|
private:
|
||||||
|
std::shared_ptr<CommandBufferState> state;
|
||||||
|
std::shared_ptr<VkCommandBuffer> commandBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COMMANDBUFFER_HPP
|
||||||
44
include/mini/commandpool.hpp
Normal file
44
include/mini/commandpool.hpp
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef COMMANDPOOL_HPP
|
||||||
|
#define COMMANDPOOL_HPP
|
||||||
|
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // COMMANDPOOL_HPP
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
#include "log.hpp"
|
#include "mini/commandpool.hpp"
|
||||||
#include "mini/image.hpp"
|
#include "mini/image.hpp"
|
||||||
#include "mini/semaphore.hpp"
|
#include "mini/semaphore.hpp"
|
||||||
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
Application::Application(VkDevice device, VkPhysicalDevice physicalDevice,
|
Application::Application(VkDevice device, VkPhysicalDevice physicalDevice,
|
||||||
VkQueue graphicsQueue, VkQueue presentQueue)
|
VkQueue graphicsQueue, uint32_t graphicsQueueFamilyIndex)
|
||||||
: device(device), physicalDevice(physicalDevice),
|
: device(device), physicalDevice(physicalDevice),
|
||||||
graphicsQueue(graphicsQueue), presentQueue(presentQueue) {
|
graphicsQueue(graphicsQueue), graphicsQueueFamilyIndex(graphicsQueueFamilyIndex) {
|
||||||
LSFG::initialize();
|
LSFG::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,6 +26,8 @@ void Application::addSwapchain(VkSwapchainKHR handle, VkFormat format, VkExtent2
|
||||||
SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapchain,
|
SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapchain,
|
||||||
VkFormat format, VkExtent2D extent, const std::vector<VkImage>& images)
|
VkFormat format, VkExtent2D extent, const std::vector<VkImage>& images)
|
||||||
: swapchain(swapchain), format(format), extent(extent), images(images) {
|
: swapchain(swapchain), format(format), extent(extent), images(images) {
|
||||||
|
this->cmdPool = Mini::CommandPool(app.getDevice(), app.getGraphicsQueueFamilyIndex());
|
||||||
|
|
||||||
int frame0fd{};
|
int frame0fd{};
|
||||||
this->frame_0 = Mini::Image(
|
this->frame_0 = Mini::Image(
|
||||||
app.getDevice(), app.getPhysicalDevice(),
|
app.getDevice(), app.getPhysicalDevice(),
|
||||||
|
|
@ -33,6 +35,7 @@ SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapch
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT, &frame0fd
|
VK_IMAGE_ASPECT_COLOR_BIT, &frame0fd
|
||||||
);
|
);
|
||||||
|
|
||||||
int frame1fd{};
|
int frame1fd{};
|
||||||
this->frame_1 = Mini::Image(
|
this->frame_1 = Mini::Image(
|
||||||
app.getDevice(), app.getPhysicalDevice(),
|
app.getDevice(), app.getPhysicalDevice(),
|
||||||
|
|
@ -40,6 +43,7 @@ SwapchainContext::SwapchainContext(const Application& app, VkSwapchainKHR swapch
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
VK_IMAGE_ASPECT_COLOR_BIT, &frame1fd
|
VK_IMAGE_ASPECT_COLOR_BIT, &frame1fd
|
||||||
);
|
);
|
||||||
|
|
||||||
auto id = LSFG::createContext(extent.width, extent.height, frame0fd, frame1fd);
|
auto id = LSFG::createContext(extent.width, extent.height, frame0fd, frame1fd);
|
||||||
this->lsfgId = std::shared_ptr<int32_t>(
|
this->lsfgId = std::shared_ptr<int32_t>(
|
||||||
new int32_t(id),
|
new int32_t(id),
|
||||||
|
|
@ -60,6 +64,29 @@ void Application::presentSwapchain(VkSwapchainKHR handle, VkQueue queue,
|
||||||
|
|
||||||
void SwapchainContext::present(const Application& app, VkQueue queue,
|
void SwapchainContext::present(const Application& app, VkQueue queue,
|
||||||
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
const std::vector<VkSemaphore>& semaphores, uint32_t idx) {
|
||||||
|
// create semaphores
|
||||||
|
int copySem{};
|
||||||
|
int presentSem{};
|
||||||
|
Mini::Semaphore& copySemaphore = this->copySemaphores.at(this->frameIdx % 8);
|
||||||
|
copySemaphore = Mini::Semaphore(app.getDevice(), ©Sem);
|
||||||
|
Mini::Semaphore& acquireSemaphore = this->acquireSemaphores.at(this->frameIdx % 8);
|
||||||
|
acquireSemaphore = Mini::Semaphore(app.getDevice());
|
||||||
|
Mini::Semaphore& renderSemaphore = this->renderSemaphores.at(this->frameIdx % 8);
|
||||||
|
renderSemaphore = Mini::Semaphore(app.getDevice());
|
||||||
|
Mini::Semaphore& presentSemaphore = this->presentSemaphores.at(this->frameIdx % 8);
|
||||||
|
presentSemaphore = Mini::Semaphore(app.getDevice(), &presentSem);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// render the intermediary frame
|
||||||
|
// FIXME: i forgot the flippin output
|
||||||
|
// FIXME: semaphores are being destroyed in the context
|
||||||
|
LSFG::presentContext(*this->lsfgId, copySem, presentSem);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
const VkPresentInfoKHR presentInfo = {
|
const VkPresentInfoKHR presentInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.waitSemaphoreCount = static_cast<uint32_t>(semaphores.size()),
|
.waitSemaphoreCount = static_cast<uint32_t>(semaphores.size()),
|
||||||
|
|
@ -71,6 +98,8 @@ void SwapchainContext::present(const Application& app, VkQueue queue,
|
||||||
auto res = vkQueuePresentKHR(queue, &presentInfo);
|
auto res = vkQueuePresentKHR(queue, &presentInfo);
|
||||||
if (res != VK_SUCCESS) // FIXME: somehow return 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");
|
||||||
|
|
||||||
|
this->frameIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::removeSwapchain(VkSwapchainKHR handle) {
|
bool Application::removeSwapchain(VkSwapchainKHR handle) {
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ namespace {
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, families.data());
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &familyCount, families.data());
|
||||||
|
|
||||||
std::optional<uint32_t> graphicsFamilyIdx;
|
std::optional<uint32_t> graphicsFamilyIdx;
|
||||||
std::optional<uint32_t> presentFamilyIdx;
|
|
||||||
for (uint32_t i = 0; i < families.size(); ++i) {
|
for (uint32_t i = 0; i < families.size(); ++i) {
|
||||||
auto it = std::ranges::find_if(queueCreateInfos,
|
auto it = std::ranges::find_if(queueCreateInfos,
|
||||||
[i](const VkDeviceQueueCreateInfo& info) {
|
[i](const VkDeviceQueueCreateInfo& info) {
|
||||||
|
|
@ -86,18 +85,14 @@ namespace {
|
||||||
continue; // skip if this family is not used by the device
|
continue; // skip if this family is not used by the device
|
||||||
if (families.at(i).queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
if (families.at(i).queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
graphicsFamilyIdx.emplace(i);
|
graphicsFamilyIdx.emplace(i);
|
||||||
if (families.at(i).queueFlags & VK_QUEUE_COMPUTE_BIT)
|
|
||||||
presentFamilyIdx.emplace(i);
|
|
||||||
}
|
}
|
||||||
if (!graphicsFamilyIdx.has_value() || !presentFamilyIdx.has_value()) {
|
if (!graphicsFamilyIdx.has_value()) {
|
||||||
Log::error("No suitable queue family found for graphics or present");
|
Log::error("No suitable queue family found for graphics or present");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkQueue graphicsQueue{};
|
VkQueue graphicsQueue{};
|
||||||
vkGetDeviceQueue(*pDevice, *graphicsFamilyIdx, 0, &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()) {
|
||||||
|
|
@ -106,7 +101,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
application.emplace(*pDevice, physicalDevice, graphicsQueue, presentQueue);
|
application.emplace(*pDevice, physicalDevice, graphicsQueue, *graphicsFamilyIdx);
|
||||||
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: {}",
|
||||||
|
|
|
||||||
88
src/mini/commandbuffer.cpp
Normal file
88
src/mini/commandbuffer.cpp
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include "mini/commandbuffer.hpp"
|
||||||
|
#include "lsfg.hpp"
|
||||||
|
|
||||||
|
using namespace Mini;
|
||||||
|
|
||||||
|
CommandBuffer::CommandBuffer(VkDevice device, const CommandPool& pool) {
|
||||||
|
// create command buffer
|
||||||
|
const VkCommandBufferAllocateInfo desc{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
.commandPool = pool.handle(),
|
||||||
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
|
.commandBufferCount = 1
|
||||||
|
};
|
||||||
|
VkCommandBuffer commandBufferHandle{};
|
||||||
|
auto res = vkAllocateCommandBuffers(device, &desc, &commandBufferHandle);
|
||||||
|
if (res != VK_SUCCESS || commandBufferHandle == VK_NULL_HANDLE)
|
||||||
|
throw LSFG::vulkan_error(res, "Unable to allocate command buffer");
|
||||||
|
|
||||||
|
// store command buffer in shared ptr
|
||||||
|
this->state = std::make_shared<CommandBufferState>(CommandBufferState::Empty);
|
||||||
|
this->commandBuffer = std::shared_ptr<VkCommandBuffer>(
|
||||||
|
new VkCommandBuffer(commandBufferHandle),
|
||||||
|
[dev = device, pool = pool.handle()](VkCommandBuffer* cmdBuffer) {
|
||||||
|
vkFreeCommandBuffers(dev, pool, 1, cmdBuffer);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandBuffer::begin() {
|
||||||
|
if (*this->state != CommandBufferState::Empty)
|
||||||
|
throw std::logic_error("Command buffer is not in Empty state");
|
||||||
|
|
||||||
|
const VkCommandBufferBeginInfo beginInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||||
|
};
|
||||||
|
auto res = vkBeginCommandBuffer(*this->commandBuffer, &beginInfo);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
throw LSFG::vulkan_error(res, "Unable to begin command buffer");
|
||||||
|
|
||||||
|
*this->state = CommandBufferState::Recording;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandBuffer::end() {
|
||||||
|
if (*this->state != CommandBufferState::Recording)
|
||||||
|
throw std::logic_error("Command buffer is not in Recording state");
|
||||||
|
|
||||||
|
auto res = vkEndCommandBuffer(*this->commandBuffer);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
throw LSFG::vulkan_error(res, "Unable to end command buffer");
|
||||||
|
|
||||||
|
*this->state = CommandBufferState::Full;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandBuffer::submit(VkQueue queue,
|
||||||
|
const std::vector<Semaphore>& waitSemaphores,
|
||||||
|
const std::vector<Semaphore>& signalSemaphores) {
|
||||||
|
if (*this->state != CommandBufferState::Full)
|
||||||
|
throw std::logic_error("Command buffer is not in Full state");
|
||||||
|
|
||||||
|
const std::vector<VkPipelineStageFlags> waitStages(waitSemaphores.size(),
|
||||||
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
|
|
||||||
|
std::vector<VkSemaphore> waitSemaphoresHandles;
|
||||||
|
waitSemaphoresHandles.reserve(waitSemaphores.size());
|
||||||
|
for (const auto& semaphore : waitSemaphores)
|
||||||
|
waitSemaphoresHandles.push_back(semaphore.handle());
|
||||||
|
std::vector<VkSemaphore> signalSemaphoresHandles;
|
||||||
|
signalSemaphoresHandles.reserve(signalSemaphores.size());
|
||||||
|
for (const auto& semaphore : signalSemaphores)
|
||||||
|
signalSemaphoresHandles.push_back(semaphore.handle());
|
||||||
|
|
||||||
|
const VkSubmitInfo submitInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size()),
|
||||||
|
.pWaitSemaphores = waitSemaphoresHandles.data(),
|
||||||
|
.pWaitDstStageMask = waitStages.data(),
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &(*this->commandBuffer),
|
||||||
|
.signalSemaphoreCount = static_cast<uint32_t>(signalSemaphores.size()),
|
||||||
|
.pSignalSemaphores = signalSemaphoresHandles.data()
|
||||||
|
};
|
||||||
|
auto res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
||||||
|
if (res != VK_SUCCESS)
|
||||||
|
throw LSFG::vulkan_error(res, "Unable to submit command buffer");
|
||||||
|
|
||||||
|
*this->state = CommandBufferState::Submitted;
|
||||||
|
}
|
||||||
24
src/mini/commandpool.cpp
Normal file
24
src/mini/commandpool.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include "mini/commandpool.hpp"
|
||||||
|
#include "lsfg.hpp"
|
||||||
|
|
||||||
|
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 = vkCreateCommandPool(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) {
|
||||||
|
vkDestroyCommandPool(dev, *commandPoolHandle, nullptr);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
#include "lsfg.hpp"
|
#include "lsfg.hpp"
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vulkan/vulkan_core.h>
|
|
||||||
|
|
||||||
using namespace Mini;
|
using namespace Mini;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#include "mini/semaphore.hpp"
|
#include "mini/semaphore.hpp"
|
||||||
#include "lsfg.hpp"
|
#include "lsfg.hpp"
|
||||||
#include <vulkan/vulkan_core.h>
|
|
||||||
|
|
||||||
using namespace Mini;
|
using namespace Mini;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue