diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-04-16 02:50:18 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-04-16 02:50:18 +0000 |
| commit | 8add3f24c9843a80ddb4dc800dc3b3c942a6267d (patch) | |
| tree | dd9f38a6d51ffa105d3d9319b05c52ee385e5ca1 /Graphics/GraphicsTools | |
| parent | Fixed issue with buffer usage flags (diff) | |
| download | DiligentCore-8add3f24c9843a80ddb4dc800dc3b3c942a6267d.tar.gz DiligentCore-8add3f24c9843a80ddb4dc800dc3b3c942a6267d.zip | |
Fixed grammatic error plus few minor updates
Diffstat (limited to 'Graphics/GraphicsTools')
| -rw-r--r-- | Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp | 459 | ||||
| -rw-r--r-- | Graphics/GraphicsTools/src/TextureUploaderGL.cpp | 387 |
2 files changed, 431 insertions, 415 deletions
diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp index dbee7022..17fffc39 100644 --- a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp +++ b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp @@ -39,290 +39,299 @@ namespace Diligent { - class UploadBufferD3D11 : public UploadBufferBase - { - public: - UploadBufferD3D11(Diligent::IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc, ID3D11Texture2D *pStagingTexture) : - UploadBufferBase(pRefCounters, Desc), - m_pStagingTexture(pStagingTexture) - {} - ~UploadBufferD3D11() - { - if (m_pStagingTexture) - LOG_INFO_MESSAGE("UploadBufferD3D11: releasing ", m_Desc.Width, 'x', m_Desc.Height, " Fmt=", m_Desc.Format, " staging texture"); - } - void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride) - { - m_pData = pData; - m_RowStride = RowStride; - m_DepthStride = DepthStride; - } +namespace +{ - // http://en.cppreference.com/w/cpp/thread/condition_variable - void WaitForMap() - { - m_BufferMappedSignal.Wait(); - } +class UploadBufferD3D11 : public UploadBufferBase +{ +public: + UploadBufferD3D11(Diligent::IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc, ID3D11Texture2D *pStagingTexture) : + UploadBufferBase(pRefCounters, Desc), + m_pStagingTexture(pStagingTexture) + {} - void SignalMapped() - { - m_BufferMappedSignal.Trigger(); - } + ~UploadBufferD3D11() + { + if (m_pStagingTexture) + LOG_INFO_MESSAGE("UploadBufferD3D11: releasing ", m_Desc.Width, 'x', m_Desc.Height, " Fmt=", m_Desc.Format, " staging texture"); + } - void SignalCopyScheduled() - { - m_CopyScheduledSignal.Trigger(); - } + void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride) + { + m_pData = pData; + m_RowStride = RowStride; + m_DepthStride = DepthStride; + } - virtual void WaitForCopyScheduled()override final - { - m_CopyScheduledSignal.Wait(); - } + // http://en.cppreference.com/w/cpp/thread/condition_variable + void WaitForMap() + { + m_BufferMappedSignal.Wait(); + } - bool DbgIsCopyScheduled() - { - return m_CopyScheduledSignal.IsTriggered(); - } + void SignalMapped() + { + m_BufferMappedSignal.Trigger(); + } - bool DbgIsMapped() - { - return m_BufferMappedSignal.IsTriggered(); - } + void SignalCopyScheduled() + { + m_CopyScheduledSignal.Trigger(); + } - void Reset() - { - m_pData = nullptr; - m_RowStride = 0; - m_DepthStride = 0; - m_BufferMappedSignal.Reset(); - m_CopyScheduledSignal.Reset(); - } + virtual void WaitForCopyScheduled()override final + { + m_CopyScheduledSignal.Wait(); + } - ID3D11Texture2D* GetStagingTex() { return m_pStagingTexture; } - private: - ThreadingTools::Signal m_BufferMappedSignal; - ThreadingTools::Signal m_CopyScheduledSignal; - CComPtr<ID3D11Texture2D> m_pStagingTexture; - }; + bool DbgIsCopyScheduled() + { + return m_CopyScheduledSignal.IsTriggered(); + } - struct TextureUploaderD3D11::InternalData + bool DbgIsMapped() { - struct PendingBufferOperation - { - enum Operation - { - Map, - Copy, - MapAndCache - }operation; - RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer; - CComPtr<ID3D11Resource> pd3d11NativeDstTexture; - UINT DstSubresource = 0; - - PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff) : - operation(op), - pUploadBuffer(pBuff) - {} - PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff, ID3D11Resource *pd3d11DstTex, UINT dstSubres) : - operation(op), - pUploadBuffer(pBuff), - pd3d11NativeDstTexture(pd3d11DstTex), - DstSubresource(dstSubres) - {} - }; + return m_BufferMappedSignal.IsTriggered(); + } - InternalData(IRenderDevice *pDevice) - { - RefCntAutoPtr<IRenderDeviceD3D11> pDeviceD3D11(pDevice, IID_RenderDeviceD3D11); - m_pd3d11NativeDevice = pDeviceD3D11->GetD3D11Device(); - } + void Reset() + { + m_pData = nullptr; + m_RowStride = 0; + m_DepthStride = 0; + m_BufferMappedSignal.Reset(); + m_CopyScheduledSignal.Reset(); + } - CComPtr<ID3D11Device> m_pd3d11NativeDevice; + ID3D11Texture2D* GetStagingTex() { return m_pStagingTexture; } +private: + ThreadingTools::Signal m_BufferMappedSignal; + ThreadingTools::Signal m_CopyScheduledSignal; + CComPtr<ID3D11Texture2D> m_pStagingTexture; +}; - void SwapMapQueues() - { - std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); - m_PendingOperations.swap(m_InWorkOperations); - } +} // namespace - void EnqueCopy(UploadBufferD3D11 *pUploadBuffer, ID3D11Resource *pd3d11DstTex, UINT dstSubres) - { - std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); - m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pd3d11DstTex, dstSubres); - } - void EnqueMap(UploadBufferD3D11 *pUploadBuffer, PendingBufferOperation::Operation Op) +struct TextureUploaderD3D11::InternalData +{ + struct PendingBufferOperation + { + enum Operation { - std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); - m_PendingOperations.emplace_back(Op, pUploadBuffer); - } + Map, + Copy, + MapAndCache + }operation; + RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer; + CComPtr<ID3D11Resource> pd3d11NativeDstTexture; + UINT DstSubresource = 0; + + PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff) : + operation(op), + pUploadBuffer(pBuff) + {} + PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff, ID3D11Resource *pd3d11DstTex, UINT dstSubres) : + operation(op), + pUploadBuffer(pBuff), + pd3d11NativeDstTexture(pd3d11DstTex), + DstSubresource(dstSubres) + {} + }; - std::mutex m_PendingOperationsMtx; - std::vector< PendingBufferOperation > m_PendingOperations; - std::vector< PendingBufferOperation > m_InWorkOperations; + InternalData(IRenderDevice *pDevice) + { + RefCntAutoPtr<IRenderDeviceD3D11> pDeviceD3D11(pDevice, IID_RenderDeviceD3D11); + m_pd3d11NativeDevice = pDeviceD3D11->GetD3D11Device(); + } - std::mutex m_UploadBuffCacheMtx; - std::unordered_map< UploadBufferDesc, std::deque< RefCntAutoPtr<UploadBufferD3D11> > > m_UploadBufferCache; - }; + CComPtr<ID3D11Device> m_pd3d11NativeDevice; - TextureUploaderD3D11::TextureUploaderD3D11(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) : - TextureUploaderBase(pRefCounters, pDevice, Desc), - m_pInternalData(new InternalData(pDevice)) + void SwapMapQueues() { + std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); + m_PendingOperations.swap(m_InWorkOperations); } - TextureUploaderD3D11::~TextureUploaderD3D11() + void EnqueCopy(UploadBufferD3D11 *pUploadBuffer, ID3D11Resource *pd3d11DstTex, UINT dstSubres) + { + std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); + m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pd3d11DstTex, dstSubres); + } + + void EnqueMap(UploadBufferD3D11 *pUploadBuffer, PendingBufferOperation::Operation Op) + { + std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); + m_PendingOperations.emplace_back(Op, pUploadBuffer); + } + + std::mutex m_PendingOperationsMtx; + std::vector< PendingBufferOperation > m_PendingOperations; + std::vector< PendingBufferOperation > m_InWorkOperations; + + std::mutex m_UploadBuffCacheMtx; + std::unordered_map< UploadBufferDesc, std::deque< RefCntAutoPtr<UploadBufferD3D11> > > m_UploadBufferCache; +}; + +TextureUploaderD3D11::TextureUploaderD3D11(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) : + TextureUploaderBase(pRefCounters, pDevice, Desc), + m_pInternalData(new InternalData(pDevice)) +{ +} + +TextureUploaderD3D11::~TextureUploaderD3D11() +{ + for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache) { - for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache) + if (BuffQueueIt.second.size()) { - if (BuffQueueIt.second.size()) - { - const auto &desc = BuffQueueIt.first; - auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format); - LOG_INFO_MESSAGE("TextureUploaderD3D11: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " staging texture(s) "); - } + const auto &desc = BuffQueueIt.first; + auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format); + LOG_INFO_MESSAGE("TextureUploaderD3D11: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " staging texture(s) "); } } +} - void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext) +void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext) +{ + m_pInternalData->SwapMapQueues(); + if (!m_pInternalData->m_InWorkOperations.empty()) { - m_pInternalData->SwapMapQueues(); - if (!m_pInternalData->m_InWorkOperations.empty()) + RefCntAutoPtr<IDeviceContextD3D11> pContextD3D11(pContext, IID_DeviceContextD3D11); + auto* pd3d11NativeCtx = pContextD3D11->GetD3D11DeviceContext(); + + for (auto &OperationInfo : m_pInternalData->m_InWorkOperations) { - RefCntAutoPtr<IDeviceContextD3D11> pContextD3D11(pContext, IID_DeviceContextD3D11); - auto* pd3d11NativeCtx = pContextD3D11->GetD3D11DeviceContext(); + auto &pBuffer = OperationInfo.pUploadBuffer; - for (auto &OperationInfo : m_pInternalData->m_InWorkOperations) + switch (OperationInfo.operation) { - auto &pBuffer = OperationInfo.pUploadBuffer; - - switch (OperationInfo.operation) + case InternalData::PendingBufferOperation::MapAndCache: + case InternalData::PendingBufferOperation::Map: { - case InternalData::PendingBufferOperation::MapAndCache: - case InternalData::PendingBufferOperation::Map: + D3D11_MAPPED_SUBRESOURCE MappedData; + auto hr = pd3d11NativeCtx->Map(pBuffer->GetStagingTex(), 0, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &MappedData); + if (SUCCEEDED(hr)) + { + pBuffer->SetDataPtr(MappedData.pData, MappedData.RowPitch, MappedData.DepthPitch); + pBuffer->SignalMapped(); + if (OperationInfo.operation == InternalData::PendingBufferOperation::MapAndCache) + { + std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); + auto &Cache = m_pInternalData->m_UploadBufferCache; + Cache[pBuffer->GetDesc()].emplace_back( std::move(pBuffer) ); + } + } + else { - D3D11_MAPPED_SUBRESOURCE MappedData; - auto hr = pd3d11NativeCtx->Map(pBuffer->GetStagingTex(), 0, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &MappedData); - if (SUCCEEDED(hr)) + if (hr == DXGI_ERROR_WAS_STILL_DRAWING) { - pBuffer->SetDataPtr(MappedData.pData, MappedData.RowPitch, MappedData.DepthPitch); - pBuffer->SignalMapped(); - if (OperationInfo.operation == InternalData::PendingBufferOperation::MapAndCache) - { - std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); - auto &Cache = m_pInternalData->m_UploadBufferCache; - Cache[pBuffer->GetDesc()].emplace_back( std::move(pBuffer) ); - } + m_pInternalData->EnqueMap(pBuffer, OperationInfo.operation); } else { - if (hr == DXGI_ERROR_WAS_STILL_DRAWING) - { - m_pInternalData->EnqueMap(pBuffer, OperationInfo.operation); - } - else - { - LOG_ERROR("Unknown DX error when mapping staging texture: ", hr); - } + LOG_ERROR("Unknown DX error when mapping staging texture: ", hr); } } - break; + } + break; - case InternalData::PendingBufferOperation::Copy: - { - VERIFY(pBuffer->DbgIsMapped(), "Upload buffer must be copied only after it has been mapped"); - pd3d11NativeCtx->Unmap(pBuffer->GetStagingTex(), 0); - pd3d11NativeCtx->CopySubresourceRegion(OperationInfo.pd3d11NativeDstTexture, OperationInfo.DstSubresource, - 0, 0, 0, // DstX, DstY, DstZ - pBuffer->GetStagingTex(), - 0, // SrcSubresource - nullptr // pSrcBox - ); - pBuffer->SignalCopyScheduled(); - } - break; + case InternalData::PendingBufferOperation::Copy: + { + VERIFY(pBuffer->DbgIsMapped(), "Upload buffer must be copied only after it has been mapped"); + pd3d11NativeCtx->Unmap(pBuffer->GetStagingTex(), 0); + pd3d11NativeCtx->CopySubresourceRegion(OperationInfo.pd3d11NativeDstTexture, OperationInfo.DstSubresource, + 0, 0, 0, // DstX, DstY, DstZ + pBuffer->GetStagingTex(), + 0, // SrcSubresource + nullptr // pSrcBox + ); + pBuffer->SignalCopyScheduled(); } + break; } - m_pInternalData->m_InWorkOperations.clear(); } + m_pInternalData->m_InWorkOperations.clear(); } +} - void TextureUploaderD3D11::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer) - { - *ppBuffer = nullptr; +void TextureUploaderD3D11::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer) +{ + *ppBuffer = nullptr; + { + std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); + auto &Cache = m_pInternalData->m_UploadBufferCache; + if (!Cache.empty()) { - std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); - auto &Cache = m_pInternalData->m_UploadBufferCache; - if (!Cache.empty()) + auto DequeIt = Cache.find(Desc); + if (DequeIt != Cache.end()) { - auto DequeIt = Cache.find(Desc); - if (DequeIt != Cache.end()) + auto &Deque = DequeIt->second; + if (!Deque.empty()) { - auto &Deque = DequeIt->second; - if (!Deque.empty()) - { - *ppBuffer = Deque.front().Detach(); - Deque.pop_front(); - } + *ppBuffer = Deque.front().Detach(); + Deque.pop_front(); } } } + } - if( *ppBuffer == nullptr ) + if( *ppBuffer == nullptr ) + { + D3D11_TEXTURE2D_DESC StagingTexDesc = { - D3D11_TEXTURE2D_DESC StagingTexDesc = - { - static_cast<UINT>(Desc.Width), - static_cast<UINT>(Desc.Height), - 1, // UINT MipLevels; - 1, // UINT ArraySize; - TexFormatToDXGI_Format(Desc.Format), - {1, 0}, // DXGI_SAMPLE_DESC SampleDesc; - D3D11_USAGE_STAGING, - 0, // UINT BindFlags; - D3D11_CPU_ACCESS_WRITE, // UINT CPUAccessFlags; - 0, // UINT MiscFlags; - }; - - CComPtr<ID3D11Texture2D> pStagingTex; - HRESULT hr = m_pInternalData->m_pd3d11NativeDevice->CreateTexture2D(&StagingTexDesc, nullptr, &pStagingTex); - if (FAILED(hr)) - { - LOG_ERROR_MESSAGE("Failed to allocate staging D3D11 texture"); - return; - } - - LOG_INFO_MESSAGE("TextureUploaderD3D11: created ", Desc.Width, 'x', Desc.Height, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " staging texture"); + static_cast<UINT>(Desc.Width), + static_cast<UINT>(Desc.Height), + 1, // UINT MipLevels; + 1, // UINT ArraySize; + TexFormatToDXGI_Format(Desc.Format), + {1, 0}, // DXGI_SAMPLE_DESC SampleDesc; + D3D11_USAGE_STAGING, + 0, // UINT BindFlags; + D3D11_CPU_ACCESS_WRITE, // UINT CPUAccessFlags; + 0, // UINT MiscFlags; + }; - RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer(MakeNewRCObj<UploadBufferD3D11>()(Desc, pStagingTex)); - m_pInternalData->EnqueMap(pUploadBuffer, InternalData::PendingBufferOperation::Map); - pUploadBuffer->WaitForMap(); - *ppBuffer = pUploadBuffer.Detach(); + CComPtr<ID3D11Texture2D> pStagingTex; + HRESULT hr = m_pInternalData->m_pd3d11NativeDevice->CreateTexture2D(&StagingTexDesc, nullptr, &pStagingTex); + if (FAILED(hr)) + { + LOG_ERROR_MESSAGE("Failed to allocate staging D3D11 texture"); + return; } - } - void TextureUploaderD3D11::ScheduleGPUCopy(Diligent::ITexture *pDstTexture, - Uint32 ArraySlice, - Uint32 MipLevel, - IUploadBuffer *pUploadBuffer) - { - auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(pUploadBuffer); - RefCntAutoPtr<ITextureD3D11> pDstTexD3D11(pDstTexture, IID_TextureD3D11); - auto *pd3d11NativeDstTex = pDstTexD3D11->GetD3D11Texture(); - const auto &DstTexDesc = pDstTexture->GetDesc(); - UINT DstSubres = D3D11CalcSubresource(static_cast<UINT>(MipLevel), static_cast<UINT>(ArraySlice), static_cast<UINT>(DstTexDesc.MipLevels)); - m_pInternalData->EnqueCopy(pUploadBufferD3D11, pd3d11NativeDstTex, DstSubres); + LOG_INFO_MESSAGE("TextureUploaderD3D11: created ", Desc.Width, 'x', Desc.Height, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " staging texture"); + + RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer(MakeNewRCObj<UploadBufferD3D11>()(Desc, pStagingTex)); + m_pInternalData->EnqueMap(pUploadBuffer, InternalData::PendingBufferOperation::Map); + pUploadBuffer->WaitForMap(); + *ppBuffer = pUploadBuffer.Detach(); } +} - void TextureUploaderD3D11::RecycleBuffer(IUploadBuffer *pUploadBuffer) - { - auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(pUploadBuffer); - VERIFY(pUploadBufferD3D11->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU"); - pUploadBufferD3D11->Reset(); +void TextureUploaderD3D11::ScheduleGPUCopy(Diligent::ITexture *pDstTexture, + Uint32 ArraySlice, + Uint32 MipLevel, + IUploadBuffer *pUploadBuffer) +{ + auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(pUploadBuffer); + RefCntAutoPtr<ITextureD3D11> pDstTexD3D11(pDstTexture, IID_TextureD3D11); + auto *pd3d11NativeDstTex = pDstTexD3D11->GetD3D11Texture(); + const auto &DstTexDesc = pDstTexture->GetDesc(); + UINT DstSubres = D3D11CalcSubresource(static_cast<UINT>(MipLevel), static_cast<UINT>(ArraySlice), static_cast<UINT>(DstTexDesc.MipLevels)); + m_pInternalData->EnqueCopy(pUploadBufferD3D11, pd3d11NativeDstTex, DstSubres); +} + +void TextureUploaderD3D11::RecycleBuffer(IUploadBuffer *pUploadBuffer) +{ + auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(pUploadBuffer); + VERIFY(pUploadBufferD3D11->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU"); + pUploadBufferD3D11->Reset(); - m_pInternalData->EnqueMap(pUploadBufferD3D11, InternalData::PendingBufferOperation::MapAndCache); - } -}
\ No newline at end of file + m_pInternalData->EnqueMap(pUploadBufferD3D11, InternalData::PendingBufferOperation::MapAndCache); +} + +} // namespace Diligent diff --git a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp index fa954d93..5b5f2f91 100644 --- a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp +++ b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp @@ -32,243 +32,250 @@ namespace Diligent { - class UploadBufferGL : public UploadBufferBase +namespace +{ + +class UploadBufferGL : public UploadBufferBase +{ +public: + UploadBufferGL(IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc) : + UploadBufferBase(pRefCounters, Desc) + {} + + void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride) { - public: - UploadBufferGL(IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc) : - UploadBufferBase(pRefCounters, Desc) - {} + m_pData = pData; + m_RowStride = RowStride; + m_DepthStride = DepthStride; + } - void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride) - { - m_pData = pData; - m_RowStride = RowStride; - m_DepthStride = DepthStride; - } + // http://en.cppreference.com/w/cpp/thread/condition_variable + void WaitForMap() + { + m_BufferMappedSignal.Wait(); + } - // http://en.cppreference.com/w/cpp/thread/condition_variable - void WaitForMap() - { - m_BufferMappedSignal.Wait(); - } + void SignalMapped() + { + m_BufferMappedSignal.Trigger(); + } - void SignalMapped() - { - m_BufferMappedSignal.Trigger(); - } + void SignalCopyScheduled() + { + m_CopyScheduledSignal.Trigger(); + } - void SignalCopyScheduled() - { - m_CopyScheduledSignal.Trigger(); - } + virtual void WaitForCopyScheduled()override final + { + m_CopyScheduledSignal.Wait(); + } - virtual void WaitForCopyScheduled()override final - { - m_CopyScheduledSignal.Wait(); - } + bool DbgIsCopyScheduled()const { return m_CopyScheduledSignal.IsTriggered(); } - bool DbgIsCopyScheduled()const { return m_CopyScheduledSignal.IsTriggered(); } + void Reset() + { + m_BufferMappedSignal.Reset(); + m_CopyScheduledSignal.Reset(); + m_pData = nullptr; + // Do not zero out strides + } - void Reset() - { - m_BufferMappedSignal.Reset(); - m_CopyScheduledSignal.Reset(); - m_pData = nullptr; - // Do not zero out strides - } +private: + friend class TextureUploaderGL; + ThreadingTools::Signal m_BufferMappedSignal; + ThreadingTools::Signal m_CopyScheduledSignal; + RefCntAutoPtr<IBuffer> m_pStagingBuffer; +}; - private: - friend class TextureUploaderGL; - ThreadingTools::Signal m_BufferMappedSignal; - ThreadingTools::Signal m_CopyScheduledSignal; - RefCntAutoPtr<IBuffer> m_pStagingBuffer; - }; +} // namespace - struct TextureUploaderGL::InternalData + +struct TextureUploaderGL::InternalData +{ + void SwapMapQueues() { - void SwapMapQueues() - { - std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); - m_PendingOperations.swap(m_InWorkOperations); - } + std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); + m_PendingOperations.swap(m_InWorkOperations); + } - void EnqueCopy(UploadBufferGL *pUploadBuffer, ITexture *pDstTexture, Uint32 dstSlice, Uint32 dstMip) - { - std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); - m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pDstTexture, dstSlice, dstMip); - } + void EnqueCopy(UploadBufferGL *pUploadBuffer, ITexture *pDstTexture, Uint32 dstSlice, Uint32 dstMip) + { + std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); + m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pDstTexture, dstSlice, dstMip); + } - void EnqueMap(UploadBufferGL *pUploadBuffer) - { - std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); - m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Map, pUploadBuffer); - } + void EnqueMap(UploadBufferGL *pUploadBuffer) + { + std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx); + m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Map, pUploadBuffer); + } - struct PendingBufferOperation + struct PendingBufferOperation + { + enum Operation { - enum Operation - { - Map, - Copy - }operation; - RefCntAutoPtr<UploadBufferGL> pUploadBuffer; - RefCntAutoPtr<ITexture> pDstTexture; - Uint32 DstSlice = 0; - Uint32 DstMip = 0; - - PendingBufferOperation(Operation op, UploadBufferGL* pBuff) : - operation(op), - pUploadBuffer(pBuff) - {} - PendingBufferOperation(Operation op, UploadBufferGL* pBuff, ITexture *pDstTex, Uint32 dstSlice, Uint32 dstMip) : - operation(op), - pUploadBuffer(pBuff), - pDstTexture(pDstTex), - DstSlice(dstSlice), - DstMip(dstMip) - {} - }; - - std::mutex m_PendingOperationsMtx; - std::vector< PendingBufferOperation > m_PendingOperations; - std::vector< PendingBufferOperation > m_InWorkOperations; - - std::mutex m_UploadBuffCacheMtx; - std::unordered_map< UploadBufferDesc, std::deque<RefCntAutoPtr<UploadBufferGL> > > m_UploadBufferCache; + Map, + Copy + }operation; + RefCntAutoPtr<UploadBufferGL> pUploadBuffer; + RefCntAutoPtr<ITexture> pDstTexture; + Uint32 DstSlice = 0; + Uint32 DstMip = 0; + + PendingBufferOperation(Operation op, UploadBufferGL* pBuff) : + operation(op), + pUploadBuffer(pBuff) + {} + PendingBufferOperation(Operation op, UploadBufferGL* pBuff, ITexture *pDstTex, Uint32 dstSlice, Uint32 dstMip) : + operation(op), + pUploadBuffer(pBuff), + pDstTexture(pDstTex), + DstSlice(dstSlice), + DstMip(dstMip) + {} }; - TextureUploaderGL::TextureUploaderGL(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) : - TextureUploaderBase(pRefCounters, pDevice, Desc), - m_pInternalData(new InternalData()) - { - } + std::mutex m_PendingOperationsMtx; + std::vector< PendingBufferOperation > m_PendingOperations; + std::vector< PendingBufferOperation > m_InWorkOperations; + + std::mutex m_UploadBuffCacheMtx; + std::unordered_map< UploadBufferDesc, std::deque<RefCntAutoPtr<UploadBufferGL> > > m_UploadBufferCache; +}; + +TextureUploaderGL::TextureUploaderGL(IReferenceCounters *pRefCounters, IRenderDevice *pDevice, const TextureUploaderDesc Desc) : + TextureUploaderBase(pRefCounters, pDevice, Desc), + m_pInternalData(new InternalData()) +{ +} - TextureUploaderGL::~TextureUploaderGL() +TextureUploaderGL::~TextureUploaderGL() +{ + for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache) { - for (auto BuffQueueIt : m_pInternalData->m_UploadBufferCache) + if (BuffQueueIt.second.size()) { - if (BuffQueueIt.second.size()) - { - const auto &desc = BuffQueueIt.first; - auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format); - LOG_INFO_MESSAGE("TextureUploaderGL: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " upload buffer(s) "); - } + const auto &desc = BuffQueueIt.first; + auto &FmtInfo = m_pDevice->GetTextureFormatInfo(desc.Format); + LOG_INFO_MESSAGE("TextureUploaderGL: releasing ", BuffQueueIt.second.size(), ' ', desc.Width, 'x', desc.Height, 'x', desc.Depth, ' ', FmtInfo.Name, " upload buffer(s) "); } } +} - void TextureUploaderGL::RenderThreadUpdate(IDeviceContext *pContext) +void TextureUploaderGL::RenderThreadUpdate(IDeviceContext *pContext) +{ + m_pInternalData->SwapMapQueues(); + if (!m_pInternalData->m_InWorkOperations.empty()) { - m_pInternalData->SwapMapQueues(); - if (!m_pInternalData->m_InWorkOperations.empty()) + for (auto &OperationInfo : m_pInternalData->m_InWorkOperations) { - for (auto &OperationInfo : m_pInternalData->m_InWorkOperations) - { - auto &pBuffer = OperationInfo.pUploadBuffer; + auto &pBuffer = OperationInfo.pUploadBuffer; - switch (OperationInfo.operation) + switch (OperationInfo.operation) + { + case InternalData::PendingBufferOperation::Map: { - case InternalData::PendingBufferOperation::Map: + Uint32 RowStride = static_cast<Uint32>(pBuffer->GetRowStride()); + if (pBuffer->m_pStagingBuffer == nullptr) { - Uint32 RowStride = static_cast<Uint32>(pBuffer->GetRowStride()); - if (pBuffer->m_pStagingBuffer == nullptr) - { - const auto &Desc = pBuffer->GetDesc(); - BufferDesc BuffDesc; - BuffDesc.Name = "Staging buffer for UploadBufferGL"; - BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE; - BuffDesc.Usage = USAGE_STAGING; - - const auto &TexFmtInfo = m_pDevice->GetTextureFormatInfo(Desc.Format); - RowStride = Desc.Width * Uint32{TexFmtInfo.ComponentSize} * Uint32{TexFmtInfo.NumComponents}; - const Uint32 Alignment = 16; - const Uint32 AlignmentMask = Alignment-1; - RowStride = (RowStride + AlignmentMask) & (~AlignmentMask); - - BuffDesc.uiSizeInBytes = Desc.Height * RowStride; - RefCntAutoPtr<IBuffer> pStagingBuffer; - m_pDevice->CreateBuffer(BuffDesc, nullptr, &pBuffer->m_pStagingBuffer); - } - - PVoid CpuAddress = nullptr; - pContext->MapBuffer(pBuffer->m_pStagingBuffer, MAP_WRITE, MAP_FLAG_DISCARD, CpuAddress); - pBuffer->SetDataPtr(CpuAddress, RowStride, 0); - - pBuffer->SignalMapped(); + const auto &Desc = pBuffer->GetDesc(); + BufferDesc BuffDesc; + BuffDesc.Name = "Staging buffer for UploadBufferGL"; + BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE; + BuffDesc.Usage = USAGE_STAGING; + + const auto &TexFmtInfo = m_pDevice->GetTextureFormatInfo(Desc.Format); + RowStride = Desc.Width * Uint32{TexFmtInfo.ComponentSize} * Uint32{TexFmtInfo.NumComponents}; + const Uint32 Alignment = 16; + const Uint32 AlignmentMask = Alignment-1; + RowStride = (RowStride + AlignmentMask) & (~AlignmentMask); + + BuffDesc.uiSizeInBytes = Desc.Height * RowStride; + RefCntAutoPtr<IBuffer> pStagingBuffer; + m_pDevice->CreateBuffer(BuffDesc, nullptr, &pBuffer->m_pStagingBuffer); } - break; - case InternalData::PendingBufferOperation::Copy: - { - pContext->UnmapBuffer(pBuffer->m_pStagingBuffer, MAP_WRITE); - TextureSubResData SubResData(pBuffer->m_pStagingBuffer, 0, static_cast<Uint32>(pBuffer->GetRowStride())); - Box DstBox; - const auto &TexDesc = OperationInfo.pDstTexture->GetDesc(); - DstBox.MaxX = TexDesc.Width; - DstBox.MaxY = TexDesc.Height; - pContext->UpdateTexture(OperationInfo.pDstTexture, OperationInfo.DstMip, OperationInfo.DstSlice, DstBox, - SubResData, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pBuffer->SignalCopyScheduled(); - } - break; + PVoid CpuAddress = nullptr; + pContext->MapBuffer(pBuffer->m_pStagingBuffer, MAP_WRITE, MAP_FLAG_DISCARD, CpuAddress); + pBuffer->SetDataPtr(CpuAddress, RowStride, 0); + + pBuffer->SignalMapped(); } + break; + + case InternalData::PendingBufferOperation::Copy: + { + pContext->UnmapBuffer(pBuffer->m_pStagingBuffer, MAP_WRITE); + TextureSubResData SubResData(pBuffer->m_pStagingBuffer, 0, static_cast<Uint32>(pBuffer->GetRowStride())); + Box DstBox; + const auto &TexDesc = OperationInfo.pDstTexture->GetDesc(); + DstBox.MaxX = TexDesc.Width; + DstBox.MaxY = TexDesc.Height; + pContext->UpdateTexture(OperationInfo.pDstTexture, OperationInfo.DstMip, OperationInfo.DstSlice, DstBox, + SubResData, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pBuffer->SignalCopyScheduled(); + } + break; } - m_pInternalData->m_InWorkOperations.clear(); } + m_pInternalData->m_InWorkOperations.clear(); } +} - void TextureUploaderGL::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer) - { - *ppBuffer = nullptr; - RefCntAutoPtr<UploadBufferGL> pUploadBuffer; +void TextureUploaderGL::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool IsRenderThread, IUploadBuffer **ppBuffer) +{ + *ppBuffer = nullptr; + RefCntAutoPtr<UploadBufferGL> pUploadBuffer; + { + std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); + auto &Cache = m_pInternalData->m_UploadBufferCache; + if (!Cache.empty()) { - std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); - auto &Cache = m_pInternalData->m_UploadBufferCache; - if (!Cache.empty()) + auto DequeIt = Cache.find(Desc); + if (DequeIt != Cache.end()) { - auto DequeIt = Cache.find(Desc); - if (DequeIt != Cache.end()) + auto &Deque = DequeIt->second; + if (!Deque.empty()) { - auto &Deque = DequeIt->second; - if (!Deque.empty()) - { - pUploadBuffer.Attach(Deque.front().Detach()); - Deque.pop_front(); - } + pUploadBuffer.Attach(Deque.front().Detach()); + Deque.pop_front(); } } } - - if( !pUploadBuffer ) - { - pUploadBuffer = MakeNewRCObj<UploadBufferGL>()(Desc); - LOG_INFO_MESSAGE("TextureUploaderGL: created upload buffer for ", Desc.Width, 'x', Desc.Height, 'x', Desc.Depth, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " texture"); - } - - m_pInternalData->EnqueMap(pUploadBuffer); - pUploadBuffer->WaitForMap(); - *ppBuffer = pUploadBuffer.Detach(); } - void TextureUploaderGL::ScheduleGPUCopy(ITexture *pDstTexture, - Uint32 ArraySlice, - Uint32 MipLevel, - IUploadBuffer *pUploadBuffer) + if( !pUploadBuffer ) { - auto *pUploadBufferGL = ValidatedCast<UploadBufferGL>(pUploadBuffer); - m_pInternalData->EnqueCopy(pUploadBufferGL, pDstTexture, ArraySlice, MipLevel); + pUploadBuffer = MakeNewRCObj<UploadBufferGL>()(Desc); + LOG_INFO_MESSAGE("TextureUploaderGL: created upload buffer for ", Desc.Width, 'x', Desc.Height, 'x', Desc.Depth, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " texture"); } - void TextureUploaderGL::RecycleBuffer(IUploadBuffer *pUploadBuffer) - { - auto *pUploadBufferGL = ValidatedCast<UploadBufferGL>(pUploadBuffer); - VERIFY(pUploadBufferGL->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU"); - pUploadBufferGL->Reset(); + m_pInternalData->EnqueMap(pUploadBuffer); + pUploadBuffer->WaitForMap(); + *ppBuffer = pUploadBuffer.Detach(); +} - std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); - auto &Cache = m_pInternalData->m_UploadBufferCache; - auto &Deque = Cache[pUploadBufferGL->GetDesc()]; - Deque.emplace_back( pUploadBufferGL ); - } +void TextureUploaderGL::ScheduleGPUCopy(ITexture *pDstTexture, + Uint32 ArraySlice, + Uint32 MipLevel, + IUploadBuffer *pUploadBuffer) +{ + auto *pUploadBufferGL = ValidatedCast<UploadBufferGL>(pUploadBuffer); + m_pInternalData->EnqueCopy(pUploadBufferGL, pDstTexture, ArraySlice, MipLevel); } + +void TextureUploaderGL::RecycleBuffer(IUploadBuffer *pUploadBuffer) +{ + auto *pUploadBufferGL = ValidatedCast<UploadBufferGL>(pUploadBuffer); + VERIFY(pUploadBufferGL->DbgIsCopyScheduled(), "Upload buffer must be recycled only after copy operation has been scheduled on the GPU"); + pUploadBufferGL->Reset(); + + std::lock_guard<std::mutex> CacheLock(m_pInternalData->m_UploadBuffCacheMtx); + auto &Cache = m_pInternalData->m_UploadBufferCache; + auto &Deque = Cache[pUploadBufferGL->GetDesc()]; + Deque.emplace_back( pUploadBufferGL ); +} + +} // namespace Diligent |
