From 453fbb404575cf5d6308385d5991bbcf7434b648 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Tue, 31 Mar 2020 13:25:20 -0400 Subject: [PATCH] MVKImage fixes for texture view creation. Fix potential deadlock when getMTLTexture(MTLPixelFormat) calls getMTLTexture(). Clear texture views when base texture is removed. --- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index e6947cc3..1176b6a1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -287,11 +287,13 @@ id MVKImage::getMTLTexture(MTLPixelFormat mtlPixFmt) { id mtlTex = _mtlTextureViews[mtlPixFmt]; if ( !mtlTex ) { - // Lock and check again in case another thread has created the texture. + // Lock and check again in case another thread has created the view texture. + // baseTex retreived outside of lock to avoid deadlock if it too needs to be lazily created. + id baseTex = getMTLTexture(); lock_guard lock(_lock); mtlTex = _mtlTextureViews[mtlPixFmt]; if ( !mtlTex ) { - mtlTex = [getMTLTexture() newTextureViewWithPixelFormat: mtlPixFmt]; // retained + mtlTex = [baseTex newTextureViewWithPixelFormat: mtlPixFmt]; // retained _mtlTextureViews[mtlPixFmt] = mtlTex; } } @@ -348,10 +350,12 @@ id MVKImage::newMTLTexture() { return mtlTex; } -// Removes and releases the MTLTexture object, so that it can be lazily created by getMTLTexture(). +// Removes and releases the MTLTexture object, and all associated texture views void MVKImage::resetMTLTexture() { [_mtlTexture release]; _mtlTexture = nil; + for (auto elem : _mtlTextureViews) { [elem.second release]; } + _mtlTextureViews.clear(); } void MVKImage::resetIOSurface() { @@ -364,6 +368,7 @@ void MVKImage::resetIOSurface() { IOSurfaceRef MVKImage::getIOSurface() { return _ioSurface; } VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) { + lock_guard lock(_lock); if (!_device->_pMetalFeatures->ioSurfaces) { return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkUseIOSurfaceMVK() : IOSurfaces are not supported on this platform."); } @@ -787,7 +792,6 @@ MVKImage::~MVKImage() { if (_deviceMemory) { _deviceMemory->removeImage(this); } resetMTLTexture(); resetIOSurface(); - for (auto elem : _mtlTextureViews) { [elem.second release]; } }