Merge pull request #1393 from billhollings/retain-queue-during-submit
Retain MVKQueue in MVKQueueSubmission to avoid possible race condition.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
index 1379687..c5b8bd7 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h
@@ -176,6 +176,8 @@
uint32_t waitSemaphoreCount,
const VkSemaphore* pWaitSemaphores);
+ ~MVKQueueSubmission() override;
+
protected:
friend class MVKQueue;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
index 286946a..b23bbe2 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm
@@ -251,12 +251,18 @@
uint32_t waitSemaphoreCount,
const VkSemaphore* pWaitSemaphores) {
_queue = queue;
+ _queue->retain(); // Retain here and release in destructor. See note for MVKQueueCommandBufferSubmission::finish().
+
_waitSemaphores.reserve(waitSemaphoreCount);
for (uint32_t i = 0; i < waitSemaphoreCount; i++) {
_waitSemaphores.push_back(make_pair((MVKSemaphore*)pWaitSemaphores[i], (uint64_t)0));
}
}
+MVKQueueSubmission::~MVKQueueSubmission() {
+ _queue->release();
+}
+
#pragma mark -
#pragma mark MVKQueueCommandBufferSubmission
@@ -390,6 +396,11 @@
[mtlCmdBuff release]; // retained
}
+// Be sure to retain() any API objects referenced in this function, and release() them in the
+// destructor (or superclass destructor). It is possible for rare race conditions to result
+// in the app destroying API objects before this function completes execution. For example,
+// this may occur if a GPU semaphore here triggers another submission that triggers a fence,
+// and the app immediately destroys objects. Rare, but it has been encountered.
void MVKQueueCommandBufferSubmission::finish() {
// MVKLogDebug("Finishing submission %p. Submission count %u.", this, _subCount--);