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