diff --git a/engine/include/nova/render/render_driver.h b/engine/include/nova/render/render_driver.h index 136cddb..9b02343 100644 --- a/engine/include/nova/render/render_driver.h +++ b/engine/include/nova/render/render_driver.h @@ -15,7 +15,6 @@ #include namespace Nova { - class NOVA_API RenderDriver { public: static RenderDriver* create(RenderAPI api, WindowDriver* window_driver = nullptr); @@ -48,5 +47,15 @@ namespace Nova { [[nodiscard]] virtual PipelineID create_pipeline(GraphicsPipelineParams& params) = 0; [[nodiscard]] virtual PipelineID create_pipeline(ComputePipelineParams& params) = 0; virtual void destroy_pipeline(PipelineID pipeline) = 0; + + [[nodiscard]] virtual QueueID create_queue() = 0; + virtual void destroy_queue(QueueID queue) = 0; + + [[nodiscard]] virtual CommandPoolID create_command_pool(QueueID queue) = 0; + virtual void destroy_command_pool(CommandPoolID command_pool) = 0; + + [[nodiscard]] virtual CommandBufferID create_command_buffer(CommandPoolID pool) = 0; + virtual void begin_command_buffer(CommandBufferID command_buffer) = 0; + virtual void end_command_buffer(CommandBufferID command_buffer) = 0; }; } // namespace Nova diff --git a/engine/include/nova/render/render_fwd.h b/engine/include/nova/render/render_fwd.h index 4e63411..9e74732 100644 --- a/engine/include/nova/render/render_fwd.h +++ b/engine/include/nova/render/render_fwd.h @@ -246,13 +246,19 @@ namespace Nova { struct GraphicsPipelineParams; struct ComputePipelineParams; + struct CommandBuffer; + struct CommandPool; struct Pipeline; + struct Queue; struct RenderPass; struct Shader; struct Surface; struct Swapchain; + using CommandBufferID = CommandBuffer*; + using CommandPoolID = CommandPool*; using PipelineID = Pipeline*; + using QueueID = Queue*; using RenderPassID = RenderPass*; using ShaderID = Shader*; using SurfaceID = Surface*; diff --git a/engine/src/drivers/vulkan/render_driver.cpp b/engine/src/drivers/vulkan/render_driver.cpp index 555b47c..2419507 100644 --- a/engine/src/drivers/vulkan/render_driver.cpp +++ b/engine/src/drivers/vulkan/render_driver.cpp @@ -830,6 +830,83 @@ void VulkanRenderDriver::destroy_pipeline(PipelineID p_pipeline) { delete p_pipeline; } +QueueID VulkanRenderDriver::create_queue() { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(m_device); + // TODO: Actually create/get a queue + Queue* queue = new Queue(); + queue->family_index = 0; + return queue; +} + +void VulkanRenderDriver::destroy_queue(QueueID p_queue) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(p_queue); + delete p_queue; +} + +CommandPoolID VulkanRenderDriver::create_command_pool(QueueID p_queue) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(p_queue); + CommandPool* pool = new CommandPool(); + + VkCommandPoolCreateInfo create {}; + create.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + create.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; // TODO: Support other pool type + create.queueFamilyIndex = p_queue->family_index; + + if (vkCreateCommandPool(m_device, &create, get_allocator(VK_OBJECT_TYPE_COMMAND_POOL), &pool->handle) != VK_SUCCESS) { + throw std::runtime_error("Failed to create command pool"); + } + + NOVA_LOG("VkCommandPool created"); + return pool; +} + +void VulkanRenderDriver::destroy_command_pool(CommandPoolID p_command_pool) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(p_command_pool); + if (p_command_pool->handle) { + vkDestroyCommandPool(m_device, p_command_pool->handle, get_allocator(VK_OBJECT_TYPE_COMMAND_POOL)); + } + for (const CommandBufferID buffer : p_command_pool->allocated_buffers) { + delete buffer; + } + delete p_command_pool; +} + +CommandBufferID VulkanRenderDriver::create_command_buffer(CommandPoolID p_pool) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(p_pool); + CommandBuffer* buffer = new CommandBuffer(); + + VkCommandBufferAllocateInfo alloc {}; + alloc.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc.commandPool = p_pool->handle; + alloc.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; // TODO: Support other buffer levels + alloc.commandBufferCount = 1; + + if (vkAllocateCommandBuffers(m_device, &alloc, &buffer->handle) != VK_SUCCESS) { + throw std::runtime_error("Failed to allocate command buffer"); + } + + NOVA_LOG("VkCommandBuffer created"); + p_pool->allocated_buffers.push_back(buffer); + return nullptr; +} + +void VulkanRenderDriver::begin_command_buffer(CommandBufferID p_command_buffer) { + VkCommandBufferBeginInfo info {}; + info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + // TODO: Support flag options + vkBeginCommandBuffer(p_command_buffer->handle, &info); + // TODO: Check result +}; + +void VulkanRenderDriver::end_command_buffer(CommandBufferID p_command_buffer) { + vkEndCommandBuffer(p_command_buffer->handle); +} + VkInstance VulkanRenderDriver::get_instance() const { return m_instance; } diff --git a/engine/src/drivers/vulkan/render_driver.h b/engine/src/drivers/vulkan/render_driver.h index 2aea364..79de49c 100644 --- a/engine/src/drivers/vulkan/render_driver.h +++ b/engine/src/drivers/vulkan/render_driver.h @@ -14,12 +14,25 @@ #include namespace Nova { + struct CommandBuffer { + VkCommandBuffer handle = VK_NULL_HANDLE; + }; + + struct CommandPool { + VkCommandPool handle = VK_NULL_HANDLE; + std::vector allocated_buffers; + }; + struct Pipeline { PipelineType type; VkPipeline handle = VK_NULL_HANDLE; VkPipelineLayout layout = VK_NULL_HANDLE; }; + struct Queue { + u32 family_index; + }; + struct RenderPass { VkRenderPass handle = VK_NULL_HANDLE; }; @@ -81,6 +94,16 @@ namespace Nova { [[nodiscard]] PipelineID create_pipeline(ComputePipelineParams& params) override; void destroy_pipeline(PipelineID pipeline) override; + [[nodiscard]] QueueID create_queue() override; + void destroy_queue(QueueID queue) override; + + [[nodiscard]] CommandPoolID create_command_pool(QueueID queue) override; + void destroy_command_pool(CommandPoolID command_pool) override; + + [[nodiscard]] CommandBufferID create_command_buffer(CommandPoolID pool) override; + void begin_command_buffer(CommandBufferID command_buffer) override; + void end_command_buffer(CommandBufferID command_buffer) override; + [[nodiscard]] VkInstance get_instance() const; [[nodiscard]] VkAllocationCallbacks* get_allocator(VkObjectType type) const;