Fix intermittent corruption uploading textures in Dota 2.

The problem was that MVKBuffer::getMTLBuffer() was not thread-safe.  If
multiple threads called it at the same time, more than one underlying
_mtlBuffer would be created.  This could make the vkCmdCopyBufferToImage
copy from an unfilled buffer leaving the texture corrupted.  I also
added similar thread safety to MVKImage::getMTLTexture() and
MVKImageView::getMTLTexture() since they both looked like they would
have the same potential problem.
This commit is contained in:
Dan Ginsburg 2018-01-30 12:28:14 -05:00
parent d1cd122201
commit 6d50a88178
4 changed files with 24 additions and 2 deletions

View File

@ -79,6 +79,7 @@ protected:
VkBufferMemoryBarrier* pBufferMemoryBarrier);
id<MTLBuffer> _mtlBuffer;
std::mutex _lock;
};

View File

@ -154,6 +154,13 @@ id<MTLBuffer> MVKBuffer::getMTLBuffer() {
if (_mtlBuffer) { return _mtlBuffer; }
lock_guard<mutex> lock(_lock);
// Check again in case another thread has created the buffer.
if (_mtlBuffer) {
return _mtlBuffer;
}
id<MTLBuffer> devMemMTLBuff = _deviceMemory->getMTLBuffer();
if (devMemMTLBuff) { return devMemMTLBuff; }

View File

@ -222,6 +222,7 @@ protected:
MTLPixelFormat _mtlPixelFormat;
MTLTextureType _mtlTextureType;
id<MTLTexture> _mtlTexture;
std::mutex _lock;
IOSurfaceRef _ioSurface;
bool _isDepthStencilAttachment;
bool _canSupportMTLTextureView;
@ -279,6 +280,7 @@ protected:
MVKImage* _image;
VkImageSubresourceRange _subresourceRange;
id<MTLTexture> _mtlTexture;
std::mutex _lock;
MTLPixelFormat _mtlPixelFormat;
MTLTextureType _mtlTextureType;
bool _useMTLTextureView;

View File

@ -215,7 +215,13 @@ void* MVKImage::map(VkDeviceSize offset, VkDeviceSize size) {
#pragma mark Metal
id<MTLTexture> MVKImage::getMTLTexture() {
if ( !_mtlTexture && _mtlPixelFormat ) { _mtlTexture = newMTLTexture(); } // retained
if ( !_mtlTexture && _mtlPixelFormat ) {
lock_guard<mutex> lock(_lock);
// Check again in case another thread has created the texture.
if ( !_mtlTexture ) {
_mtlTexture = newMTLTexture();
}
} // retained
return _mtlTexture;
}
@ -537,7 +543,13 @@ void MVKImageView::populateMTLRenderPassAttachmentDescriptorResolve(MTLRenderPas
id<MTLTexture> MVKImageView::getMTLTexture() {
// If we can use a Metal texture view, lazily create it, otherwise use the image texture directly.
if (_useMTLTextureView) {
if ( !_mtlTexture && _mtlPixelFormat ) { _mtlTexture = newMTLTexture(); } // retained
if ( !_mtlTexture && _mtlPixelFormat ) {
lock_guard<mutex> lock(_lock);
// Check again in case another thread created the texture view
if ( !_mtlTexture ) {
_mtlTexture = newMTLTexture(); // retained
}
}
return _mtlTexture;
} else {
return _image->getMTLTexture();