mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Feat] (MG_Backend/DirectVulkan): FrameContext: command buffer lifecycle
This commit is contained in:
@@ -70,24 +70,51 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
return m_frames[currentFrameIndex];
|
||||
}
|
||||
|
||||
Bool FrameContext::IsCommandRecording() const {
|
||||
return GetCurrent().isCommandRecording;
|
||||
}
|
||||
|
||||
void FrameContext::AdvanceToNext() {
|
||||
MOBILEGL_ASSERT(!m_frames.empty(), "FrameContext is not initialized");
|
||||
currentFrameIndex = (currentFrameIndex + 1) % static_cast<Uint32>(m_frames.size());
|
||||
GetCurrent().isCommandRecording = false;
|
||||
GetCurrent().hasCommandBufferRecorded = false;
|
||||
}
|
||||
|
||||
VkCommandBuffer& FrameContext::BeginCommandRecording(VkCommandBufferUsageFlags flags,
|
||||
const VkCommandBufferInheritanceInfo* pInheritanceInfo) {
|
||||
auto& frame = GetCurrent();
|
||||
MOBILEGL_ASSERT(!frame.isCommandRecording, "BeginCommandRecording called while command buffer is already recording");
|
||||
|
||||
frame.hasCommandBufferRecorded = false;
|
||||
VK_VERIFY(vkResetCommandBuffer(frame.commandBuffer, 0), "BeginCommandRecording, vkResetCommandBuffer");
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
beginInfo.flags = flags;
|
||||
beginInfo.pInheritanceInfo = pInheritanceInfo;
|
||||
VK_VERIFY(vkBeginCommandBuffer(frame.commandBuffer, &beginInfo), "BeginCommandRecording, vkBeginCommandBuffer");
|
||||
|
||||
frame.isCommandRecording = true;
|
||||
return frame.commandBuffer;
|
||||
}
|
||||
|
||||
void FrameContext::EndCommandRecording() {
|
||||
auto& frame = GetCurrent();
|
||||
MOBILEGL_ASSERT(frame.isCommandRecording, "EndCommandRecording called without active command buffer recording");
|
||||
VK_VERIFY(vkEndCommandBuffer(frame.commandBuffer), "EndCommandRecording, vkEndCommandBuffer");
|
||||
frame.isCommandRecording = false;
|
||||
frame.hasCommandBufferRecorded = true;
|
||||
}
|
||||
|
||||
Bool FrameContext::TransitionToPresent(VkImage image, VkImageLayout oldLayout, VkImageLayout presentLayout) {
|
||||
auto& frame = GetCurrent();
|
||||
if (frame.hasCommandBufferRecorded || oldLayout == presentLayout ||
|
||||
if (frame.hasCommandBufferRecorded || frame.isCommandRecording || oldLayout == presentLayout ||
|
||||
oldLayout == VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VK_VERIFY(vkResetCommandBuffer(frame.commandBuffer, 0), "TransitionToPresent, vkResetCommandBuffer");
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo{};
|
||||
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
VK_VERIFY(vkBeginCommandBuffer(frame.commandBuffer, &beginInfo), "TransitionToPresent, vkBeginCommandBuffer");
|
||||
auto& commandBuffer = BeginCommandRecording();
|
||||
|
||||
VkImageMemoryBarrier presentBarrier{};
|
||||
presentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
@@ -103,15 +130,16 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
presentBarrier.subresourceRange.levelCount = 1;
|
||||
presentBarrier.subresourceRange.baseArrayLayer = 0;
|
||||
presentBarrier.subresourceRange.layerCount = 1;
|
||||
vkCmdPipelineBarrier(frame.commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &presentBarrier);
|
||||
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0,
|
||||
nullptr, 0, nullptr, 1, &presentBarrier);
|
||||
|
||||
VK_VERIFY(vkEndCommandBuffer(frame.commandBuffer), "TransitionToPresent, vkEndCommandBuffer");
|
||||
EndCommandRecording();
|
||||
return true;
|
||||
}
|
||||
|
||||
FrameContext::SubmitInfoPacket FrameContext::GetSubmitInfo(Bool shouldSubmitCommandBuffer) const {
|
||||
const auto& frame = GetCurrent();
|
||||
MOBILEGL_ASSERT(!frame.isCommandRecording, "GetSubmitInfo called while command buffer recording is still active");
|
||||
SubmitInfoPacket packet{};
|
||||
packet.waitSemaphore = frame.imageAvailableSemaphore;
|
||||
packet.signalSemaphore = frame.renderFinishedSemaphore;
|
||||
@@ -202,6 +230,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
frame.hasCommandBufferRecorded = false;
|
||||
frame.isCommandRecording = false;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -222,6 +251,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
vkDestroySemaphore(device, frame.imageAvailableSemaphore, nullptr);
|
||||
}
|
||||
frame.imageAvailableSemaphore = VK_NULL_HANDLE;
|
||||
frame.isCommandRecording = false;
|
||||
frame.hasCommandBufferRecorded = false;
|
||||
}
|
||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
VkSemaphore imageAvailableSemaphore = VK_NULL_HANDLE;
|
||||
VkSemaphore renderFinishedSemaphore = VK_NULL_HANDLE;
|
||||
VkFence imageInFlightFence = VK_NULL_HANDLE;
|
||||
Bool isCommandRecording = false;
|
||||
Bool hasCommandBufferRecorded = false;
|
||||
};
|
||||
|
||||
@@ -43,7 +44,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// Lifecycle functions
|
||||
FrameData& GetCurrent();
|
||||
const FrameData& GetCurrent() const;
|
||||
Bool IsCommandRecording() const;
|
||||
void AdvanceToNext();
|
||||
VkCommandBuffer& BeginCommandRecording(VkCommandBufferUsageFlags flags = 0,
|
||||
const VkCommandBufferInheritanceInfo* pInheritanceInfo = nullptr);
|
||||
void EndCommandRecording();
|
||||
Bool TransitionToPresent(VkImage image, VkImageLayout oldLayout,
|
||||
VkImageLayout presentLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
SubmitInfoPacket GetSubmitInfo(Bool shouldSubmitCommandBuffer) const;
|
||||
|
||||
@@ -248,16 +248,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
}
|
||||
|
||||
void VulkanRenderer::Render() {
|
||||
auto& frame = m_frameContext.GetCurrent();
|
||||
VkCommandBuffer& commandBuffer = frame.commandBuffer;
|
||||
VK_VERIFY(vkResetCommandBuffer(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(commandBuffer, &beginInfo));
|
||||
VkCommandBuffer& commandBuffer = m_frameContext.BeginCommandRecording();
|
||||
|
||||
// Begin render pass
|
||||
VkRenderPassBeginInfo renderPassInfo{};
|
||||
@@ -295,8 +286,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
vkCmdEndRenderPass(commandBuffer);
|
||||
|
||||
// End command buffer
|
||||
VK_VERIFY(vkEndCommandBuffer(commandBuffer));
|
||||
frame.hasCommandBufferRecorded = true;
|
||||
m_frameContext.EndCommandRecording();
|
||||
}
|
||||
|
||||
void VulkanRenderer::Present() {
|
||||
@@ -311,6 +301,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
// 1) Submit current frame work.
|
||||
auto submitPacket = m_frameContext.GetSubmitInfo(shouldSubmitCommandBuffer);
|
||||
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitPacket.submitInfo, frame.imageInFlightFence));
|
||||
frame.isCommandRecording = false;
|
||||
frame.hasCommandBufferRecorded = false;
|
||||
m_swapchainObject.SetImageLayout(m_imageIndexAcquired, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
@@ -848,6 +839,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
||||
CreateDefaultRenderPass();
|
||||
CreateDefaultFramebuffers();
|
||||
if (m_frameContext.GetFrameCount() > 0) {
|
||||
m_frameContext.GetCurrent().isCommandRecording = false;
|
||||
m_frameContext.GetCurrent().hasCommandBufferRecorded = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user