mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +09:00
[Fix] (MG_Backend/DirectVulkan): fixing inter-frame swapchain sync?
This commit is contained in:
@@ -53,6 +53,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
for (Uint32 i = 0; i < frameCount; ++i) {
|
for (Uint32 i = 0; i < frameCount; ++i) {
|
||||||
DestroySyncObjectsForFrame(device, i);
|
DestroySyncObjectsForFrame(device, i);
|
||||||
}
|
}
|
||||||
|
DestroySwapchainSemaphores(device);
|
||||||
if (device != VK_NULL_HANDLE && commandPool != VK_NULL_HANDLE && !m_frames.empty()) {
|
if (device != VK_NULL_HANDLE && commandPool != VK_NULL_HANDLE && !m_frames.empty()) {
|
||||||
vkFreeCommandBuffers(device, commandPool, frameCount, commandBuffers.data());
|
vkFreeCommandBuffers(device, commandPool, frameCount, commandBuffers.data());
|
||||||
}
|
}
|
||||||
@@ -107,6 +108,36 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
frame.hasCommandBufferRecorded = true;
|
frame.hasCommandBufferRecorded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkResult FrameContext::InitializeSwapchainSemaphores(VkDevice device, Uint32 swapchainImageCount) {
|
||||||
|
DestroySwapchainSemaphores(device);
|
||||||
|
if (swapchainImageCount == 0) {
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_swapchainImageRenderFinishedSemaphores.assign(swapchainImageCount, VK_NULL_HANDLE);
|
||||||
|
VkSemaphoreCreateInfo semaphoreInfo{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
||||||
|
for (Uint32 imageIndex = 0; imageIndex < swapchainImageCount; ++imageIndex) {
|
||||||
|
VkResult result =
|
||||||
|
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &m_swapchainImageRenderFinishedSemaphores[imageIndex]);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
DestroySwapchainSemaphores(device);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameContext::DestroySwapchainSemaphores(VkDevice device) {
|
||||||
|
if (device != VK_NULL_HANDLE) {
|
||||||
|
for (auto semaphore : m_swapchainImageRenderFinishedSemaphores) {
|
||||||
|
if (semaphore != VK_NULL_HANDLE) {
|
||||||
|
vkDestroySemaphore(device, semaphore, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_swapchainImageRenderFinishedSemaphores.clear();
|
||||||
|
}
|
||||||
|
|
||||||
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 || frame.isCommandRecording || oldLayout == presentLayout ||
|
if (frame.hasCommandBufferRecorded || frame.isCommandRecording || oldLayout == presentLayout ||
|
||||||
@@ -137,12 +168,14 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameContext::SubmitInfoPacket FrameContext::GetSubmitInfo(Bool shouldSubmitCommandBuffer) const {
|
FrameContext::SubmitInfoPacket FrameContext::GetSubmitInfo(Bool shouldSubmitCommandBuffer,
|
||||||
|
Uint32 swapchainImageIndex) const {
|
||||||
const auto& frame = GetCurrent();
|
const auto& frame = GetCurrent();
|
||||||
MOBILEGL_ASSERT(!frame.isCommandRecording, "GetSubmitInfo called while command buffer recording is still active");
|
MOBILEGL_ASSERT(!frame.isCommandRecording, "GetSubmitInfo called while command buffer recording is still active");
|
||||||
|
AssertValidSwapchainImageIndex(swapchainImageIndex);
|
||||||
SubmitInfoPacket packet{};
|
SubmitInfoPacket packet{};
|
||||||
packet.waitSemaphore = frame.imageAvailableSemaphore;
|
packet.waitSemaphore = frame.imageAvailableSemaphore;
|
||||||
packet.signalSemaphore = frame.renderFinishedSemaphore;
|
packet.signalSemaphore = m_swapchainImageRenderFinishedSemaphores[swapchainImageIndex];
|
||||||
packet.commandBuffer = frame.commandBuffer;
|
packet.commandBuffer = frame.commandBuffer;
|
||||||
|
|
||||||
packet.submitInfo.waitSemaphoreCount = 1;
|
packet.submitInfo.waitSemaphoreCount = 1;
|
||||||
@@ -156,9 +189,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FrameContext::PresentInfoPacket FrameContext::GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const {
|
FrameContext::PresentInfoPacket FrameContext::GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const {
|
||||||
const auto& frame = GetCurrent();
|
AssertValidSwapchainImageIndex(imageIndex);
|
||||||
PresentInfoPacket packet{};
|
PresentInfoPacket packet{};
|
||||||
packet.waitSemaphore = frame.renderFinishedSemaphore;
|
packet.waitSemaphore = m_swapchainImageRenderFinishedSemaphores[imageIndex];
|
||||||
packet.swapchain = swapchain;
|
packet.swapchain = swapchain;
|
||||||
packet.imageIndex = &imageIndex;
|
packet.imageIndex = &imageIndex;
|
||||||
|
|
||||||
@@ -200,6 +233,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
MOBILEGL_ASSERT(frameIndex < m_frames.size(), "FrameContext index out of range");
|
MOBILEGL_ASSERT(frameIndex < m_frames.size(), "FrameContext index out of range");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameContext::AssertValidSwapchainImageIndex(Uint32 imageIndex) const {
|
||||||
|
MOBILEGL_ASSERT(imageIndex < m_swapchainImageRenderFinishedSemaphores.size(),
|
||||||
|
"FrameContext swapchain image index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
VkResult FrameContext::CreateSyncObjectsForFrame(VkDevice device, Uint32 frameIndex,
|
VkResult FrameContext::CreateSyncObjectsForFrame(VkDevice device, Uint32 frameIndex,
|
||||||
const VkSemaphoreCreateInfo& semaphoreInfo,
|
const VkSemaphoreCreateInfo& semaphoreInfo,
|
||||||
const VkFenceCreateInfo& fenceInfo) {
|
const VkFenceCreateInfo& fenceInfo) {
|
||||||
@@ -213,18 +251,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = vkCreateSemaphore(device, &semaphoreInfo, nullptr, &frame.renderFinishedSemaphore);
|
|
||||||
if (result != VK_SUCCESS) {
|
|
||||||
vkDestroySemaphore(device, frame.imageAvailableSemaphore, nullptr);
|
|
||||||
frame.imageAvailableSemaphore = VK_NULL_HANDLE;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = vkCreateFence(device, &fenceInfo, nullptr, &frame.imageInFlightFence);
|
result = vkCreateFence(device, &fenceInfo, nullptr, &frame.imageInFlightFence);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
vkDestroySemaphore(device, frame.renderFinishedSemaphore, nullptr);
|
|
||||||
vkDestroySemaphore(device, frame.imageAvailableSemaphore, nullptr);
|
vkDestroySemaphore(device, frame.imageAvailableSemaphore, nullptr);
|
||||||
frame.renderFinishedSemaphore = VK_NULL_HANDLE;
|
|
||||||
frame.imageAvailableSemaphore = VK_NULL_HANDLE;
|
frame.imageAvailableSemaphore = VK_NULL_HANDLE;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -242,11 +271,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
}
|
}
|
||||||
frame.imageInFlightFence = VK_NULL_HANDLE;
|
frame.imageInFlightFence = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if (device != VK_NULL_HANDLE && frame.renderFinishedSemaphore != VK_NULL_HANDLE) {
|
|
||||||
vkDestroySemaphore(device, frame.renderFinishedSemaphore, nullptr);
|
|
||||||
}
|
|
||||||
frame.renderFinishedSemaphore = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
if (device != VK_NULL_HANDLE && frame.imageAvailableSemaphore != VK_NULL_HANDLE) {
|
if (device != VK_NULL_HANDLE && frame.imageAvailableSemaphore != VK_NULL_HANDLE) {
|
||||||
vkDestroySemaphore(device, frame.imageAvailableSemaphore, nullptr);
|
vkDestroySemaphore(device, frame.imageAvailableSemaphore, nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
struct FrameData {
|
struct FrameData {
|
||||||
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
||||||
VkSemaphore imageAvailableSemaphore = VK_NULL_HANDLE;
|
VkSemaphore imageAvailableSemaphore = VK_NULL_HANDLE;
|
||||||
VkSemaphore renderFinishedSemaphore = VK_NULL_HANDLE;
|
|
||||||
VkFence imageInFlightFence = VK_NULL_HANDLE;
|
VkFence imageInFlightFence = VK_NULL_HANDLE;
|
||||||
Bool isCommandRecording = false;
|
Bool isCommandRecording = false;
|
||||||
Bool hasCommandBufferRecorded = false;
|
Bool hasCommandBufferRecorded = false;
|
||||||
@@ -49,9 +48,11 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
VkCommandBuffer& BeginCommandRecording(VkCommandBufferUsageFlags flags = 0,
|
VkCommandBuffer& BeginCommandRecording(VkCommandBufferUsageFlags flags = 0,
|
||||||
const VkCommandBufferInheritanceInfo* pInheritanceInfo = nullptr);
|
const VkCommandBufferInheritanceInfo* pInheritanceInfo = nullptr);
|
||||||
void EndCommandRecording();
|
void EndCommandRecording();
|
||||||
|
VkResult InitializeSwapchainSemaphores(VkDevice device, Uint32 swapchainImageCount);
|
||||||
|
void DestroySwapchainSemaphores(VkDevice device);
|
||||||
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, Uint32 swapchainImageIndex) const;
|
||||||
PresentInfoPacket GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const;
|
PresentInfoPacket GetPresentInfo(VkSwapchainKHR swapchain, const Uint32& imageIndex) const;
|
||||||
VkResult WaitAndAcquireNextImage(VkDevice device, VkSwapchainKHR swapchain, Uint32& outImageIndex,
|
VkResult WaitAndAcquireNextImage(VkDevice device, VkSwapchainKHR swapchain, Uint32& outImageIndex,
|
||||||
Uint64 timeout = UINT64_MAX, VkFence acquireFence = VK_NULL_HANDLE);
|
Uint64 timeout = UINT64_MAX, VkFence acquireFence = VK_NULL_HANDLE);
|
||||||
@@ -61,6 +62,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void AssertValidFrameIndex(Uint32 frameIndex) const;
|
void AssertValidFrameIndex(Uint32 frameIndex) const;
|
||||||
|
void AssertValidSwapchainImageIndex(Uint32 imageIndex) const;
|
||||||
|
|
||||||
VkResult CreateSyncObjectsForFrame(VkDevice device, Uint32 frameIndex,
|
VkResult CreateSyncObjectsForFrame(VkDevice device, Uint32 frameIndex,
|
||||||
const VkSemaphoreCreateInfo& semaphoreInfo,
|
const VkSemaphoreCreateInfo& semaphoreInfo,
|
||||||
@@ -68,6 +70,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void DestroySyncObjectsForFrame(VkDevice device, Uint32 frameIndex);
|
void DestroySyncObjectsForFrame(VkDevice device, Uint32 frameIndex);
|
||||||
|
|
||||||
Vector<FrameData> m_frames;
|
Vector<FrameData> m_frames;
|
||||||
|
Vector<VkSemaphore> m_swapchainImageRenderFinishedSemaphores;
|
||||||
Uint32 currentFrameIndex = 0;
|
Uint32 currentFrameIndex = 0;
|
||||||
};
|
};
|
||||||
} // namespace MobileGL::MG_Backend::DirectVulkan
|
} // namespace MobileGL::MG_Backend::DirectVulkan
|
||||||
|
|||||||
@@ -103,6 +103,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
void VulkanRenderer::CreateFrameContexts() {
|
void VulkanRenderer::CreateFrameContexts() {
|
||||||
VK_VERIFY(m_frameContext.Initialize(m_device, m_commandPool, m_config.MaxFramesInFlight),
|
VK_VERIFY(m_frameContext.Initialize(m_device, m_commandPool, m_config.MaxFramesInFlight),
|
||||||
"CreateFrameContexts");
|
"CreateFrameContexts");
|
||||||
|
VK_VERIFY(m_frameContext.InitializeSwapchainSemaphores(
|
||||||
|
m_device, static_cast<Uint32>(m_swapchainObject.GetImageCount())),
|
||||||
|
"CreateFrameContexts, InitializeSwapchainSemaphores");
|
||||||
MGLOG_I("CreateFrameContexts completed");
|
MGLOG_I("CreateFrameContexts completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +691,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
const Bool shouldSubmitCommandBuffer = frame.hasCommandBufferRecorded || needsLayoutTransitionForPresent;
|
const Bool shouldSubmitCommandBuffer = frame.hasCommandBufferRecorded || needsLayoutTransitionForPresent;
|
||||||
|
|
||||||
// 1) Submit current frame work.
|
// 1) Submit current frame work.
|
||||||
auto submitPacket = m_frameContext.GetSubmitInfo(shouldSubmitCommandBuffer);
|
auto submitPacket = m_frameContext.GetSubmitInfo(shouldSubmitCommandBuffer, m_imageIndexAcquired);
|
||||||
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitPacket.submitInfo, frame.imageInFlightFence));
|
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitPacket.submitInfo, frame.imageInFlightFence));
|
||||||
frame.isCommandRecording = false;
|
frame.isCommandRecording = false;
|
||||||
frame.hasCommandBufferRecorded = false;
|
frame.hasCommandBufferRecorded = false;
|
||||||
@@ -1399,6 +1402,9 @@ namespace MobileGL::MG_Backend::DirectVulkan {
|
|||||||
ShutdownSwapchain();
|
ShutdownSwapchain();
|
||||||
|
|
||||||
CreateSwapchain();
|
CreateSwapchain();
|
||||||
|
VK_VERIFY(m_frameContext.InitializeSwapchainSemaphores(
|
||||||
|
m_device, static_cast<Uint32>(m_swapchainObject.GetImageCount())),
|
||||||
|
"RecreateSwapchain, InitializeSwapchainSemaphores");
|
||||||
CreateDepthStencilResources();
|
CreateDepthStencilResources();
|
||||||
CreateDefaultRenderPass();
|
CreateDefaultRenderPass();
|
||||||
CreateDefaultFramebuffers();
|
CreateDefaultFramebuffers();
|
||||||
|
|||||||
Reference in New Issue
Block a user