Skip to content

Commit 909adc1

Browse files
authored
Merge pull request #901 from microsoft/user/tvandewalle/TightAlignmentSample
Add sample for Tight Aligned resources
2 parents 64a65f8 + 428e923 commit 909adc1

File tree

5 files changed

+448
-22
lines changed

5 files changed

+448
-22
lines changed

Samples/Desktop/D3D12HelloWorld/src/D3D12HelloWorld.sln

+28-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 16
4-
VisualStudioVersion = 16.0.30621.155.26403.0
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.12.35707.178 d17.12
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloTriangle", "HelloTriangle\D3D12HelloTriangle.vcxproj", "{5018F6A3-6533-4744-B1FD-727D199FD2E9}"
77
EndProject
@@ -21,13 +21,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloVADecode", "Hello
2121
EndProject
2222
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloVAResourceInterop", "HelloVAResourceInterop\D3D12HelloVAResourceInterop.vcxproj", "{17171787-C5D2-4014-9D1D-BC43074F36A1}"
2323
EndProject
24-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloWorkGraphs", "HelloWorkGraphs\D3D12HelloWorkGraphs.vcxproj", "{05080adc-d456-4058-8064-4791865f796b}"
24+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloWorkGraphs", "HelloWorkGraphs\D3D12HelloWorkGraphs.vcxproj", "{05080ADC-D456-4058-8064-4791865F796B}"
2525
EndProject
26-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12WorkGraphsSandbox", "WorkGraphsSandbox\D3D12WorkGraphsSandbox.vcxproj", "{2725e8ec-0892-499b-acd5-0ea18157682a}"
26+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12WorkGraphsSandbox", "WorkGraphsSandbox\D3D12WorkGraphsSandbox.vcxproj", "{2725E8EC-0892-499B-ACD5-0EA18157682A}"
2727
EndProject
28-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloGenericPrograms", "HelloGenericPrograms\D3D12HelloGenericPrograms.vcxproj", "{7db43f09-7bd6-4e69-8987-9a919a142852}"
28+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloGenericPrograms", "HelloGenericPrograms\D3D12HelloGenericPrograms.vcxproj", "{7DB43F09-7BD6-4E69-8987-9A919A142852}"
2929
EndProject
30-
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloMeshNodes", "HelloMeshNodes\D3D12HelloMeshNodes.vcxproj", "{b9680899-f009-406b-beee-d0214c1e7592}"
30+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloMeshNodes", "HelloMeshNodes\D3D12HelloMeshNodes.vcxproj", "{B9680899-F009-406B-BEEE-D0214C1E7592}"
31+
EndProject
32+
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12HelloTightAlignment", "HelloTightAlignment\D3D12HelloTightAlignment.vcxproj", "{69B1A348-DF87-4335-BC68-FE8C060C7A60}"
3133
EndProject
3234
Global
3335
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -71,22 +73,26 @@ Global
7173
{17171787-C5D2-4014-9D1D-BC43074F36A1}.Debug|x64.Build.0 = Debug|x64
7274
{17171787-C5D2-4014-9D1D-BC43074F36A1}.Release|x64.ActiveCfg = Release|x64
7375
{17171787-C5D2-4014-9D1D-BC43074F36A1}.Release|x64.Build.0 = Release|x64
74-
{05080adc-d456-4058-8064-4791865f796b}.Debug|x64.ActiveCfg = Debug|x64
75-
{05080adc-d456-4058-8064-4791865f796b}.Debug|x64.Build.0 = Debug|x64
76-
{05080adc-d456-4058-8064-4791865f796b}.Release|x64.ActiveCfg = Release|x64
77-
{05080adc-d456-4058-8064-4791865f796b}.Release|x64.Build.0 = Release|x64
78-
{2725e8ec-0892-499b-acd5-0ea18157682a}.Debug|x64.ActiveCfg = Debug|x64
79-
{2725e8ec-0892-499b-acd5-0ea18157682a}.Debug|x64.Build.0 = Debug|x64
80-
{2725e8ec-0892-499b-acd5-0ea18157682a}.Release|x64.ActiveCfg = Release|x64
81-
{2725e8ec-0892-499b-acd5-0ea18157682a}.Release|x64.Build.0 = Release|x64
82-
{7db43f09-7bd6-4e69-8987-9a919a142852}.Debug|x64.ActiveCfg = Debug|x64
83-
{7db43f09-7bd6-4e69-8987-9a919a142852}.Debug|x64.Build.0 = Debug|x64
84-
{7db43f09-7bd6-4e69-8987-9a919a142852}.Release|x64.ActiveCfg = Release|x64
85-
{7db43f09-7bd6-4e69-8987-9a919a142852}.Release|x64.Build.0 = Release|x64
86-
{b9680899-f009-406b-beee-d0214c1e7592}.Debug|x64.ActiveCfg = Debug|x64
87-
{b9680899-f009-406b-beee-d0214c1e7592}.Debug|x64.Build.0 = Debug|x64
88-
{b9680899-f009-406b-beee-d0214c1e7592}.Release|x64.ActiveCfg = Release|x64
89-
{b9680899-f009-406b-beee-d0214c1e7592}.Release|x64.Build.0 = Release|x64
76+
{05080ADC-D456-4058-8064-4791865F796B}.Debug|x64.ActiveCfg = Debug|x64
77+
{05080ADC-D456-4058-8064-4791865F796B}.Debug|x64.Build.0 = Debug|x64
78+
{05080ADC-D456-4058-8064-4791865F796B}.Release|x64.ActiveCfg = Release|x64
79+
{05080ADC-D456-4058-8064-4791865F796B}.Release|x64.Build.0 = Release|x64
80+
{2725E8EC-0892-499B-ACD5-0EA18157682A}.Debug|x64.ActiveCfg = Debug|x64
81+
{2725E8EC-0892-499B-ACD5-0EA18157682A}.Debug|x64.Build.0 = Debug|x64
82+
{2725E8EC-0892-499B-ACD5-0EA18157682A}.Release|x64.ActiveCfg = Release|x64
83+
{2725E8EC-0892-499B-ACD5-0EA18157682A}.Release|x64.Build.0 = Release|x64
84+
{7DB43F09-7BD6-4E69-8987-9A919A142852}.Debug|x64.ActiveCfg = Debug|x64
85+
{7DB43F09-7BD6-4E69-8987-9A919A142852}.Debug|x64.Build.0 = Debug|x64
86+
{7DB43F09-7BD6-4E69-8987-9A919A142852}.Release|x64.ActiveCfg = Release|x64
87+
{7DB43F09-7BD6-4E69-8987-9A919A142852}.Release|x64.Build.0 = Release|x64
88+
{B9680899-F009-406B-BEEE-D0214C1E7592}.Debug|x64.ActiveCfg = Debug|x64
89+
{B9680899-F009-406B-BEEE-D0214C1E7592}.Debug|x64.Build.0 = Debug|x64
90+
{B9680899-F009-406B-BEEE-D0214C1E7592}.Release|x64.ActiveCfg = Release|x64
91+
{B9680899-F009-406B-BEEE-D0214C1E7592}.Release|x64.Build.0 = Release|x64
92+
{69B1A348-DF87-4335-BC68-FE8C060C7A60}.Debug|x64.ActiveCfg = Debug|x64
93+
{69B1A348-DF87-4335-BC68-FE8C060C7A60}.Debug|x64.Build.0 = Debug|x64
94+
{69B1A348-DF87-4335-BC68-FE8C060C7A60}.Release|x64.ActiveCfg = Release|x64
95+
{69B1A348-DF87-4335-BC68-FE8C060C7A60}.Release|x64.Build.0 = Release|x64
9096
EndGlobalSection
9197
GlobalSection(SolutionProperties) = preSolution
9298
HideSolutionNode = FALSE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
// D3D12HelloTightAlignment.cpp : This file contains the 'main' function. Program execution begins and ends there.
2+
//
3+
4+
#include <windows.h>
5+
#include <iostream>
6+
#include <atlbase.h>
7+
#include <vector>
8+
#include <initguid.h>
9+
#include "dxcapi.h"
10+
#include "d3d12.h"
11+
#include "d3dx12.h"
12+
#include <dxgi1_6.h>
13+
14+
extern "C" { __declspec(dllexport) extern const UINT D3D12SDKVersion = 716; }
15+
extern "C" { __declspec(dllexport) extern const char* D3D12SDKPath = u8".\\D3D12\\"; }
16+
extern "C" { __declspec(dllexport) extern const char* WarpPath = u8".\\WARP\\"; }
17+
18+
// use a warp device instead of a hardware device
19+
bool g_useWarpDevice = false;
20+
21+
#pragma region helper_and_setup
22+
//=================================================================================================================================
23+
// Helper / setup code, not specific to work graphs
24+
// Look for "Start of interesting code" further below or just collapse this region.
25+
//=================================================================================================================================
26+
#define PRINT(text) std::cout << (char*)text << "\n" << std::flush;
27+
#define VERIFY_SUCCEEDED(hr) {HRESULT hrLocal = hr; if(FAILED(hrLocal)) {PRINT("Error at: " << __FILE__ << ", line: " << __LINE__ << ", HRESULT: 0x" << std::hex << hrLocal); throw E_FAIL;} }
28+
29+
struct D3DContext
30+
{
31+
CComPtr<ID3D12Device14> spDevice;
32+
CComPtr<IDXGIAdapter3> spAdapter;
33+
bool bIsHeapTier1;
34+
};
35+
36+
//=================================================================================================================================
37+
void InitDeviceAndContext(D3DContext& D3D, bool useWarp)
38+
{
39+
D3D.spDevice.Release();
40+
D3D.spAdapter.Release();
41+
42+
CComPtr<ID3D12Debug1> pDebug;
43+
VERIFY_SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&pDebug)));
44+
pDebug->EnableDebugLayer();
45+
46+
D3D_FEATURE_LEVEL FL = D3D_FEATURE_LEVEL_11_0;
47+
CComPtr<ID3D12Device> spDevice;
48+
CComPtr<IDXGIFactory4> factory;
49+
VERIFY_SUCCEEDED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)));
50+
51+
if (useWarp)
52+
{
53+
VERIFY_SUCCEEDED(factory->EnumWarpAdapter(IID_PPV_ARGS(&D3D.spAdapter)));
54+
VERIFY_SUCCEEDED(D3D12CreateDevice(D3D.spAdapter, FL, IID_PPV_ARGS(&spDevice)));
55+
}
56+
else
57+
{
58+
VERIFY_SUCCEEDED(D3D12CreateDevice(NULL, FL, IID_PPV_ARGS(&spDevice)));
59+
LUID luid = spDevice->GetAdapterLuid();
60+
factory->EnumAdapterByLuid(luid, IID_PPV_ARGS(&D3D.spAdapter));
61+
}
62+
D3D.spDevice = spDevice;
63+
D3D.bIsHeapTier1 = false;
64+
}
65+
66+
template <UINT _Size>
67+
LPSTR FormatMemoryUsage(UINT64 usage, CHAR(&result)[_Size])
68+
{
69+
const UINT64 mb = 1 << 20;
70+
const UINT64 kb = 1 << 10;
71+
if (usage > mb)
72+
{
73+
sprintf_s(result, "%.2f MB", static_cast<float>(usage) / mb);
74+
}
75+
else if (usage > kb)
76+
{
77+
sprintf_s(result, "%.2f KB", static_cast<float>(usage) / kb);
78+
}
79+
else
80+
{
81+
sprintf_s(result, "%I64d B", usage);
82+
}
83+
return result;
84+
}
85+
86+
void PrintGPUMemoryUsage(D3DContext& D3D, UINT64 baselineUsage = 0)
87+
{
88+
DXGI_QUERY_VIDEO_MEMORY_INFO memoryInfo;
89+
D3D.spAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memoryInfo);
90+
91+
char text[100];
92+
char usageString[20];
93+
UINT64 usage = memoryInfo.CurrentUsage - baselineUsage;
94+
if (baselineUsage > memoryInfo.CurrentUsage)
95+
{
96+
PRINT(" ## Error - baseline usage was greater than current usage");
97+
return;
98+
}
99+
sprintf_s(text, " Memory Used: %s", FormatMemoryUsage(usage, usageString));
100+
PRINT(text);
101+
}
102+
103+
#pragma endregion
104+
105+
template<UINT32 numBuffers>
106+
void CreateManyPlacedBuffers(D3DContext& D3D, const CD3DX12_RESOURCE_DESC1& rDesc)
107+
{
108+
DXGI_QUERY_VIDEO_MEMORY_INFO baslineMemoryInfo;
109+
D3D.spAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &baslineMemoryInfo);
110+
111+
D3D12_RESOURCE_ALLOCATION_INFO1 infos[numBuffers];
112+
D3D12_RESOURCE_DESC1 pResourceDescs[numBuffers];
113+
std::fill_n(pResourceDescs, numBuffers, rDesc);
114+
D3D12_RESOURCE_ALLOCATION_INFO aggregateInfo = D3D.spDevice->GetResourceAllocationInfo2(0, numBuffers, pResourceDescs, infos);
115+
116+
CComPtr<ID3D12Heap> pHeap;
117+
CComPtr<ID3D12Resource> buffers[numBuffers];
118+
CD3DX12_HEAP_DESC heapDesc = CD3DX12_HEAP_DESC(aggregateInfo.SizeInBytes, D3D12_HEAP_TYPE_DEFAULT);
119+
heapDesc.Flags = D3D.bIsHeapTier1 ? D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS : D3D12_HEAP_FLAG_NONE;
120+
VERIFY_SUCCEEDED(D3D.spDevice->CreateHeap(&heapDesc, IID_PPV_ARGS(&pHeap)));
121+
for (UINT32 i = 0; i < numBuffers; i++)
122+
{
123+
VERIFY_SUCCEEDED(D3D.spDevice->CreatePlacedResource1(pHeap, infos[i].Offset, &rDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&buffers[i])));
124+
}
125+
PrintGPUMemoryUsage(D3D, baslineMemoryInfo.CurrentUsage);
126+
}
127+
128+
template<UINT32 numBuffers>
129+
void ComparePlacedBufferMemoryFootprint(D3DContext& D3D)
130+
{
131+
PRINT("Comparing memory footprint for " << numBuffers << " placed buffers...\n");
132+
CD3DX12_RESOURCE_DESC1 bufferDesc;
133+
//Beyond the obvious benefits for small resources, you can also see savings for large buffers that go beyond the 64KiB mark
134+
UINT bufferSizes[] = { 1, 16, 256, 4096, 32000, 65540, 80000 };
135+
for (UINT bufferSize : bufferSizes)
136+
{
137+
PRINT("Size: " << bufferSize << " B");
138+
PRINT(" Classic buffer alignment:");
139+
bufferDesc = CD3DX12_RESOURCE_DESC1::Buffer(bufferSize);
140+
CreateManyPlacedBuffers<numBuffers>(D3D, bufferDesc);
141+
142+
PRINT(" Tight buffer alignment:");
143+
bufferDesc = CD3DX12_RESOURCE_DESC1::Buffer(bufferSize, D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT);
144+
CreateManyPlacedBuffers<numBuffers>(D3D, bufferDesc);
145+
146+
PRINT("----------");
147+
}
148+
PRINT("====================");
149+
}
150+
151+
template<UINT32 numBuffers>
152+
void CreateManyCommittedBuffers(D3DContext& D3D, const CD3DX12_RESOURCE_DESC1& rDesc)
153+
{
154+
DXGI_QUERY_VIDEO_MEMORY_INFO baslineMemoryInfo;
155+
D3D.spAdapter->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &baslineMemoryInfo);
156+
157+
CD3DX12_HEAP_PROPERTIES heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
158+
CComPtr<ID3D12Resource> buffers[numBuffers];
159+
for (UINT32 i = 0; i < numBuffers; i++)
160+
{
161+
VERIFY_SUCCEEDED(D3D.spDevice->CreateCommittedResource2(&heapProperties, D3D12_HEAP_FLAG_NONE, &rDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, nullptr, IID_PPV_ARGS(&buffers[i])));
162+
}
163+
164+
PrintGPUMemoryUsage(D3D, baslineMemoryInfo.CurrentUsage);
165+
}
166+
167+
template<UINT32 numBuffers>
168+
void CompareCommittedBufferMemoryFootprint(D3DContext& D3D)
169+
{
170+
PRINT("Comparing memory footprint for " << numBuffers << " committed buffers...\n");
171+
CD3DX12_RESOURCE_DESC1 bufferDesc;
172+
173+
UINT bufferSizes[] = { 1, 16, 256, 4096, 65536, 65540, 80000 };
174+
for (UINT bufferSize : bufferSizes)
175+
{
176+
PRINT("Size: " << bufferSize << " B");
177+
PRINT(" Classic buffer alignment:");
178+
bufferDesc = CD3DX12_RESOURCE_DESC1::Buffer(bufferSize);
179+
CreateManyCommittedBuffers<numBuffers>(D3D, bufferDesc);
180+
181+
PRINT(" Tight buffer alignment:");
182+
bufferDesc = CD3DX12_RESOURCE_DESC1::Buffer(bufferSize, D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT);
183+
CreateManyCommittedBuffers<numBuffers>(D3D, bufferDesc);
184+
185+
PRINT("----------");
186+
}
187+
PRINT("====================");
188+
}
189+
190+
int main()
191+
{
192+
try
193+
{
194+
PRINT("\n" <<
195+
"==================================================================================\n" <<
196+
" Hello Tight Alignment\n" <<
197+
"==================================================================================");
198+
D3DContext D3D;
199+
InitDeviceAndContext(D3D, g_useWarpDevice);
200+
bool warpFallback = false;
201+
202+
CD3DX12FeatureSupport featureSupport;
203+
featureSupport.Init(D3D.spDevice);
204+
if (featureSupport.TightAlignmentSupportTier() == D3D12_TIGHT_ALIGNMENT_TIER_NOT_SUPPORTED && !g_useWarpDevice)
205+
{
206+
PRINT("Tight alignment is not supported on this driver. Retrying with Warp...");
207+
InitDeviceAndContext(D3D, true);
208+
featureSupport.Init(D3D.spDevice);
209+
warpFallback = true;
210+
}
211+
if (featureSupport.TightAlignmentSupportTier() == D3D12_TIGHT_ALIGNMENT_TIER_NOT_SUPPORTED)
212+
{
213+
PRINT("Tight alignment is not supported on this driver or the currently installed version of Warp. Aborting.");
214+
return 0;
215+
}
216+
DXGI_ADAPTER_DESC desc;
217+
VERIFY_SUCCEEDED(D3D.spAdapter->GetDesc(&desc));
218+
std::wcout << L"Running sample on " << desc.Description << L"\n\n" << std::flush;
219+
220+
D3D12_FEATURE_DATA_D3D12_OPTIONS options{};
221+
VERIFY_SUCCEEDED(D3D.spDevice->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)));
222+
D3D.bIsHeapTier1 = options.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1;
223+
224+
ComparePlacedBufferMemoryFootprint<1>(D3D); // No benefit due to the heap allocations being made in 64KiB chuncks
225+
ComparePlacedBufferMemoryFootprint<8>(D3D); // Can already see some benefit being realized
226+
ComparePlacedBufferMemoryFootprint<4096>(D3D); // drastic savings in most cases
227+
228+
PRINT("\n========================================\n========================================\n");
229+
230+
CompareCommittedBufferMemoryFootprint<1>(D3D);
231+
CompareCommittedBufferMemoryFootprint<8>(D3D);
232+
CompareCommittedBufferMemoryFootprint<4096>(D3D);
233+
}
234+
catch (HRESULT)
235+
{
236+
PRINT("Aborting.");
237+
return -1;
238+
}
239+
return 0;
240+
241+
}

0 commit comments

Comments
 (0)