[Fix|Refactor] (MG_Backend/DirectVulkan): Fix incorrect vkAcquireNextImageKHR call. MOBILEGL_ASSERT_VK -> VK_VERIFY.

This commit is contained in:
BZLZHH
2026-02-08 16:28:12 +08:00
parent 3b2c2028b9
commit e39af3b940
9 changed files with 66 additions and 61 deletions
@@ -18,20 +18,19 @@ namespace MobileGL::MG_Backend::DirectVulkan {
abci.commandPool = pool; abci.commandPool = pool;
abci.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; abci.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
abci.commandBufferCount = 1; abci.commandBufferCount = 1;
MOBILEGL_ASSERT_VK(vkAllocateCommandBuffers(ctx.GetDevice(), &abci, &CommandBuffer), VK_VERIFY(vkAllocateCommandBuffers(ctx.GetDevice(), &abci, &CommandBuffer), "vkAllocateCommandBuffers");
"vkAllocateCommandBuffers");
// semaphores // semaphores
VkSemaphoreCreateInfo sci{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO}; VkSemaphoreCreateInfo sci{VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
MOBILEGL_ASSERT_VK(vkCreateSemaphore(ctx.GetDevice(), &sci, nullptr, &ImageAvailable), VK_VERIFY(vkCreateSemaphore(ctx.GetDevice(), &sci, nullptr, &ImageAvailable),
"vkCreateSemaphore ImageAvailable"); "vkCreateSemaphore ImageAvailable");
MOBILEGL_ASSERT_VK(vkCreateSemaphore(ctx.GetDevice(), &sci, nullptr, &RenderFinished), VK_VERIFY(vkCreateSemaphore(ctx.GetDevice(), &sci, nullptr, &RenderFinished),
"vkCreateSemaphore RenderFinished"); "vkCreateSemaphore RenderFinished");
// fence (start signaled) // fence (start signaled)
VkFenceCreateInfo fci{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO}; VkFenceCreateInfo fci{VK_STRUCTURE_TYPE_FENCE_CREATE_INFO};
fci.flags = VK_FENCE_CREATE_SIGNALED_BIT; fci.flags = VK_FENCE_CREATE_SIGNALED_BIT;
MOBILEGL_ASSERT_VK(vkCreateFence(ctx.GetDevice(), &fci, nullptr, &InFlightFence), "vkCreateFence"); VK_VERIFY(vkCreateFence(ctx.GetDevice(), &fci, nullptr, &InFlightFence), "vkCreateFence");
} }
void FrameContext::Cleanup(VulkanContext& ctx) { void FrameContext::Cleanup(VulkanContext& ctx) {
@@ -23,5 +23,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkSemaphore ImageAvailable = VK_NULL_HANDLE; VkSemaphore ImageAvailable = VK_NULL_HANDLE;
VkSemaphore RenderFinished = VK_NULL_HANDLE; VkSemaphore RenderFinished = VK_NULL_HANDLE;
VkFence InFlightFence = VK_NULL_HANDLE; VkFence InFlightFence = VK_NULL_HANDLE;
Uint32 CurrentImageIndex = 0;
}; };
} // namespace MobileGL::MG_Backend::DirectVulkan } // namespace MobileGL::MG_Backend::DirectVulkan
@@ -18,8 +18,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void PipelineManager::EnsurePipelineLayout() { void PipelineManager::EnsurePipelineLayout() {
if (PipelineLayout != VK_NULL_HANDLE) return; if (PipelineLayout != VK_NULL_HANDLE) return;
VkPipelineLayoutCreateInfo plci{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; VkPipelineLayoutCreateInfo plci{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO};
MOBILEGL_ASSERT_VK(vkCreatePipelineLayout(Ctx.GetDevice(), &plci, nullptr, &PipelineLayout), VK_VERIFY(vkCreatePipelineLayout(Ctx.GetDevice(), &plci, nullptr, &PipelineLayout), "vkCreatePipelineLayout");
"vkCreatePipelineLayout");
} }
VkPipeline PipelineManager::CreateGraphicsPipelineFromSpv(const std::string& key, VkPipeline PipelineManager::CreateGraphicsPipelineFromSpv(const std::string& key,
@@ -36,12 +35,12 @@ namespace MobileGL::MG_Backend::DirectVulkan {
smci.codeSize = vsSpv.size() * sizeof(uint32_t); smci.codeSize = vsSpv.size() * sizeof(uint32_t);
smci.pCode = vsSpv.data(); smci.pCode = vsSpv.data();
VkShaderModule vs; VkShaderModule vs;
MOBILEGL_ASSERT_VK(vkCreateShaderModule(Ctx.GetDevice(), &smci, nullptr, &vs), "vkCreateShaderModule VS"); VK_VERIFY(vkCreateShaderModule(Ctx.GetDevice(), &smci, nullptr, &vs), "vkCreateShaderModule VS");
smci.codeSize = fsSpv.size() * sizeof(uint32_t); smci.codeSize = fsSpv.size() * sizeof(uint32_t);
smci.pCode = fsSpv.data(); smci.pCode = fsSpv.data();
VkShaderModule fs; VkShaderModule fs;
MOBILEGL_ASSERT_VK(vkCreateShaderModule(Ctx.GetDevice(), &smci, nullptr, &fs), "vkCreateShaderModule FS"); VK_VERIFY(vkCreateShaderModule(Ctx.GetDevice(), &smci, nullptr, &fs), "vkCreateShaderModule FS");
VkPipelineShaderStageCreateInfo stages[2]{}; VkPipelineShaderStageCreateInfo stages[2]{};
stages[0] = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; stages[0] = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO};
@@ -105,7 +104,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
gpi.subpass = 0; gpi.subpass = 0;
VkPipeline pipeline; VkPipeline pipeline;
MOBILEGL_ASSERT_VK(vkCreateGraphicsPipelines(Ctx.GetDevice(), VK_NULL_HANDLE, 1, &gpi, nullptr, &pipeline), VK_VERIFY(vkCreateGraphicsPipelines(Ctx.GetDevice(), VK_NULL_HANDLE, 1, &gpi, nullptr, &pipeline),
"vkCreateGraphicsPipelines"); "vkCreateGraphicsPipelines");
vkDestroyShaderModule(Ctx.GetDevice(), vs, nullptr); vkDestroyShaderModule(Ctx.GetDevice(), vs, nullptr);
@@ -18,6 +18,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void SwapchainManager::Initialize() { void SwapchainManager::Initialize() {
CreateSwapchainInternal(); CreateSwapchainInternal();
CreateImageViews(); CreateImageViews();
ImagesInFlight.resize(Images.size(), VK_NULL_HANDLE);
} }
void SwapchainManager::Recreate() { void SwapchainManager::Recreate() {
@@ -28,6 +29,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
CreateSwapchainInternal(); CreateSwapchainInternal();
CreateImageViews(); CreateImageViews();
ImagesInFlight.resize(Images.size(), VK_NULL_HANDLE);
Framebuffers.clear(); Framebuffers.clear();
MGLOG_D("Swapchain recreated"); MGLOG_D("Swapchain recreated");
} }
@@ -72,7 +75,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void SwapchainManager::CreateSwapchainInternal() { void SwapchainManager::CreateSwapchainInternal() {
VkSurfaceCapabilitiesKHR caps; VkSurfaceCapabilitiesKHR caps;
MOBILEGL_ASSERT_VK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Ctx.GetPhysicalDevice(), Ctx.GetSurface(), &caps), VK_VERIFY(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(Ctx.GetPhysicalDevice(), Ctx.GetSurface(), &caps),
"vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
Extent = caps.currentExtent; Extent = caps.currentExtent;
@@ -91,13 +94,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
sci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; sci.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
sci.presentMode = QueryPossiblePresentMode(); sci.presentMode = QueryPossiblePresentMode();
MOBILEGL_ASSERT_VK(vkCreateSwapchainKHR(Ctx.GetDevice(), &sci, nullptr, &Swapchain), "vkCreateSwapchainKHR"); VK_VERIFY(vkCreateSwapchainKHR(Ctx.GetDevice(), &sci, nullptr, &Swapchain), "vkCreateSwapchainKHR");
uint32_t count = 0; uint32_t count = 0;
MOBILEGL_ASSERT_VK(vkGetSwapchainImagesKHR(Ctx.GetDevice(), Swapchain, &count, nullptr), VK_VERIFY(vkGetSwapchainImagesKHR(Ctx.GetDevice(), Swapchain, &count, nullptr),
"vkGetSwapchainImagesKHR count"); "vkGetSwapchainImagesKHR count");
Images.resize(count); Images.resize(count);
MOBILEGL_ASSERT_VK(vkGetSwapchainImagesKHR(Ctx.GetDevice(), Swapchain, &count, Images.data()), VK_VERIFY(vkGetSwapchainImagesKHR(Ctx.GetDevice(), Swapchain, &count, Images.data()),
"vkGetSwapchainImagesKHR images"); "vkGetSwapchainImagesKHR images");
MGLOG_D("Swapchain created (%u images)", count); MGLOG_D("Swapchain created (%u images)", count);
} }
@@ -117,7 +120,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
ivci.subresourceRange.levelCount = 1; ivci.subresourceRange.levelCount = 1;
ivci.subresourceRange.baseArrayLayer = 0; ivci.subresourceRange.baseArrayLayer = 0;
ivci.subresourceRange.layerCount = 1; ivci.subresourceRange.layerCount = 1;
MOBILEGL_ASSERT_VK(vkCreateImageView(Ctx.GetDevice(), &ivci, nullptr, &ImageViews[i]), "vkCreateImageView"); VK_VERIFY(vkCreateImageView(Ctx.GetDevice(), &ivci, nullptr, &ImageViews[i]), "vkCreateImageView");
} }
MGLOG_D("ImageViews created"); MGLOG_D("ImageViews created");
} }
@@ -26,6 +26,8 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkExtent2D GetExtent() const { return Extent; } VkExtent2D GetExtent() const { return Extent; }
const std::vector<VkImageView>& GetImageViews() const { return ImageViews; } const std::vector<VkImageView>& GetImageViews() const { return ImageViews; }
const std::vector<VkFramebuffer>& GetFramebuffers() const { return Framebuffers; } const std::vector<VkFramebuffer>& GetFramebuffers() const { return Framebuffers; }
const std::vector<VkImage>& GetImages() const { return Images; }
std::vector<VkFence>& GetImagesInFlight() { return ImagesInFlight; }
void SetFramebuffers(std::vector<VkFramebuffer>&& fbs); void SetFramebuffers(std::vector<VkFramebuffer>&& fbs);
@@ -36,6 +38,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkExtent2D Extent{0, 0}; VkExtent2D Extent{0, 0};
std::vector<VkImage> Images; std::vector<VkImage> Images;
std::vector<VkImageView> ImageViews; std::vector<VkImageView> ImageViews;
std::vector<VkFence> ImagesInFlight;
std::vector<VkFramebuffer> Framebuffers; std::vector<VkFramebuffer> Framebuffers;
void CreateSwapchainInternal(); void CreateSwapchainInternal();
@@ -59,20 +59,19 @@ namespace MobileGL::MG_Backend::DirectVulkan {
ci.enabledExtensionCount = 2; ci.enabledExtensionCount = 2;
ci.ppEnabledExtensionNames = exts; ci.ppEnabledExtensionNames = exts;
MOBILEGL_ASSERT_VK(vkCreateInstance(&ci, nullptr, &Instance), "vkCreateInstance failed"); VK_VERIFY(vkCreateInstance(&ci, nullptr, &Instance), "vkCreateInstance failed");
} }
void VulkanContext::CreateSurface(NativeWindowType window) { void VulkanContext::CreateSurface(NativeWindowType window) {
#if __ANDROID__ #if __ANDROID__
if (!Instance) MOBILEGL_ASSERT(false, "Instance not created"); if (!Instance) throw RuntimeError("Instance not created");
auto* nativeWindow = static_cast<ANativeWindow*>(window); auto* nativeWindow = static_cast<ANativeWindow*>(window);
if (!nativeWindow) MOBILEGL_ASSERT(false, "ANativeWindowType is null"); if (!nativeWindow) throw RuntimeError("ANativeWindowType is null");
VkAndroidSurfaceCreateInfoKHR sci{VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR}; VkAndroidSurfaceCreateInfoKHR sci{VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR};
sci.window = nativeWindow; sci.window = nativeWindow;
MOBILEGL_ASSERT_VK(vkCreateAndroidSurfaceKHR(Instance, &sci, nullptr, &Surface), VK_VERIFY(vkCreateAndroidSurfaceKHR(Instance, &sci, nullptr, &Surface), "vkCreateAndroidSurfaceKHR failed");
"vkCreateAndroidSurfaceKHR failed");
#else #else
MGLOG_W("VulkanRenderer::Initialize called on a platform which is not supported yet"); // TODO: support more MGLOG_W("VulkanRenderer::Initialize called on a platform which is not supported yet"); // TODO: support more
// platforms // platforms
@@ -81,10 +80,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void VulkanContext::PickPhysicalDevice() { void VulkanContext::PickPhysicalDevice() {
uint32_t count = 0; uint32_t count = 0;
MOBILEGL_ASSERT_VK(vkEnumeratePhysicalDevices(Instance, &count, nullptr), "vkEnumeratePhysicalDevices count"); VK_VERIFY(vkEnumeratePhysicalDevices(Instance, &count, nullptr), "vkEnumeratePhysicalDevices count");
if (count == 0) MOBILEGL_ASSERT(false, "No physical devices"); if (count == 0) throw RuntimeError("No physical devices");
std::vector<VkPhysicalDevice> devs(count); std::vector<VkPhysicalDevice> devs(count);
MOBILEGL_ASSERT_VK(vkEnumeratePhysicalDevices(Instance, &count, devs.data()), "vkEnumeratePhysicalDevices"); VK_VERIFY(vkEnumeratePhysicalDevices(Instance, &count, devs.data()), "vkEnumeratePhysicalDevices");
for (auto d : devs) { for (auto d : devs) {
uint32_t qcount = 0; uint32_t qcount = 0;
@@ -102,7 +101,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
} }
} }
MOBILEGL_ASSERT(false, "No suitable physical device"); throw RuntimeError("No suitable physical device");
} }
void VulkanContext::CreateLogicalDevice() { void VulkanContext::CreateLogicalDevice() {
@@ -120,7 +119,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
dci.enabledExtensionCount = 1; dci.enabledExtensionCount = 1;
dci.ppEnabledExtensionNames = devExts; dci.ppEnabledExtensionNames = devExts;
MOBILEGL_ASSERT_VK(vkCreateDevice(PhysicalDevice, &dci, nullptr, &Device), "vkCreateDevice failed"); VK_VERIFY(vkCreateDevice(PhysicalDevice, &dci, nullptr, &Device), "vkCreateDevice failed");
vkGetDeviceQueue(Device, GraphicsQueueFamily, 0, &GraphicsQueue); vkGetDeviceQueue(Device, GraphicsQueueFamily, 0, &GraphicsQueue);
MGLOG_D("Logical device created"); MGLOG_D("Logical device created");
} }
@@ -9,7 +9,13 @@
#pragma once #pragma once
#include <Includes.h> #include <Includes.h>
#define MOBILEGL_ASSERT_VK(exp, ...) MOBILEGL_ASSERT((exp) == VK_SUCCESS, __VA_ARGS__) #define VK_VERIFY(expr, ...) \
do { \
VkResult _vk_verify_result = (expr); \
if (_vk_verify_result != VK_SUCCESS) { \
MGLOG_E("Vulkan error %d at %s:%d" __VA_OPT__(" - ") __VA_ARGS__, _vk_verify_result, __FILE__, __LINE__); \
} \
} while (0)
namespace MobileGL::MG_Backend::DirectVulkan { namespace MobileGL::MG_Backend::DirectVulkan {
class VulkanContext { class VulkanContext {
@@ -82,7 +82,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
rpci.subpassCount = 1; rpci.subpassCount = 1;
rpci.pSubpasses = &sub; rpci.pSubpasses = &sub;
MOBILEGL_ASSERT_VK(vkCreateRenderPass(Ctx->GetDevice(), &rpci, nullptr, &RenderPass), "vkCreateRenderPass"); VK_VERIFY(vkCreateRenderPass(Ctx->GetDevice(), &rpci, nullptr, &RenderPass), "vkCreateRenderPass");
// Create framebuffers now (use swapchain imageviews) // Create framebuffers now (use swapchain imageviews)
const auto& imageViews = Swapchain->GetImageViews(); const auto& imageViews = Swapchain->GetImageViews();
@@ -98,7 +98,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
fbci.height = Swapchain->GetExtent().height; fbci.height = Swapchain->GetExtent().height;
fbci.layers = 1; fbci.layers = 1;
VkFramebuffer fb; VkFramebuffer fb;
MOBILEGL_ASSERT_VK(vkCreateFramebuffer(Ctx->GetDevice(), &fbci, nullptr, &fb), "vkCreateFramebuffer"); VK_VERIFY(vkCreateFramebuffer(Ctx->GetDevice(), &fbci, nullptr, &fb), "vkCreateFramebuffer");
fbs.push_back(fb); fbs.push_back(fb);
} }
Swapchain->SetFramebuffers(std::move(fbs)); Swapchain->SetFramebuffers(std::move(fbs));
@@ -116,7 +116,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkCommandPoolCreateInfo cpci{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO}; VkCommandPoolCreateInfo cpci{VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO};
cpci.queueFamilyIndex = Ctx->GetGraphicsQueueFamily(); cpci.queueFamilyIndex = Ctx->GetGraphicsQueueFamily();
cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; cpci.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
MOBILEGL_ASSERT_VK(vkCreateCommandPool(Ctx->GetDevice(), &cpci, nullptr, &CommandPool), "vkCreateCommandPool"); VK_VERIFY(vkCreateCommandPool(Ctx->GetDevice(), &cpci, nullptr, &CommandPool), "vkCreateCommandPool");
} }
void VulkanRenderer::DestroyCommandPool() { void VulkanRenderer::DestroyCommandPool() {
@@ -128,7 +128,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void VulkanRenderer::CreateFrameResources() { void VulkanRenderer::CreateFrameResources() {
uint32_t imageCount = static_cast<uint32_t>(Swapchain->GetImageViews().size()); uint32_t imageCount = static_cast<uint32_t>(Swapchain->GetImageViews().size());
if (imageCount == 0) MOBILEGL_ASSERT(false, "Swapchain has zero images"); if (imageCount == 0) throw RuntimeError("Swapchain has zero images");
uint32_t frames = std::min<uint32_t>(Config.MaxFramesInFlight, imageCount); uint32_t frames = std::min<uint32_t>(Config.MaxFramesInFlight, imageCount);
Frames.clear(); Frames.clear();
for (uint32_t i = 0; i < frames; ++i) { for (uint32_t i = 0; i < frames; ++i) {
@@ -150,7 +150,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
void VulkanRenderer::RecordFrameCommandBuffer(FrameContext& frame, uint32_t imageIndex) { void VulkanRenderer::RecordFrameCommandBuffer(FrameContext& frame, uint32_t imageIndex) {
// Begin // Begin
VkCommandBufferBeginInfo bi{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; VkCommandBufferBeginInfo bi{VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO};
MOBILEGL_ASSERT_VK(vkBeginCommandBuffer(frame.CommandBuffer, &bi), "vkBeginCommandBuffer"); VK_VERIFY(vkBeginCommandBuffer(frame.CommandBuffer, &bi), "vkBeginCommandBuffer");
VkClearValue clear{}; VkClearValue clear{};
clear.color = {{0.0f, 0.0f, 0.0f, 1.0f}}; clear.color = {{0.0f, 0.0f, 0.0f, 1.0f}};
@@ -171,7 +171,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
vkCmdEndRenderPass(frame.CommandBuffer); vkCmdEndRenderPass(frame.CommandBuffer);
MOBILEGL_ASSERT_VK(vkEndCommandBuffer(frame.CommandBuffer), "vkEndCommandBuffer"); VK_VERIFY(vkEndCommandBuffer(frame.CommandBuffer), "vkEndCommandBuffer");
} }
void VulkanRenderer::RecreateSwapchainIfNeeded() { void VulkanRenderer::RecreateSwapchainIfNeeded() {
@@ -185,28 +185,33 @@ namespace MobileGL::MG_Backend::DirectVulkan {
// Wait fence & Acquire image & Record commands & Submit // Wait fence & Acquire image & Record commands & Submit
void VulkanRenderer::RenderFrame() { void VulkanRenderer::RenderFrame() {
if (!Ctx) MOBILEGL_ASSERT(false, "Renderer not initialized"); if (!Ctx) throw RuntimeError("Renderer not initialized");
FrameContext& frame = *Frames[CurrentFrame]; FrameContext& frame = *Frames[CurrentFrame];
// Wait fence and reset // Wait fence and reset
MOBILEGL_ASSERT_VK(vkWaitForFences(Ctx->GetDevice(), 1, &frame.InFlightFence, VK_TRUE, UINT64_MAX), VK_VERIFY(vkWaitForFences(Ctx->GetDevice(), 1, &frame.InFlightFence, VK_TRUE, UINT64_MAX), "vkWaitForFences");
"vkWaitForFences"); VK_VERIFY(vkResetFences(Ctx->GetDevice(), 1, &frame.InFlightFence), "vkResetFences");
MOBILEGL_ASSERT_VK(vkResetFences(Ctx->GetDevice(), 1, &frame.InFlightFence), "vkResetFences");
// Acquire image // Acquire image
uint32_t imageIndex = 0; auto& imagesInFlight = Swapchain->GetImagesInFlight();
Uint32 imageIndex = 0;
VkResult res = vkAcquireNextImageKHR(Ctx->GetDevice(), Swapchain->GetSwapchain(), UINT64_MAX, VkResult res = vkAcquireNextImageKHR(Ctx->GetDevice(), Swapchain->GetSwapchain(), UINT64_MAX,
frame.ImageAvailable, VK_NULL_HANDLE, &imageIndex); frame.ImageAvailable, VK_NULL_HANDLE, &imageIndex);
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
vkWaitForFences(Ctx->GetDevice(), 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
}
imagesInFlight[imageIndex] = frame.InFlightFence;
frame.CurrentImageIndex = imageIndex;
if (res == VK_ERROR_OUT_OF_DATE_KHR) { if (res == VK_ERROR_OUT_OF_DATE_KHR) {
MGLOG_D("vkAcquireNextImageKHR: OUT_OF_DATE -> recreate"); MGLOG_D("vkAcquireNextImageKHR: OUT_OF_DATE -> recreate");
RecreateSwapchainIfNeeded(); RecreateSwapchainIfNeeded();
return; return;
} }
MOBILEGL_ASSERT_VK(res, "vkAcquireNextImageKHR"); VK_VERIFY(res, "vkAcquireNextImageKHR");
// Record commands // Record commands
MOBILEGL_ASSERT_VK(vkResetCommandBuffer(frame.CommandBuffer, 0), "vkResetCommandBuffer"); VK_VERIFY(vkResetCommandBuffer(frame.CommandBuffer, 0), "vkResetCommandBuffer");
RecordFrameCommandBuffer(frame, imageIndex); RecordFrameCommandBuffer(frame, frame.CurrentImageIndex);
// Submit // Submit
VkSubmitInfo si{VK_STRUCTURE_TYPE_SUBMIT_INFO}; VkSubmitInfo si{VK_STRUCTURE_TYPE_SUBMIT_INFO};
@@ -221,23 +226,13 @@ namespace MobileGL::MG_Backend::DirectVulkan {
si.signalSemaphoreCount = 1; si.signalSemaphoreCount = 1;
si.pSignalSemaphores = signalSemaphores; si.pSignalSemaphores = signalSemaphores;
MOBILEGL_ASSERT_VK(vkQueueSubmit(Ctx->GetGraphicsQueue(), 1, &si, frame.InFlightFence), "vkQueueSubmit"); VK_VERIFY(vkQueueSubmit(Ctx->GetGraphicsQueue(), 1, &si, frame.InFlightFence), "vkQueueSubmit");
} }
void VulkanRenderer::Present() { void VulkanRenderer::Present() {
if (!Ctx) MOBILEGL_ASSERT(false, "Renderer not initialized"); if (!Ctx) throw RuntimeError("Renderer not initialized");
FrameContext& frame = *Frames[CurrentFrame]; FrameContext& frame = *Frames[CurrentFrame];
const Uint32& imageIndex = frame.CurrentImageIndex;
// Acquire image
uint32_t imageIndex = 0;
VkResult res = vkAcquireNextImageKHR(Ctx->GetDevice(), Swapchain->GetSwapchain(), UINT64_MAX,
frame.ImageAvailable, VK_NULL_HANDLE, &imageIndex);
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
MGLOG_D("vkAcquireNextImageKHR: OUT_OF_DATE -> recreate");
RecreateSwapchainIfNeeded();
return;
}
MOBILEGL_ASSERT_VK(res, "vkAcquireNextImageKHR");
// Present // Present
VkPresentInfoKHR pi{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR}; VkPresentInfoKHR pi{VK_STRUCTURE_TYPE_PRESENT_INFO_KHR};
@@ -253,7 +248,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
MGLOG_D("vkQueuePresentKHR: out_of_date/suboptimal -> recreate"); MGLOG_D("vkQueuePresentKHR: out_of_date/suboptimal -> recreate");
RecreateSwapchainIfNeeded(); RecreateSwapchainIfNeeded();
} else { } else {
MOBILEGL_ASSERT_VK(pres, "vkQueuePresentKHR"); VK_VERIFY(pres, "vkQueuePresentKHR");
} }
CurrentFrame = (CurrentFrame + 1) % Frames.size(); CurrentFrame = (CurrentFrame + 1) % Frames.size();
@@ -55,7 +55,7 @@ namespace MobileGL::MG_Backend::DirectVulkan {
VkCommandPool CommandPool = VK_NULL_HANDLE; VkCommandPool CommandPool = VK_NULL_HANDLE;
std::vector<std::unique_ptr<FrameContext>> Frames; std::vector<std::unique_ptr<FrameContext>> Frames;
uint32_t CurrentFrame = 0; Uint32 CurrentFrame = 0;
// Render callbacks map // Render callbacks map
std::vector<std::pair<std::string, RenderCallback>> RenderCallbacks; std::vector<std::pair<std::string, RenderCallback>> RenderCallbacks;