Merge pull request #1410 from billhollings/swapchain-image-acquisition-order

Fix issue where swapchain images were acquired out of order under heavy load.
diff --git a/Docs/ b/Docs/
index 26b7e76..2683e1c 100644
--- a/Docs/
+++ b/Docs/
@@ -19,6 +19,7 @@
 Released TBD
 - Vulkan timestamp query pools use Metal GPU counters when available.
+- Fix issue where swapchain images were acquired out of order under heavy load.
 - Fix incorrect translation of clear color values on Apple Silicon.
 - Fix swizzle of depth and stencil values into RGBA (`float4`) variable in shaders.
diff --git a/MoltenVK/MoltenVK/GPUObjects/ b/MoltenVK/MoltenVK/GPUObjects/
index 0f1b596..1a4f78e 100644
--- a/MoltenVK/MoltenVK/GPUObjects/
+++ b/MoltenVK/MoltenVK/GPUObjects/
@@ -1185,19 +1185,18 @@
 void MVKPresentableSwapchainImage::makeAvailable(const MVKSwapchainSignaler& signaler) {
 	lock_guard<mutex> lock(_availabilityLock);
-	// Mark when this event happened, relative to that of other images
-	_availability.acquisitionID = _swapchain->getNextAcquisitionID();
 	// Signal the semaphore and fence, and let them know they are no longer being tracked.
 	signal(signaler, nil);
-//	MVKLogDebug("Signaling%s swapchain image %p semaphore %p from present, with %lu remaining semaphores.", (_availability.isAvailable ? " pre-signaled" : ""), this, signaler.first, _availabilitySignalers.size());
 void MVKPresentableSwapchainImage::acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence) {
 	lock_guard<mutex> lock(_availabilityLock);
+	// Upon acquisition, update acquisition ID immediately, to move it to the back of the chain,
+	// so other images will be preferred if either all images are available or no images are available.
+	_availability.acquisitionID = _swapchain->getNextAcquisitionID();
 	// Now that this image is being acquired, release the existing drawable and its texture.
 	// This is not done earlier so the texture is retained for any post-processing such as screen captures, etc.
@@ -1223,8 +1222,6 @@
-//	MVKLogDebug("%s swapchain image %p semaphore %p in acquire with %lu other semaphores.", (_availability.isAvailable ? "Signaling" : "Tracking"), this, semaphore, _availabilitySignalers.size());
 // If present, signal the semaphore for the first waiter for the given image.