mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Perf] (MG_Backend): pool DirectVulkan's upload staging and batch its submits
Every dirty texture bought itself a fresh staging buffer (vmaCreateBuffer + vmaMapMemory), a fresh command buffer, a fresh fence, and its own vkQueueSubmit. A perf profile of the sprite-animation case put 41% of the whole run in the kernel on the resulting ioctl traffic; the reclaim list already avoided waiting on the fences, so the cost was the allocation and submission machinery itself, paid per texture per frame. Staging now comes from a pool of persistently-mapped blocks (1 MiB minimum, exact-size beyond that, bump-allocated, 32 MiB idle cap), and uploads record into one shared batch command buffer from a dedicated command pool, going out as one submit with one pooled fence per flush. Fences, command buffers and blocks all recycle through the existing fence-list reclaim instead of being destroyed. Flush points: before every frame command buffer submission (which is what preserves the old ordering argument - the batch reaches the queue strictly before anything that could sample its images), on the glFlush finite-time path, when a batch would outgrow its staging bound, and eagerly at 128 KiB, which measured faster because the GPU overlaps the copy with the rest of the frame's CPU recording. The mid-frame upload-draw-upload-again sequence detects itself through the batch image list and flushes first, reproducing the old two-submit granularity exactly; a deferred image release flushes any open batch that still references the image, because drain proofs only cover submitted work. ns per op, DriverBench on a GTX 1660 SUPER: mc_tex_stream 9405 -> 5373 (2.3x the native driver, from 3.9x), atlas_sprite -57%, lightmap -89%, chunk_upload -10%; draw-path cases unchanged. The suite's sampler-churn number reads a few percent worse right after the now-much-faster upload case, which was chased to schedutil downclocking during the newly-blocking-free frames - isolated and frequency-pinned runs measure parity; noted here so the next person does not re-chase it. Unit tests 421/421; Vulkan validation layer clean across draw and upload cases.
This commit is contained in:
@@ -2710,7 +2710,8 @@ void main() {
|
||||
succeeded = m_textureManager->Initialize(
|
||||
{m_device, m_physicalDevice.handle, m_allocator, m_commandPool, m_graphicsQueue,
|
||||
m_frameContext.GetFrameCount(), m_imageFormatListExtensionEnabled,
|
||||
m_sampledReadStageMask});
|
||||
m_sampledReadStageMask,
|
||||
static_cast<Uint32>(m_physicalDevice.queueFamilies.graphicsFamily)});
|
||||
MOBILEGL_ASSERT(succeeded, "VkTextureManager initialization failed.");
|
||||
m_clearManager = MakeUnique<VkClearManager>();
|
||||
MOBILEGL_ASSERT(m_clearManager != nullptr, "VkClearManager creation failed.");
|
||||
@@ -9445,6 +9446,12 @@ void main() {
|
||||
}
|
||||
|
||||
Bool VulkanRenderer::SubmitPendingCommandBuffer(FrameContext::FrameData& frame, VkFence fence, Bool pooledFence) {
|
||||
// Batched texture uploads must reach the queue before the frame's
|
||||
// commands: the recording being submitted may sample images whose
|
||||
// texels only exist in the texture manager's open upload batch.
|
||||
if (m_textureManager) {
|
||||
m_textureManager->FlushPendingUploads();
|
||||
}
|
||||
VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
VkSemaphore waitSemaphore = frame.imageAvailableSemaphore;
|
||||
VkSubmitInfo submitInfo{VK_STRUCTURE_TYPE_SUBMIT_INFO};
|
||||
@@ -9488,6 +9495,11 @@ void main() {
|
||||
RefreshCompletedSubmits();
|
||||
auto& frame = m_frameContext.GetCurrent();
|
||||
if (!frame.isCommandRecording && !frame.hasCommandBufferRecorded) {
|
||||
// GL flush semantics still demand batched texture uploads start
|
||||
// executing in finite time even when no draw was recorded.
|
||||
if (m_textureManager) {
|
||||
m_textureManager->FlushPendingUploads();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Acquire the fence while recording is still open: failing here must
|
||||
@@ -9787,6 +9799,12 @@ void main() {
|
||||
|
||||
// 1) Submit current frame work (the pre-pass stream, when recorded,
|
||||
// rides the same submission strictly ahead of the frame commands).
|
||||
// Batched texture uploads go first: the frame's commands may sample
|
||||
// images whose texels only exist in the open upload batch, and
|
||||
// flushing here also bounds upload latency to one frame.
|
||||
if (m_textureManager) {
|
||||
m_textureManager->FlushPendingUploads();
|
||||
}
|
||||
auto submitPacket = m_frameContext.GetSubmitInfo(shouldSubmitCommandBuffer, m_imageIndexAcquired);
|
||||
VK_VERIFY(vkQueueSubmit(m_graphicsQueue, 1, &submitPacket.submitInfo, frame.imageInFlightFence));
|
||||
RegisterSubmit(frame.imageInFlightFence, /*pooledFence=*/false);
|
||||
|
||||
Reference in New Issue
Block a user