Skip to content

Commit d2b7c36

Browse files
Changed the logic so that creating resource in D3D12_HEAP_TYPE_GPU_UPLOAD fails with E_NOTIMPL when unsupported
Instead of asserting. Also updated the documentation and test.
1 parent 0262ac6 commit d2b7c36

File tree

4 files changed

+66
-46
lines changed

4 files changed

+66
-46
lines changed

docs/html/optimal_allocation.html

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -212,32 +212,30 @@ <h1><a class="anchor" id="optimal_allocation_gpu_upload_heap"></a>
212212
<li>As the new <code>D3D12_HEAP_TYPE_GPU_UPLOAD</code> uses the video memory, copies or direct access from the GPU are faster, while writes from the CPU code through a mapped pointer can be slower, because they need to go through PCIe. For maximum performance of copy operations from this heap, a graphics or compute queue should be used, not a copy queue.</li>
213213
</ul>
214214
<p>GPU Upload Heap can be used for performance optimization of some resources that need to be written by the CPU and read by the GPU. It can be beneficial especially for resources that need to change frequently (often called "dynamic").</p>
215-
<p>D3D12MA supports GPU upload heap when recent enough version of DirectX 12 SDK is used and when the current system supports it. The support can be queried using function <a class="el" href="class_d3_d12_m_a_1_1_allocator.html#a3f3fd1e88cf2cd02257fe272e08a273c" title="Returns true if GPU Upload Heaps are supported on the current system.">D3D12MA::Allocator::IsGPUUploadHeapSupported()</a>. When it returns <code>TRUE</code>, you can create resources using <code>D3D12_HEAP_TYPE_GPU_UPLOAD</code>.</p>
216-
<p>Example:</p>
217-
<div class="fragment"><div class="line"><span class="comment">// Fast path for data upload.</span></div>
218-
<div class="line"><span class="keywordflow">if</span>(allocator-&gt;IsGPUUploadHeapSupported())</div>
219-
<div class="line">{</div>
220-
<div class="line"> <a class="code hl_struct" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html">D3D12MA::ALLOCATION_DESC</a> allocDesc = {};</div>
221-
<div class="line"> allocDesc.<a class="code hl_variable" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">HeapType</a> = D3D12_HEAP_TYPE_GPU_UPLOAD; <span class="comment">// !!!</span></div>
215+
<p>D3D12MA supports GPU upload heap when recent enough version of DirectX 12 SDK is used and when the current system supports it. The support can be queried using function <a class="el" href="class_d3_d12_m_a_1_1_allocator.html#a3f3fd1e88cf2cd02257fe272e08a273c" title="Returns true if GPU Upload Heaps are supported on the current system.">D3D12MA::Allocator::IsGPUUploadHeapSupported()</a>. When it returns <code>TRUE</code>, you can create resources using <code>D3D12_HEAP_TYPE_GPU_UPLOAD</code>. You can also just try creating such resource. Example:</p>
216+
<div class="fragment"><div class="line"><a class="code hl_struct" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html">D3D12MA::ALLOCATION_DESC</a> allocDesc = {};</div>
217+
<div class="line">allocDesc.<a class="code hl_variable" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">HeapType</a> = D3D12_HEAP_TYPE_GPU_UPLOAD; <span class="comment">// !!!</span></div>
222218
<div class="line"> </div>
223-
<div class="line"> D3D12_RESOURCE_DESC resDesc = {};</div>
224-
<div class="line"> resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;</div>
225-
<div class="line"> resDesc.Alignment = 0;</div>
226-
<div class="line"> resDesc.Width = 1048576; <span class="comment">// Requested buffer size.</span></div>
227-
<div class="line"> resDesc.Height = 1;</div>
228-
<div class="line"> resDesc.DepthOrArraySize = 1;</div>
229-
<div class="line"> resDesc.MipLevels = 1;</div>
230-
<div class="line"> resDesc.Format = DXGI_FORMAT_UNKNOWN;</div>
231-
<div class="line"> resDesc.SampleDesc.Count = 1;</div>
232-
<div class="line"> resDesc.SampleDesc.Quality = 0;</div>
233-
<div class="line"> resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;</div>
234-
<div class="line"> resDesc.Flags = D3D12_RESOURCE_FLAG_NONE;</div>
219+
<div class="line">D3D12_RESOURCE_DESC resDesc = {};</div>
220+
<div class="line">resDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;</div>
221+
<div class="line">resDesc.Alignment = 0;</div>
222+
<div class="line">resDesc.Width = 1048576; <span class="comment">// Requested buffer size.</span></div>
223+
<div class="line">resDesc.Height = 1;</div>
224+
<div class="line">resDesc.DepthOrArraySize = 1;</div>
225+
<div class="line">resDesc.MipLevels = 1;</div>
226+
<div class="line">resDesc.Format = DXGI_FORMAT_UNKNOWN;</div>
227+
<div class="line">resDesc.SampleDesc.Count = 1;</div>
228+
<div class="line">resDesc.SampleDesc.Quality = 0;</div>
229+
<div class="line">resDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;</div>
230+
<div class="line">resDesc.Flags = D3D12_RESOURCE_FLAG_NONE;</div>
235231
<div class="line"> </div>
236-
<div class="line"> <a class="code hl_class" href="class_d3_d12_m_a_1_1_allocation.html">D3D12MA::Allocation</a>* alloc;</div>
237-
<div class="line"> ID3D12Resource* res;</div>
238-
<div class="line"> hr = allocator-&gt;CreateResource(&amp;allocDesc, &amp;resDesc, D3D12_RESOURCE_STATE_COMMON,</div>
239-
<div class="line"> NULL, &amp;alloc, IID_PPV_ARGS(&amp;res));</div>
240-
<div class="line"> <span class="comment">// Check hr...</span></div>
232+
<div class="line"><a class="code hl_class" href="class_d3_d12_m_a_1_1_allocation.html">D3D12MA::Allocation</a>* alloc;</div>
233+
<div class="line">ID3D12Resource* res;</div>
234+
<div class="line">hr = allocator-&gt;CreateResource(&amp;allocDesc, &amp;resDesc, D3D12_RESOURCE_STATE_COMMON,</div>
235+
<div class="line"> NULL, &amp;alloc, IID_PPV_ARGS(&amp;res));</div>
236+
<div class="line"><span class="keywordflow">if</span>(SUCCEEDED(hr))</div>
237+
<div class="line">{</div>
238+
<div class="line"> <span class="comment">// Fast path for data upload.</span></div>
241239
<div class="line"> </div>
242240
<div class="line"> D3D12_RANGE emptyRange = {0, 0};</div>
243241
<div class="line"> <span class="keywordtype">void</span>* mappedPtr = NULL;</div>
@@ -247,6 +245,16 @@ <h1><a class="anchor" id="optimal_allocation_gpu_upload_heap"></a>
247245
<div class="line"> </div>
248246
<div class="line"> D3D12_GPU_VIRTUAL_ADDRESS gpuva = res-&gt;GetGPUVirtualAddress();</div>
249247
<div class="line"> <span class="comment">// Use gpuva to access the buffer on the GPU...</span></div>
248+
<div class="line">}</div>
249+
<div class="line"><span class="keywordflow">else</span> <span class="keywordflow">if</span>(hr == E_NOTIMPL)</div>
250+
<div class="line">{</div>
251+
<div class="line"> <span class="comment">// GPU Upload Heap not supported in this system.</span></div>
252+
<div class="line"> <span class="comment">// Fall back to creating a staging buffer in UPLOAD and another copy in DEFAULT.</span></div>
253+
<div class="line"> allocDesc.<a class="code hl_variable" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">HeapType</a> = D3D12_HEAP_TYPE_UPLOAD;</div>
254+
<div class="line"> <span class="comment">// ...</span></div>
255+
<div class="line">}</div>
256+
<div class="line"><span class="keywordflow">else</span></div>
257+
<div class="line"> <span class="comment">// Some other error code e.g., out of memory...</span></div>
250258
<div class="ttc" id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c_html_aa46b3c0456e5a23edef3328607ebf4d7"><div class="ttname"><a href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">D3D12MA::ALLOCATION_DESC::HeapType</a></div><div class="ttdeci">D3D12_HEAP_TYPE HeapType</div><div class="ttdoc">The type of memory heap where the new allocation should be placed.</div><div class="ttdef"><b>Definition</b> D3D12MemAlloc.h:316</div></div>
251259
</div><!-- fragment --><h1><a class="anchor" id="optimal_allocation_committed_vs_placed"></a>
252260
Committed versus placed resources</h1>

include/D3D12MemAlloc.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2215,13 +2215,9 @@ It can be beneficial especially for resources that need to change frequently (of
22152215
%D3D12MA supports GPU upload heap when recent enough version of DirectX 12 SDK is used and when the current system supports it.
22162216
The support can be queried using function D3D12MA::Allocator::IsGPUUploadHeapSupported().
22172217
When it returns `TRUE`, you can create resources using `D3D12_HEAP_TYPE_GPU_UPLOAD`.
2218-
2219-
Example:
2218+
You can also just try creating such resource. Example:
22202219
22212220
\code
2222-
// Fast path for data upload.
2223-
if(allocator->IsGPUUploadHeapSupported())
2224-
{
22252221
D3D12MA::ALLOCATION_DESC allocDesc = {};
22262222
allocDesc.HeapType = D3D12_HEAP_TYPE_GPU_UPLOAD; // !!!
22272223
@@ -2242,16 +2238,29 @@ if(allocator->IsGPUUploadHeapSupported())
22422238
ID3D12Resource* res;
22432239
hr = allocator->CreateResource(&allocDesc, &resDesc, D3D12_RESOURCE_STATE_COMMON,
22442240
NULL, &alloc, IID_PPV_ARGS(&res));
2245-
// Check hr...
2241+
if(SUCCEEDED(hr))
2242+
{
2243+
// Fast path for data upload.
22462244
2247-
D3D12_RANGE emptyRange = {0, 0};
2248-
void* mappedPtr = NULL;
2249-
hr = res->Map(0, &emptyRange, &mappedPtr);
2250-
memcpy(mappedPtr, srcData, 1048576);
2251-
res->Unmap(0, NULL); // Optional. You can leave it persistently mapped.
2245+
D3D12_RANGE emptyRange = {0, 0};
2246+
void* mappedPtr = NULL;
2247+
hr = res->Map(0, &emptyRange, &mappedPtr);
2248+
memcpy(mappedPtr, srcData, 1048576);
2249+
res->Unmap(0, NULL); // Optional. You can leave it persistently mapped.
22522250
2253-
D3D12_GPU_VIRTUAL_ADDRESS gpuva = res->GetGPUVirtualAddress();
2254-
// Use gpuva to access the buffer on the GPU...
2251+
D3D12_GPU_VIRTUAL_ADDRESS gpuva = res->GetGPUVirtualAddress();
2252+
// Use gpuva to access the buffer on the GPU...
2253+
}
2254+
else if(hr == E_NOTIMPL)
2255+
{
2256+
// GPU Upload Heap not supported in this system.
2257+
// Fall back to creating a staging buffer in UPLOAD and another copy in DEFAULT.
2258+
2259+
allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
2260+
// ...
2261+
}
2262+
else
2263+
// Some other error code e.g., out of memory...
22552264
\endcode
22562265
22572266
\section optimal_allocation_committed_vs_placed Committed versus placed resources

src/D3D12MemAlloc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7402,8 +7402,8 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
74027402
outCommittedAllocationParams = CommittedAllocationParameters();
74037403
outPreferCommitted = false;
74047404

7405-
D3D12MA_ASSERT((allocDesc.HeapType != D3D12_HEAP_TYPE_GPU_UPLOAD_COPY || IsGPUUploadHeapSupported()) &&
7406-
"Trying to allocate from D3D12_HEAP_TYPE_GPU_UPLOAD while GPUUploadHeapSupported == FALSE.");
7405+
if (allocDesc.HeapType == D3D12_HEAP_TYPE_GPU_UPLOAD_COPY && !IsGPUUploadHeapSupported())
7406+
return E_NOTIMPL;
74077407

74087408
bool msaaAlwaysCommitted;
74097409
if (allocDesc.CustomPool != NULL)

src/Tests.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,11 +2922,7 @@ static void TestGPUUploadHeap(const TestContext& ctx)
29222922

29232923
wprintf(L"Test GPU Upload Heap\n");
29242924

2925-
if(!ctx.allocator->IsGPUUploadHeapSupported())
2926-
{
2927-
wprintf(L" Skipped due to GPUUploadHeap not supported.\n");
2928-
return;
2929-
}
2925+
const bool supported = ctx.allocator->IsGPUUploadHeapSupported();
29302926

29312927
Budget begLocalBudget = {};
29322928
ctx.allocator->GetBudget(&begLocalBudget, NULL);
@@ -2940,8 +2936,15 @@ static void TestGPUUploadHeap(const TestContext& ctx)
29402936
FillResourceDescForBuffer(resDesc, 64 * KILOBYTE);
29412937

29422938
ComPtr<Allocation> alloc;
2943-
CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc,
2944-
D3D12_RESOURCE_STATE_COMMON, NULL, &alloc, IID_NULL, NULL));
2939+
HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc,
2940+
D3D12_RESOURCE_STATE_COMMON, NULL, &alloc, IID_NULL, NULL);
2941+
if (!supported)
2942+
{
2943+
// Skip further tests. Just wanted to test that the respource creation fails with the right error code.
2944+
CHECK_BOOL(hr == E_NOTIMPL);
2945+
return;
2946+
}
2947+
CHECK_HR(hr);
29452948
CHECK_BOOL(alloc && alloc->GetResource());
29462949
CHECK_BOOL(alloc->GetResource()->GetGPUVirtualAddress() != 0);
29472950

0 commit comments

Comments
 (0)