From 0f9002d724e94d0776b5c5d2dca9f9a71934b1ef Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 1 May 2017 14:13:59 -0700 Subject: [PATCH] Prevent possible crash in texture buffering thread --- libraries/gpu-gl/src/gpu/gl/GLTexture.cpp | 10 +++++++++- libraries/gpu-gl/src/gpu/gl/GLTexture.h | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp index 7f075a1698..e85e74ce73 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.cpp @@ -150,6 +150,7 @@ GLExternalTexture::~GLExternalTexture() { // Variable sized textures using MemoryPressureState = GLVariableAllocationSupport::MemoryPressureState; using WorkQueue = GLVariableAllocationSupport::WorkQueue; +using TransferJobPointer = GLVariableAllocationSupport::TransferJobPointer; std::list GLVariableAllocationSupport::_memoryManagedTextures; MemoryPressureState GLVariableAllocationSupport::_memoryPressureState { MemoryPressureState::Idle }; @@ -159,6 +160,7 @@ WorkQueue GLVariableAllocationSupport::_transferQueue; WorkQueue GLVariableAllocationSupport::_promoteQueue; WorkQueue GLVariableAllocationSupport::_demoteQueue; TexturePointer GLVariableAllocationSupport::_currentTransferTexture; +TransferJobPointer GLVariableAllocationSupport::_currentTransferJob; size_t GLVariableAllocationSupport::_frameTexturesCreated { 0 }; #define OVERSUBSCRIBED_PRESSURE_VALUE 0.95f @@ -553,9 +555,15 @@ void GLVariableAllocationSupport::executeNextTransfer(const TexturePointer& curr if (!_pendingTransfers.empty()) { // Keeping hold of a strong pointer during the transfer ensures that the transfer thread cannot try to access a destroyed texture _currentTransferTexture = currentTexture; - if (_pendingTransfers.front()->tryTransfer()) { + // Keeping hold of a strong pointer to the transfer job ensures that if the pending transfer queue is rebuilt, the transfer job + // doesn't leave scope, causing a crash in the buffering thread + _currentTransferJob = _pendingTransfers.front(); + // transfer jobs use asynchronous buffering of the texture data because it may involve disk IO, so we execute a try here to determine if the buffering + // is complete + if (_currentTransferJob->tryTransfer()) { _pendingTransfers.pop(); _currentTransferTexture.reset(); + _currentTransferJob.reset(); } } } diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index e0b8a63a99..2603b36b21 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -86,7 +86,8 @@ public: void transfer(); }; - using TransferQueue = std::queue>; + using TransferJobPointer = std::shared_ptr; + using TransferQueue = std::queue; static MemoryPressureState _memoryPressureState; public: @@ -100,6 +101,7 @@ protected: static WorkQueue _promoteQueue; static WorkQueue _demoteQueue; static TexturePointer _currentTransferTexture; + static TransferJobPointer _currentTransferJob; static const uvec3 INITIAL_MIP_TRANSFER_DIMENSIONS; static const uvec3 MAX_TRANSFER_DIMENSIONS; static const size_t MAX_TRANSFER_SIZE;