diff --git a/src/modules/graphics/metal/Graphics.h b/src/modules/graphics/metal/Graphics.h index a0568f2f0..ab2e8fc2b 100644 --- a/src/modules/graphics/metal/Graphics.h +++ b/src/modules/graphics/metal/Graphics.h @@ -208,6 +208,8 @@ private: void initCapabilities() override; void getAPIStats(int &shaderswitches) const override; + void processCompletedCommandBuffers(); + void endPass(bool presenting); id getCachedDepthStencilState(const DepthState &depth, const StencilState &stencil); @@ -251,7 +253,7 @@ private: std::map cachedSamplers; std::unordered_map cachedDepthStencilStates; - std::atomic completeCommandBufferIndex; + std::vector> activeCommandBuffers; DeviceFamilies families; diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index 4c9ba328f..f07433cd6 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -408,8 +408,20 @@ Graphics::Graphics() Graphics::~Graphics() { @autoreleasepool { submitCommandBuffer(SUBMIT_DONE); - delete uniformBuffer; - delete defaultAttributesBuffer; + processCompletedCommandBuffers(); + + // Wait for all active command buffers to complete before returning from + // the destructor. + for (id cmd : activeCommandBuffers) + { + if (cmd.status == MTLCommandBufferStatusNotEnqueued || cmd.status == MTLCommandBufferStatusEnqueued) + [cmd commit]; + + [cmd waitUntilCompleted]; + } + + uniformBuffer->release(); + defaultAttributesBuffer->release(); passDesc = nil; commandQueue = nil; device = nil; @@ -562,18 +574,22 @@ id Graphics::useCommandBuffer() if (commandBuffer == nil) { commandBuffer = [commandQueue commandBuffer]; - - Graphics *pthis = this; - pthis->retain(); - [commandBuffer addCompletedHandler:^(id _Nonnull) { - pthis->completeCommandBufferIndex.fetch_add(1, std::memory_order_relaxed); - pthis->release(); - }]; + activeCommandBuffers.push_back(commandBuffer); } return commandBuffer; } +void Graphics::processCompletedCommandBuffers() +{ + for (int i = (int) activeCommandBuffers.size() - 1; i >= 0; i--) + { + auto status = activeCommandBuffers[i].status; + if (status == MTLCommandBufferStatusCompleted || status == MTLCommandBufferStatusError) + activeCommandBuffers.erase(activeCommandBuffers.begin() + i); + } +} + void Graphics::submitCommandBuffer(SubmitType type) { submitAllEncoders(type); @@ -1717,6 +1733,7 @@ void Graphics::present(void *screenshotCallbackData) updatePendingReadbacks(); updateTemporaryResources(); + processCompletedCommandBuffers(); }} int Graphics::getRequestedBackbufferMSAA() const