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:
parent
d1cd122201
commit
6d50a88178
@ -79,6 +79,7 @@ protected:
|
|||||||
VkBufferMemoryBarrier* pBufferMemoryBarrier);
|
VkBufferMemoryBarrier* pBufferMemoryBarrier);
|
||||||
|
|
||||||
id<MTLBuffer> _mtlBuffer;
|
id<MTLBuffer> _mtlBuffer;
|
||||||
|
std::mutex _lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,6 +154,13 @@ id<MTLBuffer> MVKBuffer::getMTLBuffer() {
|
|||||||
|
|
||||||
if (_mtlBuffer) { return _mtlBuffer; }
|
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();
|
id<MTLBuffer> devMemMTLBuff = _deviceMemory->getMTLBuffer();
|
||||||
if (devMemMTLBuff) { return devMemMTLBuff; }
|
if (devMemMTLBuff) { return devMemMTLBuff; }
|
||||||
|
|
||||||
|
@ -222,6 +222,7 @@ protected:
|
|||||||
MTLPixelFormat _mtlPixelFormat;
|
MTLPixelFormat _mtlPixelFormat;
|
||||||
MTLTextureType _mtlTextureType;
|
MTLTextureType _mtlTextureType;
|
||||||
id<MTLTexture> _mtlTexture;
|
id<MTLTexture> _mtlTexture;
|
||||||
|
std::mutex _lock;
|
||||||
IOSurfaceRef _ioSurface;
|
IOSurfaceRef _ioSurface;
|
||||||
bool _isDepthStencilAttachment;
|
bool _isDepthStencilAttachment;
|
||||||
bool _canSupportMTLTextureView;
|
bool _canSupportMTLTextureView;
|
||||||
@ -279,6 +280,7 @@ protected:
|
|||||||
MVKImage* _image;
|
MVKImage* _image;
|
||||||
VkImageSubresourceRange _subresourceRange;
|
VkImageSubresourceRange _subresourceRange;
|
||||||
id<MTLTexture> _mtlTexture;
|
id<MTLTexture> _mtlTexture;
|
||||||
|
std::mutex _lock;
|
||||||
MTLPixelFormat _mtlPixelFormat;
|
MTLPixelFormat _mtlPixelFormat;
|
||||||
MTLTextureType _mtlTextureType;
|
MTLTextureType _mtlTextureType;
|
||||||
bool _useMTLTextureView;
|
bool _useMTLTextureView;
|
||||||
|
@ -215,7 +215,13 @@ void* MVKImage::map(VkDeviceSize offset, VkDeviceSize size) {
|
|||||||
#pragma mark Metal
|
#pragma mark Metal
|
||||||
|
|
||||||
id<MTLTexture> MVKImage::getMTLTexture() {
|
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;
|
return _mtlTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -537,7 +543,13 @@ void MVKImageView::populateMTLRenderPassAttachmentDescriptorResolve(MTLRenderPas
|
|||||||
id<MTLTexture> MVKImageView::getMTLTexture() {
|
id<MTLTexture> MVKImageView::getMTLTexture() {
|
||||||
// If we can use a Metal texture view, lazily create it, otherwise use the image texture directly.
|
// If we can use a Metal texture view, lazily create it, otherwise use the image texture directly.
|
||||||
if (_useMTLTextureView) {
|
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;
|
return _mtlTexture;
|
||||||
} else {
|
} else {
|
||||||
return _image->getMTLTexture();
|
return _image->getMTLTexture();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user