Fix: Metal: GPU_finish() not syncing when there's no (current) command buffer to sync on #128987

Merged
Clément Foucault merged 1 commits from Jason-Fielder/blender:Metal_fix_missing_gpu_syncs into main 2024-10-14 17:12:22 +02:00
3 changed files with 37 additions and 10 deletions

View File

@ -20,7 +20,7 @@ using namespace blender::gpu;
namespace blender::gpu {
/* Counter for active command buffers. */
int MTLCommandBufferManager::num_active_cmd_bufs = 0;
volatile std::atomic<int> MTLCommandBufferManager::num_active_cmd_bufs_in_system = 0;
/* -------------------------------------------------------------------- */
/** \name MTLCommandBuffer initialization and render coordination.
@ -50,7 +50,7 @@ id<MTLCommandBuffer> MTLCommandBufferManager::ensure_begin()
*
* NOTE: We currently stall until completion of GPU work upon ::submit if we have reached the
* in-flight command buffer limit. */
BLI_assert(MTLCommandBufferManager::num_active_cmd_bufs <
BLI_assert(MTLCommandBufferManager::num_active_cmd_bufs_in_system <
GHOST_ContextCGL::max_command_buffer_count);
if (G.debug & G_DEBUG_GPU) {
@ -68,7 +68,7 @@ id<MTLCommandBuffer> MTLCommandBufferManager::ensure_begin()
}
[active_command_buffer_ retain];
MTLCommandBufferManager::num_active_cmd_bufs++;
context_.main_command_buffer.inc_active_command_buffer_count();
/* Ensure we begin new Scratch Buffer if we are on a new frame. */
MTLScratchBufferManager &mem = context_.memory_manager;
@ -90,6 +90,12 @@ bool MTLCommandBufferManager::submit(bool wait)
{
/* Skip submission if command buffer is empty. */
if (empty_ || active_command_buffer_ == nil) {
if (wait) {
/* Wait for any previously submitted work on this context to complete. */
while (context_.main_command_buffer.get_active_command_buffer_count()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
return false;
}
@ -123,7 +129,7 @@ bool MTLCommandBufferManager::submit(bool wait)
[cmd_buffer_ref release];
/* Decrement count. */
MTLCommandBufferManager::num_active_cmd_bufs--;
context_.main_command_buffer.dec_active_command_buffer_count();
}];
/* Submit command buffer to GPU. */
@ -131,7 +137,7 @@ bool MTLCommandBufferManager::submit(bool wait)
/* If we have too many active command buffers in flight, wait until completed to avoid running
* out. We can increase */
if (MTLCommandBufferManager::num_active_cmd_bufs >=
if (MTLCommandBufferManager::num_active_cmd_bufs_in_system >=
(GHOST_ContextCGL::max_command_buffer_count - 1))
{
wait = true;

View File

@ -548,8 +548,8 @@ class MTLCommandBufferManager {
friend class MTLContext;
public:
/* Counter for active command buffers. */
static int num_active_cmd_bufs;
/* Counter for all active command buffers. */
static volatile std::atomic<int> num_active_cmd_bufs_in_system;
private:
/* Associated Context and properties. */
@ -559,6 +559,7 @@ class MTLCommandBufferManager {
/* CommandBuffer tracking. */
id<MTLCommandBuffer> active_command_buffer_ = nil;
id<MTLCommandBuffer> last_submitted_command_buffer_ = nil;
volatile std::atomic<int> num_active_cmd_bufs = 0;
/* Active MTLCommandEncoders. */
enum {
@ -653,6 +654,24 @@ class MTLCommandBufferManager {
void push_debug_group(const char *name, int index);
void pop_debug_group();
void inc_active_command_buffer_count()
{
num_active_cmd_bufs_in_system++;
num_active_cmd_bufs++;
}
void dec_active_command_buffer_count()
{
BLI_assert(num_active_cmd_bufs_in_system > 0 && num_active_cmd_bufs > 0);
num_active_cmd_bufs_in_system--;
num_active_cmd_bufs--;
}
int get_active_command_buffer_count()
{
return num_active_cmd_bufs;
}
private:
/* Begin new command buffer. */
id<MTLCommandBuffer> ensure_begin();

View File

@ -2706,7 +2706,7 @@ void present(MTLRenderPassDescriptor *blit_descriptor,
* possible. This command buffer is separate as it does not utilize the global state
* for rendering as the main context does. */
id<MTLCommandBuffer> cmdbuf = [ctx->queue commandBuffer];
MTLCommandBufferManager::num_active_cmd_bufs++;
ctx->main_command_buffer.inc_active_command_buffer_count();
/* Do Present Call and final Blit to MTLDrawable. */
id<MTLRenderCommandEncoder> enc = [cmdbuf renderCommandEncoderWithDescriptor:blit_descriptor];
@ -2739,8 +2739,10 @@ void present(MTLRenderPassDescriptor *blit_descriptor,
[cmd_buffer_ref release];
/* Decrement count */
MTLCommandBufferManager::num_active_cmd_bufs--;
MTL_LOG_INFO("Active command buffers: %d", MTLCommandBufferManager::num_active_cmd_bufs);
ctx->main_command_buffer.dec_active_command_buffer_count();
MTL_LOG_INFO("Active command buffers: %d",
int(MTLCommandBufferManager::num_active_cmd_bufs_in_system));
/* Drawable count and latency management. */
MTLContext::max_drawables_in_flight--;