diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-08-28 14:42:08 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-08-28 14:42:08 +0000 |
| commit | ad97af5a953b8c158e0896ae25e72afe4d1c3a9e (patch) | |
| tree | e76a9ef4dffa2d63ba2cf339918841b5effe6d6e /Graphics/GraphicsEngineD3D12 | |
| parent | Updated LockHelper to spin few times before yielding thread (diff) | |
| download | DiligentCore-ad97af5a953b8c158e0896ae25e72afe4d1c3a9e.tar.gz DiligentCore-ad97af5a953b8c158e0896ae25e72afe4d1c3a9e.zip | |
Fixed https://github.com/DiligentGraphics/DiligentCore/issues/17 (Add support for Update Texture on DX12)
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
4 files changed, 96 insertions, 25 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h index 3fd9c1f8..ae006d32 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h @@ -109,13 +109,34 @@ public: void UpdateBufferRegion(class BufferD3D12Impl *pBuffD3D12, struct DynamicAllocation& Allocation, Uint64 DstOffset, Uint64 NumBytes); void UpdateBufferRegion(class BufferD3D12Impl *pBuffD3D12, const void *pData, Uint64 DstOffset, Uint64 NumBytes); void CopyBufferRegion(class BufferD3D12Impl *pSrcBuffD3D12, class BufferD3D12Impl *pDstBuffD3D12, Uint64 SrcOffset, Uint64 DstOffset, Uint64 NumBytes); - void CopyTextureRegion(class TextureD3D12Impl *pSrcTexture, Uint32 SrcSubResIndex, const D3D12_BOX *pD3D12SrcBox, + void CopyTextureRegion(class TextureD3D12Impl *pSrcTexture, Uint32 SrcSubResIndex, const D3D12_BOX* pD3D12SrcBox, class TextureD3D12Impl *pDstTexture, Uint32 DstSubResIndex, Uint32 DstX, Uint32 DstY, Uint32 DstZ); - void CopyTextureRegion(IBuffer *pSrcBuffer, Uint32 SrcStride, Uint32 SrcDepthStride, class TextureD3D12Impl *pTextureD3D12, Uint32 DstSubResIndex, const Box &DstBox); + void CopyTextureRegion(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + Uint32 SrcStride, + Uint32 SrcDepthStride, + class TextureD3D12Impl* pTextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox); + void CopyTextureRegion(ID3D12Resource* pd3d12Buffer, + Uint32 SrcOffset, + Uint32 SrcStride, + Uint32 SrcDepthStride, + Uint32 BufferSize, + class TextureD3D12Impl* pTextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox); + + void UpdateTextureRegion(const void* pSrcData, + Uint32 SrcStride, + Uint32 SrcDepthStride, + class TextureD3D12Impl* pTextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox); void GenerateMips(class TextureViewD3D12Impl *pTexView); - struct DynamicAllocation AllocateDynamicSpace(size_t NumBytes); + struct DynamicAllocation AllocateDynamicSpace(size_t NumBytes, size_t Alignment); Uint32 GetContextId()const{return m_ContextId;} diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp index f0a9e4b3..92b734f4 100644 --- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp @@ -354,7 +354,7 @@ void BufferD3D12Impl :: Map(IDeviceContext* pContext, MAP_TYPE MapType, Uint32 M auto ContextId = pDeviceContextD3D12->GetContextId(); if ((MapFlags & MAP_FLAG_DISCARD) != 0 || m_DynamicData[ContextId].CPUAddress == nullptr) { - m_DynamicData[ContextId] = pCtxD3D12->AllocateDynamicSpace(m_Desc.uiSizeInBytes); + m_DynamicData[ContextId] = pCtxD3D12->AllocateDynamicSpace(m_Desc.uiSizeInBytes, 0); } else { diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 66477281..70dddbcd 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -690,9 +690,9 @@ namespace Diligent } } - DynamicAllocation DeviceContextD3D12Impl::AllocateDynamicSpace(size_t NumBytes) + DynamicAllocation DeviceContextD3D12Impl::AllocateDynamicSpace(size_t NumBytes, size_t Alignment) { - return m_pUploadHeap->Allocate(NumBytes); + return m_pUploadHeap->Allocate(NumBytes + Alignment); } void DeviceContextD3D12Impl::UpdateBufferRegion(class BufferD3D12Impl* pBuffD3D12, DynamicAllocation& Allocation, Uint64 DstOffset, Uint64 NumBytes) @@ -754,12 +754,16 @@ namespace Diligent ++m_NumCommandsInCurCtx; } - void DeviceContextD3D12Impl::CopyTextureRegion(IBuffer* pSrcBuffer, Uint32 SrcStride, Uint32 SrcDepthStride, class TextureD3D12Impl* pTextureD3D12, Uint32 DstSubResIndex, const Box& DstBox) + void DeviceContextD3D12Impl::CopyTextureRegion(ID3D12Resource* pd3d12Buffer, + Uint32 SrcOffset, + Uint32 SrcStride, + Uint32 SrcDepthStride, + Uint32 BufferSize, + class TextureD3D12Impl* pTextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox) { - auto *pBufferD3D12 = ValidatedCast<BufferD3D12Impl>(pSrcBuffer); const auto& TexDesc = pTextureD3D12->GetDesc(); - VERIFY(pBufferD3D12->GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Staging buffer is expected to always be in D3D12_RESOURCE_STATE_GENERIC_READ state"); - auto *pCmdCtx = RequestCmdContext(); auto *pCmdList = pCmdCtx->GetCommandList(); auto TextureState = pTextureD3D12->GetState(); @@ -781,16 +785,16 @@ namespace Diligent D3D12_TEXTURE_COPY_LOCATION SrcLocation; SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - SrcLocation.pResource = pBufferD3D12->GetD3D12Resource(); + SrcLocation.pResource = pd3d12Buffer; D3D12_PLACED_SUBRESOURCE_FOOTPRINT &Footpring = SrcLocation.PlacedFootprint; - Footpring.Offset = 0; - Footpring.Footprint.Width = static_cast<UINT>(DstBox.MaxX - DstBox.MinX); + Footpring.Offset = SrcOffset; + Footpring.Footprint.Width = static_cast<UINT>(DstBox.MaxX - DstBox.MinX); Footpring.Footprint.Height = static_cast<UINT>(DstBox.MaxY - DstBox.MinY); - Footpring.Footprint.Depth = static_cast<UINT>(DstBox.MaxZ - DstBox.MinZ); // Depth cannot be 0 + Footpring.Footprint.Depth = static_cast<UINT>(DstBox.MaxZ - DstBox.MinZ); // Depth cannot be 0 Footpring.Footprint.Format = TexFormatToDXGI_Format(TexDesc.Format); Footpring.Footprint.RowPitch = static_cast<UINT>(SrcStride); - VERIFY(Footpring.Footprint.RowPitch * Footpring.Footprint.Height * Footpring.Footprint.Depth <= pBufferD3D12->GetDesc().uiSizeInBytes, "Buffer is not large enough"); + VERIFY(Footpring.Footprint.RowPitch * Footpring.Footprint.Height * Footpring.Footprint.Depth <= BufferSize, "Buffer is not large enough"); VERIFY(SrcDepthStride == 0 || static_cast<UINT>(SrcDepthStride) == Footpring.Footprint.RowPitch * Footpring.Footprint.Height, "Depth stride must be equal to the size 2D level"); D3D12_BOX D3D12SrcBox; @@ -815,6 +819,58 @@ namespace Diligent } } + void DeviceContextD3D12Impl::CopyTextureRegion(IBuffer* pSrcBuffer, + Uint32 SrcOffset, + Uint32 SrcStride, + Uint32 SrcDepthStride, + class TextureD3D12Impl* pTextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox) + { + auto* pBufferD3D12 = ValidatedCast<BufferD3D12Impl>(pSrcBuffer); + VERIFY(pBufferD3D12->GetState() == D3D12_RESOURCE_STATE_GENERIC_READ, "Staging buffer is expected to always be in D3D12_RESOURCE_STATE_GENERIC_READ state"); + CopyTextureRegion(pBufferD3D12->GetD3D12Resource(), SrcOffset, SrcStride, SrcDepthStride, pBufferD3D12->GetDesc().uiSizeInBytes, pTextureD3D12, DstSubResIndex, DstBox); + } + + void DeviceContextD3D12Impl::UpdateTextureRegion(const void* pSrcData, + Uint32 SrcStride, + Uint32 SrcDepthStride, + TextureD3D12Impl* pTextureD3D12, + Uint32 DstSubResIndex, + const Box& DstBox) + { + const auto& TexDesc = pTextureD3D12->GetDesc(); + const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + VERIFY_EXPR(DstBox.MaxX > DstBox.MinX && DstBox.MaxY > DstBox.MinY && DstBox.MaxZ > DstBox.MinZ); + auto UpdateRegionWidth = DstBox.MaxX - DstBox.MinX; + auto UpdateRegionHeight = DstBox.MaxY - DstBox.MinY; + auto UpdateRegionDepth = DstBox.MaxZ - DstBox.MinZ; + auto BufferDataStride = UpdateRegionWidth * FmtAttribs.ComponentSize * FmtAttribs.NumComponents; + auto BufferDataDepthStride = UpdateRegionHeight * BufferDataStride; + auto MemorySize = UpdateRegionDepth * BufferDataDepthStride; + auto UploadSpace = AllocateDynamicSpace(MemorySize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); + auto AlignedOffset = (UploadSpace.Offset + (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1)) & ~(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1); + + for(Uint32 slice = 0; slice < UpdateRegionDepth; ++slice) + { + for(Uint32 row = 0; row < UpdateRegionHeight; ++row) + { + const auto* pSrcPtr = + reinterpret_cast<const Uint8*>(pSrcData) + + row * SrcStride + + slice * SrcDepthStride; + auto* pDstPtr = + reinterpret_cast<Uint8*>(UploadSpace.CPUAddress) + + (AlignedOffset - UploadSpace.Offset) + + row * BufferDataStride + + slice * BufferDataDepthStride; + + memcpy(pDstPtr, pSrcPtr, BufferDataStride); + } + } + CopyTextureRegion(UploadSpace.pBuffer, static_cast<Uint32>(AlignedOffset), BufferDataStride, BufferDataDepthStride, MemorySize, pTextureD3D12, DstSubResIndex, DstBox); + } + void DeviceContextD3D12Impl::GenerateMips(TextureViewD3D12Impl* pTexView) { auto *pCtx = RequestCmdContext(); diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index bf01b26c..77d8894f 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -408,19 +408,13 @@ void TextureD3D12Impl::UpdateData( IDeviceContext* pContext, const TextureSubResData& SubresData ) { TTextureBase::UpdateData( pContext, MipLevel, Slice, DstBox, SubresData ); - if (SubresData.pSrcBuffer == nullptr) - { - LOG_ERROR("D3D12 does not allow updating texture subresource from CPU memory"); - return; - } - - VERIFY( m_Desc.Usage == USAGE_DEFAULT, "Only default usage resiurces can be updated with UpdateData()" ); auto *pCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext); - auto DstSubResIndex = D3D12CalcSubresource(MipLevel, Slice, 0, m_Desc.MipLevels, m_Desc.ArraySize); - - pCtxD3D12->CopyTextureRegion(SubresData.pSrcBuffer, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox); + if (SubresData.pSrcBuffer == nullptr) + pCtxD3D12->UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox); + else + pCtxD3D12->CopyTextureRegion(SubresData.pSrcBuffer, 0, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox); } void TextureD3D12Impl :: CopyData(IDeviceContext* pContext, |
