Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/metal/mtl_command_buffer.mm
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | /* SPDX-License-Identifier: GPL-2.0-or-later */ | ||||
| #include "DNA_userdef_types.h" | #include "DNA_userdef_types.h" | ||||
| #include "mtl_backend.hh" | #include "mtl_backend.hh" | ||||
| #include "mtl_common.hh" | #include "mtl_common.hh" | ||||
| #include "mtl_context.hh" | #include "mtl_context.hh" | ||||
| #include "mtl_debug.hh" | #include "mtl_debug.hh" | ||||
| #include "mtl_framebuffer.hh" | #include "mtl_framebuffer.hh" | ||||
| #include "intern/GHOST_ContextCGL.h" | |||||
| #include <fstream> | #include <fstream> | ||||
| using namespace blender; | using namespace blender; | ||||
| using namespace blender::gpu; | using namespace blender::gpu; | ||||
| namespace blender::gpu { | namespace blender::gpu { | ||||
| /* Global sync event used across MTLContext's. | /* Global sync event used across MTLContext's. | ||||
| Show All 21 Lines | void MTLCommandBufferManager::register_encoder_counters() | ||||
| empty_ = false; | empty_ = false; | ||||
| } | } | ||||
| id<MTLCommandBuffer> MTLCommandBufferManager::ensure_begin() | id<MTLCommandBuffer> MTLCommandBufferManager::ensure_begin() | ||||
| { | { | ||||
| if (active_command_buffer_ == nil) { | if (active_command_buffer_ == nil) { | ||||
| /* Verify number of active command buffers is below limit. | /* Verify number of active command buffers is below limit. | ||||
| * Exceeding this limit will mean we either have a leak/GPU hang | * Exceeding this limit will mean we either have a command buffer leak/GPU hang | ||||
| * or we should increase the command buffer limit during MTLQueue creation */ | * or we should increase the command buffer limit during MTLQueue creation. | ||||
| BLI_assert(MTLCommandBufferManager::num_active_cmd_bufs < MTL_MAX_COMMAND_BUFFERS); | * Excessive command buffers can also be caused by frequent GPUContext switches, which cause | ||||
| * the GPU pipeline to flush. This is common during indirect light baking operations. | |||||
| * | |||||
| * 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 < | |||||
| GHOST_ContextCGL::max_command_buffer_count); | |||||
| if (G.debug & G_DEBUG_GPU) { | if (G.debug & G_DEBUG_GPU) { | ||||
| /* Debug: Enable Advanced Errors for GPU work execution. */ | /* Debug: Enable Advanced Errors for GPU work execution. */ | ||||
| MTLCommandBufferDescriptor *desc = [[MTLCommandBufferDescriptor alloc] init]; | MTLCommandBufferDescriptor *desc = [[MTLCommandBufferDescriptor alloc] init]; | ||||
| desc.errorOptions = MTLCommandBufferErrorOptionEncoderExecutionStatus; | desc.errorOptions = MTLCommandBufferErrorOptionEncoderExecutionStatus; | ||||
| desc.retainedReferences = YES; | desc.retainedReferences = YES; | ||||
| BLI_assert(context_.queue != nil); | BLI_assert(context_.queue != nil); | ||||
| active_command_buffer_ = [context_.queue commandBufferWithDescriptor:desc]; | active_command_buffer_ = [context_.queue commandBufferWithDescriptor:desc]; | ||||
| ▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | [cmd_buffer_ref addCompletedHandler:^(id<MTLCommandBuffer> cb) { | ||||
| /* Decrement count. */ | /* Decrement count. */ | ||||
| MTLCommandBufferManager::num_active_cmd_bufs--; | MTLCommandBufferManager::num_active_cmd_bufs--; | ||||
| }]; | }]; | ||||
| /* Submit command buffer to GPU. */ | /* Submit command buffer to GPU. */ | ||||
| [active_command_buffer_ commit]; | [active_command_buffer_ commit]; | ||||
| /* 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 >= | |||||
| (GHOST_ContextCGL::max_command_buffer_count - 1)) { | |||||
| wait = true; | |||||
| MTL_LOG_WARNING( | |||||
| "Maximum number of command buffers in flight. Host will wait until GPU work has " | |||||
| "completed. Consider increasing GHOST_ContextCGL::max_command_buffer_count or reducing " | |||||
| "work fragmentation to better utilise system hardware. Command buffers are flushed upon " | |||||
| "GPUContext switches, this is the most common cause of excessive command buffer " | |||||
| "generation.\n"); | |||||
| } | |||||
| if (wait || (G.debug & G_DEBUG_GPU)) { | if (wait || (G.debug & G_DEBUG_GPU)) { | ||||
| /* Wait until current GPU work has finished executing. */ | /* Wait until current GPU work has finished executing. */ | ||||
| [active_command_buffer_ waitUntilCompleted]; | [active_command_buffer_ waitUntilCompleted]; | ||||
| /* Command buffer execution debugging can return an error message if | /* Command buffer execution debugging can return an error message if | ||||
| * execution has failed or encountered GPU-side errors. */ | * execution has failed or encountered GPU-side errors. */ | ||||
| if (G.debug & G_DEBUG_GPU) { | if (G.debug & G_DEBUG_GPU) { | ||||
| ▲ Show 20 Lines • Show All 671 Lines • Show Last 20 Lines | |||||