diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-08-30 05:33:33 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-08-30 05:33:33 +0000 |
| commit | 7dcb7b4a2c5965a90a7fdd5fd1950d5a1036900a (patch) | |
| tree | 7559c64aebaaae5a2c4a2f7a2de7e22377191af2 /Graphics/GraphicsEngineD3D12 | |
| parent | Fixed debug checks (diff) | |
| download | DiligentCore-7dcb7b4a2c5965a90a7fdd5fd1950d5a1036900a.tar.gz DiligentCore-7dcb7b4a2c5965a90a7fdd5fd1950d5a1036900a.zip | |
Fixed handling of small compressed texture subresources
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
3 files changed, 76 insertions, 26 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h index 65f0d493..95430ade 100644 --- a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h @@ -58,13 +58,13 @@ public: ID3D12Resource* pTexture); ~TextureD3D12Impl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; + virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override final; - virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override; + virtual void UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )override final; //virtual void CopyData(CTexture *pSrcTexture, Uint32 SrcOffset, Uint32 DstOffset, Uint32 Size); - virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData )override; - virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override; + virtual void Map( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags, MappedTextureSubresource &MappedData )override final; + virtual void Unmap( IDeviceContext *pContext, Uint32 Subresource, MAP_TYPE MapType, Uint32 MapFlags )override final; virtual ID3D12Resource* GetD3D12Texture(){ return GetD3D12Resource(); } @@ -94,7 +94,7 @@ public: } protected: - void CreateViewInternal( const struct TextureViewDesc &ViewDesc, ITextureView **ppView, bool bIsDefaultView )override; + void CreateViewInternal( const struct TextureViewDesc &ViewDesc, ITextureView **ppView, bool bIsDefaultView )override final; //void PrepareD3D12InitData(const TextureData &InitData, Uint32 NumSubresources, std::vector<D3D12_SUBRESOURCE_DATA> &D3D12InitData); void CreateSRV( TextureViewDesc &SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle ); diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index b30925b0..ab1ae905 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -794,8 +794,15 @@ namespace Diligent Footpring.Footprint.Format = TexFormatToDXGI_Format(TexDesc.Format); Footpring.Footprint.RowPitch = static_cast<UINT>(SrcStride); - 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"); + +#ifdef _DEBUG + { + const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + const Uint32 RowCount = std::max((Footpring.Footprint.Height/FmtAttribs.BlockHeight), 1u); + VERIFY(BufferSize >= Footpring.Footprint.RowPitch * RowCount * Footpring.Footprint.Depth, "Buffer is not large enough"); + VERIFY(Footpring.Footprint.Depth == 1 || static_cast<UINT>(SrcDepthStride) == Footpring.Footprint.RowPitch * RowCount, "Depth stride must be equal to the size of 2D plane"); + } +#endif D3D12_BOX D3D12SrcBox; D3D12SrcBox.left = 0; @@ -847,24 +854,41 @@ namespace Diligent 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); - const auto UpdateRegionWidth = DstBox.MaxX - DstBox.MinX; - const auto UpdateRegionHeight = DstBox.MaxY - DstBox.MinY; - const auto UpdateRegionDepth = DstBox.MaxZ - DstBox.MinZ; - const Uint32 RowSize = FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED ? - UpdateRegionWidth / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize} : - UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents}; - VERIFY(SrcStride >= RowSize, "Source data stride (", SrcStride, ") is below the image row size (", RowSize, ")"); - VERIFY(SrcDepthStride == 0 || SrcDepthStride >= SrcStride * (UpdateRegionHeight / FmtAttribs.BlockHeight), "Source data depth stride (", SrcDepthStride, ") is below the image plane size (", SrcStride * UpdateRegionHeight, ")"); + auto UpdateRegionWidth = DstBox.MaxX - DstBox.MinX; + auto UpdateRegionHeight = DstBox.MaxY - DstBox.MinY; + auto UpdateRegionDepth = DstBox.MaxZ - DstBox.MinZ; + Uint32 RowSize = 0; + Uint32 RowCount = 0; + if(FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED) + { + // Box must be aligned by the calling function + VERIFY_EXPR((UpdateRegionWidth % FmtAttribs.BlockWidth) == 0); + VERIFY_EXPR((UpdateRegionHeight % FmtAttribs.BlockHeight) == 0); + RowSize = UpdateRegionWidth / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize}; + RowCount = UpdateRegionHeight / FmtAttribs.BlockHeight; + } + else + { + RowSize = UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents}; + RowCount = UpdateRegionHeight; + } +#ifdef _DEBUG + { + VERIFY(SrcStride >= RowSize, "Source data stride (", SrcStride, ") is below the image row size (", RowSize, ")"); + const Uint32 PlaneSize = SrcStride * RowCount; + VERIFY(UpdateRegionDepth == 1 || SrcDepthStride >= PlaneSize, "Source data depth stride (", SrcDepthStride, ") is below the image plane size (", PlaneSize, ")"); + } +#endif // RowPitch must be a multiple of 256 (aka. D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) - const auto BufferDataStride = (RowSize + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1); - const auto BufferDataDepthStride = UpdateRegionHeight * BufferDataStride; - const auto MemorySize = UpdateRegionDepth * BufferDataDepthStride; - const auto UploadSpace = AllocateDynamicSpace(MemorySize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); - const auto AlignedOffset = (UploadSpace.Offset + (D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1)) & ~(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT-1); + const auto AlignedStride = (RowSize + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT-1); + const auto AlignedDepthStride = RowCount * AlignedStride; + const auto MemorySize = UpdateRegionDepth * AlignedDepthStride; + const auto UploadSpace = AllocateDynamicSpace(MemorySize, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); + const 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 / FmtAttribs.BlockHeight; ++row) + for(Uint32 row = 0; row < RowCount; ++row) { const auto* pSrcPtr = reinterpret_cast<const Uint8*>(pSrcData) @@ -873,13 +897,13 @@ namespace Diligent auto* pDstPtr = reinterpret_cast<Uint8*>(UploadSpace.CPUAddress) + (AlignedOffset - UploadSpace.Offset) - + row * BufferDataStride - + slice * BufferDataDepthStride; + + row * AlignedStride + + slice * AlignedDepthStride; memcpy(pDstPtr, pSrcPtr, RowSize); } } - CopyTextureRegion(UploadSpace.pBuffer, static_cast<Uint32>(AlignedOffset), BufferDataStride, BufferDataDepthStride, MemorySize, pTextureD3D12, DstSubResIndex, DstBox); + CopyTextureRegion(UploadSpace.pBuffer, static_cast<Uint32>(AlignedOffset), AlignedStride, AlignedDepthStride, MemorySize, pTextureD3D12, DstSubResIndex, DstBox); } void DeviceContextD3D12Impl::GenerateMips(TextureViewD3D12Impl* pTexView) diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index 77d8894f..2ea0938e 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -409,12 +409,38 @@ void TextureD3D12Impl::UpdateData( IDeviceContext* pContext, { TTextureBase::UpdateData( pContext, MipLevel, Slice, DstBox, SubresData ); + Box BlockAlignedBox; + const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format); + const Box* pBox = nullptr; + if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED) + { + // Align update region by the compressed block size + + VERIFY( (DstBox.MinX % FmtAttribs.BlockWidth) == 0, "Update region min x (", DstBox.MinX, ") must be multiple of a compressed block width (", FmtAttribs.BlockWidth, ")"); + BlockAlignedBox.MinX = DstBox.MinX; + VERIFY( (FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth-1)) == 0, "Compressed block width (", FmtAttribs.BlockWidth, ") is expected to be power of 2"); + BlockAlignedBox.MaxX = (DstBox.MaxX + FmtAttribs.BlockWidth-1) & ~(FmtAttribs.BlockWidth-1); + + VERIFY( (DstBox.MinY % FmtAttribs.BlockHeight) == 0, "Update region min y (", DstBox.MinY, ") must be multiple of a compressed block height (", FmtAttribs.BlockHeight, ")"); + BlockAlignedBox.MinY = DstBox.MinY; + VERIFY( (FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight-1)) == 0, "Compressed block height (", FmtAttribs.BlockHeight, ") is expected to be power of 2"); + BlockAlignedBox.MaxY = (DstBox.MaxY + FmtAttribs.BlockHeight-1) & ~(FmtAttribs.BlockHeight-1); + + BlockAlignedBox.MinZ = DstBox.MinZ; + BlockAlignedBox.MaxZ = DstBox.MaxZ; + + pBox = &BlockAlignedBox; + } + else + { + pBox = &DstBox; + } auto *pCtxD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pContext); auto DstSubResIndex = D3D12CalcSubresource(MipLevel, Slice, 0, m_Desc.MipLevels, m_Desc.ArraySize); if (SubresData.pSrcBuffer == nullptr) - pCtxD3D12->UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox); + pCtxD3D12->UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, *pBox); else - pCtxD3D12->CopyTextureRegion(SubresData.pSrcBuffer, 0, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox); + pCtxD3D12->CopyTextureRegion(SubresData.pSrcBuffer, 0, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, *pBox); } void TextureD3D12Impl :: CopyData(IDeviceContext* pContext, |
