summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsTools
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-04-19 15:25:42 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-04-19 15:25:42 +0000
commit27b1effc36ffd228123ded18401f7dc5c34b6f78 (patch)
tree7da0c34d974e15526170b54b18132e0ce1cb7d62 /Graphics/GraphicsTools
parentFixed issues with multi-mip level staging resource in Vk and D3D12 back-ends (diff)
downloadDiligentCore-27b1effc36ffd228123ded18401f7dc5c34b6f78.tar.gz
DiligentCore-27b1effc36ffd228123ded18401f7dc5c34b6f78.zip
Updated texture uploader to support multi-mip resources
Diffstat (limited to 'Graphics/GraphicsTools')
-rw-r--r--Graphics/GraphicsTools/include/TextureUploader.h14
-rw-r--r--Graphics/GraphicsTools/include/TextureUploaderBase.h35
-rw-r--r--Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp145
-rw-r--r--Graphics/GraphicsTools/src/TextureUploaderD3D12_Vk.cpp71
-rw-r--r--Graphics/GraphicsTools/src/TextureUploaderGL.cpp112
5 files changed, 256 insertions, 121 deletions
diff --git a/Graphics/GraphicsTools/include/TextureUploader.h b/Graphics/GraphicsTools/include/TextureUploader.h
index dbc4383f..059e32c6 100644
--- a/Graphics/GraphicsTools/include/TextureUploader.h
+++ b/Graphics/GraphicsTools/include/TextureUploader.h
@@ -30,10 +30,12 @@ namespace Diligent
{
struct UploadBufferDesc
{
- Uint32 Width = 0;
- Uint32 Height = 0;
- Uint32 Depth = 1;
- TEXTURE_FORMAT Format = TEX_FORMAT_UNKNOWN;
+ Uint32 Width = 0;
+ Uint32 Height = 0;
+ Uint32 Depth = 1;
+ Uint32 MipLevels = 1;
+ Uint32 ArraySize = 1;
+ TEXTURE_FORMAT Format = TEX_FORMAT_UNKNOWN;
bool operator == (const UploadBufferDesc &rhs) const
{
@@ -48,9 +50,7 @@ namespace Diligent
{
public:
virtual void WaitForCopyScheduled() = 0;
- virtual void* GetDataPtr() = 0;
- virtual size_t GetRowStride() const = 0;
- virtual size_t GetDepthStride()const = 0;
+ virtual MappedTextureSubresource GetMappedData(Uint32 Mip, Uint32 Slice) = 0;
virtual const UploadBufferDesc& GetDesc()const = 0;
};
diff --git a/Graphics/GraphicsTools/include/TextureUploaderBase.h b/Graphics/GraphicsTools/include/TextureUploaderBase.h
index d1c460a1..5d3c489b 100644
--- a/Graphics/GraphicsTools/include/TextureUploaderBase.h
+++ b/Graphics/GraphicsTools/include/TextureUploaderBase.h
@@ -23,6 +23,8 @@
#pragma once
+#include <vector>
+
#include "TextureUploader.h"
#include "../../../Common/interface/ObjectBase.h"
#include "../../../Common/interface/HashUtils.h"
@@ -47,20 +49,39 @@ namespace Diligent
public:
UploadBufferBase(IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc) :
ObjectBase<IUploadBuffer>(pRefCounters),
- m_Desc(Desc)
+ m_Desc(Desc),
+ m_MappedData(m_Desc.ArraySize * m_Desc.MipLevels)
{
}
- virtual void* GetDataPtr() override final { return m_pData; }
- virtual size_t GetRowStride() const override final{ return m_RowStride; }
- virtual size_t GetDepthStride()const override final{ return m_DepthStride; }
+ virtual MappedTextureSubresource GetMappedData(Uint32 Mip, Uint32 Slice)override final
+ {
+ VERIFY_EXPR(Mip < m_Desc.MipLevels && Slice < m_Desc.ArraySize);
+ return m_MappedData[m_Desc.MipLevels * Slice + Mip];
+ }
virtual const UploadBufferDesc& GetDesc()const override final{ return m_Desc; }
+ void SetMappedData(Uint32 Mip, Uint32 Slice, const MappedTextureSubresource& MappedData)
+ {
+ VERIFY_EXPR(Mip < m_Desc.MipLevels && Slice < m_Desc.ArraySize);
+ m_MappedData[m_Desc.MipLevels * Slice + Mip] = MappedData;
+ }
+
+ bool IsMapped(Uint32 Mip, Uint32 Slice)const
+ {
+ VERIFY_EXPR(Mip < m_Desc.MipLevels && Slice < m_Desc.ArraySize);
+ return m_MappedData[m_Desc.MipLevels * Slice + Mip].pData != nullptr;
+ }
+
+ void Reset()
+ {
+ for (auto& MappedData : m_MappedData)
+ MappedData = MappedTextureSubresource{};
+ }
+
protected:
const UploadBufferDesc m_Desc;
- void* m_pData = 0;
- size_t m_RowStride = 0;
- size_t m_DepthStride = 0;
+ std::vector<MappedTextureSubresource> m_MappedData;
};
class TextureUploaderBase : public ObjectBase<ITextureUploader>
diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp
index 3d21df48..9b3ee9a3 100644
--- a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp
+++ b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp
@@ -36,6 +36,7 @@
#include "TextureD3D11.h"
#include "DXGITypeConversions.h"
#include "ThreadSignal.h"
+#include "GraphicsAccessories.h"
namespace Diligent
{
@@ -47,22 +48,13 @@ namespace
class UploadBufferD3D11 : public UploadBufferBase
{
public:
- UploadBufferD3D11(Diligent::IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc, ID3D11Texture2D *pStagingTexture) :
+ UploadBufferD3D11(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;
}
// http://en.cppreference.com/w/cpp/thread/condition_variable
@@ -98,11 +90,9 @@ public:
void Reset()
{
- m_pData = nullptr;
- m_RowStride = 0;
- m_DepthStride = 0;
m_BufferMappedSignal.Reset();
m_CopyScheduledSignal.Reset();
+ UploadBufferBase::Reset();
}
ID3D11Texture2D* GetStagingTex() { return m_pStagingTexture; }
@@ -127,21 +117,25 @@ struct TextureUploaderD3D11::InternalData
}operation;
RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer;
CComPtr<ID3D11Resource> pd3d11NativeDstTexture;
- UINT DstSubresource = 0;
+ Uint32 DstMip = 0;
+ Uint32 DstSlice = 0;
+ Uint32 DstMipLevels = 0;
PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff) :
- operation(op),
+ operation (op),
pUploadBuffer(pBuff)
{}
- PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff, ID3D11Resource *pd3d11DstTex, UINT dstSubres) :
- operation(op),
- pUploadBuffer(pBuff),
+ PendingBufferOperation(Operation op, UploadBufferD3D11* pBuff, ID3D11Resource* pd3d11DstTex, Uint32 Mip, Uint32 Slice, Uint32 MipLevels) :
+ operation (op),
+ pUploadBuffer (pBuff),
pd3d11NativeDstTexture(pd3d11DstTex),
- DstSubresource(dstSubres)
+ DstMip (Mip),
+ DstSlice (Slice),
+ DstMipLevels (MipLevels)
{}
};
- InternalData(IRenderDevice *pDevice)
+ InternalData(IRenderDevice* pDevice)
{
RefCntAutoPtr<IRenderDeviceD3D11> pDeviceD3D11(pDevice, IID_RenderDeviceD3D11);
m_pd3d11NativeDevice = pDeviceD3D11->GetD3D11Device();
@@ -155,10 +149,10 @@ struct TextureUploaderD3D11::InternalData
m_PendingOperations.swap(m_InWorkOperations);
}
- void EnqueCopy(UploadBufferD3D11 *pUploadBuffer, ID3D11Resource *pd3d11DstTex, UINT dstSubres)
+ void EnqueCopy(UploadBufferD3D11* pUploadBuffer, ID3D11Resource* pd3d11DstTex, Uint32 Mip, Uint32 Slice, Uint32 MipLevels)
{
std::lock_guard<std::mutex> QueueLock(m_PendingOperationsMtx);
- m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pd3d11DstTex, dstSubres);
+ m_PendingOperations.emplace_back(PendingBufferOperation::Operation::Copy, pUploadBuffer, pd3d11DstTex, Mip, Slice, MipLevels);
}
void EnqueMap(UploadBufferD3D11 *pUploadBuffer, PendingBufferOperation::Operation Op)
@@ -203,7 +197,7 @@ TextureUploaderD3D11::~TextureUploaderD3D11()
}
}
-void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext)
+void TextureUploaderD3D11::RenderThreadUpdate(IDeviceContext* pContext)
{
m_pInternalData->SwapMapQueues();
if (!m_pInternalData->m_InWorkOperations.empty())
@@ -213,18 +207,45 @@ void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext
for (auto &OperationInfo : m_pInternalData->m_InWorkOperations)
{
- auto &pBuffer = OperationInfo.pUploadBuffer;
+ auto& pBuffer = OperationInfo.pUploadBuffer;
+ const auto& UploadBuffDesc = pBuffer->GetDesc();
switch (OperationInfo.operation)
{
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))
+ bool AllMapped = true;
+ for (Uint32 Slice = 0; Slice < UploadBuffDesc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < UploadBuffDesc.MipLevels; ++Mip)
+ {
+ if (!pBuffer->IsMapped(Mip, Slice))
+ {
+ D3D11_MAPPED_SUBRESOURCE MappedData;
+ UINT Subres = D3D11CalcSubresource(static_cast<UINT>(Mip), static_cast<UINT>(Slice), static_cast<UINT>(UploadBuffDesc.MipLevels));
+ auto hr = pd3d11NativeCtx->Map(pBuffer->GetStagingTex(), Subres, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &MappedData);
+ if (SUCCEEDED(hr))
+ {
+ pBuffer->SetMappedData(Mip, Slice, MappedTextureSubresource{MappedData.pData, MappedData.RowPitch, MappedData.DepthPitch});
+ }
+ else
+ {
+ if (hr == DXGI_ERROR_WAS_STILL_DRAWING)
+ {
+ AllMapped = false;
+ }
+ else
+ {
+ LOG_ERROR("Unknown DX error when mapping staging texture: ", hr);
+ }
+ }
+ }
+ }
+ }
+
+ if (AllMapped)
{
- pBuffer->SetDataPtr(MappedData.pData, MappedData.RowPitch, MappedData.DepthPitch);
pBuffer->SignalMapped();
if (OperationInfo.operation == InternalData::PendingBufferOperation::MapAndCache)
{
@@ -235,14 +256,7 @@ void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext
}
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);
- }
+ m_pInternalData->EnqueMap(pBuffer, OperationInfo.operation);
}
}
break;
@@ -250,13 +264,34 @@ void TextureUploaderD3D11::RenderThreadUpdate(Diligent::IDeviceContext *pContext
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
- );
+ // Unmap all subresources first to avoid D3D11 warnings
+ for (Uint32 Subres = 0; Subres < UploadBuffDesc.MipLevels * UploadBuffDesc.ArraySize; ++Subres)
+ {
+ pd3d11NativeCtx->Unmap(pBuffer->GetStagingTex(), Subres);
+ }
+
+ for (Uint32 Slice = 0; Slice < UploadBuffDesc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < UploadBuffDesc.MipLevels; ++Mip)
+ {
+ UINT SrcSubres = D3D11CalcSubresource(
+ static_cast<UINT>(Mip),
+ static_cast<UINT>(Slice),
+ static_cast<UINT>(UploadBuffDesc.MipLevels)
+ );
+ UINT DstSubres = D3D11CalcSubresource(
+ static_cast<UINT>(OperationInfo.DstMip + Mip),
+ static_cast<UINT>(OperationInfo.DstSlice + Slice),
+ static_cast<UINT>(OperationInfo.DstMipLevels)
+ );
+ pd3d11NativeCtx->CopySubresourceRegion(OperationInfo.pd3d11NativeDstTexture, DstSubres,
+ 0, 0, 0, // DstX, DstY, DstZ
+ pBuffer->GetStagingTex(),
+ SrcSubres,
+ nullptr // pSrcBox
+ );
+ }
+ }
pBuffer->SignalCopyScheduled();
}
break;
@@ -294,8 +329,8 @@ void TextureUploaderD3D11::AllocateUploadBuffer(const UploadBufferDesc& Desc, bo
{
static_cast<UINT>(Desc.Width),
static_cast<UINT>(Desc.Height),
- 1, // UINT MipLevels;
- 1, // UINT ArraySize;
+ static_cast<UINT>(Desc.MipLevels),
+ static_cast<UINT>(Desc.ArraySize),
TexFormatToDXGI_Format(Desc.Format),
{1, 0}, // DXGI_SAMPLE_DESC SampleDesc;
D3D11_USAGE_STAGING,
@@ -312,7 +347,8 @@ void TextureUploaderD3D11::AllocateUploadBuffer(const UploadBufferDesc& Desc, bo
return;
}
- LOG_INFO_MESSAGE("TextureUploaderD3D11: created ", Desc.Width, 'x', Desc.Height, ' ', m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " staging texture");
+ LOG_INFO_MESSAGE("TextureUploaderD3D11: created ", Desc.Width, 'x', Desc.Height, 'x', Desc.Depth, ' ', Desc.MipLevels, "-mip ",
+ m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " staging texture");
RefCntAutoPtr<UploadBufferD3D11> pUploadBuffer(MakeNewRCObj<UploadBufferD3D11>()(Desc, pStagingTex));
m_pInternalData->EnqueMap(pUploadBuffer, InternalData::PendingBufferOperation::Map);
@@ -321,17 +357,16 @@ void TextureUploaderD3D11::AllocateUploadBuffer(const UploadBufferDesc& Desc, bo
}
}
-void TextureUploaderD3D11::ScheduleGPUCopy(Diligent::ITexture *pDstTexture,
- Uint32 ArraySlice,
- Uint32 MipLevel,
- IUploadBuffer *pUploadBuffer)
+void TextureUploaderD3D11::ScheduleGPUCopy(ITexture* pDstTexture,
+ Uint32 ArraySlice,
+ Uint32 MipLevel,
+ IUploadBuffer* pUploadBuffer)
{
- auto *pUploadBufferD3D11 = ValidatedCast<UploadBufferD3D11>(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);
+ auto* pd3d11NativeDstTex = pDstTexD3D11->GetD3D11Texture();
+ const auto& DstTexDesc = pDstTexture->GetDesc();
+ m_pInternalData->EnqueCopy(pUploadBufferD3D11, pd3d11NativeDstTex, MipLevel, ArraySlice, DstTexDesc.MipLevels);
}
void TextureUploaderD3D11::RecycleBuffer(IUploadBuffer *pUploadBuffer)
diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D12_Vk.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D12_Vk.cpp
index 775c9523..28ba46b4 100644
--- a/Graphics/GraphicsTools/src/TextureUploaderD3D12_Vk.cpp
+++ b/Graphics/GraphicsTools/src/TextureUploaderD3D12_Vk.cpp
@@ -49,7 +49,13 @@ public:
~UploadTexture()
{
- DEV_CHECK_ERR(m_pData == nullptr, "Releasing mapped staging texture");
+ for (Uint32 Slice = 0; Slice < m_Desc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ DEV_CHECK_ERR(!IsMapped(Mip, Slice), "Releasing mapped staging texture");
+ }
+ }
}
void WaitForMap()
@@ -68,22 +74,19 @@ public:
m_CopyScheduledSignal.Trigger();
}
- void Unmap(IDeviceContext* pDeviceContext)
+ void Unmap(IDeviceContext* pDeviceContext, Uint32 Mip, Uint32 Slice)
{
- pDeviceContext->UnmapTextureSubresource(m_pStagingTexture, 0, 0);
- m_pData = nullptr;
- m_RowStride = 0;
- m_DepthStride = 0;
+ VERIFY(IsMapped(Mip, Slice), "This subresource is not mapped");
+ pDeviceContext->UnmapTextureSubresource(m_pStagingTexture, Mip, Slice);
+ SetMappedData(Mip, Slice, MappedTextureSubresource{});
}
- void Map(IDeviceContext* pDeviceContext)
+ void Map(IDeviceContext* pDeviceContext, Uint32 Mip, Uint32 Slice)
{
- VERIFY(m_pData == nullptr, "Staging texture is already mapped");
+ VERIFY(!IsMapped(Mip, Slice), "This subresource is already mapped");
MappedTextureSubresource MappedData;
- pDeviceContext->MapTextureSubresource(m_pStagingTexture, 0, 0, MAP_WRITE, MAP_FLAG_DO_NOT_SYNCHRONIZE, nullptr, MappedData);
- m_pData = MappedData.pData;
- m_RowStride = MappedData.Stride;
- m_DepthStride = MappedData.DepthStride;
+ pDeviceContext->MapTextureSubresource(m_pStagingTexture, Mip, Slice, MAP_WRITE, MAP_FLAG_DO_NOT_SYNCHRONIZE, nullptr, MappedData);
+ SetMappedData(Mip, Slice, MappedData);
}
void Reset()
@@ -91,6 +94,7 @@ public:
m_CopyScheduledSignal.Reset();
m_TextureMappedSignal.Reset();
m_CopyScheduledFenceValue = 0;
+ UploadBufferBase::Reset();
}
virtual void WaitForCopyScheduled()override final
@@ -286,12 +290,19 @@ void TextureUploaderD3D12_Vk::RenderThreadUpdate(IDeviceContext* pContext)
for (auto& OperationInfo : InWorkOperations)
{
auto& pUploadTex = OperationInfo.pUploadTexture;
+ const auto& StagingTexDesc = pUploadTex->GetDesc();
switch (OperationInfo.operation)
{
case InternalData::PendingBufferOperation::Map:
{
- pUploadTex->Map(pContext);
+ for (Uint32 Slice = 0; Slice < StagingTexDesc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < StagingTexDesc.MipLevels; ++Mip)
+ {
+ pUploadTex->Map(pContext, Mip, Slice);
+ }
+ }
pUploadTex->SignalMapped();
}
break;
@@ -299,18 +310,26 @@ void TextureUploaderD3D12_Vk::RenderThreadUpdate(IDeviceContext* pContext)
case InternalData::PendingBufferOperation::Copy:
{
VERIFY(pUploadTex->DbgIsMapped(), "Upload texture must be copied only after it has been mapped");
- pUploadTex->Unmap(pContext);
-
- CopyTextureAttribs CopyInfo
+ for (Uint32 Slice = 0; Slice < StagingTexDesc.ArraySize; ++Slice)
{
- pUploadTex->GetStagingTexture(),
- RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
- OperationInfo.pDstTexture,
- RESOURCE_STATE_TRANSITION_MODE_TRANSITION
- };
- CopyInfo.DstSlice = OperationInfo.DstSlice;
- CopyInfo.DstMipLevel = OperationInfo.DstMip;
- pContext->CopyTexture(CopyInfo);
+ for (Uint32 Mip = 0; Mip < StagingTexDesc.MipLevels; ++Mip)
+ {
+ pUploadTex->Unmap(pContext, Mip, Slice);
+
+ CopyTextureAttribs CopyInfo
+ {
+ pUploadTex->GetStagingTexture(),
+ RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
+ OperationInfo.pDstTexture,
+ RESOURCE_STATE_TRANSITION_MODE_TRANSITION
+ };
+ CopyInfo.SrcMipLevel = Mip;
+ CopyInfo.SrcSlice = Slice;
+ CopyInfo.DstMipLevel = OperationInfo.DstMip + Mip;
+ CopyInfo.DstSlice = OperationInfo.DstSlice + Slice;
+ pContext->CopyTexture(CopyInfo);
+ }
+ }
++NumCopyOperations;
}
break;
@@ -349,13 +368,15 @@ void TextureUploaderD3D12_Vk::AllocateUploadBuffer(const UploadBufferDesc& Desc,
StagingTexDesc.Width = Desc.Width;
StagingTexDesc.Height = Desc.Height;
StagingTexDesc.Format = Desc.Format;
+ StagingTexDesc.MipLevels = Desc.MipLevels;
StagingTexDesc.CPUAccessFlags = CPU_ACCESS_WRITE;
StagingTexDesc.Usage = USAGE_STAGING;
RefCntAutoPtr<ITexture> pStagingTexture;
m_pDevice->CreateTexture(StagingTexDesc, nullptr, &pStagingTexture);
- LOG_INFO_MESSAGE("Created ", Desc.Width, "x", Desc.Height, " ", GetTextureFormatAttribs(Desc.Format).Name, " staging texture");
+ LOG_INFO_MESSAGE("Created ", Desc.Width, "x", Desc.Height, 'x', Desc.Depth, ' ', Desc.MipLevels, "-mip ",
+ GetTextureFormatAttribs(Desc.Format).Name, " staging texture");
pUploadTexture = MakeNewRCObj<UploadTexture>()(Desc, pStagingTexture);
}
diff --git a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp
index be85e196..2fe321e4 100644
--- a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp
+++ b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp
@@ -26,8 +26,12 @@
#include <deque>
#include <unordered_map>
#include <vector>
+#include <algorithm>
+
#include "TextureUploaderGL.h"
#include "ThreadSignal.h"
+#include "GraphicsAccessories.h"
+#include "Align.h"
namespace Diligent
{
@@ -39,14 +43,32 @@ class UploadBufferGL : public UploadBufferBase
{
public:
UploadBufferGL(IReferenceCounters *pRefCounters, const UploadBufferDesc &Desc) :
- UploadBufferBase(pRefCounters, Desc)
- {}
-
- void SetDataPtr(void *pData, size_t RowStride, size_t DepthStride)
+ UploadBufferBase(pRefCounters, Desc),
+ m_SubresourceOffsets(Desc.MipLevels * Desc.ArraySize + 1),
+ m_SubresourceStrides(Desc.MipLevels * Desc.ArraySize)
{
- m_pData = pData;
- m_RowStride = RowStride;
- m_DepthStride = DepthStride;
+ const auto& FmtAttribs = GetTextureFormatAttribs(Desc.Format);
+ Uint32 SubRes = 0;
+ for (Uint32 Slice = 0; Slice < Desc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < Desc.MipLevels; ++Mip)
+ {
+ auto MipWidth = std::max(Desc.Width >> Mip, 1u);
+ auto MipHeight = std::max(Desc.Height >> Mip, 1u);
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED)
+ {
+ MipWidth = Align(MipWidth, Uint32{FmtAttribs.BlockWidth});
+ MipHeight = Align(MipHeight, Uint32{FmtAttribs.BlockHeight});
+ }
+
+ auto RowStride = MipWidth / Uint32{FmtAttribs.BlockWidth} * FmtAttribs.GetElementSize();
+ m_SubresourceStrides[SubRes] = RowStride;
+
+ auto MipSize = MipHeight / Uint32{FmtAttribs.BlockHeight} * RowStride;
+ m_SubresourceOffsets[SubRes + 1] = m_SubresourceOffsets[SubRes] + MipSize;
+ ++SubRes;
+ }
+ }
}
// http://en.cppreference.com/w/cpp/thread/condition_variable
@@ -72,19 +94,48 @@ public:
bool DbgIsCopyScheduled()const { return m_CopyScheduledSignal.IsTriggered(); }
+ void SetDataPtr(Uint8* pBufferData)
+ {
+ for (Uint32 Slice = 0; Slice < m_Desc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < m_Desc.MipLevels; ++Mip)
+ {
+ SetMappedData(Mip, Slice, MappedTextureSubresource{pBufferData + GetOffset(Mip,Slice), GetStride(Mip,Slice), 0});
+ }
+ }
+ }
+
+ Uint32 GetOffset(Uint32 Mip, Uint32 Slice)
+ {
+ VERIFY_EXPR(Mip < m_Desc.MipLevels && Slice < m_Desc.ArraySize);
+ return m_SubresourceOffsets[m_Desc.MipLevels * Slice + Mip];
+ }
+
void Reset()
{
m_BufferMappedSignal.Reset();
m_CopyScheduledSignal.Reset();
- m_pData = nullptr;
- // Do not zero out strides
+ UploadBufferBase::Reset();
+ }
+
+ Uint32 GetTotalSize()const
+ {
+ return m_SubresourceOffsets.back();
}
private:
+ Uint32 GetStride(Uint32 Mip, Uint32 Slice)
+ {
+ VERIFY_EXPR(Mip < m_Desc.MipLevels && Slice < m_Desc.ArraySize);
+ return m_SubresourceStrides[m_Desc.MipLevels * Slice + Mip];
+ }
+
friend TextureUploaderGL;
ThreadingTools::Signal m_BufferMappedSignal;
ThreadingTools::Signal m_CopyScheduledSignal;
RefCntAutoPtr<IBuffer> m_pStagingBuffer;
+ std::vector<Uint32> m_SubresourceOffsets;
+ std::vector<Uint32> m_SubresourceStrides;
};
} // namespace
@@ -177,48 +228,54 @@ void TextureUploaderGL::RenderThreadUpdate(IDeviceContext *pContext)
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;
+ const auto& UploadBuffDesc = pBuffer->GetDesc();
switch (OperationInfo.operation)
{
case InternalData::PendingBufferOperation::Map:
{
- 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.BlockWidth} * TexFmtInfo.GetElementSize();
- BuffDesc.uiSizeInBytes = Desc.Height / Uint32{TexFmtInfo.BlockHeight} * RowStride;
+ BuffDesc.uiSizeInBytes = pBuffer->GetTotalSize();
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->SetDataPtr(reinterpret_cast<Uint8*>(CpuAddress));
+
pBuffer->SignalMapped();
}
break;
case InternalData::PendingBufferOperation::Copy:
{
+ const auto& TexDesc = OperationInfo.pDstTexture->GetDesc();
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
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);
+ for (Uint32 Slice = 0; Slice < UploadBuffDesc.ArraySize; ++Slice)
+ {
+ for (Uint32 Mip = 0; Mip < UploadBuffDesc.MipLevels; ++Mip)
+ {
+ auto SrcOffset = pBuffer->GetOffset(Mip, Slice);
+ auto SrcStride = pBuffer->GetMappedData(Mip, Slice).Stride;
+ TextureSubResData SubResData(pBuffer->m_pStagingBuffer, SrcOffset, SrcStride);
+ auto MipLevelProps = GetMipLevelProperties(TexDesc, Mip);
+ Box DstBox;
+ DstBox.MaxX = MipLevelProps.Width;
+ DstBox.MaxY = MipLevelProps.Height;
+ pContext->UpdateTexture(OperationInfo.pDstTexture, OperationInfo.DstMip + Mip, OperationInfo.DstSlice + Slice, DstBox,
+ SubResData, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
+ }
+ }
pBuffer->SignalCopyScheduled();
}
break;
@@ -254,7 +311,8 @@ void TextureUploaderGL::AllocateUploadBuffer(const UploadBufferDesc& Desc, bool
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");
+ LOG_INFO_MESSAGE("TextureUploaderGL: created upload buffer for ", Desc.Width, 'x', Desc.Height, 'x', Desc.Depth, ' ', Desc.MipLevels, "-mip ",
+ m_pDevice->GetTextureFormatInfo(Desc.Format).Name, " texture");
}
m_pInternalData->EnqueMap(pUploadBuffer);