Path: blob/master/thirdparty/directx_headers/include/directx/d3dx12_resource_helpers.h
22004 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 "d3dx12_property_format_table.h"14#include "d3d12.h"15#include "d3dx12_core.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,398const bool tightAlignmentSupported = false,399const bool alignAsCommitted = false)400{401return D3DX12ConditionallyExpandAPIDesc(static_cast<CD3DX12_RESOURCE_DESC1&>(LclDesc), static_cast<const CD3DX12_RESOURCE_DESC1*>(pDesc), tightAlignmentSupported, alignAsCommitted);402}403404#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 606)405//------------------------------------------------------------------------------------------------406// The difference between D3DX12GetCopyableFootprints and ID3D12Device::GetCopyableFootprints407// is that this one loses a lot of error checking by assuming the arguments are correct408inline bool D3DX12GetCopyableFootprints(409_In_ const D3D12_RESOURCE_DESC1& ResourceDesc,410_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,411_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,412UINT64 BaseOffset,413_Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,414_Out_writes_opt_(NumSubresources) UINT* pNumRows,415_Out_writes_opt_(NumSubresources) UINT64* pRowSizeInBytes,416_Out_opt_ UINT64* pTotalBytes)417{418constexpr UINT64 uint64_max = ~0ull;419UINT64 TotalBytes = uint64_max;420UINT uSubRes = 0;421422bool bResourceOverflow = false;423TotalBytes = 0;424425const DXGI_FORMAT Format = ResourceDesc.Format;426427CD3DX12_RESOURCE_DESC1 LresourceDesc;428const CD3DX12_RESOURCE_DESC1& resourceDesc = *D3DX12ConditionallyExpandAPIDesc(LresourceDesc, &ResourceDesc);429430// Check if its a valid format431D3DX12_ASSERT(D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::FormatExists(Format));432433// D3DX12GetCopyableFootprints does not support buffers with width larger than UINT_MAX.434if (ResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && ResourceDesc.Width >= UINT_MAX)435{436return false;437}438439const UINT WidthAlignment = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetWidthAlignment( Format );440const UINT HeightAlignment = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetHeightAlignment( Format );441const UINT16 DepthAlignment = UINT16( D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetDepthAlignment( Format ) );442443for (; uSubRes < NumSubresources; ++uSubRes)444{445bool bOverflow = false;446UINT Subresource = FirstSubresource + uSubRes;447448D3DX12_ASSERT(resourceDesc.MipLevels != 0);449UINT subresourceCount = resourceDesc.MipLevels * resourceDesc.ArraySize() * D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetPlaneCount(resourceDesc.Format);450451if (Subresource > subresourceCount)452{453break;454}455456TotalBytes = D3DX12Align< UINT64 >( TotalBytes, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT );457458UINT MipLevel, ArraySlice, PlaneSlice;459D3D12DecomposeSubresource(Subresource, resourceDesc.MipLevels, resourceDesc.ArraySize(), /*_Out_*/MipLevel, /*_Out_*/ArraySlice, /*_Out_*/PlaneSlice);460461const UINT64 Width = D3DX12AlignAtLeast<UINT64>(resourceDesc.Width >> MipLevel, WidthAlignment);462const UINT Height = D3DX12AlignAtLeast(resourceDesc.Height >> MipLevel, HeightAlignment);463const UINT16 Depth = D3DX12AlignAtLeast<UINT16>(resourceDesc.Depth() >> MipLevel, DepthAlignment);464465// Adjust for the current PlaneSlice. Most formats have only one plane.466DXGI_FORMAT PlaneFormat;467UINT32 MinPlanePitchWidth, PlaneWidth, PlaneHeight;468D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetPlaneSubsampledSizeAndFormatForCopyableLayout(PlaneSlice, Format, (UINT)Width, Height, /*_Out_*/ PlaneFormat, /*_Out_*/ MinPlanePitchWidth, /* _Out_ */ PlaneWidth, /*_Out_*/ PlaneHeight);469470D3D12_SUBRESOURCE_FOOTPRINT LocalPlacement = {};471auto& Placement = pLayouts ? pLayouts[uSubRes].Footprint : LocalPlacement;472Placement.Format = PlaneFormat;473Placement.Width = PlaneWidth;474Placement.Height = PlaneHeight;475Placement.Depth = Depth;476477// Calculate row pitch478UINT MinPlaneRowPitch = 0;479D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, MinPlanePitchWidth, MinPlaneRowPitch);480481// Formats with more than one plane choose a larger pitch alignment to ensure that each plane begins on the row482// immediately following the previous plane while still adhering to subresource alignment restrictions.483static_assert( D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT >= D3D12_TEXTURE_DATA_PITCH_ALIGNMENT484&& ((D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) == 0),485"D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT must be >= and evenly divisible by D3D12_TEXTURE_DATA_PITCH_ALIGNMENT." );486487Placement.RowPitch = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format)488? D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT )489: D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT );490491if (pRowSizeInBytes)492{493UINT PlaneRowSize = 0;494D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, PlaneWidth, PlaneRowSize);495496pRowSizeInBytes[uSubRes] = PlaneRowSize;497}498499// Number of rows (accounting for block compression and additional planes)500UINT NumRows = 0;501if (D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format))502{503NumRows = PlaneHeight;504}505else506{507D3DX12_ASSERT(Height % HeightAlignment == 0);508NumRows = Height / HeightAlignment;509}510511if (pNumRows)512{513pNumRows[uSubRes] = NumRows;514}515516// Offsetting517if (pLayouts)518{519pLayouts[uSubRes].Offset = (bOverflow ? uint64_max : TotalBytes + BaseOffset);520}521522const UINT16 NumSlices = Depth;523const UINT64 SubresourceSize = (NumRows * NumSlices - 1) * Placement.RowPitch + MinPlaneRowPitch;524525// uint64 addition with overflow checking526TotalBytes = TotalBytes + SubresourceSize;527if(TotalBytes < SubresourceSize)528{529TotalBytes = uint64_max;530}531bResourceOverflow = bResourceOverflow || bOverflow;532}533534// Overflow error535if (bResourceOverflow)536{537TotalBytes = uint64_max;538}539540541if (pLayouts)542{543memset( pLayouts + uSubRes, -1, sizeof( *pLayouts ) * (NumSubresources - uSubRes) );544}545if (pNumRows)546{547memset(pNumRows + uSubRes, -1, sizeof(*pNumRows) * (NumSubresources - uSubRes));548}549if (pRowSizeInBytes)550{551memset(pRowSizeInBytes + uSubRes, -1, sizeof(*pRowSizeInBytes) * (NumSubresources - uSubRes));552}553if (pTotalBytes)554{555*pTotalBytes = TotalBytes;556}557if(TotalBytes == uint64_max)558{559return false;560}561return true;562}563564//------------------------------------------------------------------------------------------------565inline D3D12_RESOURCE_DESC1 D3DX12ResourceDesc0ToDesc1(D3D12_RESOURCE_DESC const& desc0)566{567D3D12_RESOURCE_DESC1 desc1;568desc1.Dimension = desc0.Dimension;569desc1.Alignment = desc0.Alignment;570desc1.Width = desc0.Width;571desc1.Height = desc0.Height;572desc1.DepthOrArraySize = desc0.DepthOrArraySize;573desc1.MipLevels = desc0.MipLevels;574desc1.Format = desc0.Format;575desc1.SampleDesc.Count = desc0.SampleDesc.Count;576desc1.SampleDesc.Quality = desc0.SampleDesc.Quality;577desc1.Layout = desc0.Layout;578desc1.Flags = desc0.Flags;579desc1.SamplerFeedbackMipRegion.Width = 0;580desc1.SamplerFeedbackMipRegion.Height = 0;581desc1.SamplerFeedbackMipRegion.Depth = 0;582return desc1;583}584585//------------------------------------------------------------------------------------------------586inline bool D3DX12GetCopyableFootprints(587_In_ const D3D12_RESOURCE_DESC& pResourceDesc,588_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,589_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,590UINT64 BaseOffset,591_Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,592_Out_writes_opt_(NumSubresources) UINT* pNumRows,593_Out_writes_opt_(NumSubresources) UINT64* pRowSizeInBytes,594_Out_opt_ UINT64* pTotalBytes)595{596// From D3D12_RESOURCE_DESC to D3D12_RESOURCE_DESC1597D3D12_RESOURCE_DESC1 desc = D3DX12ResourceDesc0ToDesc1(pResourceDesc);598return D3DX12GetCopyableFootprints(599*static_cast<CD3DX12_RESOURCE_DESC1*>(&desc),// From D3D12_RESOURCE_DESC1 to CD3DX12_RESOURCE_DESC1600FirstSubresource,601NumSubresources,602BaseOffset,603pLayouts,604pNumRows,605pRowSizeInBytes,606pTotalBytes);607}608609#endif // D3D12_SDK_VERSION >= 606610611612613614