From 23f27816ad0297e1218cf4e7e77be00234f6d5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Pi=C3=B1eiro?= Date: Mon, 22 Feb 2021 14:04:46 +0100 Subject: [PATCH] Staging: add a limit of how many commands to stage Although staging commands can be a good idea from performance pov, it also means that we are increasing the size of the command buffer, until the queue submission is set (in most drivers). For example, when computing the Interactions, staged command buffers can be easily greater that 15k. This could be a problem with low-memory devices, like rpi4. This patch adds a new variable to configure the maximum size of staged commands. When that limit is reached a Flush is done (similar to the existing limit on the UploadBufferSize). --- neo/renderer/Vulkan/Staging_VK.cpp | 11 +++++++++++ neo/renderer/Vulkan/Staging_VK.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/neo/renderer/Vulkan/Staging_VK.cpp b/neo/renderer/Vulkan/Staging_VK.cpp index c3c35f2f..061a671c 100644 --- a/neo/renderer/Vulkan/Staging_VK.cpp +++ b/neo/renderer/Vulkan/Staging_VK.cpp @@ -34,6 +34,7 @@ If you have questions concerning this license or the applicable additional terms #include "Staging_VK.h" idCVar r_vkUploadBufferSizeMB( "r_vkUploadBufferSizeMB", "64", CVAR_INTEGER | CVAR_INIT, "Size of gpu upload buffer." ); +idCVar r_vkStagingMaxCommands( "r_vkStagingMaxCommands", "-1", CVAR_INTEGER | CVAR_INIT, "Maximum amount of commands staged (-1 for no limit)" ); /* =========================================================================== @@ -182,6 +183,12 @@ byte* idVulkanStagingManager::Stage( const int size, const int alignment, VkComm Flush(); } + int maxCommands = r_vkStagingMaxCommands.GetInteger(); + if ( ( maxCommands > 0 ) && ( stage->stagedCommands >= maxCommands) ) + { + Flush(); + } + stage = &buffers[ currentBuffer ]; if( stage->submitted ) { @@ -195,6 +202,8 @@ byte* idVulkanStagingManager::Stage( const int size, const int alignment, VkComm byte* data = stage->data + stage->offset; stage->offset += size; + stage->stagedCommands++; + return data; } @@ -237,6 +246,7 @@ void idVulkanStagingManager::Flush() vkQueueSubmit( vkcontext.graphicsQueue, 1, &submitInfo, stage.fence ); stage.submitted = true; + stage.stagedCommands = 0; currentBuffer = ( currentBuffer + 1 ) % NUM_FRAME_DATA; } @@ -256,6 +266,7 @@ void idVulkanStagingManager::Wait( stagingBuffer_t& stage ) ID_VK_CHECK( vkWaitForFences( vkcontext.device, 1, &stage.fence, VK_TRUE, UINT64_MAX ) ); ID_VK_CHECK( vkResetFences( vkcontext.device, 1, &stage.fence ) ); + stage.stagedCommands = 0; stage.offset = 0; stage.submitted = false; diff --git a/neo/renderer/Vulkan/Staging_VK.h b/neo/renderer/Vulkan/Staging_VK.h index 62a33e29..7a2c27ba 100644 --- a/neo/renderer/Vulkan/Staging_VK.h +++ b/neo/renderer/Vulkan/Staging_VK.h @@ -54,6 +54,8 @@ struct stagingBuffer_t VkFence fence; VkDeviceSize offset; byte* data; + + int stagedCommands; }; class idVulkanStagingManager