mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_Test/Backend/DirectVulkan): use per-frame resources
This commit is contained in:
@@ -222,9 +222,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkSemaphoreCreateInfo semaphoreInfo{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
VkSemaphoreCreateInfo semaphoreInfo{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
||||||
VkFenceCreateInfo fenceInfo{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
VkFenceCreateInfo fenceInfo{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
|
||||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
VK_VERIFY(vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphore));
|
|
||||||
VK_VERIFY(vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphore));
|
m_imageAvailableSemaphores.resize(m_swapchainImages.size(), VK_NULL_HANDLE);
|
||||||
VK_VERIFY(vkCreateFence(m_device, &fenceInfo, nullptr, &m_imageInFlightFence));
|
m_renderFinishedSemaphores.resize(m_swapchainImages.size(), VK_NULL_HANDLE);
|
||||||
|
m_imageInFlightFences.resize(m_swapchainImages.size(), VK_NULL_HANDLE);
|
||||||
|
|
||||||
|
for (SizeT i = 0; i < m_swapchainImages.size(); i++) {
|
||||||
|
VK_VERIFY(vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]));
|
||||||
|
VK_VERIFY(vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]));
|
||||||
|
VK_VERIFY(vkCreateFence(m_device, &fenceInfo, nullptr, &m_imageInFlightFences[i]));
|
||||||
|
}
|
||||||
|
|
||||||
MGLOG_I("CreateSyncObjects completed");
|
MGLOG_I("CreateSyncObjects completed");
|
||||||
}
|
}
|
||||||
@@ -237,7 +244,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
CreateSwapchain();
|
CreateSwapchain();
|
||||||
CreateSwapchainImageViews();
|
CreateSwapchainImageViews();
|
||||||
CreateCommandPool();
|
CreateCommandPool();
|
||||||
CreateCommandBuffer();
|
CreateCommandBuffers();
|
||||||
CreateDefaultRenderPass();
|
CreateDefaultRenderPass();
|
||||||
PrepareDemoPipeline();
|
PrepareDemoPipeline();
|
||||||
CreateSyncObjects();
|
CreateSyncObjects();
|
||||||
@@ -247,18 +254,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void VulkanRenderer::Shutdown() {
|
void VulkanRenderer::Shutdown() {
|
||||||
VK_VERIFY(vkDeviceWaitIdle(m_device));
|
VK_VERIFY(vkDeviceWaitIdle(m_device));
|
||||||
|
|
||||||
if (m_imageInFlightFence != VK_NULL_HANDLE) {
|
for (auto fence: m_imageInFlightFences) {
|
||||||
vkDestroyFence(m_device, m_imageInFlightFence, nullptr);
|
vkDestroyFence(m_device, fence, nullptr);
|
||||||
m_imageInFlightFence = VK_NULL_HANDLE;
|
|
||||||
}
|
}
|
||||||
|
m_imageInFlightFences.clear();
|
||||||
|
|
||||||
if (m_renderFinishedSemaphore != VK_NULL_HANDLE) {
|
for (auto s: m_renderFinishedSemaphores) {
|
||||||
vkDestroySemaphore(m_device, m_renderFinishedSemaphore, nullptr);
|
vkDestroySemaphore(m_device, s, nullptr);
|
||||||
}
|
}
|
||||||
|
m_renderFinishedSemaphores.clear();
|
||||||
|
|
||||||
if (m_imageAvailableSemaphore != VK_NULL_HANDLE) {
|
for (auto s: m_imageAvailableSemaphores) {
|
||||||
vkDestroySemaphore(m_device, m_imageAvailableSemaphore, nullptr);
|
vkDestroySemaphore(m_device, s, nullptr);
|
||||||
}
|
}
|
||||||
|
m_imageAvailableSemaphores.clear();
|
||||||
|
|
||||||
if (m_pipeline != VK_NULL_HANDLE) {
|
if (m_pipeline != VK_NULL_HANDLE) {
|
||||||
vkDestroyPipeline(m_device, m_pipeline, nullptr);
|
vkDestroyPipeline(m_device, m_pipeline, nullptr);
|
||||||
@@ -316,14 +325,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::Render() {
|
void VulkanRenderer::Render() {
|
||||||
VK_VERIFY(vkResetCommandBuffer(m_commandBuffer, 0));
|
VK_VERIFY(vkResetCommandBuffer(m_commandBuffers[m_currentFrameIndex], 0));
|
||||||
|
|
||||||
// Begin command buffer
|
// Begin command buffer
|
||||||
VkCommandBufferBeginInfo beginInfo{};
|
VkCommandBufferBeginInfo beginInfo{};
|
||||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
beginInfo.flags = 0;
|
beginInfo.flags = 0;
|
||||||
beginInfo.pInheritanceInfo = nullptr;
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
VK_VERIFY(vkBeginCommandBuffer(m_commandBuffer, &beginInfo));
|
VK_VERIFY(vkBeginCommandBuffer(m_commandBuffers[m_currentFrameIndex], &beginInfo));
|
||||||
|
|
||||||
// Begin render pass
|
// Begin render pass
|
||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPassBeginInfo renderPassInfo{};
|
||||||
@@ -335,10 +344,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}};
|
||||||
renderPassInfo.clearValueCount = 1;
|
renderPassInfo.clearValueCount = 1;
|
||||||
renderPassInfo.pClearValues = &clearColor;
|
renderPassInfo.pClearValues = &clearColor;
|
||||||
vkCmdBeginRenderPass(m_commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(m_commandBuffers[m_currentFrameIndex], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
// Render commands
|
// Render commands
|
||||||
vkCmdBindPipeline(m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
|
vkCmdBindPipeline(m_commandBuffers[m_currentFrameIndex], VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
|
||||||
|
|
||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
viewport.x = 0.0f;
|
viewport.x = 0.0f;
|
||||||
@@ -347,44 +356,44 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
viewport.height = static_cast<float>(m_swapChainExtent.height);
|
viewport.height = static_cast<float>(m_swapChainExtent.height);
|
||||||
viewport.minDepth = 0.0f;
|
viewport.minDepth = 0.0f;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
vkCmdSetViewport(m_commandBuffer, 0, 1, &viewport);
|
vkCmdSetViewport(m_commandBuffers[m_currentFrameIndex], 0, 1, &viewport);
|
||||||
|
|
||||||
VkRect2D scissor{};
|
VkRect2D scissor{};
|
||||||
scissor.offset = {0, 0};
|
scissor.offset = {0, 0};
|
||||||
scissor.extent = m_swapChainExtent;
|
scissor.extent = m_swapChainExtent;
|
||||||
vkCmdSetScissor(m_commandBuffer, 0, 1, &scissor);
|
vkCmdSetScissor(m_commandBuffers[m_currentFrameIndex], 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdDraw(m_commandBuffer, 3, 1, 0, 0);
|
vkCmdDraw(m_commandBuffers[m_currentFrameIndex], 3, 1, 0, 0);
|
||||||
|
|
||||||
// End render pass
|
// End render pass
|
||||||
vkCmdEndRenderPass(m_commandBuffer);
|
vkCmdEndRenderPass(m_commandBuffers[m_currentFrameIndex]);
|
||||||
|
|
||||||
// End command buffer
|
// End command buffer
|
||||||
VK_VERIFY(vkEndCommandBuffer(m_commandBuffer));
|
VK_VERIFY(vkEndCommandBuffer(m_commandBuffers[m_currentFrameIndex]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::Present() {
|
void VulkanRenderer::Present() {
|
||||||
VK_VERIFY(vkWaitForFences(m_device, 1, &m_imageInFlightFence, VK_TRUE, UINT64_MAX));
|
VK_VERIFY(vkWaitForFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex], VK_TRUE, UINT64_MAX));
|
||||||
VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFence));
|
VK_VERIFY(vkResetFences(m_device, 1, &m_imageInFlightFences[m_currentFrameIndex]));
|
||||||
VK_VERIFY(vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_imageAvailableSemaphore, VK_NULL_HANDLE, &m_imageIndexAcquired));
|
VK_VERIFY(vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_imageAvailableSemaphores[m_currentFrameIndex], VK_NULL_HANDLE, &m_imageIndexAcquired));
|
||||||
|
|
||||||
// Do demo drawing
|
// Do demo drawing
|
||||||
VK_VERIFY(vkResetCommandBuffer(m_commandBuffer, 0));
|
VK_VERIFY(vkResetCommandBuffer(m_commandBuffers[m_currentFrameIndex], 0));
|
||||||
Render();
|
Render();
|
||||||
VkSubmitInfo submitInfo{};
|
VkSubmitInfo submitInfo{};
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
|
||||||
VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphore};
|
VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrameIndex]};
|
||||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
|
||||||
submitInfo.waitSemaphoreCount = 1;
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
submitInfo.pWaitSemaphores = waitSemaphores;
|
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||||
submitInfo.pWaitDstStageMask = waitStages;
|
submitInfo.pWaitDstStageMask = waitStages;
|
||||||
submitInfo.commandBufferCount = 1;
|
submitInfo.commandBufferCount = 1;
|
||||||
submitInfo.pCommandBuffers = &m_commandBuffer;
|
submitInfo.pCommandBuffers = &m_commandBuffers[m_currentFrameIndex];
|
||||||
VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphore};
|
VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[m_currentFrameIndex]};
|
||||||
submitInfo.signalSemaphoreCount = 1;
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_imageInFlightFence));
|
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, m_imageInFlightFences[m_currentFrameIndex]));
|
||||||
|
|
||||||
VkPresentInfoKHR presentInfo{};
|
VkPresentInfoKHR presentInfo{};
|
||||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
@@ -398,6 +407,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
presentInfo.pImageIndices = &m_imageIndexAcquired;
|
presentInfo.pImageIndices = &m_imageIndexAcquired;
|
||||||
presentInfo.pResults = nullptr;
|
presentInfo.pResults = nullptr;
|
||||||
VK_VERIFY(vkQueuePresentKHR(m_presentQueue, &presentInfo));
|
VK_VERIFY(vkQueuePresentKHR(m_presentQueue, &presentInfo));
|
||||||
|
m_currentFrameIndex = (m_currentFrameIndex + 1) % m_swapchainImages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateInstance() {
|
void VulkanRenderer::CreateInstance() {
|
||||||
@@ -1102,7 +1112,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
Uint32 gotImageCount = 0;
|
Uint32 gotImageCount = 0;
|
||||||
VK_VERIFY(vkGetSwapchainImagesKHR(m_device, m_swapchain, &gotImageCount, nullptr));
|
VK_VERIFY(vkGetSwapchainImagesKHR(m_device, m_swapchain, &gotImageCount, nullptr));
|
||||||
m_swapchainImages.resize(gotImageCount);
|
m_swapchainImages.resize(gotImageCount, VK_NULL_HANDLE);
|
||||||
VK_VERIFY(vkGetSwapchainImagesKHR(m_device, m_swapchain, &gotImageCount, m_swapchainImages.data()));
|
VK_VERIFY(vkGetSwapchainImagesKHR(m_device, m_swapchain, &gotImageCount, m_swapchainImages.data()));
|
||||||
m_swapChainExtent = swapchainCaps.currentExtent;
|
m_swapChainExtent = swapchainCaps.currentExtent;
|
||||||
|
|
||||||
@@ -1110,7 +1120,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateSwapchainImageViews() {
|
void VulkanRenderer::CreateSwapchainImageViews() {
|
||||||
m_swapchainImageViews.resize(m_swapchainImages.size());
|
m_swapchainImageViews.resize(m_swapchainImages.size(), VK_NULL_HANDLE);
|
||||||
for (size_t i = 0; i < m_swapchainImageViews.size(); i++) {
|
for (size_t i = 0; i < m_swapchainImageViews.size(); i++) {
|
||||||
VkImageViewCreateInfo createInfo{};
|
VkImageViewCreateInfo createInfo{};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
@@ -1139,13 +1149,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MGLOG_I("Command pool created");
|
MGLOG_I("Command pool created");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::CreateCommandBuffer() {
|
void VulkanRenderer::CreateCommandBuffers() {
|
||||||
|
m_commandBuffers.resize(m_swapchainImages.size(), VK_NULL_HANDLE);
|
||||||
VkCommandBufferAllocateInfo allocInfo{};
|
VkCommandBufferAllocateInfo allocInfo{};
|
||||||
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
allocInfo.commandPool = m_commandPool;
|
allocInfo.commandPool = m_commandPool;
|
||||||
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
allocInfo.commandBufferCount = 1;
|
allocInfo.commandBufferCount = m_swapchainImages.size();
|
||||||
VK_VERIFY(vkAllocateCommandBuffers(m_device, &allocInfo, &m_commandBuffer));
|
VK_VERIFY(vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data()));
|
||||||
MGLOG_I("Command buffer created");
|
MGLOG_I("Command buffer created");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkQueue m_presentQueue = VK_NULL_HANDLE;
|
VkQueue m_presentQueue = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
VkCommandPool m_commandPool = VK_NULL_HANDLE;
|
||||||
VkCommandBuffer m_commandBuffer = VK_NULL_HANDLE;
|
Vector<VkCommandBuffer> m_commandBuffers;
|
||||||
|
|
||||||
VkRenderPass m_renderPass = VK_NULL_HANDLE;
|
VkRenderPass m_renderPass = VK_NULL_HANDLE;
|
||||||
Vector<VkFramebuffer> m_framebuffers;
|
Vector<VkFramebuffer> m_framebuffers;
|
||||||
@@ -104,9 +104,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
Uint m_imageIndexAcquired = 0;
|
Uint m_imageIndexAcquired = 0;
|
||||||
Uint m_currentFrameIndex = 0;
|
Uint m_currentFrameIndex = 0;
|
||||||
VkSemaphore m_imageAvailableSemaphore;
|
Vector<VkSemaphore> m_imageAvailableSemaphores;
|
||||||
VkSemaphore m_renderFinishedSemaphore;
|
Vector<VkSemaphore> m_renderFinishedSemaphores;
|
||||||
VkFence m_imageInFlightFence;
|
Vector<VkFence> m_imageInFlightFences;
|
||||||
|
|
||||||
void CreateInstance();
|
void CreateInstance();
|
||||||
VkResult SetupDebugMessenger();
|
VkResult SetupDebugMessenger();
|
||||||
@@ -118,7 +118,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void CreateSwapchain();
|
void CreateSwapchain();
|
||||||
void CreateSwapchainImageViews();
|
void CreateSwapchainImageViews();
|
||||||
void CreateCommandPool();
|
void CreateCommandPool();
|
||||||
void CreateCommandBuffer();
|
void CreateCommandBuffers();
|
||||||
void CreateDefaultRenderPass();
|
void CreateDefaultRenderPass();
|
||||||
void PrepareDemoPipeline();
|
void PrepareDemoPipeline();
|
||||||
void CreateSyncObjects();
|
void CreateSyncObjects();
|
||||||
|
|||||||
Reference in New Issue
Block a user