Path: blob/master/thirdparty/directx_headers/include/directx/d3dx12_resource_helpers.h
9906 views
//*********************************************************1//2// Copyright (c) Microsoft Corporation.3// Licensed under the MIT License (MIT).4//5//*********************************************************67#pragma once89#ifndef __cplusplus10#error D3DX12 requires C++11#endif1213#include "d3d12.h"14#include "d3dx12_core.h"15#include "d3dx12_property_format_table.h"16//------------------------------------------------------------------------------------------------17template <typename T, typename U, typename V>18inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) noexcept19{20MipSlice = static_cast<T>(Subresource % MipLevels);21ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);22PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));23}2425//------------------------------------------------------------------------------------------------26// Row-by-row memcpy27inline void MemcpySubresource(28_In_ const D3D12_MEMCPY_DEST* pDest,29_In_ const D3D12_SUBRESOURCE_DATA* pSrc,30SIZE_T RowSizeInBytes,31UINT NumRows,32UINT NumSlices) noexcept33{34for (UINT z = 0; z < NumSlices; ++z)35{36auto pDestSlice = static_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;37auto pSrcSlice = static_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * LONG_PTR(z);38for (UINT y = 0; y < NumRows; ++y)39{40memcpy(pDestSlice + pDest->RowPitch * y,41pSrcSlice + pSrc->RowPitch * LONG_PTR(y),42RowSizeInBytes);43}44}45}4647//------------------------------------------------------------------------------------------------48// Row-by-row memcpy49inline void MemcpySubresource(50_In_ const D3D12_MEMCPY_DEST* pDest,51_In_ const void* pResourceData,52_In_ const D3D12_SUBRESOURCE_INFO* pSrc,53SIZE_T RowSizeInBytes,54UINT NumRows,55UINT NumSlices) noexcept56{57for (UINT z = 0; z < NumSlices; ++z)58{59auto pDestSlice = static_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;60auto pSrcSlice = (static_cast<const BYTE*>(pResourceData) + pSrc->Offset) + pSrc->DepthPitch * ULONG_PTR(z);61for (UINT y = 0; y < NumRows; ++y)62{63memcpy(pDestSlice + pDest->RowPitch * y,64pSrcSlice + pSrc->RowPitch * ULONG_PTR(y),65RowSizeInBytes);66}67}68}6970//------------------------------------------------------------------------------------------------71// Returns required size of a buffer to be used for data upload72inline UINT64 GetRequiredIntermediateSize(73_In_ ID3D12Resource* pDestinationResource,74_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,75_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) noexcept76{77#if defined(_MSC_VER) || !defined(_WIN32)78const auto Desc = pDestinationResource->GetDesc();79#else80D3D12_RESOURCE_DESC tmpDesc;81const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);82#endif83UINT64 RequiredSize = 0;8485ID3D12Device* pDevice = nullptr;86pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));87pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);88pDevice->Release();8990return RequiredSize;91}9293//------------------------------------------------------------------------------------------------94// All arrays must be populated (e.g. by calling GetCopyableFootprints)95inline UINT64 UpdateSubresources(96_In_ ID3D12GraphicsCommandList* pCmdList,97_In_ ID3D12Resource* pDestinationResource,98_In_ ID3D12Resource* pIntermediate,99_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,100_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,101UINT64 RequiredSize,102_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,103_In_reads_(NumSubresources) const UINT* pNumRows,104_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,105_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept106{107// Minor validation108#if defined(_MSC_VER) || !defined(_WIN32)109const auto IntermediateDesc = pIntermediate->GetDesc();110const auto DestinationDesc = pDestinationResource->GetDesc();111#else112D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2;113const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1);114const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2);115#endif116if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||117IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||118RequiredSize > SIZE_T(-1) ||119(DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&120(FirstSubresource != 0 || NumSubresources != 1)))121{122return 0;123}124125BYTE* pData;126HRESULT hr = pIntermediate->Map(0, nullptr, reinterpret_cast<void**>(&pData));127if (FAILED(hr))128{129return 0;130}131132for (UINT i = 0; i < NumSubresources; ++i)133{134if (pRowSizesInBytes[i] > SIZE_T(-1)) return 0;135D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, SIZE_T(pLayouts[i].Footprint.RowPitch) * SIZE_T(pNumRows[i]) };136MemcpySubresource(&DestData, &pSrcData[i], static_cast<SIZE_T>(pRowSizesInBytes[i]), pNumRows[i], pLayouts[i].Footprint.Depth);137}138pIntermediate->Unmap(0, nullptr);139140if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)141{142pCmdList->CopyBufferRegion(143pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);144}145else146{147for (UINT i = 0; i < NumSubresources; ++i)148{149const CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);150const CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);151pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);152}153}154return RequiredSize;155}156157//------------------------------------------------------------------------------------------------158// All arrays must be populated (e.g. by calling GetCopyableFootprints)159inline UINT64 UpdateSubresources(160_In_ ID3D12GraphicsCommandList* pCmdList,161_In_ ID3D12Resource* pDestinationResource,162_In_ ID3D12Resource* pIntermediate,163_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,164_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,165UINT64 RequiredSize,166_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,167_In_reads_(NumSubresources) const UINT* pNumRows,168_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,169_In_ const void* pResourceData,170_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept171{172// Minor validation173#if defined(_MSC_VER) || !defined(_WIN32)174const auto IntermediateDesc = pIntermediate->GetDesc();175const auto DestinationDesc = pDestinationResource->GetDesc();176#else177D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2;178const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1);179const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2);180#endif181if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||182IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||183RequiredSize > SIZE_T(-1) ||184(DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&185(FirstSubresource != 0 || NumSubresources != 1)))186{187return 0;188}189190BYTE* pData;191HRESULT hr = pIntermediate->Map(0, nullptr, reinterpret_cast<void**>(&pData));192if (FAILED(hr))193{194return 0;195}196197for (UINT i = 0; i < NumSubresources; ++i)198{199if (pRowSizesInBytes[i] > SIZE_T(-1)) return 0;200D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, SIZE_T(pLayouts[i].Footprint.RowPitch) * SIZE_T(pNumRows[i]) };201MemcpySubresource(&DestData, pResourceData, &pSrcData[i], static_cast<SIZE_T>(pRowSizesInBytes[i]), pNumRows[i], pLayouts[i].Footprint.Depth);202}203pIntermediate->Unmap(0, nullptr);204205if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)206{207pCmdList->CopyBufferRegion(208pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);209}210else211{212for (UINT i = 0; i < NumSubresources; ++i)213{214const CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);215const CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);216pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);217}218}219return RequiredSize;220}221222//------------------------------------------------------------------------------------------------223// Heap-allocating UpdateSubresources implementation224inline UINT64 UpdateSubresources(225_In_ ID3D12GraphicsCommandList* pCmdList,226_In_ ID3D12Resource* pDestinationResource,227_In_ ID3D12Resource* pIntermediate,228UINT64 IntermediateOffset,229_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,230_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,231_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept232{233UINT64 RequiredSize = 0;234const auto MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;235if (MemToAlloc > SIZE_MAX)236{237return 0;238}239void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));240if (pMem == nullptr)241{242return 0;243}244auto pLayouts = static_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);245auto pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);246auto pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);247248#if defined(_MSC_VER) || !defined(_WIN32)249const auto Desc = pDestinationResource->GetDesc();250#else251D3D12_RESOURCE_DESC tmpDesc;252const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);253#endif254ID3D12Device* pDevice = nullptr;255pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));256pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);257pDevice->Release();258259const UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);260HeapFree(GetProcessHeap(), 0, pMem);261return Result;262}263264//------------------------------------------------------------------------------------------------265// Heap-allocating UpdateSubresources implementation266inline UINT64 UpdateSubresources(267_In_ ID3D12GraphicsCommandList* pCmdList,268_In_ ID3D12Resource* pDestinationResource,269_In_ ID3D12Resource* pIntermediate,270UINT64 IntermediateOffset,271_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,272_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,273_In_ const void* pResourceData,274_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept275{276UINT64 RequiredSize = 0;277const auto MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;278if (MemToAlloc > SIZE_MAX)279{280return 0;281}282void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));283if (pMem == nullptr)284{285return 0;286}287auto pLayouts = static_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);288auto pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);289auto pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);290291#if defined(_MSC_VER) || !defined(_WIN32)292const auto Desc = pDestinationResource->GetDesc();293#else294D3D12_RESOURCE_DESC tmpDesc;295const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);296#endif297ID3D12Device* pDevice = nullptr;298pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));299pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);300pDevice->Release();301302const UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pResourceData, pSrcData);303HeapFree(GetProcessHeap(), 0, pMem);304return Result;305}306307//------------------------------------------------------------------------------------------------308// Stack-allocating UpdateSubresources implementation309template <UINT MaxSubresources>310inline UINT64 UpdateSubresources(311_In_ ID3D12GraphicsCommandList* pCmdList,312_In_ ID3D12Resource* pDestinationResource,313_In_ ID3D12Resource* pIntermediate,314UINT64 IntermediateOffset,315_In_range_(0,MaxSubresources) UINT FirstSubresource,316_In_range_(1,MaxSubresources-FirstSubresource) UINT NumSubresources,317_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept318{319UINT64 RequiredSize = 0;320D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];321UINT NumRows[MaxSubresources];322UINT64 RowSizesInBytes[MaxSubresources];323324#if defined(_MSC_VER) || !defined(_WIN32)325const auto Desc = pDestinationResource->GetDesc();326#else327D3D12_RESOURCE_DESC tmpDesc;328const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);329#endif330ID3D12Device* pDevice = nullptr;331pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));332pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);333pDevice->Release();334335return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);336}337338//------------------------------------------------------------------------------------------------339// Stack-allocating UpdateSubresources implementation340template <UINT MaxSubresources>341inline UINT64 UpdateSubresources(342_In_ ID3D12GraphicsCommandList* pCmdList,343_In_ ID3D12Resource* pDestinationResource,344_In_ ID3D12Resource* pIntermediate,345UINT64 IntermediateOffset,346_In_range_(0,MaxSubresources) UINT FirstSubresource,347_In_range_(1,MaxSubresources-FirstSubresource) UINT NumSubresources,348_In_ const void* pResourceData,349_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept350{351UINT64 RequiredSize = 0;352D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];353UINT NumRows[MaxSubresources];354UINT64 RowSizesInBytes[MaxSubresources];355356#if defined(_MSC_VER) || !defined(_WIN32)357const auto Desc = pDestinationResource->GetDesc();358#else359D3D12_RESOURCE_DESC tmpDesc;360const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);361#endif362ID3D12Device* pDevice = nullptr;363pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));364pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);365pDevice->Release();366367return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pResourceData, pSrcData);368}369370//------------------------------------------------------------------------------------------------371constexpr bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) noexcept372{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }373374//------------------------------------------------------------------------------------------------375template< typename T >376inline T D3DX12Align(T uValue, T uAlign)377{378// Assert power of 2 alignment379D3DX12_ASSERT(0 == (uAlign & (uAlign - 1)));380T uMask = uAlign - 1;381T uResult = (uValue + uMask) & ~uMask;382D3DX12_ASSERT(uResult >= uValue);383D3DX12_ASSERT(0 == (uResult % uAlign));384return uResult;385}386387//------------------------------------------------------------------------------------------------388template< typename T >389inline T D3DX12AlignAtLeast(T uValue, T uAlign)390{391T aligned = D3DX12Align(uValue, uAlign);392return aligned > uAlign ? aligned : uAlign;393}394395inline const CD3DX12_RESOURCE_DESC1* D3DX12ConditionallyExpandAPIDesc(396D3D12_RESOURCE_DESC1& LclDesc,397const D3D12_RESOURCE_DESC1* pDesc)398{399return D3DX12ConditionallyExpandAPIDesc(static_cast<CD3DX12_RESOURCE_DESC1&>(LclDesc), static_cast<const CD3DX12_RESOURCE_DESC1*>(pDesc));400}401402#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 606)403//------------------------------------------------------------------------------------------------404// The difference between D3DX12GetCopyableFootprints and ID3D12Device::GetCopyableFootprints405// is that this one loses a lot of error checking by assuming the arguments are correct406inline bool D3DX12GetCopyableFootprints(407_In_ const D3D12_RESOURCE_DESC1& ResourceDesc,408_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,409_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,410UINT64 BaseOffset,411_Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,412_Out_writes_opt_(NumSubresources) UINT* pNumRows,413_Out_writes_opt_(NumSubresources) UINT64* pRowSizeInBytes,414_Out_opt_ UINT64* pTotalBytes)415{416constexpr UINT64 uint64_max = ~0ull;417UINT64 TotalBytes = uint64_max;418UINT uSubRes = 0;419420bool bResourceOverflow = false;421TotalBytes = 0;422423const DXGI_FORMAT Format = ResourceDesc.Format;424425CD3DX12_RESOURCE_DESC1 LresourceDesc;426const CD3DX12_RESOURCE_DESC1& resourceDesc = *D3DX12ConditionallyExpandAPIDesc(LresourceDesc, &ResourceDesc);427428// Check if its a valid format429D3DX12_ASSERT(D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::FormatExists(Format));430431const UINT WidthAlignment = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetWidthAlignment( Format );432const UINT HeightAlignment = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetHeightAlignment( Format );433const UINT16 DepthAlignment = UINT16( D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetDepthAlignment( Format ) );434435for (; uSubRes < NumSubresources; ++uSubRes)436{437bool bOverflow = false;438UINT Subresource = FirstSubresource + uSubRes;439440D3DX12_ASSERT(resourceDesc.MipLevels != 0);441UINT subresourceCount = resourceDesc.MipLevels * resourceDesc.ArraySize() * D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetPlaneCount(resourceDesc.Format);442443if (Subresource > subresourceCount)444{445break;446}447448TotalBytes = D3DX12Align< UINT64 >( TotalBytes, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT );449450UINT MipLevel, ArraySlice, PlaneSlice;451D3D12DecomposeSubresource(Subresource, resourceDesc.MipLevels, resourceDesc.ArraySize(), /*_Out_*/MipLevel, /*_Out_*/ArraySlice, /*_Out_*/PlaneSlice);452453const UINT64 Width = D3DX12AlignAtLeast<UINT64>(resourceDesc.Width >> MipLevel, WidthAlignment);454const UINT Height = D3DX12AlignAtLeast(resourceDesc.Height >> MipLevel, HeightAlignment);455const UINT16 Depth = D3DX12AlignAtLeast<UINT16>(resourceDesc.Depth() >> MipLevel, DepthAlignment);456457// Adjust for the current PlaneSlice. Most formats have only one plane.458DXGI_FORMAT PlaneFormat;459UINT32 MinPlanePitchWidth, PlaneWidth, PlaneHeight;460D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetPlaneSubsampledSizeAndFormatForCopyableLayout(PlaneSlice, Format, (UINT)Width, Height, /*_Out_*/ PlaneFormat, /*_Out_*/ MinPlanePitchWidth, /* _Out_ */ PlaneWidth, /*_Out_*/ PlaneHeight);461462D3D12_SUBRESOURCE_FOOTPRINT LocalPlacement;463auto& Placement = pLayouts ? pLayouts[uSubRes].Footprint : LocalPlacement;464Placement.Format = PlaneFormat;465Placement.Width = PlaneWidth;466Placement.Height = PlaneHeight;467Placement.Depth = Depth;468469// Calculate row pitch470UINT MinPlaneRowPitch = 0;471D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, MinPlanePitchWidth, MinPlaneRowPitch);472473// Formats with more than one plane choose a larger pitch alignment to ensure that each plane begins on the row474// immediately following the previous plane while still adhering to subresource alignment restrictions.475static_assert( D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT >= D3D12_TEXTURE_DATA_PITCH_ALIGNMENT476&& ((D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) == 0),477"D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT must be >= and evenly divisible by D3D12_TEXTURE_DATA_PITCH_ALIGNMENT." );478479Placement.RowPitch = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format)480? D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT )481: D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT );482483if (pRowSizeInBytes)484{485UINT PlaneRowSize = 0;486D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, PlaneWidth, PlaneRowSize);487488pRowSizeInBytes[uSubRes] = PlaneRowSize;489}490491// Number of rows (accounting for block compression and additional planes)492UINT NumRows = 0;493if (D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format))494{495NumRows = PlaneHeight;496}497else498{499D3DX12_ASSERT(Height % HeightAlignment == 0);500NumRows = Height / HeightAlignment;501}502503if (pNumRows)504{505pNumRows[uSubRes] = NumRows;506}507508// Offsetting509if (pLayouts)510{511pLayouts[uSubRes].Offset = (bOverflow ? uint64_max : TotalBytes + BaseOffset);512}513514const UINT16 NumSlices = Depth;515const UINT64 SubresourceSize = (NumRows * NumSlices - 1) * Placement.RowPitch + MinPlaneRowPitch;516517// uint64 addition with overflow checking518TotalBytes = TotalBytes + SubresourceSize;519if(TotalBytes < SubresourceSize)520{521TotalBytes = uint64_max;522}523bResourceOverflow = bResourceOverflow || bOverflow;524}525526// Overflow error527if (bResourceOverflow)528{529TotalBytes = uint64_max;530}531532533if (pLayouts)534{535memset( pLayouts + uSubRes, -1, sizeof( *pLayouts ) * (NumSubresources - uSubRes) );536}537if (pNumRows)538{539memset(pNumRows + uSubRes, -1, sizeof(*pNumRows) * (NumSubresources - uSubRes));540}541if (pRowSizeInBytes)542{543memset(pRowSizeInBytes + uSubRes, -1, sizeof(*pRowSizeInBytes) * (NumSubresources - uSubRes));544}545if (pTotalBytes)546{547*pTotalBytes = TotalBytes;548}549if(TotalBytes == uint64_max)550{551return false;552}553return true;554}555556//------------------------------------------------------------------------------------------------557inline D3D12_RESOURCE_DESC1 D3DX12ResourceDesc0ToDesc1(D3D12_RESOURCE_DESC const& desc0)558{559D3D12_RESOURCE_DESC1 desc1;560desc1.Dimension = desc0.Dimension;561desc1.Alignment = desc0.Alignment;562desc1.Width = desc0.Width;563desc1.Height = desc0.Height;564desc1.DepthOrArraySize = desc0.DepthOrArraySize;565desc1.MipLevels = desc0.MipLevels;566desc1.Format = desc0.Format;567desc1.SampleDesc.Count = desc0.SampleDesc.Count;568desc1.SampleDesc.Quality = desc0.SampleDesc.Quality;569desc1.Layout = desc0.Layout;570desc1.Flags = desc0.Flags;571desc1.SamplerFeedbackMipRegion.Width = 0;572desc1.SamplerFeedbackMipRegion.Height = 0;573desc1.SamplerFeedbackMipRegion.Depth = 0;574return desc1;575}576577//------------------------------------------------------------------------------------------------578inline bool D3DX12GetCopyableFootprints(579_In_ const D3D12_RESOURCE_DESC& pResourceDesc,580_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,581_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,582UINT64 BaseOffset,583_Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,584_Out_writes_opt_(NumSubresources) UINT* pNumRows,585_Out_writes_opt_(NumSubresources) UINT64* pRowSizeInBytes,586_Out_opt_ UINT64* pTotalBytes)587{588// From D3D12_RESOURCE_DESC to D3D12_RESOURCE_DESC1589D3D12_RESOURCE_DESC1 desc = D3DX12ResourceDesc0ToDesc1(pResourceDesc);590return D3DX12GetCopyableFootprints(591*static_cast<CD3DX12_RESOURCE_DESC1*>(&desc),// From D3D12_RESOURCE_DESC1 to CD3DX12_RESOURCE_DESC1592FirstSubresource,593NumSubresources,594BaseOffset,595pLayouts,596pNumRows,597pRowSizeInBytes,598pTotalBytes);599}600601#endif // D3D12_SDK_VERSION >= 606602603604