Merge pull request #1281 from cdavis5e/enhanced-cmdbuf-errors
Log enhanced command buffer errors in debug mode.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
index 1450ec7..366ebdf 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCommandPool.mm
@@ -78,7 +78,7 @@
}
id<MTLCommandBuffer> MVKCommandPool::newMTLCommandBuffer(uint32_t queueIndex) {
- return [[_device->getQueue(_queueFamilyIndex, queueIndex)->getMTLCommandQueue() commandBuffer] retain];
+ return [_device->getQueue(_queueFamilyIndex, queueIndex)->getMTLCommandBuffer(true) retain];
}
// Clear the command type pool member variables.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
index b61fff1..7f65a32 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
@@ -109,7 +109,7 @@
#if MVK_MACOS
if (pBlitEnc && _mtlBuffer && _mtlStorageMode == MTLStorageModeManaged) {
- if ( !pBlitEnc->mtlCmdBuffer) { pBlitEnc->mtlCmdBuffer = [_device->getAnyQueue()->getMTLCommandQueue() commandBufferWithUnretainedReferences]; }
+ if ( !pBlitEnc->mtlCmdBuffer) { pBlitEnc->mtlCmdBuffer = _device->getAnyQueue()->getMTLCommandBuffer(); }
if ( !pBlitEnc->mtlBlitEncoder) { pBlitEnc->mtlBlitEncoder = [pBlitEnc->mtlCmdBuffer blitCommandEncoder]; }
[pBlitEnc->mtlBlitEncoder synchronizeResource: _mtlBuffer];
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 65a9524..d72d8a8 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1209,7 +1209,7 @@
@autoreleasepool {
MVKSemaphore* mvkSem = signaler.semaphore;
id<MTLCommandBuffer> mtlCmdBuff = (mvkSem && mvkSem->isUsingCommandEncoding()
- ? [_device->getAnyQueue()->getMTLCommandQueue() commandBufferWithUnretainedReferences]
+ ? _device->getAnyQueue()->getMTLCommandBuffer()
: nil);
signal(signaler, mtlCmdBuff);
[mtlCmdBuff commit];
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
index a143819..b72edd4 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
@@ -106,6 +106,9 @@
/** Returns the Metal queue underlying this queue. */
inline id<MTLCommandQueue> getMTLCommandQueue() { return _mtlQueue; }
+ /** Returns a Metal command buffer from the Metal queue. */
+ id<MTLCommandBuffer> getMTLCommandBuffer(bool retainRefs = false);
+
#pragma mark Construction
/** Constructs an instance for the device and queue family. */
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
index 940b4a5..e80be13 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
@@ -145,6 +145,26 @@
return mvkWaitForFences(_device, 1, &fence, false);
}
+id<MTLCommandBuffer> MVKQueue::getMTLCommandBuffer(bool retainRefs) {
+#if MVK_XCODE_12
+ if ([_mtlQueue respondsToSelector: @selector(commandBufferWithDescriptor:)]) {
+ MTLCommandBufferDescriptor* mtlCmdBuffDesc = [MTLCommandBufferDescriptor new]; // temp retain
+ mtlCmdBuffDesc.retainedReferences = retainRefs;
+ if (mvkGetMVKConfiguration()->debugMode) {
+ mtlCmdBuffDesc.errorOptions |= MTLCommandBufferErrorOptionEncoderExecutionStatus;
+ }
+ id<MTLCommandBuffer> cmdBuff = [_mtlQueue commandBufferWithDescriptor: mtlCmdBuffDesc];
+ [mtlCmdBuffDesc release]; // temp release
+ return cmdBuff;
+ } else
+#endif
+ if (retainRefs) {
+ return [_mtlQueue commandBuffer];
+ } else {
+ return [_mtlQueue commandBufferWithUnretainedReferences];
+ }
+}
+
#pragma mark Construction
@@ -259,7 +279,7 @@
// Returns the active MTLCommandBuffer, lazily retrieving it from the queue if needed.
id<MTLCommandBuffer> MVKQueueCommandBufferSubmission::getActiveMTLCommandBuffer() {
if ( !_activeMTLCommandBuffer ) {
- setActiveMTLCommandBuffer([_queue->_mtlQueue commandBufferWithUnretainedReferences]);
+ setActiveMTLCommandBuffer(_queue->getMTLCommandBuffer());
}
return _activeMTLCommandBuffer;
}
@@ -273,6 +293,19 @@
[_activeMTLCommandBuffer enqueue];
}
+#if MVK_XCODE_12
+static const char* mvkStringFromErrorState(MTLCommandEncoderErrorState errState) {
+ switch (errState) {
+ case MTLCommandEncoderErrorStateUnknown: return "unknown";
+ case MTLCommandEncoderErrorStateAffected: return "affected";
+ case MTLCommandEncoderErrorStateCompleted: return "completed";
+ case MTLCommandEncoderErrorStateFaulted: return "faulted";
+ case MTLCommandEncoderErrorStatePending: return "pending";
+ }
+ return "unknown";
+}
+#endif
+
// Commits and releases the currently active MTLCommandBuffer, optionally signalling
// when the MTLCommandBuffer is done. The first time this is called, it will wait on
// any semaphores. We have delayed signalling the semaphores as long as possible to
@@ -312,7 +345,33 @@
device->getPhysicalDevice()->setConfigurationResult(VK_ERROR_DEVICE_LOST);
break;
}
+#if MVK_XCODE_12
+ if (mvkGetMVKConfiguration()->debugMode) {
+ if (&MTLCommandBufferEncoderInfoErrorKey != nullptr) {
+ if (NSArray<id<MTLCommandBufferEncoderInfo>>* mtlEncInfo = mtlCB.error.userInfo[MTLCommandBufferEncoderInfoErrorKey]) {
+ MVKLogInfo("Encoders for %p \"%s\":", mtlCB, mtlCB.label ? mtlCB.label.UTF8String : "");
+ for (id<MTLCommandBufferEncoderInfo> enc in mtlEncInfo) {
+ MVKLogInfo(" - %s: %s", enc.label.UTF8String, mvkStringFromErrorState(enc.errorState));
+ if (enc.debugSignposts.count > 0) {
+ MVKLogInfo(" Debug signposts:");
+ for (NSString* signpost in enc.debugSignposts) {
+ MVKLogInfo(" - %s", signpost.UTF8String);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
}
+#if MVK_XCODE_12
+ if (mvkGetMVKConfiguration()->debugMode) {
+ MVKLogInfo("Shader log messages:");
+ for (id<MTLFunctionLog> log in mtlCB.logs) {
+ MVKLogInfo("%s", log.description.UTF8String);
+ }
+ }
+#endif
}];
_activeMTLCommandBuffer = nil;
@@ -406,7 +465,7 @@
}
id<MTLCommandBuffer> MVKQueuePresentSurfaceSubmission::getMTLCommandBuffer() {
- id<MTLCommandBuffer> mtlCmdBuff = [_queue->getMTLCommandQueue() commandBufferWithUnretainedReferences];
+ id<MTLCommandBuffer> mtlCmdBuff = _queue->getMTLCommandBuffer();
setLabelIfNotNil(mtlCmdBuff, @"vkQueuePresentKHR CommandBuffer");
[mtlCmdBuff enqueue];
return mtlCmdBuff;