Merge pull request #1806 from billhollings/fix-swapchain-mem-issues
Fix small memory issues with MVKPresentableSwapchainImage.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 1f361df..95be3e7 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -13,6 +13,18 @@
+MoltenVK 1.2.2
+--------------
+
+Released TBD
+
+- Fix Metal validation error caused by `CAMetalDrawable` released before
+ `MTLCommandBuffer` is finished using it.
+- Fix memory leak of `MVKFences` and `MVKSemaphores` when
+ a swapchain image is acquired more than it is presented.
+
+
+
MoltenVK 1.2.1
--------------
diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
index 51a605f..6aef84a 100644
--- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
+++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
@@ -51,7 +51,7 @@
*/
#define MVK_VERSION_MAJOR 1
#define MVK_VERSION_MINOR 2
-#define MVK_VERSION_PATCH 1
+#define MVK_VERSION_PATCH 2
#define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch))
#define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH)
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index fc9e5fd..2c19af4 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -473,6 +473,7 @@
void signalPresentationSemaphore(const MVKSwapchainSignaler& signaler, id<MTLCommandBuffer> mtlCmdBuff);
static void markAsTracked(const MVKSwapchainSignaler& signaler);
static void unmarkAsTracked(const MVKSwapchainSignaler& signaler);
+ void untrackAllSignalers();
void renderWatermark(id<MTLCommandBuffer> mtlCmdBuff);
id<CAMetalDrawable> _mtlDrawable;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 2cbb203..8b05bbd 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1287,6 +1287,18 @@
if (signaler.fence) { signaler.fence->release(); }
}
+// Untrack any signalers that are still tracking, releasing the fences and semaphores.
+void MVKPresentableSwapchainImage::untrackAllSignalers() {
+ lock_guard<mutex> lock(_availabilityLock);
+
+ if ( !_availability.isAvailable ) {
+ unmarkAsTracked(_preSignaler);
+ for (auto& sig : _availabilitySignalers) {
+ unmarkAsTracked(sig);
+ }
+ }
+}
+
#pragma mark Metal
@@ -1345,9 +1357,12 @@
_availabilitySignalers.erase(sigIter);
}
- // Ensure this image is not destroyed while awaiting MTLCommandBuffer completion
+ // Ensure this image and the drawable are not destroyed while awaiting MTLCommandBuffer completion.
+ // We retain the drawable separately because new drawable might be acquired by this image by then.
retain();
+ [mtlDrwbl retain];
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mcb) {
+ [mtlDrwbl release];
makeAvailable(signaler);
release();
}];
@@ -1405,8 +1420,11 @@
_preSignaler = MVKSwapchainSignaler{nullptr, nullptr, 0};
}
+// Unsignaled signalers will exist if this image is acquired more than it is presented.
+// Ensure they are untracked so the fences and semaphores will be released.
MVKPresentableSwapchainImage::~MVKPresentableSwapchainImage() {
releaseMetalDrawable();
+ untrackAllSignalers();
}