Fix memory leak where swapchains and images were not destroyed due to a retention loop.
Add Cube app iOS device rotation support, to test swapchain destruction on iOS.
diff --git a/Demos/Cube/iOS/DemoViewController.m b/Demos/Cube/iOS/DemoViewController.m
index 2edf35c..d0b272c 100644
--- a/Demos/Cube/iOS/DemoViewController.m
+++ b/Demos/Cube/iOS/DemoViewController.m
@@ -62,6 +62,12 @@
demo_draw(&demo);
}
+// Allow device rotation to resize the swapchain
+-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator {
+ [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+ demo_resize(&demo);
+}
+
@end
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 2b2bb2c..250455a 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -22,6 +22,7 @@
- Always explicitly set `CAMetalLayer` colorspace property based on _Vulkan_ parameters,
and don't rely on _Metal_ default values.
- Avoid use of _Metal_ renderpass load and store actions on memoryless attachments.
+- Fix memory leak on swapchain destruction.
- Remove project qualifiers from references to `SPIRV-Cross` header files.
- `MVKDescriptorPool` pools its descriptor sets.
- Enable `MVKConfiguration::preallocateDescriptors` and `MVK_CONFIG_PREALLOCATE_DESCRIPTORS`
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
index e00b73c..051db4c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h
@@ -97,6 +97,8 @@
/** VK_GOOGLE_display_timing - returns past presentation times */
VkResult getPastPresentationTiming(uint32_t *pCount, VkPastPresentationTimingGOOGLE *pPresentationTimings);
+ void destroy() override;
+
#pragma mark Construction
MVKSwapchain(MVKDevice* device, const VkSwapchainCreateInfoKHR* pCreateInfo);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
index 6f834a8..012d753 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
@@ -464,9 +464,16 @@
_presentHistoryIndex = (_presentHistoryIndex + 1) % kMaxPresentationHistory;
}
-MVKSwapchain::~MVKSwapchain() {
+// A retention loop exists between the swapchain and its images. The swapchain images
+// retain the swapchain because they can be in flight when the app destroys the swapchain.
+// Release the images now, when the app destroys the swapchain, so they will be destroyed when
+// no longer held by the presentation flow, and will in turn release the swapchain for destruction.
+void MVKSwapchain::destroy() {
for (auto& img : _presentableImages) { _device->destroyPresentableSwapchainImage(img, NULL); }
+ MVKVulkanAPIDeviceObject::destroy();
+}
+MVKSwapchain::~MVKSwapchain() {
if (_licenseWatermark) { _licenseWatermark->destroy(); }
[this->_layerObserver release];
}