From 7bd4d74b2c8f0c74c6e4c2324b1f8625a4f52eaf Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Sat, 14 Feb 2026 17:47:14 +0800 Subject: [PATCH] [Feat] (MG_Backend/DirectVulkan): present, dynamic states, queue submit, and...triangle! --- .../DirectVulkan/Renderer/VulkanRenderer.cpp | 56 ++++++++++++++++--- .../DirectVulkan/Renderer/VulkanRenderer.h | 8 +-- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 5b64b9b5..a9c264e6 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -139,6 +139,12 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_VERIFY(vkCreatePipelineLayout(m_device, &plci, nullptr, &m_pipelineLayout), "vkCreatePipelineLayout"); // Create the rest of pipeline component + + VkPipelineDynamicStateCreateInfo dynamicState{}; + dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamicState.dynamicStateCount = static_cast(std::size(s_dynamicStates)); + dynamicState.pDynamicStates = s_dynamicStates; + VkPipelineVertexInputStateCreateInfo vertexInput{VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO}; vertexInput.vertexBindingDescriptionCount = 0; vertexInput.vertexAttributeDescriptionCount = 0; @@ -187,6 +193,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { gpi.pRasterizationState = &raster; gpi.pMultisampleState = &ms; gpi.pColorBlendState = &blend; + gpi.pDynamicState = &dynamicState; gpi.layout = m_pipelineLayout; gpi.renderPass = m_renderPass; gpi.subpass = 0; @@ -238,6 +245,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { } void VulkanRenderer::Shutdown() { + VK_VERIFY(vkDeviceWaitIdle(m_device)); + if (m_imageInFlightFence != VK_NULL_HANDLE) { vkDestroyFence(m_device, m_imageInFlightFence, nullptr); m_imageInFlightFence = VK_NULL_HANDLE; @@ -306,16 +315,17 @@ namespace MobileGL::MG_Backend::DirectVulkan { MGLOG_I("VulkanRenderer shut down completed"); } - void VulkanRenderer::BeginCommandBuffer() { + void VulkanRenderer::Render() { VK_VERIFY(vkResetCommandBuffer(m_commandBuffer, 0)); + + // Begin command buffer VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.flags = 0; beginInfo.pInheritanceInfo = nullptr; VK_VERIFY(vkBeginCommandBuffer(m_commandBuffer, &beginInfo)); - } - void VulkanRenderer::BeginRenderPass() { + // Begin render pass VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; renderPassInfo.renderPass = m_renderPass; @@ -326,9 +336,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { renderPassInfo.clearValueCount = 1; renderPassInfo.pClearValues = &clearColor; vkCmdBeginRenderPass(m_commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - } - void VulkanRenderer::Render() { + // Render commands vkCmdBindPipeline(m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline); VkViewport viewport{}; @@ -346,13 +355,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { vkCmdSetScissor(m_commandBuffer, 0, 1, &scissor); vkCmdDraw(m_commandBuffer, 3, 1, 0, 0); - } - void VulkanRenderer::EndRenderPass() { + // End render pass vkCmdEndRenderPass(m_commandBuffer); - } - void VulkanRenderer::EndCommandBuffer() { + // End command buffer VK_VERIFY(vkEndCommandBuffer(m_commandBuffer)); } @@ -360,6 +367,37 @@ namespace MobileGL::MG_Backend::DirectVulkan { VK_VERIFY(vkWaitForFences(m_device, 1, &m_imageInFlightFence, VK_TRUE, UINT64_MAX)); VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFence)); VK_VERIFY(vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_imageAvailableSemaphore, VK_NULL_HANDLE, &m_imageIndexAcquired)); + + // Do demo drawing + VK_VERIFY(vkResetCommandBuffer(m_commandBuffer, 0)); + Render(); + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphore}; + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT}; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &m_commandBuffer; + VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphore}; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_imageInFlightFence)); + + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores; + + VkSwapchainKHR swapChains[] = {m_swapchain}; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &m_imageIndexAcquired; + presentInfo.pResults = nullptr; + VK_VERIFY(vkQueuePresentKHR(m_presentQueue, &presentInfo)); } void VulkanRenderer::CreateInstance() { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index fd932a35..87920c91 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -37,11 +37,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { void Initialize(); void Shutdown(); - void BeginCommandBuffer(); - void BeginRenderPass(); void Render(); - void EndRenderPass(); - void EndCommandBuffer(); void Present(); private: @@ -138,6 +134,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { static Bool GetMoreCapablePhysicalDevice(VkPhysicalDevice newVkDevice, VkSurfaceKHR surface, const PhysicalDevice& compareWithDevice, PhysicalDevice& outBetterDevice); static VkSurfaceFormatKHR ChooseSwapchainSurfaceFormat(const Vector& availableFormats); static VkPresentModeKHR ChooseSwapchainPresentMode(const Vector& availablePresentModes); + static constexpr VkDynamicState s_dynamicStates[] = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; static constexpr VkPresentModeKHR s_desiredPresentModes[] { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR,