MVKImage fixes for texture view creation.

Fix potential deadlock when getMTLTexture(MTLPixelFormat) calls getMTLTexture().
Clear texture views when base texture is removed.
This commit is contained in:
Bill Hollings 2020-03-31 13:25:20 -04:00
parent d5c62cc55a
commit 453fbb4045

View File

@ -287,11 +287,13 @@ id<MTLTexture> MVKImage::getMTLTexture(MTLPixelFormat mtlPixFmt) {
id<MTLTexture> mtlTex = _mtlTextureViews[mtlPixFmt]; id<MTLTexture> mtlTex = _mtlTextureViews[mtlPixFmt];
if ( !mtlTex ) { 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<MTLTexture> baseTex = getMTLTexture();
lock_guard<mutex> lock(_lock); lock_guard<mutex> lock(_lock);
mtlTex = _mtlTextureViews[mtlPixFmt]; mtlTex = _mtlTextureViews[mtlPixFmt];
if ( !mtlTex ) { if ( !mtlTex ) {
mtlTex = [getMTLTexture() newTextureViewWithPixelFormat: mtlPixFmt]; // retained mtlTex = [baseTex newTextureViewWithPixelFormat: mtlPixFmt]; // retained
_mtlTextureViews[mtlPixFmt] = mtlTex; _mtlTextureViews[mtlPixFmt] = mtlTex;
} }
} }
@ -348,10 +350,12 @@ id<MTLTexture> MVKImage::newMTLTexture() {
return mtlTex; 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() { void MVKImage::resetMTLTexture() {
[_mtlTexture release]; [_mtlTexture release];
_mtlTexture = nil; _mtlTexture = nil;
for (auto elem : _mtlTextureViews) { [elem.second release]; }
_mtlTextureViews.clear();
} }
void MVKImage::resetIOSurface() { void MVKImage::resetIOSurface() {
@ -364,6 +368,7 @@ void MVKImage::resetIOSurface() {
IOSurfaceRef MVKImage::getIOSurface() { return _ioSurface; } IOSurfaceRef MVKImage::getIOSurface() { return _ioSurface; }
VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) { VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) {
lock_guard<mutex> lock(_lock);
if (!_device->_pMetalFeatures->ioSurfaces) { return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkUseIOSurfaceMVK() : IOSurfaces are not supported on this platform."); } 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); } if (_deviceMemory) { _deviceMemory->removeImage(this); }
resetMTLTexture(); resetMTLTexture();
resetIOSurface(); resetIOSurface();
for (auto elem : _mtlTextureViews) { [elem.second release]; }
} }