Merge pull request #329 from cdavis5e/destroyed-resource-descset
Remove destroyed resources from descriptor sets.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
index edd5fc6..dcb972b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
@@ -84,7 +84,7 @@
#pragma mark MVKBufferView
/** Represents a Vulkan buffer view. */
-class MVKBufferView : public MVKBaseDeviceObject {
+class MVKBufferView : public MVKRefCountedDeviceObject {
public:
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
index ce8205d..c346ba3 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
@@ -129,7 +129,6 @@
#pragma mark -
#pragma mark MVKBufferView
-
#pragma mark Metal
id<MTLTexture> MVKBufferView::getMTLTexture() {
@@ -153,7 +152,7 @@
#pragma mark Construction
-MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
_buffer = (MVKBuffer*)pCreateInfo->buffer;
_mtlBufferOffset = _buffer->getMTLBufferOffset() + pCreateInfo->offset;
_mtlPixelFormat = mtlPixelFormatFromVkFormat(pCreateInfo->format);
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
index c5fdd2b..ec6323d 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.h
@@ -239,6 +239,9 @@
/** Constructs an instance. */
MVKDescriptorBinding(MVKDescriptorSetLayoutBinding* pBindingLayout);
+ /** Destructor. */
+ ~MVKDescriptorBinding();
+
protected:
friend class MVKDescriptorSetLayoutBinding;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index 05dd688..cb4778c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -633,9 +633,15 @@
for (uint32_t i = 0; i < dstCnt; i++) {
uint32_t dstIdx = dstStartIndex + i;
const auto* pImgInfo = &get<VkDescriptorImageInfo>(pData, stride, srcStartIndex + i);
+ auto* oldSampler = (MVKSampler*)_imageBindings[dstIdx].sampler;
_imageBindings[dstIdx] = *pImgInfo;
if (_hasDynamicSamplers) {
- _mtlSamplers[dstIdx] = pImgInfo->sampler ? ((MVKSampler*)pImgInfo->sampler)->getMTLSamplerState() : nil;
+ auto* mvkSampler = (MVKSampler*)pImgInfo->sampler;
+ mvkSampler->retain();
+ _mtlSamplers[dstIdx] = mvkSampler ? mvkSampler->getMTLSamplerState() : nil;
+ }
+ if (oldSampler) {
+ oldSampler->release();
}
}
break;
@@ -644,10 +650,22 @@
for (uint32_t i = 0; i < dstCnt; i++) {
uint32_t dstIdx = dstStartIndex + i;
const auto* pImgInfo = &get<VkDescriptorImageInfo>(pData, stride, srcStartIndex + i);
+ auto* mvkImageView = (MVKImageView*)pImgInfo->imageView;
+ auto* oldImageView = (MVKImageView*)_imageBindings[dstIdx].imageView;
+ auto* oldSampler = (MVKSampler*)_imageBindings[dstIdx].sampler;
+ mvkImageView->retain();
_imageBindings[dstIdx] = *pImgInfo;
- _mtlTextures[dstIdx] = pImgInfo->imageView ? ((MVKImageView*)pImgInfo->imageView)->getMTLTexture() : nil;
+ _mtlTextures[dstIdx] = mvkImageView ? mvkImageView->getMTLTexture() : nil;
if (_hasDynamicSamplers) {
- _mtlSamplers[dstIdx] = pImgInfo->sampler ? ((MVKSampler*)pImgInfo->sampler)->getMTLSamplerState() : nil;
+ auto* mvkSampler = (MVKSampler*)pImgInfo->sampler;
+ mvkSampler->retain();
+ _mtlSamplers[dstIdx] = mvkSampler ? mvkSampler->getMTLSamplerState() : nil;
+ }
+ if (oldImageView) {
+ oldImageView->release();
+ }
+ if (oldSampler) {
+ oldSampler->release();
}
}
break;
@@ -658,8 +676,16 @@
for (uint32_t i = 0; i < dstCnt; i++) {
uint32_t dstIdx = dstStartIndex + i;
const auto* pImgInfo = &get<VkDescriptorImageInfo>(pData, stride, srcStartIndex + i);
+ auto* mvkImageView = (MVKImageView*)pImgInfo->imageView;
+ auto* oldImageView = (MVKImageView*)_imageBindings[dstIdx].imageView;
+ if (mvkImageView) {
+ mvkImageView->retain();
+ }
_imageBindings[dstIdx] = *pImgInfo;
- _mtlTextures[dstIdx] = pImgInfo->imageView ? ((MVKImageView*)pImgInfo->imageView)->getMTLTexture() : nil;
+ _mtlTextures[dstIdx] = mvkImageView ? mvkImageView->getMTLTexture() : nil;
+ if (oldImageView) {
+ oldImageView->release();
+ }
}
break;
@@ -670,10 +696,17 @@
for (uint32_t i = 0; i < dstCnt; i++) {
uint32_t dstIdx = dstStartIndex + i;
const auto* pBuffInfo = &get<VkDescriptorBufferInfo>(pData, stride, srcStartIndex + i);
+ auto* oldBuff = (MVKBuffer*)_bufferBindings[dstIdx].buffer;
_bufferBindings[dstIdx] = *pBuffInfo;
- MVKBuffer* mtlBuff = (MVKBuffer*)pBuffInfo->buffer;
+ auto* mtlBuff = (MVKBuffer*)pBuffInfo->buffer;
+ if (mtlBuff) {
+ mtlBuff->retain();
+ }
_mtlBuffers[dstIdx] = mtlBuff ? mtlBuff->getMTLBuffer() : nil;
_mtlBufferOffsets[dstIdx] = mtlBuff ? (mtlBuff->getMTLBufferOffset() + pBuffInfo->offset) : 0;
+ if (oldBuff) {
+ oldBuff->release();
+ }
}
break;
@@ -682,8 +715,16 @@
for (uint32_t i = 0; i < dstCnt; i++) {
uint32_t dstIdx = dstStartIndex + i;
const auto* pBuffView = &get<VkBufferView>(pData, stride, srcStartIndex + i);
+ auto* mvkBuffView = (MVKBufferView*)*pBuffView;
+ auto* oldBuffView = (MVKBufferView*)_texelBufferBindings[dstIdx];
+ if (mvkBuffView) {
+ mvkBuffView->retain();
+ }
_texelBufferBindings[dstIdx] = *pBuffView;
- _mtlTextures[dstIdx] = *pBuffView ? ((MVKBufferView*)*pBuffView)->getMTLTexture() : nil;
+ _mtlTextures[dstIdx] = mvkBuffView ? mvkBuffView->getMTLTexture() : nil;
+ if (oldBuffView) {
+ oldBuffView->release();
+ }
}
break;
default:
@@ -792,6 +833,27 @@
_pBindingLayout = pBindingLayout;
}
+MVKDescriptorBinding::~MVKDescriptorBinding() {
+ for (const VkDescriptorImageInfo& imgInfo : _imageBindings) {
+ if (imgInfo.imageView) {
+ ((MVKImageView*)imgInfo.imageView)->release();
+ }
+ if (imgInfo.sampler) {
+ ((MVKSampler*)imgInfo.sampler)->release();
+ }
+ }
+ for (const VkDescriptorBufferInfo& buffInfo : _bufferBindings) {
+ if (buffInfo.buffer) {
+ ((MVKBuffer*)buffInfo.buffer)->release();
+ }
+ }
+ for (VkBufferView buffView : _texelBufferBindings) {
+ if (buffView) {
+ ((MVKBufferView*)buffView)->release();
+ }
+ }
+}
+
/**
* If the descriptor set layout binding contains immutable samplers, immediately populate
* the corresponding Metal sampler in this descriptor binding from it. Otherwise add a null
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index 81e8ea1..213c690 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -647,6 +647,37 @@
#pragma mark -
+#pragma mark MVKRefCountedDeviceObject
+
+/** Represents a device-spawned object that can live past destruction by the client. */
+class MVKRefCountedDeviceObject : public MVKBaseDeviceObject {
+
+public:
+
+ /** Increments the object reference count by one. */
+ void retain();
+
+ /** Decrements the object reference count by one. */
+ void release();
+
+ void destroy() override;
+
+#pragma mark Construction
+
+ MVKRefCountedDeviceObject(MVKDevice* device) : MVKBaseDeviceObject(device) {}
+
+private:
+
+ bool decrementRetainCount();
+ bool markDestroyed();
+
+ std::mutex _refLock;
+ unsigned _refCount = 0;
+ bool _isDestroyed = false;
+};
+
+
+#pragma mark -
#pragma mark MVKDeviceObjectPool
/** Manages a pool of instances of a particular object type that requires an MVKDevice during construction. */
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 281ea47..4c22229 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -1749,3 +1749,37 @@
}
+#pragma mark -
+#pragma mark MVKRefCountedDeviceObject
+
+void MVKRefCountedDeviceObject::retain() {
+ lock_guard<mutex> lock(_refLock);
+
+ _refCount++;
+}
+
+void MVKRefCountedDeviceObject::release() {
+ if (decrementRetainCount()) { destroy(); }
+}
+
+// Decrements the reference count, and returns whether it's time to destroy this object.
+bool MVKRefCountedDeviceObject::decrementRetainCount() {
+ lock_guard<mutex> lock(_refLock);
+
+ if (_refCount > 0) { _refCount--; }
+ return (_isDestroyed && _refCount == 0);
+}
+
+void MVKRefCountedDeviceObject::destroy() {
+ if (markDestroyed()) { MVKBaseDeviceObject::destroy(); }
+}
+
+// Marks this object as destroyed, and returns whether no references are left outstanding.
+bool MVKRefCountedDeviceObject::markDestroyed() {
+ lock_guard<mutex> lock(_refLock);
+
+ _isDestroyed = true;
+ return _refCount == 0;
+}
+
+
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index 9c3c98b..0a6b2e0 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -245,7 +245,7 @@
#pragma mark MVKImageView
/** Represents a Vulkan image view. */
-class MVKImageView : public MVKBaseDeviceObject {
+class MVKImageView : public MVKRefCountedDeviceObject {
public:
@@ -308,7 +308,7 @@
#pragma mark MVKSampler
/** Represents a Vulkan sampler. */
-class MVKSampler : public MVKBaseDeviceObject {
+class MVKSampler : public MVKRefCountedDeviceObject {
public:
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 239771f..e6edb3d 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -689,7 +689,7 @@
#pragma mark Construction
-MVKImageView::MVKImageView(MVKDevice* device, const VkImageViewCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+MVKImageView::MVKImageView(MVKDevice* device, const VkImageViewCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
_image = (MVKImage*)pCreateInfo->image;
_usage = _image->_usage;
@@ -913,7 +913,7 @@
}
// Constructs an instance on the specified image.
-MVKSampler::MVKSampler(MVKDevice* device, const VkSamplerCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device) {
+MVKSampler::MVKSampler(MVKDevice* device, const VkSamplerCreateInfo* pCreateInfo) : MVKRefCountedDeviceObject(device) {
_mtlSamplerState = [getMTLDevice() newSamplerStateWithDescriptor: getMTLSamplerDescriptor(pCreateInfo)];
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
index 5f7ce03..5e3adfc 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
@@ -28,7 +28,7 @@
#pragma mark MVKResource
/** Represents an abstract Vulkan resource. Specialized subclasses include MVKBuffer and MVKImage. */
-class MVKResource : public MVKBaseDeviceObject {
+class MVKResource : public MVKRefCountedDeviceObject {
public:
@@ -74,7 +74,7 @@
#pragma mark Construction
- MVKResource(MVKDevice* device) : MVKBaseDeviceObject(device) {}
+ MVKResource(MVKDevice* device) : MVKRefCountedDeviceObject(device) {}
protected:
virtual bool needsHostReadSync(VkPipelineStageFlags srcStageMask,
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
index 9fc8b13..9fbf517 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
@@ -101,34 +101,23 @@
#pragma mark MVKSignalable
/** Abstract class for Vulkan semaphores and fences. */
-class MVKSignalable : public MVKBaseDeviceObject {
+class MVKSignalable : public MVKRefCountedDeviceObject {
public:
/* Called when this object has been added to a tracker for later signaling. */
- void wasAddedToSignaler();
+ void wasAddedToSignaler() { retain(); }
/**
* Called when this object has been removed from a tracker for later signaling.
* If this object was destroyed while this signal was pending, it will now be deleted.
*/
- void wasRemovedFromSignaler();
-
- /** If this object is waiting to be signaled, deletion will be deferred until then. */
- void destroy() override;
+ void wasRemovedFromSignaler() { release(); }
#pragma mark Construction
- MVKSignalable(MVKDevice* device) : MVKBaseDeviceObject(device) {}
-
-protected:
- bool decrementSignalerCount();
- bool markDestroyed();
-
- std::mutex _signalerLock;
- uint32_t _signalerCount = 0;
- bool _isDestroyed = false;
+ MVKSignalable(MVKDevice* device) : MVKRefCountedDeviceObject(device) {}
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
index 0d3851a..a4f1a1b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
@@ -66,40 +66,6 @@
#pragma mark -
-#pragma mark MVKSignalable
-
-void MVKSignalable::wasAddedToSignaler() {
- lock_guard<mutex> lock(_signalerLock);
-
- _signalerCount++;
-}
-
-void MVKSignalable::wasRemovedFromSignaler() {
- if (decrementSignalerCount()) { destroy(); }
-}
-
-// Decrements the signaler count, and returns whether it's time to destroy this object.
-bool MVKSignalable::decrementSignalerCount() {
- lock_guard<mutex> lock(_signalerLock);
-
- if (_signalerCount > 0) { _signalerCount--; }
- return (_isDestroyed && _signalerCount == 0);
-}
-
-void MVKSignalable::destroy() {
- if (markDestroyed()) { MVKBaseDeviceObject::destroy(); }
-}
-
-// Marks this object as destroyed, and returns whether the compilation is complete.
-bool MVKSignalable::markDestroyed() {
- lock_guard<mutex> lock(_signalerLock);
-
- _isDestroyed = true;
- return _signalerCount == 0;
-}
-
-
-#pragma mark -
#pragma mark MVKSemaphore
bool MVKSemaphore::wait(uint64_t timeout) {