From ddb3c34cd5c8b1a34020840b8b7ff82b1dcbce69 Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Fri, 23 Oct 2020 15:14:38 -0400 Subject: [PATCH] Fix GPU capture for Metal test apps. Creating the next command buffer immediately seems to confuse the Metal GPU capture command in Xcode. If the command buffer isn't used until the next frame it apparently doesn't include it in the capture. The solution is to delay creation until we first need it. Change-Id: I95fea78a68356d319418ca15bd852e34d9efa12b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/329416 Reviewed-by: Adlai Holler Commit-Queue: Jim Van Verth --- src/gpu/mtl/GrMtlGpu.h | 5 +---- src/gpu/mtl/GrMtlGpu.mm | 33 +++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h index 6b250ae049..b8b488ebb6 100644 --- a/src/gpu/mtl/GrMtlGpu.h +++ b/src/gpu/mtl/GrMtlGpu.h @@ -48,10 +48,7 @@ public: GrMtlResourceProvider& resourceProvider() { return fResourceProvider; } - GrMtlCommandBuffer* commandBuffer() { - SkASSERT(fCurrentCmdBuffer); - return fCurrentCmdBuffer.get(); - } + GrMtlCommandBuffer* commandBuffer(); enum SyncQueue { kForce_SyncQueue, diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm index 65ae27b01c..40c89f25ce 100644 --- a/src/gpu/mtl/GrMtlGpu.mm +++ b/src/gpu/mtl/GrMtlGpu.mm @@ -192,6 +192,16 @@ GrOpsRenderPass* GrMtlGpu::getOpsRenderPass( return new GrMtlOpsRenderPass(this, renderTarget, origin, colorInfo, stencilInfo); } +GrMtlCommandBuffer* GrMtlGpu::commandBuffer() { + if (!fCurrentCmdBuffer) { + // Create a new command buffer for the next submit + fCurrentCmdBuffer = GrMtlCommandBuffer::Make(fQueue); + } + + SkASSERT(fCurrentCmdBuffer); + return fCurrentCmdBuffer.get(); +} + void GrMtlGpu::takeOwnershipOfBuffer(sk_sp buffer) { SkASSERT(fCurrentCmdBuffer); fCurrentCmdBuffer->addGrBuffer(std::move(buffer)); @@ -204,8 +214,7 @@ void GrMtlGpu::submit(GrOpsRenderPass* renderPass) { } bool GrMtlGpu::submitCommandBuffer(SyncQueue sync) { - SkASSERT(fCurrentCmdBuffer); - if (!fCurrentCmdBuffer->hasWork()) { + if (!fCurrentCmdBuffer || !fCurrentCmdBuffer->hasWork()) { if (sync == SyncQueue::kForce_SyncQueue) { // wait for the last command buffer we've submitted to finish OutstandingCommandBuffer* back = @@ -217,10 +226,13 @@ bool GrMtlGpu::submitCommandBuffer(SyncQueue sync) { } // We need to manually call the finishedCallbacks since we don't add this // to the OutstandingCommandBuffer list - fCurrentCmdBuffer->callFinishedCallbacks(); + if (fCurrentCmdBuffer) { + fCurrentCmdBuffer->callFinishedCallbacks(); + } return true; } + SkASSERT(fCurrentCmdBuffer); GrFence fence = this->insertFence(); new (fOutstandingCommandBuffers.push_back()) OutstandingCommandBuffer( fCurrentCmdBuffer, fence); @@ -229,15 +241,16 @@ bool GrMtlGpu::submitCommandBuffer(SyncQueue sync) { return false; } - // Create a new command buffer for the next submit - fCurrentCmdBuffer = GrMtlCommandBuffer::Make(fQueue); + // We don't create a new command buffer here because we may end up using it + // in the next frame, and that confuses the GPU debugger. Instead we + // create when we next need one. + fCurrentCmdBuffer = nullptr; - // This should be done after we have a new command buffer in case the freeing of any - // resources held by a finished command buffer causes us to send a new command to the gpu - // (like changing the resource state). + // If the freeing of any resources held by a finished command buffer causes us to send + // a new command to the gpu (like changing the resource state) we'll create the new + // command buffer in commandBuffer(), above. this->checkForFinishedCommandBuffers(); - SkASSERT(fCurrentCmdBuffer); return true; } @@ -278,7 +291,7 @@ void GrMtlGpu::addFinishedCallback(sk_sp finishedCallback) { if (back) { back->fCommandBuffer->addFinishedCallback(finishedCallback); } - fCurrentCmdBuffer->addFinishedCallback(std::move(finishedCallback)); + commandBuffer()->addFinishedCallback(std::move(finishedCallback)); } bool GrMtlGpu::onSubmitToGpu(bool syncCpu) {