Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/directx_headers/include/directx/d3dx12_resource_helpers.h
9906 views
1
//*********************************************************
2
//
3
// Copyright (c) Microsoft Corporation.
4
// Licensed under the MIT License (MIT).
5
//
6
//*********************************************************
7
8
#pragma once
9
10
#ifndef __cplusplus
11
#error D3DX12 requires C++
12
#endif
13
14
#include "d3d12.h"
15
#include "d3dx12_core.h"
16
#include "d3dx12_property_format_table.h"
17
//------------------------------------------------------------------------------------------------
18
template <typename T, typename U, typename V>
19
inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) noexcept
20
{
21
MipSlice = static_cast<T>(Subresource % MipLevels);
22
ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);
23
PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));
24
}
25
26
//------------------------------------------------------------------------------------------------
27
// Row-by-row memcpy
28
inline void MemcpySubresource(
29
_In_ const D3D12_MEMCPY_DEST* pDest,
30
_In_ const D3D12_SUBRESOURCE_DATA* pSrc,
31
SIZE_T RowSizeInBytes,
32
UINT NumRows,
33
UINT NumSlices) noexcept
34
{
35
for (UINT z = 0; z < NumSlices; ++z)
36
{
37
auto pDestSlice = static_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
38
auto pSrcSlice = static_cast<const BYTE*>(pSrc->pData) + pSrc->SlicePitch * LONG_PTR(z);
39
for (UINT y = 0; y < NumRows; ++y)
40
{
41
memcpy(pDestSlice + pDest->RowPitch * y,
42
pSrcSlice + pSrc->RowPitch * LONG_PTR(y),
43
RowSizeInBytes);
44
}
45
}
46
}
47
48
//------------------------------------------------------------------------------------------------
49
// Row-by-row memcpy
50
inline void MemcpySubresource(
51
_In_ const D3D12_MEMCPY_DEST* pDest,
52
_In_ const void* pResourceData,
53
_In_ const D3D12_SUBRESOURCE_INFO* pSrc,
54
SIZE_T RowSizeInBytes,
55
UINT NumRows,
56
UINT NumSlices) noexcept
57
{
58
for (UINT z = 0; z < NumSlices; ++z)
59
{
60
auto pDestSlice = static_cast<BYTE*>(pDest->pData) + pDest->SlicePitch * z;
61
auto pSrcSlice = (static_cast<const BYTE*>(pResourceData) + pSrc->Offset) + pSrc->DepthPitch * ULONG_PTR(z);
62
for (UINT y = 0; y < NumRows; ++y)
63
{
64
memcpy(pDestSlice + pDest->RowPitch * y,
65
pSrcSlice + pSrc->RowPitch * ULONG_PTR(y),
66
RowSizeInBytes);
67
}
68
}
69
}
70
71
//------------------------------------------------------------------------------------------------
72
// Returns required size of a buffer to be used for data upload
73
inline UINT64 GetRequiredIntermediateSize(
74
_In_ ID3D12Resource* pDestinationResource,
75
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
76
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources) noexcept
77
{
78
#if defined(_MSC_VER) || !defined(_WIN32)
79
const auto Desc = pDestinationResource->GetDesc();
80
#else
81
D3D12_RESOURCE_DESC tmpDesc;
82
const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);
83
#endif
84
UINT64 RequiredSize = 0;
85
86
ID3D12Device* pDevice = nullptr;
87
pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));
88
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, 0, nullptr, nullptr, nullptr, &RequiredSize);
89
pDevice->Release();
90
91
return RequiredSize;
92
}
93
94
//------------------------------------------------------------------------------------------------
95
// All arrays must be populated (e.g. by calling GetCopyableFootprints)
96
inline UINT64 UpdateSubresources(
97
_In_ ID3D12GraphicsCommandList* pCmdList,
98
_In_ ID3D12Resource* pDestinationResource,
99
_In_ ID3D12Resource* pIntermediate,
100
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
101
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
102
UINT64 RequiredSize,
103
_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
104
_In_reads_(NumSubresources) const UINT* pNumRows,
105
_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,
106
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept
107
{
108
// Minor validation
109
#if defined(_MSC_VER) || !defined(_WIN32)
110
const auto IntermediateDesc = pIntermediate->GetDesc();
111
const auto DestinationDesc = pDestinationResource->GetDesc();
112
#else
113
D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2;
114
const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1);
115
const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2);
116
#endif
117
if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
118
IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
119
RequiredSize > SIZE_T(-1) ||
120
(DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
121
(FirstSubresource != 0 || NumSubresources != 1)))
122
{
123
return 0;
124
}
125
126
BYTE* pData;
127
HRESULT hr = pIntermediate->Map(0, nullptr, reinterpret_cast<void**>(&pData));
128
if (FAILED(hr))
129
{
130
return 0;
131
}
132
133
for (UINT i = 0; i < NumSubresources; ++i)
134
{
135
if (pRowSizesInBytes[i] > SIZE_T(-1)) return 0;
136
D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, SIZE_T(pLayouts[i].Footprint.RowPitch) * SIZE_T(pNumRows[i]) };
137
MemcpySubresource(&DestData, &pSrcData[i], static_cast<SIZE_T>(pRowSizesInBytes[i]), pNumRows[i], pLayouts[i].Footprint.Depth);
138
}
139
pIntermediate->Unmap(0, nullptr);
140
141
if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
142
{
143
pCmdList->CopyBufferRegion(
144
pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
145
}
146
else
147
{
148
for (UINT i = 0; i < NumSubresources; ++i)
149
{
150
const CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);
151
const CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);
152
pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
153
}
154
}
155
return RequiredSize;
156
}
157
158
//------------------------------------------------------------------------------------------------
159
// All arrays must be populated (e.g. by calling GetCopyableFootprints)
160
inline UINT64 UpdateSubresources(
161
_In_ ID3D12GraphicsCommandList* pCmdList,
162
_In_ ID3D12Resource* pDestinationResource,
163
_In_ ID3D12Resource* pIntermediate,
164
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
165
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
166
UINT64 RequiredSize,
167
_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
168
_In_reads_(NumSubresources) const UINT* pNumRows,
169
_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,
170
_In_ const void* pResourceData,
171
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept
172
{
173
// Minor validation
174
#if defined(_MSC_VER) || !defined(_WIN32)
175
const auto IntermediateDesc = pIntermediate->GetDesc();
176
const auto DestinationDesc = pDestinationResource->GetDesc();
177
#else
178
D3D12_RESOURCE_DESC tmpDesc1, tmpDesc2;
179
const auto& IntermediateDesc = *pIntermediate->GetDesc(&tmpDesc1);
180
const auto& DestinationDesc = *pDestinationResource->GetDesc(&tmpDesc2);
181
#endif
182
if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
183
IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
184
RequiredSize > SIZE_T(-1) ||
185
(DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
186
(FirstSubresource != 0 || NumSubresources != 1)))
187
{
188
return 0;
189
}
190
191
BYTE* pData;
192
HRESULT hr = pIntermediate->Map(0, nullptr, reinterpret_cast<void**>(&pData));
193
if (FAILED(hr))
194
{
195
return 0;
196
}
197
198
for (UINT i = 0; i < NumSubresources; ++i)
199
{
200
if (pRowSizesInBytes[i] > SIZE_T(-1)) return 0;
201
D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, SIZE_T(pLayouts[i].Footprint.RowPitch) * SIZE_T(pNumRows[i]) };
202
MemcpySubresource(&DestData, pResourceData, &pSrcData[i], static_cast<SIZE_T>(pRowSizesInBytes[i]), pNumRows[i], pLayouts[i].Footprint.Depth);
203
}
204
pIntermediate->Unmap(0, nullptr);
205
206
if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
207
{
208
pCmdList->CopyBufferRegion(
209
pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
210
}
211
else
212
{
213
for (UINT i = 0; i < NumSubresources; ++i)
214
{
215
const CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);
216
const CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);
217
pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
218
}
219
}
220
return RequiredSize;
221
}
222
223
//------------------------------------------------------------------------------------------------
224
// Heap-allocating UpdateSubresources implementation
225
inline UINT64 UpdateSubresources(
226
_In_ ID3D12GraphicsCommandList* pCmdList,
227
_In_ ID3D12Resource* pDestinationResource,
228
_In_ ID3D12Resource* pIntermediate,
229
UINT64 IntermediateOffset,
230
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
231
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
232
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept
233
{
234
UINT64 RequiredSize = 0;
235
const auto MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
236
if (MemToAlloc > SIZE_MAX)
237
{
238
return 0;
239
}
240
void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
241
if (pMem == nullptr)
242
{
243
return 0;
244
}
245
auto pLayouts = static_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
246
auto pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
247
auto pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
248
249
#if defined(_MSC_VER) || !defined(_WIN32)
250
const auto Desc = pDestinationResource->GetDesc();
251
#else
252
D3D12_RESOURCE_DESC tmpDesc;
253
const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);
254
#endif
255
ID3D12Device* pDevice = nullptr;
256
pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));
257
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
258
pDevice->Release();
259
260
const UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData);
261
HeapFree(GetProcessHeap(), 0, pMem);
262
return Result;
263
}
264
265
//------------------------------------------------------------------------------------------------
266
// Heap-allocating UpdateSubresources implementation
267
inline UINT64 UpdateSubresources(
268
_In_ ID3D12GraphicsCommandList* pCmdList,
269
_In_ ID3D12Resource* pDestinationResource,
270
_In_ ID3D12Resource* pIntermediate,
271
UINT64 IntermediateOffset,
272
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
273
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
274
_In_ const void* pResourceData,
275
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept
276
{
277
UINT64 RequiredSize = 0;
278
const auto MemToAlloc = static_cast<UINT64>(sizeof(D3D12_PLACED_SUBRESOURCE_FOOTPRINT) + sizeof(UINT) + sizeof(UINT64)) * NumSubresources;
279
if (MemToAlloc > SIZE_MAX)
280
{
281
return 0;
282
}
283
void* pMem = HeapAlloc(GetProcessHeap(), 0, static_cast<SIZE_T>(MemToAlloc));
284
if (pMem == nullptr)
285
{
286
return 0;
287
}
288
auto pLayouts = static_cast<D3D12_PLACED_SUBRESOURCE_FOOTPRINT*>(pMem);
289
auto pRowSizesInBytes = reinterpret_cast<UINT64*>(pLayouts + NumSubresources);
290
auto pNumRows = reinterpret_cast<UINT*>(pRowSizesInBytes + NumSubresources);
291
292
#if defined(_MSC_VER) || !defined(_WIN32)
293
const auto Desc = pDestinationResource->GetDesc();
294
#else
295
D3D12_RESOURCE_DESC tmpDesc;
296
const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);
297
#endif
298
ID3D12Device* pDevice = nullptr;
299
pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));
300
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize);
301
pDevice->Release();
302
303
const UINT64 Result = UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pResourceData, pSrcData);
304
HeapFree(GetProcessHeap(), 0, pMem);
305
return Result;
306
}
307
308
//------------------------------------------------------------------------------------------------
309
// Stack-allocating UpdateSubresources implementation
310
template <UINT MaxSubresources>
311
inline UINT64 UpdateSubresources(
312
_In_ ID3D12GraphicsCommandList* pCmdList,
313
_In_ ID3D12Resource* pDestinationResource,
314
_In_ ID3D12Resource* pIntermediate,
315
UINT64 IntermediateOffset,
316
_In_range_(0,MaxSubresources) UINT FirstSubresource,
317
_In_range_(1,MaxSubresources-FirstSubresource) UINT NumSubresources,
318
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData) noexcept
319
{
320
UINT64 RequiredSize = 0;
321
D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];
322
UINT NumRows[MaxSubresources];
323
UINT64 RowSizesInBytes[MaxSubresources];
324
325
#if defined(_MSC_VER) || !defined(_WIN32)
326
const auto Desc = pDestinationResource->GetDesc();
327
#else
328
D3D12_RESOURCE_DESC tmpDesc;
329
const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);
330
#endif
331
ID3D12Device* pDevice = nullptr;
332
pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));
333
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);
334
pDevice->Release();
335
336
return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pSrcData);
337
}
338
339
//------------------------------------------------------------------------------------------------
340
// Stack-allocating UpdateSubresources implementation
341
template <UINT MaxSubresources>
342
inline UINT64 UpdateSubresources(
343
_In_ ID3D12GraphicsCommandList* pCmdList,
344
_In_ ID3D12Resource* pDestinationResource,
345
_In_ ID3D12Resource* pIntermediate,
346
UINT64 IntermediateOffset,
347
_In_range_(0,MaxSubresources) UINT FirstSubresource,
348
_In_range_(1,MaxSubresources-FirstSubresource) UINT NumSubresources,
349
_In_ const void* pResourceData,
350
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_INFO* pSrcData) noexcept
351
{
352
UINT64 RequiredSize = 0;
353
D3D12_PLACED_SUBRESOURCE_FOOTPRINT Layouts[MaxSubresources];
354
UINT NumRows[MaxSubresources];
355
UINT64 RowSizesInBytes[MaxSubresources];
356
357
#if defined(_MSC_VER) || !defined(_WIN32)
358
const auto Desc = pDestinationResource->GetDesc();
359
#else
360
D3D12_RESOURCE_DESC tmpDesc;
361
const auto& Desc = *pDestinationResource->GetDesc(&tmpDesc);
362
#endif
363
ID3D12Device* pDevice = nullptr;
364
pDestinationResource->GetDevice(IID_ID3D12Device, reinterpret_cast<void**>(&pDevice));
365
pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, Layouts, NumRows, RowSizesInBytes, &RequiredSize);
366
pDevice->Release();
367
368
return UpdateSubresources(pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, Layouts, NumRows, RowSizesInBytes, pResourceData, pSrcData);
369
}
370
371
//------------------------------------------------------------------------------------------------
372
constexpr bool D3D12IsLayoutOpaque( D3D12_TEXTURE_LAYOUT Layout ) noexcept
373
{ return Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN || Layout == D3D12_TEXTURE_LAYOUT_64KB_UNDEFINED_SWIZZLE; }
374
375
//------------------------------------------------------------------------------------------------
376
template< typename T >
377
inline T D3DX12Align(T uValue, T uAlign)
378
{
379
// Assert power of 2 alignment
380
D3DX12_ASSERT(0 == (uAlign & (uAlign - 1)));
381
T uMask = uAlign - 1;
382
T uResult = (uValue + uMask) & ~uMask;
383
D3DX12_ASSERT(uResult >= uValue);
384
D3DX12_ASSERT(0 == (uResult % uAlign));
385
return uResult;
386
}
387
388
//------------------------------------------------------------------------------------------------
389
template< typename T >
390
inline T D3DX12AlignAtLeast(T uValue, T uAlign)
391
{
392
T aligned = D3DX12Align(uValue, uAlign);
393
return aligned > uAlign ? aligned : uAlign;
394
}
395
396
inline const CD3DX12_RESOURCE_DESC1* D3DX12ConditionallyExpandAPIDesc(
397
D3D12_RESOURCE_DESC1& LclDesc,
398
const D3D12_RESOURCE_DESC1* pDesc)
399
{
400
return D3DX12ConditionallyExpandAPIDesc(static_cast<CD3DX12_RESOURCE_DESC1&>(LclDesc), static_cast<const CD3DX12_RESOURCE_DESC1*>(pDesc));
401
}
402
403
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 606)
404
//------------------------------------------------------------------------------------------------
405
// The difference between D3DX12GetCopyableFootprints and ID3D12Device::GetCopyableFootprints
406
// is that this one loses a lot of error checking by assuming the arguments are correct
407
inline bool D3DX12GetCopyableFootprints(
408
_In_ const D3D12_RESOURCE_DESC1& ResourceDesc,
409
_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
410
_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,
411
UINT64 BaseOffset,
412
_Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
413
_Out_writes_opt_(NumSubresources) UINT* pNumRows,
414
_Out_writes_opt_(NumSubresources) UINT64* pRowSizeInBytes,
415
_Out_opt_ UINT64* pTotalBytes)
416
{
417
constexpr UINT64 uint64_max = ~0ull;
418
UINT64 TotalBytes = uint64_max;
419
UINT uSubRes = 0;
420
421
bool bResourceOverflow = false;
422
TotalBytes = 0;
423
424
const DXGI_FORMAT Format = ResourceDesc.Format;
425
426
CD3DX12_RESOURCE_DESC1 LresourceDesc;
427
const CD3DX12_RESOURCE_DESC1& resourceDesc = *D3DX12ConditionallyExpandAPIDesc(LresourceDesc, &ResourceDesc);
428
429
// Check if its a valid format
430
D3DX12_ASSERT(D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::FormatExists(Format));
431
432
const UINT WidthAlignment = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetWidthAlignment( Format );
433
const UINT HeightAlignment = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetHeightAlignment( Format );
434
const UINT16 DepthAlignment = UINT16( D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetDepthAlignment( Format ) );
435
436
for (; uSubRes < NumSubresources; ++uSubRes)
437
{
438
bool bOverflow = false;
439
UINT Subresource = FirstSubresource + uSubRes;
440
441
D3DX12_ASSERT(resourceDesc.MipLevels != 0);
442
UINT subresourceCount = resourceDesc.MipLevels * resourceDesc.ArraySize() * D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetPlaneCount(resourceDesc.Format);
443
444
if (Subresource > subresourceCount)
445
{
446
break;
447
}
448
449
TotalBytes = D3DX12Align< UINT64 >( TotalBytes, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT );
450
451
UINT MipLevel, ArraySlice, PlaneSlice;
452
D3D12DecomposeSubresource(Subresource, resourceDesc.MipLevels, resourceDesc.ArraySize(), /*_Out_*/MipLevel, /*_Out_*/ArraySlice, /*_Out_*/PlaneSlice);
453
454
const UINT64 Width = D3DX12AlignAtLeast<UINT64>(resourceDesc.Width >> MipLevel, WidthAlignment);
455
const UINT Height = D3DX12AlignAtLeast(resourceDesc.Height >> MipLevel, HeightAlignment);
456
const UINT16 Depth = D3DX12AlignAtLeast<UINT16>(resourceDesc.Depth() >> MipLevel, DepthAlignment);
457
458
// Adjust for the current PlaneSlice. Most formats have only one plane.
459
DXGI_FORMAT PlaneFormat;
460
UINT32 MinPlanePitchWidth, PlaneWidth, PlaneHeight;
461
D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::GetPlaneSubsampledSizeAndFormatForCopyableLayout(PlaneSlice, Format, (UINT)Width, Height, /*_Out_*/ PlaneFormat, /*_Out_*/ MinPlanePitchWidth, /* _Out_ */ PlaneWidth, /*_Out_*/ PlaneHeight);
462
463
D3D12_SUBRESOURCE_FOOTPRINT LocalPlacement;
464
auto& Placement = pLayouts ? pLayouts[uSubRes].Footprint : LocalPlacement;
465
Placement.Format = PlaneFormat;
466
Placement.Width = PlaneWidth;
467
Placement.Height = PlaneHeight;
468
Placement.Depth = Depth;
469
470
// Calculate row pitch
471
UINT MinPlaneRowPitch = 0;
472
D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, MinPlanePitchWidth, MinPlaneRowPitch);
473
474
// Formats with more than one plane choose a larger pitch alignment to ensure that each plane begins on the row
475
// immediately following the previous plane while still adhering to subresource alignment restrictions.
476
static_assert( D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT >= D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
477
&& ((D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT % D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) == 0),
478
"D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT must be >= and evenly divisible by D3D12_TEXTURE_DATA_PITCH_ALIGNMENT." );
479
480
Placement.RowPitch = D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format)
481
? D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT )
482
: D3DX12Align< UINT >( MinPlaneRowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT );
483
484
if (pRowSizeInBytes)
485
{
486
UINT PlaneRowSize = 0;
487
D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::CalculateMinimumRowMajorRowPitch(PlaneFormat, PlaneWidth, PlaneRowSize);
488
489
pRowSizeInBytes[uSubRes] = PlaneRowSize;
490
}
491
492
// Number of rows (accounting for block compression and additional planes)
493
UINT NumRows = 0;
494
if (D3D12_PROPERTY_LAYOUT_FORMAT_TABLE::Planar(Format))
495
{
496
NumRows = PlaneHeight;
497
}
498
else
499
{
500
D3DX12_ASSERT(Height % HeightAlignment == 0);
501
NumRows = Height / HeightAlignment;
502
}
503
504
if (pNumRows)
505
{
506
pNumRows[uSubRes] = NumRows;
507
}
508
509
// Offsetting
510
if (pLayouts)
511
{
512
pLayouts[uSubRes].Offset = (bOverflow ? uint64_max : TotalBytes + BaseOffset);
513
}
514
515
const UINT16 NumSlices = Depth;
516
const UINT64 SubresourceSize = (NumRows * NumSlices - 1) * Placement.RowPitch + MinPlaneRowPitch;
517
518
// uint64 addition with overflow checking
519
TotalBytes = TotalBytes + SubresourceSize;
520
if(TotalBytes < SubresourceSize)
521
{
522
TotalBytes = uint64_max;
523
}
524
bResourceOverflow = bResourceOverflow || bOverflow;
525
}
526
527
// Overflow error
528
if (bResourceOverflow)
529
{
530
TotalBytes = uint64_max;
531
}
532
533
534
if (pLayouts)
535
{
536
memset( pLayouts + uSubRes, -1, sizeof( *pLayouts ) * (NumSubresources - uSubRes) );
537
}
538
if (pNumRows)
539
{
540
memset(pNumRows + uSubRes, -1, sizeof(*pNumRows) * (NumSubresources - uSubRes));
541
}
542
if (pRowSizeInBytes)
543
{
544
memset(pRowSizeInBytes + uSubRes, -1, sizeof(*pRowSizeInBytes) * (NumSubresources - uSubRes));
545
}
546
if (pTotalBytes)
547
{
548
*pTotalBytes = TotalBytes;
549
}
550
if(TotalBytes == uint64_max)
551
{
552
return false;
553
}
554
return true;
555
}
556
557
//------------------------------------------------------------------------------------------------
558
inline D3D12_RESOURCE_DESC1 D3DX12ResourceDesc0ToDesc1(D3D12_RESOURCE_DESC const& desc0)
559
{
560
D3D12_RESOURCE_DESC1 desc1;
561
desc1.Dimension = desc0.Dimension;
562
desc1.Alignment = desc0.Alignment;
563
desc1.Width = desc0.Width;
564
desc1.Height = desc0.Height;
565
desc1.DepthOrArraySize = desc0.DepthOrArraySize;
566
desc1.MipLevels = desc0.MipLevels;
567
desc1.Format = desc0.Format;
568
desc1.SampleDesc.Count = desc0.SampleDesc.Count;
569
desc1.SampleDesc.Quality = desc0.SampleDesc.Quality;
570
desc1.Layout = desc0.Layout;
571
desc1.Flags = desc0.Flags;
572
desc1.SamplerFeedbackMipRegion.Width = 0;
573
desc1.SamplerFeedbackMipRegion.Height = 0;
574
desc1.SamplerFeedbackMipRegion.Depth = 0;
575
return desc1;
576
}
577
578
//------------------------------------------------------------------------------------------------
579
inline bool D3DX12GetCopyableFootprints(
580
_In_ const D3D12_RESOURCE_DESC& pResourceDesc,
581
_In_range_(0, D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
582
_In_range_(0, D3D12_REQ_SUBRESOURCES - FirstSubresource) UINT NumSubresources,
583
UINT64 BaseOffset,
584
_Out_writes_opt_(NumSubresources) D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
585
_Out_writes_opt_(NumSubresources) UINT* pNumRows,
586
_Out_writes_opt_(NumSubresources) UINT64* pRowSizeInBytes,
587
_Out_opt_ UINT64* pTotalBytes)
588
{
589
// From D3D12_RESOURCE_DESC to D3D12_RESOURCE_DESC1
590
D3D12_RESOURCE_DESC1 desc = D3DX12ResourceDesc0ToDesc1(pResourceDesc);
591
return D3DX12GetCopyableFootprints(
592
*static_cast<CD3DX12_RESOURCE_DESC1*>(&desc),// From D3D12_RESOURCE_DESC1 to CD3DX12_RESOURCE_DESC1
593
FirstSubresource,
594
NumSubresources,
595
BaseOffset,
596
pLayouts,
597
pNumRows,
598
pRowSizeInBytes,
599
pTotalBytes);
600
}
601
602
#endif // D3D12_SDK_VERSION >= 606
603
604