Merge pull request #1080 from cdavis5e/display-timing-use-after-free
MVKSwapchainImage: Retain image and swapchain until presentation is done.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index a7b81b8..4dab04b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -402,6 +402,8 @@
MVKSwapchain* swapchain,
uint32_t swapchainIndex);
+ ~MVKSwapchainImage() override;
+
protected:
friend class MVKPeerSwapchainImage;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 8b07945..52e2e8d 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1115,6 +1115,12 @@
uint32_t swapchainIndex) : MVKImage(device, pCreateInfo) {
_swapchain = swapchain;
_swapchainIndex = swapchainIndex;
+
+ _swapchain->retain();
+}
+
+MVKSwapchainImage::~MVKSwapchainImage() {
+ if (_swapchain) { _swapchain->release(); }
}
@@ -1275,11 +1281,13 @@
_swapchain->recordPresentTime(presentID, desiredPresentTime, desiredPresentTime);
#else
if ([_mtlDrawable respondsToSelector: @selector(addPresentedHandler:)]) {
+ retain(); // Ensure this image is not destroyed while awaiting presentation
[_mtlDrawable addPresentedHandler: ^(id<MTLDrawable> drawable) {
// Record the presentation time
CFTimeInterval presentedTimeSeconds = drawable.presentedTime;
uint64_t presentedTimeNanoseconds = (uint64_t)(presentedTimeSeconds * 1.0e9);
_swapchain->recordPresentTime(presentID, desiredPresentTime, presentedTimeNanoseconds);
+ release();
}];
} else {
// If MTLDrawable.presentedTime/addPresentedHandler isn't supported, just treat it as if the