diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-04-19 15:11:58 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-04-19 15:11:58 +0000 |
| commit | 3f81d1daa7b13e935cf43a6af30367f2b39c09bf (patch) | |
| tree | 6203a390741d2179acca18397eced96af33167cb /Graphics | |
| parent | Fixed parameter issue in ALLOCATE macro (diff) | |
| download | DiligentCore-3f81d1daa7b13e935cf43a6af30367f2b39c09bf.tar.gz DiligentCore-3f81d1daa7b13e935cf43a6af30367f2b39c09bf.zip | |
Fixed issues with multi-mip level staging resource in Vk and D3D12 back-ends
Diffstat (limited to 'Graphics')
9 files changed, 91 insertions, 116 deletions
diff --git a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.h b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.h index f6a290a3..c5bb97b0 100644 --- a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.h +++ b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.h @@ -302,4 +302,17 @@ inline bool IsAnisotropicFilter(FILTER_TYPE FilterType) bool VerifyResourceStates(RESOURCE_STATE State, bool IsTexture); +/// Describes the mip level properties +struct MipLevelProperties +{ + Uint32 Width = 0; + Uint32 Height = 0; + Uint32 Depth = 1; + Uint32 RowSize = 0; + Uint32 DepthSliceSize = 0; + Uint32 MipSize = 0; +}; + +MipLevelProperties GetMipLevelProperties(const TextureDesc& TexDesc, Uint32 MipLevel); + } diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 21fe6719..d40114b1 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -21,9 +21,11 @@ * of the possibility of such damages. */ +#include <algorithm> + #include "GraphicsAccessories.h" #include "DebugUtilities.h" -#include <algorithm> +#include "Align.h" namespace Diligent { @@ -934,4 +936,34 @@ if ( (State & ExclusiveState) != 0 && (State & ~ExclusiveState) != 0 )\ return true; } +MipLevelProperties GetMipLevelProperties(const TextureDesc& TexDesc, Uint32 MipLevel) +{ + MipLevelProperties MipProps; + const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + + MipProps.Width = std::max(TexDesc.Width >> MipLevel, 1u); + MipProps.Height = std::max(TexDesc.Height >> MipLevel, 1u); + MipProps.Depth = (TexDesc.Type == RESOURCE_DIM_TEX_3D) ? std::max(TexDesc.Depth >> MipLevel, 1u) : 1u; + if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED) + { + VERIFY_EXPR(FmtAttribs.BlockWidth > 1 && FmtAttribs.BlockHeight > 1); + VERIFY((FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth-1)) == 0, "Compressed block width is expected to be power of 2"); + VERIFY((FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight-1)) == 0, "Compressed block height is expected to be power of 2"); + // For block-compression formats, all parameters are still specified in texels rather than compressed texel blocks (18.4.1) + MipProps.Width = Align(MipProps.Width, Uint32{FmtAttribs.BlockWidth}); + MipProps.Height = Align(MipProps.Height,Uint32{FmtAttribs.BlockHeight}); + MipProps.RowSize = MipProps.Width / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize}; // ComponentSize is the block size + MipProps.DepthSliceSize = MipProps.Height / Uint32{FmtAttribs.BlockHeight} * MipProps.RowSize; + MipProps.MipSize = MipProps.DepthSliceSize * MipProps.Depth; + } + else + { + MipProps.RowSize = MipProps.Width * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents}; + MipProps.DepthSliceSize = MipProps.RowSize * MipProps.Height; + MipProps.MipSize = MipProps.DepthSliceSize * MipProps.Depth; + } + + return MipProps; +} + } diff --git a/Graphics/GraphicsEngine/src/Texture.cpp b/Graphics/GraphicsEngine/src/Texture.cpp index d33701ea..57b58279 100644 --- a/Graphics/GraphicsEngine/src/Texture.cpp +++ b/Graphics/GraphicsEngine/src/Texture.cpp @@ -238,18 +238,10 @@ void ValidateCopyTextureParams(const CopyTextureAttribs& CopyAttribs ) auto pSrcBox = CopyAttribs.pSrcBox; if( pSrcBox == nullptr ) { - SrcBox.MaxX = std::max( SrcTexDesc.Width >> CopyAttribs.SrcMipLevel, 1u ); - if( SrcTexDesc.Type == RESOURCE_DIM_TEX_1D || - SrcTexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY ) - SrcBox.MaxY = 1; - else - SrcBox.MaxY = std::max( SrcTexDesc.Height >> CopyAttribs.SrcMipLevel, 1u ); - - if( SrcTexDesc.Type == RESOURCE_DIM_TEX_3D ) - SrcBox.MaxZ = std::max( SrcTexDesc.Depth >> CopyAttribs.SrcMipLevel, 1u ); - else - SrcBox.MaxZ = 1; - + auto MipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel); + SrcBox.MaxX = MipLevelAttribs.Width; + SrcBox.MaxY = MipLevelAttribs.Height; + SrcBox.MaxZ = MipLevelAttribs.Depth; pSrcBox = &SrcBox; } ValidateTextureRegion(SrcTexDesc, CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, *pSrcBox); 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<D3D12_SUBRESOURCE_DATA> &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<RenderDeviceD3D12Impl>()->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<RenderDeviceD3D12Impl>()->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<RenderDeviceD3D12Impl>()->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<SIZE_T>(Footprint.Offset); - InvalidateRange.End = static_cast<SIZE_T>(Footprint.Offset + TotalBytes); + const auto& NextFootprint = TextureD3D12.GetStagingFootprint(Subres+1); + InvalidateRange.End = static_cast<SIZE_T>(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<Uint8*>(pMappedDataPtr) + Footprint.Offset; MappedData.Stride = static_cast<Uint32>(Footprint.Footprint.RowPitch); - MappedData.DepthStride = static_cast<Uint32>(Footprint.Footprint.RowPitch * NumRows); + const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + MappedData.DepthStride = static_cast<Uint32>(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<RenderDeviceD3D12Impl>()->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<SIZE_T>(Footprint.Offset); - FlushRange.End = static_cast<SIZE_T>(Footprint.Offset + TotalBytes); + FlushRange.End = static_cast<SIZE_T>(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<RenderDeviceD3D12Impl>(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 ) diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h index d3d0883a..39ec0ea1 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h @@ -38,16 +38,6 @@ namespace Diligent class FixedBlockMemoryAllocator; -struct MipLevelProperties -{ - Uint32 Width = 0; - Uint32 Height = 0; - Uint32 Depth = 1; - Uint32 RowSize = 0; - Uint32 MipSize = 0; -}; - -MipLevelProperties GetMipLevelProperties(const TextureDesc& TexDesc, Uint32 MipLevel); Uint32 GetStagingDataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel); /// Base implementation of the Diligent::ITextureVk interface diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index ee6331fb..865d4177 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -31,6 +31,7 @@ #include "BufferVkImpl.h" #include "VulkanTypeConversions.h" #include "CommandListVkImpl.h" +#include "GraphicsAccessories.h" namespace Diligent { @@ -1331,12 +1332,10 @@ namespace Diligent Box FullMipBox; if (pSrcBox == nullptr) { - FullMipBox.MaxX = std::max(DstTexDesc.Width >> CopyAttribs.SrcMipLevel, 1u); - FullMipBox.MaxY = std::max(DstTexDesc.Height >> CopyAttribs.SrcMipLevel, 1u); - if(DstTexDesc.Type == RESOURCE_DIM_TEX_3D) - FullMipBox.MaxZ = std::max(DstTexDesc.Depth >> CopyAttribs.SrcMipLevel, 1u); - else - FullMipBox.MaxZ = 1; + auto MipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel); + FullMipBox.MaxX = MipLevelAttribs.Width; + FullMipBox.MaxY = MipLevelAttribs.Height; + FullMipBox.MaxZ = MipLevelAttribs.Depth; pSrcBox = &FullMipBox; } const auto& DstFmtAttribs = GetTextureFormatAttribs(DstTexDesc.Format); @@ -1714,10 +1713,10 @@ namespace Diligent Box FullExtentBox; if (pMapRegion == nullptr) { - FullExtentBox.MaxX = std::max(TexDesc.Width >> MipLevel, 1u); - FullExtentBox.MaxY = std::max(TexDesc.Height >> MipLevel, 1u); - if (TexDesc.Type == RESOURCE_DIM_TEX_3D) - FullExtentBox.MaxZ = std::max(TexDesc.Depth >> MipLevel, 1u); + auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel); + FullExtentBox.MaxX = MipLevelAttribs.Width; + FullExtentBox.MaxY = MipLevelAttribs.Height; + FullExtentBox.MaxZ = MipLevelAttribs.Depth; pMapRegion = &FullExtentBox; } @@ -1774,7 +1773,7 @@ namespace Diligent MappedData.pData = TextureVk.GetStagingDataCPUAddress() + MapStartOffset; MappedData.Stride = MipLevelAttribs.RowSize; - MappedData.DepthStride = MipLevelAttribs.RowSize * MipLevelAttribs.Height; + MappedData.DepthStride = MipLevelAttribs.DepthSliceSize; if (MapType == MAP_READ) { diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp index c6f336ee..dfed36b9 100644 --- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp @@ -30,37 +30,11 @@ #include "VulkanTypeConversions.h" #include "EngineMemory.h" #include "StringTools.h" +#include "GraphicsAccessories.h" namespace Diligent { -MipLevelProperties GetMipLevelProperties(const TextureDesc& TexDesc, Uint32 MipLevel) -{ - MipLevelProperties MipProps; - const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); - - MipProps.Width = std::max(TexDesc.Width >> MipLevel, 1u); - MipProps.Height = std::max(TexDesc.Height >> MipLevel, 1u); - MipProps.Depth = (TexDesc.Type == RESOURCE_DIM_TEX_3D) ? std::max(TexDesc.Depth >> MipLevel, 1u) : 1u; - if (FmtAttribs.ComponentType == COMPONENT_TYPE_COMPRESSED) - { - VERIFY_EXPR(FmtAttribs.BlockWidth > 1 && FmtAttribs.BlockHeight > 1); - VERIFY((FmtAttribs.BlockWidth & (FmtAttribs.BlockWidth-1)) == 0, "Compressed block widht is expected to be power of 2"); - VERIFY((FmtAttribs.BlockHeight & (FmtAttribs.BlockHeight-1)) == 0, "Compressed block widht is expected to be power of 2"); - // For block-compression formats, all parameters are still specified in texels rather than compressed texel blocks (18.4.1) - MipProps.Width = Align(MipProps.Width, Uint32{FmtAttribs.BlockWidth}); - MipProps.Height = Align(MipProps.Height,Uint32{FmtAttribs.BlockHeight}); - MipProps.RowSize = MipProps.Width / Uint32{FmtAttribs.BlockWidth} * Uint32{FmtAttribs.ComponentSize}; // ComponentSize is the block size - } - else - { - MipProps.RowSize = MipProps.Width * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents}; - } - MipProps.MipSize = MipProps.RowSize * MipProps.Height * MipProps.Depth; - - return MipProps; -} - TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, RenderDeviceVkImpl* pRenderDeviceVk, |
