1#ifndef VULKAN_COMMANDBUFFER
2#define VULKAN_COMMANDBUFFER
4#include <vulkan/vulkan.h>
20namespace Vulkan {
class CommandBuffer; }
23class Vulkan::CommandBuffer {
26 CommandBuffer(
const LogicalDevice& virtualGpu,
const CommandBufferPool& commandBufferPool) : virtualGpu{ &virtualGpu }, commandBufferPool{ &commandBufferPool } {
27 allocateCommandBuffer(virtualGpu, commandBufferPool);
45 template<
typename... Args,
template<
typename...>
class... Command>
requires (std::same_as<Command<int>, std::tuple<int>> && ...)
46 CommandBuffer(
const LogicalDevice& virtualGpu,
const CommandBufferPool& commandBufferPool,
const PipelineOptions::RenderPass& renderPass,
const Framebuffer& framebuffer,
const Pipeline& pipeline, Command<
void(*)(VkCommandBuffer, Args...), Args...>&&... commands) : virtualGpu{ virtualGpu }, commandBufferPool{ commandBufferPool } {
47 allocateCommandBuffer(virtualGpu, commandBufferPool);
48 reset(renderPass, framebuffer, pipeline);
51 (std::apply([
this]<
typename... Args>(Args&&... args) {
52 this->addCommand(std::forward<Args>(args)...);
59 CommandBuffer(
const CommandBuffer&) =
delete;
60 CommandBuffer& operator=(
const CommandBuffer&) =
delete;
62 CommandBuffer(CommandBuffer&& movedFrom) noexcept : CommandBuffer{} {
63 std::swap(commandBuffer, movedFrom.commandBuffer);
64 std::swap(virtualGpu, movedFrom.virtualGpu);
65 std::swap(commandBufferPool, movedFrom.commandBufferPool);
68 CommandBuffer& operator=(CommandBuffer&&) =
delete;
71 if (commandBuffer != VK_NULL_HANDLE) {
72 vkFreeCommandBuffers(+*virtualGpu, +*commandBufferPool, 1, &commandBuffer);
90 CommandBuffer& reset(
const PipelineOptions::RenderPass& renderPass,
const Framebuffer& framebuffer) {
92 vkResetCommandBuffer(commandBuffer, 0);
95 VkCommandBufferBeginInfo beginInfo{};
96 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
98 beginInfo.pInheritanceInfo =
nullptr;
99 if (VkResult result = vkBeginCommandBuffer(commandBuffer, &beginInfo); result != VK_SUCCESS) {
100 throw VulkanException(
"Failed to begin recording command buffer!", result);
104 VkRenderPassBeginInfo renderPassInfo{};
105 renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
106 renderPassInfo.renderPass = +renderPass;
107 renderPassInfo.framebuffer = +framebuffer;
108 renderPassInfo.renderArea.offset = { 0, 0 };
109 renderPassInfo.renderArea.extent = VkExtent2D{ framebuffer.getResolution().first, framebuffer.getResolution().second };
110 VkClearValue clearvalues[] = { {{0.0f, 0.0f, 0.0f, 1.0f}}, {1.0f, 0} };
111 renderPassInfo.clearValueCount = renderPass.getAttachmentCount();
112 renderPassInfo.pClearValues = clearvalues;
113 vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
116 VkViewport viewport{};
119 viewport.width =
static_cast<float>(framebuffer.getResolution().first);
120 viewport.height =
static_cast<float>(framebuffer.getResolution().second);
121 viewport.minDepth = 0.0f;
122 viewport.maxDepth = 1.0f;
123 vkCmdSetViewport(commandBuffer, 0, 1, &viewport);
127 scissor.offset = { 0, 0 };
128 scissor.extent = VkExtent2D{ framebuffer.getResolution().first, framebuffer.getResolution().second };
129 vkCmdSetScissor(commandBuffer, 0, 1, &scissor);
139 CommandBuffer& reset() {
141 vkResetCommandBuffer(commandBuffer, 0);
144 VkCommandBufferBeginInfo beginInfo{};
145 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
146 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
147 beginInfo.pInheritanceInfo =
nullptr;
149 if (VkResult result = vkBeginCommandBuffer(commandBuffer, &beginInfo); result != VK_SUCCESS) {
150 throw VulkanException(
"Failed to begin recording command buffer!", result);
175 template<
typename... Args,
typename... Params>
176 CommandBuffer& addCommand(
void(*command)(VkCommandBuffer, Params...), Args&&... args) {
177 command(commandBuffer, std::forward<Args>(args)...);
189 template<
typename... Args,
template<
typename...>
class... Command>
requires (std::same_as<Command<>, std::tuple<>> && ...)
190 CommandBuffer& addCommands(Command<
void(*)(VkCommandBuffer, Args...), Args...>&&... commands) {
192 (std::apply([
this]<
typename... Args>(Args&&... args) {
193 this->addCommand(std::forward<Args>(args)...);
199 CommandBuffer& endCommand() {
200 if (VkResult result = vkEndCommandBuffer(commandBuffer); result != VK_SUCCESS) {
201 throw VulkanException(
"Failed to record command buffer!", result);
208 CommandBuffer& sendCommand(Queue queue,
const std::vector<VkSemaphore>& waitSemaphores,
const std::vector<VkSemaphore>& signalSemaphores,
const std::vector<VkPipelineStageFlags>& waitStages,
const SynchronizationPrimitives::Fence& fence) {
209 VkSubmitInfo submitInfo{};
210 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
211 submitInfo.waitSemaphoreCount = waitSemaphores.size();
212 submitInfo.pWaitSemaphores = waitSemaphores.size() != 0 ? waitSemaphores.data() :
nullptr;
213 submitInfo.pWaitDstStageMask = waitStages.size() != 0 ? waitStages.data() :
nullptr;
214 submitInfo.commandBufferCount = 1;
215 submitInfo.pCommandBuffers = &commandBuffer;
216 submitInfo.signalSemaphoreCount = signalSemaphores.size();
217 submitInfo.pSignalSemaphores = signalSemaphores.size() != 0 ? signalSemaphores.data() :
nullptr;
219 if (VkResult result = vkQueueSubmit(+queue, 1, &submitInfo, +fence); result != VK_SUCCESS) {
220 throw VulkanException{
"Failed to submit the command buffer for the current frame", result };
227 CommandBuffer& sendCommand(Queue queue) {
228 VkSubmitInfo submitInfo{};
229 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
230 submitInfo.waitSemaphoreCount = 0;
231 submitInfo.pWaitSemaphores =
nullptr;
232 submitInfo.pWaitDstStageMask =
nullptr;
233 submitInfo.commandBufferCount = 1;
234 submitInfo.pCommandBuffers = &commandBuffer;
235 submitInfo.signalSemaphoreCount = 0;
236 submitInfo.pSignalSemaphores =
nullptr;
238 if (VkResult result = vkQueueSubmit(+queue, 1, &submitInfo, VK_NULL_HANDLE); result != VK_SUCCESS) {
239 throw VulkanException{
"Failed to submit the command buffer for the current frame", result };
249 CommandBuffer() : commandBuffer{ VK_NULL_HANDLE }, commandBufferPool{ nullptr }, virtualGpu{ nullptr }{}
251 void allocateCommandBuffer(
const LogicalDevice& virtualGpu,
const CommandBufferPool& commandBufferPool) {
252 VkCommandBufferAllocateInfo allocInfo{};
253 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
254 allocInfo.commandPool = +commandBufferPool;
255 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
256 allocInfo.commandBufferCount = 1;
258 if (VkResult result = vkAllocateCommandBuffers(+virtualGpu, &allocInfo, &commandBuffer); result != VK_SUCCESS) {
259 throw VulkanException(
"Failed to allocate command buffers!", result);
264 VkCommandBuffer commandBuffer;
265 CommandBufferPool
const* commandBufferPool;
266 LogicalDevice
const * virtualGpu;
Position operator+(Position origin, DeltaSpace spaceCovered)
Definition: Foundations.h:307
Types of queue families.
Definition: Animations.h:17