#pragma once #include "vk/core/descriptorset.hpp" #include "vk/core/commandpool.hpp" #include "vk/core/semaphore.hpp" #include "vk/core/pipeline.hpp" #include "vk/core/device.hpp" #include "vk/core/fence.hpp" #include #include #include #include #include namespace VK::Core { /// 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 VK::vulkan_error if object creation fails. /// CommandBuffer(const Device& device, const CommandPool& pool); /// /// Begin recording commands in the command buffer. /// /// @throws std::logic_error if the command buffer is not in Empty state /// @throws VK::vulkan_error if beginning the command buffer fails. /// void begin(); /// /// Bind a compute pipeline to the command buffer. /// /// @param pipeline Vulkan compute pipeline /// /// @throws std::logic_error if the command buffer is not in Recording state /// void bindPipeline(const Pipeline& pipeline) const; /// /// Bind a descriptor set to the command buffer. /// /// @param pipeline Vulkan compute pipeline /// @param set Vulkan descriptor set /// /// @throws std::logic_error if the command buffer is not in Recording state /// void bindDescriptorSet(const Pipeline& pipeline, const DescriptorSet& set) const; /// /// Insert memory barriers transitioning images into the general layout. /// /// @param images Images to transition to general layout /// /// @throws std::logic_error if the command buffer is not in Recording state /// void insertBarrier(const std::vector& images) const; /// /// Insert memory barriers for images in the command buffer. /// /// @param readableImages Images that will be transitioned from rw to read-only /// @param writableImages Images that will be transitioned from read-only to rw /// /// @throws std::logic_error if the command buffer is not in Recording state /// void insertBarrier( const std::vector& readableImages, const std::vector& writableImages) const; /// /// Copy a buffer to an image. /// /// @param buffer Vulkan buffer /// @param image Vulkan image /// /// @throws std::logic_error if the command buffer is not in Recording state /// void copyBufferToImage(const Buffer& buffer, const Image& image) const; /// /// Clear an image to a color. /// /// @param image Vulkan image /// @param white If true, clear to white; otherwise, clear to black /// /// @throws std::logic_error if the command buffer is not in Recording state /// void clearImage(const Image& image, bool white) const; /// /// Dispatch a compute command. /// /// @param x Number of groups in the X dimension /// @param y Number of groups in the Y dimension /// @param z Number of groups in the Z dimension /// /// @throws std::logic_error if the command buffer is not in Recording state /// void dispatch(uint32_t x, uint32_t y, uint32_t z) const; /// /// End recording commands in the command buffer. /// /// @throws std::logic_error if the command buffer is not in Recording state /// @throws VK::vulkan_error if ending the command buffer fails. /// void end(); // FIXME: Submit logic is kind of janky. /// /// Submit the command buffer to a queue. /// /// @param queue Vulkan queue to submit to /// @param fence Optional fence to signal when the command buffer has finished executing /// @param waitSemaphores Semaphores to wait on before executing the command buffer /// @param waitSemaphoreValues Values for the semaphores to wait on /// @param signalSemaphores Semaphores to signal after executing the command buffer /// @param signalSemaphoreValues Values for the semaphores to signal /// /// @throws std::logic_error if the command buffer is not in Full state. /// @throws VK::vulkan_error if submission fails. /// void submit(VkQueue queue, std::optional fence, const std::vector& waitSemaphores = {}, std::optional> waitSemaphoreValues = std::nullopt, const std::vector& signalSemaphores = {}, std::optional> signalSemaphoreValues = std::nullopt); /// Get the state of the command buffer. [[nodiscard]] auto getState() const { return *this->state; } /// Get the Vulkan handle. [[nodiscard]] auto handle() const { return *this->commandBuffer; } private: std::shared_ptr state; std::shared_ptr commandBuffer; }; }