Skip to content

Commit 6f1337d

Browse files
D3D12: fixed depth-stencil texture copies (close #679)
1 parent 701d3cc commit 6f1337d

File tree

6 files changed

+80
-39
lines changed

6 files changed

+80
-39
lines changed

Graphics/GraphicsEngine/include/TextureBase.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ class TextureBase : public DeviceObjectBase<typename EngineImplTraits::TextureIn
403403
static constexpr Uint8 InvalidViewIndex = 0xFFu;
404404
std::array<Uint8, TEXTURE_VIEW_NUM_VIEWS> m_ViewIndices{};
405405

406+
// The number of planes in the format. For majority of formats, this is 1.
407+
// Depth-stencil formats may have 2 planes (depth and stencil).
408+
// YUV formats may have 3 planes (Y, U, V).
409+
Uint8 m_FormatPlaneCount = 1;
410+
406411
RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN;
407412

408413
std::unique_ptr<SparseTextureProperties> m_pSparseProps;

Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,17 @@ class DeviceContextD3D12Impl final : public DeviceContextNextGenBase<EngineD3D12
308308
Uint64 NumBytes,
309309
RESOURCE_STATE_TRANSITION_MODE StateTransitionMode);
310310

311+
struct SubresCopyMapping
312+
{
313+
Uint32 Src = 0;
314+
Uint32 Dst = 0;
315+
};
311316
void CopyTextureRegion(class TextureD3D12Impl* pSrcTexture,
312-
Uint32 SrcSubResIndex,
313317
const D3D12_BOX* pD3D12SrcBox,
314318
RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode,
315319
class TextureD3D12Impl* pDstTexture,
316-
Uint32 DstSubResIndex,
320+
const SubresCopyMapping* Planes,
321+
Uint32 NumPlanes,
317322
Uint32 DstX,
318323
Uint32 DstY,
319324
Uint32 DstZ,

Graphics/GraphicsEngineD3D12/include/TextureD3D12Impl.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019-2022 Diligent Graphics LLC
2+
* Copyright 2019-2025 Diligent Graphics LLC
33
* Copyright 2015-2019 Egor Yusov
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -90,6 +90,11 @@ class TextureD3D12Impl final : public TextureBase<EngineD3D12ImplTraits>, public
9090
return m_Desc.Usage == USAGE_SPARSE && m_Desc.Type == RESOURCE_DIM_TEX_2D_ARRAY && m_pDevice->GetDummyNVApiHeap() != nullptr;
9191
}
9292

93+
Uint8 GetFormatPlaneCount() const
94+
{
95+
return m_FormatPlaneCount;
96+
}
97+
9398
protected:
9499
void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override final;
95100

Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "DeviceContextD3D12Impl.hpp"
3131

3232
#include <sstream>
33+
#include <array>
3334

3435
#include "RenderDeviceD3D12Impl.hpp"
3536
#include "PipelineStateD3D12Impl.hpp"
@@ -1957,19 +1958,29 @@ void DeviceContextD3D12Impl::CopyTexture(const CopyTextureAttribs& CopyAttribs)
19571958
pD3D12SrcBox = &D3D12SrcBox;
19581959
}
19591960

1960-
UINT DstSubResIndex = D3D12CalcSubresource(CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, 0, DstTexDesc.MipLevels, DstTexDesc.GetArraySize());
1961-
UINT SrcSubResIndex = D3D12CalcSubresource(CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, 0, SrcTexDesc.MipLevels, SrcTexDesc.GetArraySize());
1962-
CopyTextureRegion(pSrcTexD3D12, SrcSubResIndex, pD3D12SrcBox, CopyAttribs.SrcTextureTransitionMode,
1963-
pDstTexD3D12, DstSubResIndex, CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ,
1961+
static constexpr Uint32 MaxFormatPlaneCount = 2; // Depth and stencil planes
1962+
std::array<SubresCopyMapping, MaxFormatPlaneCount> Planes;
1963+
1964+
Uint32 NumPlanes = std::min(pSrcTexD3D12->GetFormatPlaneCount(), pDstTexD3D12->GetFormatPlaneCount());
1965+
VERIFY(NumPlanes <= MaxFormatPlaneCount, "Number of planes (", NumPlanes, ") exceeds maximum supported plane count (", MaxFormatPlaneCount, ")");
1966+
NumPlanes = std::min(NumPlanes, MaxFormatPlaneCount);
1967+
for (Uint32 i = 0; i < NumPlanes; ++i)
1968+
{
1969+
Planes[i].Dst = D3D12CalcSubresource(CopyAttribs.DstMipLevel, CopyAttribs.DstSlice, i, DstTexDesc.MipLevels, DstTexDesc.GetArraySize());
1970+
Planes[i].Src = D3D12CalcSubresource(CopyAttribs.SrcMipLevel, CopyAttribs.SrcSlice, i, SrcTexDesc.MipLevels, SrcTexDesc.GetArraySize());
1971+
}
1972+
CopyTextureRegion(pSrcTexD3D12, pD3D12SrcBox, CopyAttribs.SrcTextureTransitionMode, pDstTexD3D12,
1973+
Planes.data(), NumPlanes,
1974+
CopyAttribs.DstX, CopyAttribs.DstY, CopyAttribs.DstZ,
19641975
CopyAttribs.DstTextureTransitionMode);
19651976
}
19661977

19671978
void DeviceContextD3D12Impl::CopyTextureRegion(TextureD3D12Impl* pSrcTexture,
1968-
Uint32 SrcSubResIndex,
19691979
const D3D12_BOX* pD3D12SrcBox,
19701980
RESOURCE_STATE_TRANSITION_MODE SrcTextureTransitionMode,
19711981
TextureD3D12Impl* pDstTexture,
1972-
Uint32 DstSubResIndex,
1982+
const SubresCopyMapping* Planes,
1983+
Uint32 NumPlanes,
19731984
Uint32 DstX,
19741985
Uint32 DstY,
19751986
Uint32 DstZ,
@@ -1997,35 +2008,43 @@ void DeviceContextD3D12Impl::CopyTextureRegion(TextureD3D12Impl* pS
19972008
}
19982009
TransitionOrVerifyTextureState(CmdCtx, *pDstTexture, DstTextureTransitionMode, RESOURCE_STATE_COPY_DEST, "Using resource as copy destination (DeviceContextD3D12Impl::CopyTextureRegion)");
19992010

2000-
D3D12_TEXTURE_COPY_LOCATION DstLocation = {}, SrcLocation = {};
2011+
D3D12_TEXTURE_COPY_LOCATION DstLocation{};
2012+
D3D12_TEXTURE_COPY_LOCATION SrcLocation{};
20012013

20022014
SrcLocation.pResource = pSrcTexture->GetD3D12Resource();
2003-
if (pSrcTexture->GetDesc().Usage == USAGE_STAGING)
2004-
{
2005-
SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
2006-
SrcLocation.PlacedFootprint = pSrcTexture->GetStagingFootprint(SrcSubResIndex);
2007-
}
2008-
else
2009-
{
2010-
SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
2011-
SrcLocation.SubresourceIndex = SrcSubResIndex;
2012-
}
2013-
20142015
DstLocation.pResource = pDstTexture->GetD3D12Resource();
2015-
if (pDstTexture->GetDesc().Usage == USAGE_STAGING)
2016-
{
2017-
DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
2018-
DstLocation.PlacedFootprint = pDstTexture->GetStagingFootprint(DstSubResIndex);
2019-
}
2020-
else
2021-
{
2022-
DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
2023-
DstLocation.SubresourceIndex = DstSubResIndex;
2024-
}
20252016

20262017
CmdCtx.FlushResourceBarriers();
2027-
CmdCtx.GetCommandList()->CopyTextureRegion(&DstLocation, DstX, DstY, DstZ, &SrcLocation, pD3D12SrcBox);
2028-
++m_State.NumCommands;
2018+
2019+
for (Uint32 plane = 0; plane < NumPlanes; ++plane)
2020+
{
2021+
Uint32 SrcSubResIndex = Planes[plane].Src;
2022+
Uint32 DstSubResIndex = Planes[plane].Dst;
2023+
if (pSrcTexture->GetDesc().Usage == USAGE_STAGING)
2024+
{
2025+
SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
2026+
SrcLocation.PlacedFootprint = pSrcTexture->GetStagingFootprint(SrcSubResIndex);
2027+
}
2028+
else
2029+
{
2030+
SrcLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
2031+
SrcLocation.SubresourceIndex = SrcSubResIndex;
2032+
}
2033+
2034+
if (pDstTexture->GetDesc().Usage == USAGE_STAGING)
2035+
{
2036+
DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
2037+
DstLocation.PlacedFootprint = pDstTexture->GetStagingFootprint(DstSubResIndex);
2038+
}
2039+
else
2040+
{
2041+
DstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
2042+
DstLocation.SubresourceIndex = DstSubResIndex;
2043+
}
2044+
2045+
CmdCtx.GetCommandList()->CopyTextureRegion(&DstLocation, DstX, DstY, DstZ, &SrcLocation, pD3D12SrcBox);
2046+
++m_State.NumCommands;
2047+
}
20292048
}
20302049

20312050
void DeviceContextD3D12Impl::CopyTextureRegion(ID3D12Resource* pd3d12Buffer,

Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters,
152152
D3D12_RESOURCE_DESC d3d12TexDesc = GetD3D12TextureDesc();
153153
const bool bInitializeTexture = (pInitData != nullptr && pInitData->pSubResources != nullptr && pInitData->NumSubresources > 0);
154154

155+
ID3D12Device* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
156+
if (UINT8 FormatPlaneCount = D3D12GetFormatPlaneCount(pd3d12Device, d3d12TexDesc.Format))
157+
m_FormatPlaneCount = FormatPlaneCount;
158+
155159
const SoftwareQueueIndex CmdQueueInd = pInitData != nullptr && pInitData->pContext != nullptr ?
156160
ClassPtrCast<DeviceContextD3D12Impl>(pInitData->pContext)->GetCommandQueueId() :
157161
SoftwareQueueIndex{PlatformMisc::GetLSB(m_Desc.ImmediateContextMask)};
@@ -185,7 +189,6 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters,
185189
pClearValue = &ClearValue;
186190
}
187191

188-
ID3D12Device* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
189192
if (m_Desc.Usage == USAGE_SPARSE)
190193
{
191194
d3d12TexDesc.Layout = D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE;
@@ -506,6 +509,10 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters,
506509
m_pd3d12Resource = pTexture;
507510
SetState(InitialState);
508511

512+
ID3D12Device* pd3d12Device = pDeviceD3D12->GetD3D12Device();
513+
if (UINT8 FormatPlaneCount = D3D12GetFormatPlaneCount(pd3d12Device, m_pd3d12Resource->GetDesc().Format))
514+
m_FormatPlaneCount = FormatPlaneCount;
515+
509516
if (m_Desc.Usage == USAGE_SPARSE)
510517
InitSparseProperties();
511518
}

Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,10 @@ void TextureVkImpl::InitializeContentOnDevice(const TextureData& InitDa
469469
// bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion
470470
// of a larger two- or three-dimensional image, and control the addressing calculations of
471471
// data in buffer memory. If either of these values is zero, that aspect of the buffer memory
472-
// is considered to be tightly packed according to the imageExtent. (18.4)
472+
// is considered to be tightly packed according to the imageExtent.
473473
CopyRegion.bufferRowLength = 0;
474474
CopyRegion.bufferImageHeight = 0;
475-
// For block-compression formats, all parameters are still specified in texels rather than compressed texel blocks (18.4.1)
475+
// For block-compression formats, all parameters are still specified in texels rather than compressed texel blocks
476476
CopyRegion.imageOffset = VkOffset3D{0, 0, 0};
477477
CopyRegion.imageExtent = VkExtent3D{MipInfo.LogicalWidth, MipInfo.LogicalHeight, MipInfo.Depth};
478478

@@ -485,9 +485,9 @@ void TextureVkImpl::InitializeContentOnDevice(const TextureData& InitDa
485485
// For compressed-block formats, MipInfo.RowSize is the size of one row of blocks
486486
VERIFY(SubResData.DepthStride == 0 || SubResData.DepthStride >= (MipInfo.StorageHeight / FmtAttribs.BlockHeight) * MipInfo.RowSize, "Depth stride is too small");
487487

488-
// bufferOffset must be a multiple of 4 (18.4)
488+
// bufferOffset must be a multiple of 4
489489
// If the calling command's VkImage parameter is a compressed image, bufferOffset
490-
// must be a multiple of the compressed texel block size in bytes (18.4). This
490+
// must be a multiple of the compressed texel block size in bytes. This
491491
// is automatically guaranteed as MipWidth and MipHeight are rounded to block size
492492
uploadBufferSize += (MipInfo.MipSize + 3) & (~3);
493493
++subres;
@@ -569,7 +569,7 @@ void TextureVkImpl::InitializeContentOnDevice(const TextureData& InitDa
569569
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
570570
// as copy will be the only command in the cmd buffer
571571
CmdBuffer.CopyBufferToImage(StagingBuffer, m_VulkanImage,
572-
CurrentLayout, // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
572+
CurrentLayout, // dstImageLayout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL
573573
static_cast<uint32_t>(Regions.size()), Regions.data());
574574

575575
GetDevice()->ExecuteAndDisposeTransientCmdBuff(CmdQueueInd, CmdBuffer.GetVkCmdBuffer(), std::move(CmdPool));

0 commit comments

Comments
 (0)