[Fix] (MG_Backend/DirectVulkan): upload buffer using fence, without vkQueueWaitIdle

This commit is contained in:
2026-03-05 18:02:28 +08:00
parent 668fa3033e
commit a2e8faafe5
2 changed files with 55 additions and 59 deletions
@@ -287,8 +287,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
} }
vmaUnmapMemory(m_allocator, stagingAllocation); vmaUnmapMemory(m_allocator, stagingAllocation);
// TODO: Could be uploaded asynchronously? VkCommandBufferAllocateInfo allocInfo{};
const Bool ok = ExecuteCmdBufImmediate([&](VkCommandBuffer commandBuffer) { allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = m_commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
VK_VERIFY(vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer), "vkAllocateCommandBuffers(texture)");
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VK_VERIFY(vkBeginCommandBuffer(commandBuffer, &beginInfo), "vkBeginCommandBuffer(texture)");
const VkImageAspectFlags aspectMask = GetAspectMaskForFormat(outResource.format); const VkImageAspectFlags aspectMask = GetAspectMaskForFormat(outResource.format);
Bool ok = TransitionImageLayout(commandBuffer, outResource.image, Bool ok = TransitionImageLayout(commandBuffer, outResource.image,
outResource.layout, outResource.layout,
@@ -325,8 +337,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
aspectMask); aspectMask);
MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed"); MOBILEGL_ASSERT(ok, "TransitionImageLayout to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL failed");
outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; outResource.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
return ok;
}); VK_VERIFY(vkEndCommandBuffer(commandBuffer), "vkEndCommandBuffer(texture)");
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
VkFence uploadFence = VK_NULL_HANDLE;
VK_VERIFY(vkCreateFence(m_device, &fenceInfo, nullptr, &uploadFence), "vkCreateFence(texture upload)");
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, uploadFence), "vkQueueSubmit(texture)");
VK_VERIFY(vkWaitForFences(m_device, 1, &uploadFence, VK_TRUE, UINT64_MAX), "vkWaitForFences(texture upload)");
vkDestroyFence(m_device, uploadFence, nullptr);
vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
vmaDestroyBuffer(m_allocator, stagingBuffer, stagingAllocation); vmaDestroyBuffer(m_allocator, stagingBuffer, stagingAllocation);
@@ -341,36 +368,6 @@ namespace MobileGL::MG_Backend::DirectVulkan {
return true; return true;
} }
Bool VkTextureManager::ExecuteCmdBufImmediate(const std::function<void(VkCommandBuffer)>& recorder) const {
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = m_commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1;
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
VK_VERIFY(vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer), "vkAllocateCommandBuffers(texture)");
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
VK_VERIFY(vkBeginCommandBuffer(commandBuffer, &beginInfo), "vkBeginCommandBuffer(texture)");
recorder(commandBuffer);
VK_VERIFY(vkEndCommandBuffer(commandBuffer), "vkEndCommandBuffer(texture)");
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE), "vkQueueSubmit(texture)");
VK_VERIFY(vkQueueWaitIdle(m_graphicsQueue), "vkQueueWaitIdle(texture)");
vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
return true;
}
Bool VkTextureManager::CheckMipmapCompleteness(const MG_State::GLState::ITextureObject& texture, Bool VkTextureManager::CheckMipmapCompleteness(const MG_State::GLState::ITextureObject& texture,
TextureUploadTarget& outTarget, TextureUploadTarget& outTarget,
IntVec3& outTexelSize, IntVec3& outTexelSize,
@@ -93,7 +93,6 @@ private:
Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture, Bool UploadDirtyMipLevels(MG_State::GLState::TextureObjectMipmap &mipmapTexture,
TextureUploadTarget uploadTarget, TextureUploadTarget uploadTarget,
TextureResource &outResource); TextureResource &outResource);
Bool ExecuteCmdBufImmediate(const std::function<void(VkCommandBuffer)>& recorder) const;
static Bool CheckMipmapCompleteness(const MG_State::GLState::ITextureObject& texture, static Bool CheckMipmapCompleteness(const MG_State::GLState::ITextureObject& texture,
TextureUploadTarget& outTarget, TextureUploadTarget& outTarget,
IntVec3& outTexelSize, IntVec3& outTexelSize,