From 3f81d1daa7b13e935cf43a6af30367f2b39c09bf Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Fri, 19 Apr 2019 08:11:58 -0700 Subject: Fixed issues with multi-mip level staging resource in Vk and D3D12 back-ends --- .../GraphicsEngineD3D12/include/TextureD3D12Impl.h | 9 +++ .../src/DeviceContextD3D12Impl.cpp | 68 +++++----------------- .../GraphicsEngineD3D12/src/TextureD3D12Impl.cpp | 8 ++- 3 files changed, 30 insertions(+), 55 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h index 552ebeda..0b67b262 100644 --- a/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.h @@ -72,6 +72,13 @@ public: D3D12_RESOURCE_DESC GetD3D12TextureDesc()const; + const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& GetStagingFootprint(Uint32 Subresource) + { + VERIFY_EXPR(m_StagingFootprints != nullptr); + VERIFY_EXPR(Subresource <= (Uint32{m_Desc.MipLevels} * (m_Desc.Type == RESOURCE_DIM_TEX_3D ? 1 : Uint32{m_Desc.ArraySize}))); + return m_StagingFootprints[Subresource]; + } + protected: void CreateViewInternal( const struct TextureViewDesc &ViewDesc, ITextureView **ppView, bool bIsDefaultView )override final; //void PrepareD3D12InitData(const TextureData &InitData, Uint32 NumSubresources, std::vector &D3D12InitData); @@ -81,6 +88,8 @@ protected: void CreateDSV( TextureViewDesc &DSVDesc, D3D12_CPU_DESCRIPTOR_HANDLE DSVHandle ); void CreateUAV( TextureViewDesc &UAVDesc, D3D12_CPU_DESCRIPTOR_HANDLE UAVHandle ); + D3D12_PLACED_SUBRESOURCE_FOOTPRINT* m_StagingFootprints = nullptr; + friend class RenderDeviceD3D12Impl; }; diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index c0866371..e4c04ba4 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -1139,17 +1139,7 @@ namespace Diligent if (pSrcTexture->GetDesc().Usage == USAGE_STAGING) { SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - auto d3d12TexDesc = pSrcTexture->GetD3D12TextureDesc(); - auto* pd3d12Device = m_pDevice.RawPtr()->GetD3D12Device(); - pd3d12Device->GetCopyableFootprints(&d3d12TexDesc, - SrcSubResIndex, - 1, // Num subresources - 0, // The offset, in bytes, to the resource. - &SrcLocation.PlacedFootprint, - nullptr, - nullptr, - nullptr - ); + SrcLocation.PlacedFootprint = pSrcTexture->GetStagingFootprint(SrcSubResIndex); } else { @@ -1161,17 +1151,7 @@ namespace Diligent if (pDstTexture->GetDesc().Usage == USAGE_STAGING) { DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - auto d3d12TexDesc = pDstTexture->GetD3D12TextureDesc(); - auto* pd3d12Device = m_pDevice.RawPtr()->GetD3D12Device(); - pd3d12Device->GetCopyableFootprints(&d3d12TexDesc, - DstSubResIndex, - 1, // Num subresources - 0, // The offset, in bytes, to the resource. - &DstLocation.PlacedFootprint, - nullptr, - nullptr, - nullptr - ); + DstLocation.PlacedFootprint = pDstTexture->GetStagingFootprint(DstSubResIndex); } else { @@ -1436,21 +1416,8 @@ namespace Diligent "access and map texture with MAP_FLAG_DO_NOT_SYNCHRONIZE flag."); } - auto d3d12TexDesc = TextureD3D12.GetD3D12TextureDesc(); - auto* pd3d12Device = m_pDevice.RawPtr()->GetD3D12Device(); - D3D12_PLACED_SUBRESOURCE_FOOTPRINT Footprint = {}; - UINT64 TotalBytes = 0; - UINT NumRows = 0; - pd3d12Device->GetCopyableFootprints(&d3d12TexDesc, - Subres, - 1, // Num subresources - 0, // The offset, in bytes, to the resource. - &Footprint, - &NumRows, - nullptr, - &TotalBytes - ); - + const auto& Footprint = TextureD3D12.GetStagingFootprint(Subres); + // It is valid to specify the CPU won't read any data by passing a range where // End is less than or equal to Begin. // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12resource-map @@ -1460,7 +1427,8 @@ namespace Diligent DEV_CHECK_ERR((TexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Texture '", TexDesc.Name, "' was not created with CPU_ACCESS_READ flag and can't be mapped for reading"); // Resources on D3D12_HEAP_TYPE_READBACK heaps do not support persistent map. InvalidateRange.Begin = static_cast(Footprint.Offset); - InvalidateRange.End = static_cast(Footprint.Offset + TotalBytes); + const auto& NextFootprint = TextureD3D12.GetStagingFootprint(Subres+1); + InvalidateRange.End = static_cast(NextFootprint.Offset); } else if (MapType == MAP_WRITE) { @@ -1473,9 +1441,12 @@ namespace Diligent // Map() invalidates the CPU cache, when necessary, so that CPU reads to this address // reflect any modifications made by the GPU. - TextureD3D12.GetD3D12Resource()->Map(0, &InvalidateRange, &MappedData.pData); + void* pMappedDataPtr = nullptr; + TextureD3D12.GetD3D12Resource()->Map(0, &InvalidateRange, &pMappedDataPtr); + MappedData.pData = reinterpret_cast(pMappedDataPtr) + Footprint.Offset; MappedData.Stride = static_cast(Footprint.Footprint.RowPitch); - MappedData.DepthStride = static_cast(Footprint.Footprint.RowPitch * NumRows); + const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + MappedData.DepthStride = static_cast(Footprint.Footprint.Height / FmtAttribs.BlockHeight * Footprint.Footprint.RowPitch); } else { @@ -1521,21 +1492,10 @@ namespace Diligent if (TexDesc.CPUAccessFlags == CPU_ACCESS_WRITE) { - auto d3d12TexDesc = TextureD3D12.GetD3D12TextureDesc(); - auto* pd3d12Device = m_pDevice.RawPtr()->GetD3D12Device(); - D3D12_PLACED_SUBRESOURCE_FOOTPRINT Footprint = {}; - UINT64 TotalBytes = 0; - pd3d12Device->GetCopyableFootprints(&d3d12TexDesc, - Subres, - 1, // Num subresources - 0, // The offset, in bytes, to the resource. - &Footprint, - nullptr, - nullptr, - &TotalBytes - ); + const auto& Footprint = TextureD3D12.GetStagingFootprint(Subres); + const auto& NextFootprint = TextureD3D12.GetStagingFootprint(Subres+1); FlushRange.Begin = static_cast(Footprint.Offset); - FlushRange.End = static_cast(Footprint.Offset + TotalBytes); + FlushRange.End = static_cast(NextFootprint.Offset); } // Map and Unmap can be called by multiple threads safely. Nested Map calls are supported diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index 652150ae..56847982 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -298,7 +298,9 @@ TextureD3D12Impl :: TextureD3D12Impl(IReferenceCounters* pRefCounters, UINT64 stagingBufferSize = 0; Uint32 NumSubresources = Uint32{Desc.MipLevels} * (Desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? 1 : Uint32{Desc.DepthOrArraySize}); - pd3d12Device->GetCopyableFootprints(&Desc, 0, NumSubresources, 0, nullptr, nullptr, nullptr, &stagingBufferSize); + m_StagingFootprints = ALLOCATE(GetRawAllocator(), "Memory for staging footprints", D3D12_PLACED_SUBRESOURCE_FOOTPRINT, NumSubresources+1); + pd3d12Device->GetCopyableFootprints(&Desc, 0, NumSubresources, 0, m_StagingFootprints, nullptr, nullptr, &stagingBufferSize); + m_StagingFootprints[NumSubresources] = D3D12_PLACED_SUBRESOURCE_FOOTPRINT{stagingBufferSize}; D3D12_RESOURCE_DESC BufferDesc; BufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; @@ -495,6 +497,10 @@ TextureD3D12Impl :: ~TextureD3D12Impl() // D3D12 object can only be destroyed when it is no longer used by the GPU auto *pDeviceD3D12Impl = ValidatedCast(GetDevice()); pDeviceD3D12Impl->SafeReleaseDeviceObject(std::move(m_pd3d12Resource), m_Desc.CommandQueueMask); + if (m_StagingFootprints != nullptr) + { + FREE(GetRawAllocator(), m_StagingFootprints); + } } void TextureD3D12Impl::CreateSRV( TextureViewDesc& SRVDesc, D3D12_CPU_DESCRIPTOR_HANDLE SRVHandle ) -- cgit v1.2.3