diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-01-01 01:28:00 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-01-01 01:28:00 +0000 |
| commit | ed0b353acbb104cbb94347adf1b4ea5628c3c221 (patch) | |
| tree | c1eae288ed44e18fad4bb243f223e96a12676ead /Graphics | |
| parent | Improvements for mesh shader & ray tracing (#180) (diff) | |
| download | DiligentCore-ed0b353acbb104cbb94347adf1b4ea5628c3c221.tar.gz DiligentCore-ed0b353acbb104cbb94347adf1b4ea5628c3c221.zip | |
Implemented initialization of staging textures in D3D12 and Vulkan backends
Diffstat (limited to 'Graphics')
4 files changed, 118 insertions, 8 deletions
diff --git a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp index 130a8f61..1312c9df 100644 --- a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp +++ b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp @@ -573,4 +573,22 @@ BufferToTextureCopyInfo GetBufferToTextureCopyInfo(const TextureDesc& TexDesc, const Box& Region, Uint32 RowStrideAlignment); + +/// Copies texture subresource data on the CPU. + +/// \param [in] SrcSubres - Source subresource data. +/// \param [in] NumRows - The number of rows in the subresource. +/// \param [in] NumDepthSlices - The number of depth slices in the subresource. +/// \param [in] RowSize - Subresource data row size, in bytes. +/// \param [in] pDstData - Pointer to the destination subresource data. +/// \param [in] DstRowStride - Destination subresource row stride, in bytes. +/// \param [in] DstDepthStride - Destination subresource depth stride, in bytes. +void CopyTextureSubresource(const TextureSubResData& SrcSubres, + Uint32 NumRows, + Uint32 NumDepthSlices, + Uint32 RowSize, + void* pDstData, + Uint32 DstRowStride, + Uint32 DstDepthStride); + } // namespace Diligent diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 3b114655..08725c86 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1449,6 +1449,7 @@ Uint32 GetStagingTextureLocationOffset(const TextureDesc& TexDesc, Uint32 LocationY, Uint32 LocationZ) { + VERIFY_EXPR(TexDesc.MipLevels > 0 && TexDesc.ArraySize > 0 && TexDesc.Width > 0 && TexDesc.Height > 0 && TexDesc.Format != TEX_FORMAT_UNKNOWN); VERIFY_EXPR(ArraySlice < TexDesc.ArraySize && MipLevel < TexDesc.MipLevels || ArraySlice == TexDesc.ArraySize && MipLevel == 0); Uint32 Offset = 0; @@ -1552,4 +1553,31 @@ BufferToTextureCopyInfo GetBufferToTextureCopyInfo(const TextureDesc& TexDesc, return CopyInfo; } + +void CopyTextureSubresource(const TextureSubResData& SrcSubres, + Uint32 NumRows, + Uint32 NumDepthSlices, + Uint32 RowSize, + void* pDstData, + Uint32 DstRowStride, + Uint32 DstDepthStride) +{ + VERIFY_EXPR(SrcSubres.pSrcBuffer == nullptr && SrcSubres.pData != nullptr); + VERIFY_EXPR(pDstData != nullptr); + VERIFY(SrcSubres.Stride >= RowSize, "Source data row stride (", SrcSubres.Stride, ") is smaller than the row size (", RowSize, ")"); + VERIFY(DstRowStride >= RowSize, "Dst data row stride (", DstRowStride, ") is smaller than the row size (", RowSize, ")"); + for (Uint32 z = 0; z < NumDepthSlices; ++z) + { + const auto* pSrcSlice = reinterpret_cast<const Uint8*>(SrcSubres.pData) + SrcSubres.DepthStride * z; + auto* pDstSlice = reinterpret_cast<Uint8*>(pDstData) + DstDepthStride * z; + + for (Uint32 y = 0; y < NumRows; ++y) + { + memcpy(pDstSlice + DstRowStride * y, + pSrcSlice + SrcSubres.Stride * y, + RowSize); + } + } +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index 358f3b4d..496255e5 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -148,7 +148,8 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, D3D12_RESOURCE_DESC Desc = GetD3D12TextureDesc(); - auto* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device(); + auto* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device(); + bool bInitializeTexture = (pInitData != nullptr && pInitData->pSubResources != nullptr && pInitData->NumSubresources > 0); if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC) { D3D12_CLEAR_VALUE ClearValue = {}; @@ -184,8 +185,7 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, HeapProps.CreationNodeMask = 1; HeapProps.VisibleNodeMask = 1; - bool bInitializeTexture = (pInitData != nullptr && pInitData->pSubResources != nullptr && pInitData->NumSubresources > 0); - auto InitialState = bInitializeTexture ? RESOURCE_STATE_COPY_DEST : RESOURCE_STATE_UNDEFINED; + auto InitialState = bInitializeTexture ? RESOURCE_STATE_COPY_DEST : RESOURCE_STATE_UNDEFINED; SetState(InitialState); auto D3D12State = ResourceStateFlagsToD3D12ResourceStates(InitialState); auto hr = @@ -289,6 +289,7 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, RESOURCE_STATE InitialState = RESOURCE_STATE_UNKNOWN; if (m_Desc.CPUAccessFlags & CPU_ACCESS_READ) { + DEV_CHECK_ERR(!bInitializeTexture, "Readback textures should not be initialized with data"); StaginHeapProps.Type = D3D12_HEAP_TYPE_READBACK; InitialState = RESOURCE_STATE_COPY_DEST; } @@ -337,6 +338,41 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, nullptr, __uuidof(m_pd3d12Resource), reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&m_pd3d12Resource))); if (FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create staging buffer"); + + if (bInitializeTexture) + { + const auto FmtAttribs = GetTextureFormatAttribs(TexDesc.Format); + + void* pStagingData = nullptr; + m_pd3d12Resource->Map(0, nullptr, &pStagingData); + DEV_CHECK_ERR(pStagingData != nullptr, "Failed to map staging buffer"); + if (pStagingData != nullptr) + { + for (Uint32 Subres = 0; Subres < NumSubresources; ++Subres) + { + const auto Mip = Subres % m_Desc.MipLevels; + const auto MipProps = GetMipLevelProperties(m_Desc, Mip); + + const auto& SrcSubresData = pInitData->pSubResources[Subres]; + const auto& DstFootprint = GetStagingFootprint(Subres); + + VERIFY_EXPR(MipProps.StorageWidth == DstFootprint.Footprint.Width); + VERIFY_EXPR(MipProps.StorageHeight == DstFootprint.Footprint.Height); + VERIFY_EXPR(MipProps.Depth == DstFootprint.Footprint.Depth); + + CopyTextureSubresource(SrcSubresData, + MipProps.StorageHeight / FmtAttribs.BlockHeight, // NumRows + MipProps.Depth, + MipProps.RowSize, + reinterpret_cast<Uint8*>(pStagingData) + DstFootprint.Offset, + DstFootprint.Footprint.RowPitch, + DstFootprint.Footprint.RowPitch * DstFootprint.Footprint.Height / FmtAttribs.BlockHeight // DstDepthStride + ); + } + } + D3D12_RANGE FlushRange{0, stagingBufferSize}; + m_pd3d12Resource->Unmap(0, &FlushRange); + } } else { @@ -355,8 +391,8 @@ static TextureDesc InitTexDescFromD3D12Resource(ID3D12Resource* pTexture, const else { auto RefFormat = DXGI_FormatToTexFormat(ResourceDesc.Format); - DEV_CHECK_ERR(RefFormat == TexDesc.Format, "The format specified by texture description (", GetTextureFormatAttribs(TexDesc.Format).Name, ")" - " does not match the D3D12 resource format (", + DEV_CHECK_ERR(RefFormat == TexDesc.Format, "The format specified by texture description (", GetTextureFormatAttribs(TexDesc.Format).Name, + ") does not match the D3D12 resource format (", GetTextureFormatAttribs(RefFormat).Name, ")"); (void)RefFormat; } @@ -384,7 +420,7 @@ static TextureDesc InitTexDescFromD3D12Resource(ID3D12Resource* pTexture, const TexDesc.BindFlags |= BIND_UNORDERED_ACCESS; if ((ResourceDesc.Flags & D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE) == 0) { - auto FormatAttribs = GetTextureFormatAttribs(TexDesc.Format); + const auto& FormatAttribs = GetTextureFormatAttribs(TexDesc.Format); if (FormatAttribs.IsTypeless || (FormatAttribs.ComponentType != COMPONENT_TYPE_DEPTH && FormatAttribs.ComponentType != COMPONENT_TYPE_DEPTH_STENCIL)) diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp index 8445617b..b83be298 100644 --- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp @@ -60,6 +60,7 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format); const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); + const bool bInitializeTexture = (pInitData != nullptr && pInitData->pSubResources != nullptr && pInitData->NumSubresources > 0); if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC) { VkImageCreateInfo ImageCI = {}; @@ -178,8 +179,6 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, // and the transition away from this layout is not guaranteed to preserve that data. ImageCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - bool bInitializeTexture = (pInitData != nullptr && pInitData->pSubResources != nullptr && pInitData->NumSubresources > 0); - m_VulkanImage = LogicalDevice.CreateImage(ImageCI, m_Desc.Name); VkMemoryRequirements MemReqs = LogicalDevice.GetImageMemoryRequirements(m_VulkanImage); @@ -418,6 +417,8 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, VkMemoryPropertyFlags MemProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT; if (m_Desc.CPUAccessFlags & CPU_ACCESS_READ) { + DEV_CHECK_ERR(!bInitializeTexture, "Readback textures should not be initialized with data"); + VkStagingBuffCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; MemProperties |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT; SetState(RESOURCE_STATE_COPY_DEST); @@ -461,6 +462,33 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory"); m_StagingDataAlignedOffset = AlignedStagingMemOffset; + + if (bInitializeTexture) + { + uint8_t* const pStagingData = GetStagingDataCPUAddress(); + + Uint32 subres = 0; + for (Uint32 layer = 0; layer < m_Desc.ArraySize; ++layer) + { + for (Uint32 mip = 0; mip < m_Desc.MipLevels; ++mip) + { + const auto& SubResData = pInitData->pSubResources[subres++]; + const auto MipProps = GetMipLevelProperties(m_Desc, mip); + + const auto DstSubresOffset = + GetStagingTextureSubresourceOffset(m_Desc, layer, mip, StagingBufferOffsetAlignment); + + CopyTextureSubresource(SubResData, + MipProps.StorageHeight / FmtAttribs.BlockHeight, // NumRows + MipProps.Depth, + MipProps.RowSize, + pStagingData + DstSubresOffset, + MipProps.RowSize, // DstRowStride + MipProps.DepthSliceSize // DstDepthStride + ); + } + } + } } else { |
