Merge pull request #652 from billhollings/master

Fix race condition between swapchain image destruction and presentation completion callback
This commit is contained in:
Bill Hollings 2019-06-30 18:18:01 -04:00 committed by GitHub
commit 4115d8ad3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 15 additions and 34 deletions

View File

@ -27,7 +27,8 @@ Released TBD
- Skip `SPIRV-Tools` build in Travis because Travis does not support the required Python 3.
- Separate `SPIRVToMSLConverterContext` into input config and output results.
- Fix pipeline cache lookups.
- Doument that the functions in `vk_mvk_moltenvk.h` cannot be used with objects
- Fix race condition between swapchain image destruction and presentation completion callback.
- Document that the functions in `vk_mvk_moltenvk.h` cannot be used with objects
retrieved through the *Vulkan SDK Loader and Layers* framework.
- Update `VK_MVK_MOLTENVK_SPEC_VERSION` to 21.
- Update to latest SPIRV-Cross version:

View File

@ -1323,7 +1323,12 @@ void MVKSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff)
// Signal the semaphore device-side.
_availabilitySignalers.front().first->encodeSignal(mtlCmdBuff);
}
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mcb) { makeAvailable(); }];
retain(); // Ensure this image is not destroyed while awaiting MTLCommandBuffer completion
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mcb) {
makeAvailable();
release();
}];
} else {
[mtlDrawable present];
resetMetalSurface();

View File

@ -21,7 +21,7 @@
#include "MVKBaseObject.h"
#include <vulkan/vk_icd.h>
#include <string>
#include <mutex>
#include <atomic>
#import <Foundation/NSString.h>
@ -93,25 +93,18 @@ public:
static MVKVulkanAPIObject* getMVKVulkanAPIObject(VkObjectType objType, uint64_t objectHandle);
/** Construct an empty instance. Declared here to support copy constructor. */
MVKVulkanAPIObject() {}
MVKVulkanAPIObject() : _refCount(1) {}
/**
* Construct an instance from a copy. Default copy constructor disallowed due to mutex.
* Copies start with fresh reference counts.
*/
MVKVulkanAPIObject(const MVKVulkanAPIObject& other) {}
/** Default copy constructor disallowed due to mutex. Copy starts with fresh reference counts. */
MVKVulkanAPIObject(const MVKVulkanAPIObject& other) : _refCount(1) {}
~MVKVulkanAPIObject() override;
protected:
bool decrementRetainCount();
bool markDestroyed();
virtual void propogateDebugName() = 0;
std::atomic<uint32_t> _refCount;
NSString* _debugName = nil;
std::mutex _refLock;
unsigned _refCount = 0;
bool _isDestroyed = false;
};

View File

@ -25,33 +25,15 @@ using namespace std;
#pragma mark MVKVulkanAPIObject
void MVKVulkanAPIObject::retain() {
lock_guard<mutex> lock(_refLock);
_refCount++;
}
void MVKVulkanAPIObject::release() {
if (decrementRetainCount()) { destroy(); }
if (--_refCount == 0) { MVKConfigurableObject::destroy(); }
}
void MVKVulkanAPIObject::destroy() {
if (markDestroyed()) { MVKConfigurableObject::destroy(); }
}
// Decrements the reference count, and returns whether it's time to destroy this object.
bool MVKVulkanAPIObject::decrementRetainCount() {
lock_guard<mutex> lock(_refLock);
if (_refCount > 0) { _refCount--; }
return (_isDestroyed && _refCount == 0);
}
// Marks this object as destroyed, and returns whether no references are left outstanding.
bool MVKVulkanAPIObject::markDestroyed() {
lock_guard<mutex> lock(_refLock);
_isDestroyed = true;
return _refCount == 0;
release();
}
VkResult MVKVulkanAPIObject::setDebugName(const char* pObjectName) {