summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-01-01 01:28:00 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-01-01 01:28:00 +0000
commited0b353acbb104cbb94347adf1b4ea5628c3c221 (patch)
treec1eae288ed44e18fad4bb243f223e96a12676ead /Graphics
parentImprovements for mesh shader & ray tracing (#180) (diff)
downloadDiligentCore-ed0b353acbb104cbb94347adf1b4ea5628c3c221.tar.gz
DiligentCore-ed0b353acbb104cbb94347adf1b4ea5628c3c221.zip
Implemented initialization of staging textures in D3D12 and Vulkan backends
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp18
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp28
-rw-r--r--Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp48
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp32
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
{