Skip to content

Commit 69d1b97

Browse files
committed
Merge pull request #106 from Microsoft/develop
Develop
2 parents d86b25f + 1a7dd70 commit 69d1b97

File tree

97 files changed

+6842
-278
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+6842
-278
lines changed

Samples/Desktop/D3D12HelloWorld/src/HelloFrameBuffering/D3D12HelloFrameBuffering.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ D3D12HelloFrameBuffering::D3D12HelloFrameBuffering(UINT width, UINT height, std:
1717
m_frameIndex(0),
1818
m_viewport(),
1919
m_scissorRect(),
20+
m_fenceValues{},
2021
m_rtvDescriptorSize(0)
2122
{
2223
m_viewport.Width = static_cast<float>(width);

Samples/Desktop/D3D12HeterogeneousMultiadapter/src/D3D12HeterogeneousMultiadapter.cpp

Lines changed: 152 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ D3D12HeterogeneousMultiadapter::D3D12HeterogeneousMultiadapter(int width, int he
3131
m_currentRenderFenceValue(1),
3232
m_currentCrossAdapterFenceValue(1),
3333
m_workloadConstantBufferData(),
34-
m_blurWorkloadConstantBufferData()
34+
m_blurWorkloadConstantBufferData(),
35+
m_crossAdapterTextureSupport(false)
3536
{
3637
ZeroMemory(m_rtvDescriptorSizes, sizeof(m_rtvDescriptorSizes));
3738
ZeroMemory(m_srvDescriptorSizes, sizeof(m_srvDescriptorSizes));
@@ -78,15 +79,6 @@ HRESULT D3D12HeterogeneousMultiadapter::GetHardwareAdapters(IDXGIFactory2* pFact
7879
ThrowIfFailed(pFactory->EnumAdapters1(0, ppSecondaryAdapter));
7980
ThrowIfFailed(pFactory->EnumAdapters1(1, ppPrimaryAdapter));
8081

81-
DXGI_ADAPTER_DESC1 desc;
82-
(*ppPrimaryAdapter)->GetDesc1(&desc);
83-
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
84-
{
85-
// There is actually only one physical GPU on the system.
86-
// Reduce the starting triangle count to make the sample run better.
87-
m_triangleCount = MaxTriangleCount / 50;
88-
}
89-
9082
return S_OK;
9183
}
9284

@@ -122,6 +114,15 @@ void D3D12HeterogeneousMultiadapter::LoadPipeline()
122114
ThrowIfFailed(GetHardwareAdapters(factory.Get(), &primaryAdapter, &secondaryAdapter));
123115
}
124116

117+
DXGI_ADAPTER_DESC1 desc;
118+
primaryAdapter->GetDesc1(&desc);
119+
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
120+
{
121+
// There is actually only one physical GPU on the system.
122+
// Reduce the starting triangle count to make the sample run better.
123+
m_triangleCount = MaxTriangleCount / 50;
124+
}
125+
125126
IDXGIAdapter1* ppAdapters[] = { primaryAdapter.Get(), secondaryAdapter.Get() };
126127
for (UINT i = 0; i < GraphicsAdaptersCount; i++)
127128
{
@@ -288,34 +289,96 @@ void D3D12HeterogeneousMultiadapter::LoadPipeline()
288289

289290
// Create cross-adapter shared resources on the primary adapter, and open the shared handles on the secondary adapter.
290291
{
291-
D3D12_RESOURCE_DESC crossAdapterDesc = m_renderTargets[Primary][0]->GetDesc();
292-
crossAdapterDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
293-
crossAdapterDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
292+
// Check whether shared row-major textures can be directly sampled by the
293+
// secondary adapter. Support of this feature (or the lack thereof) will
294+
// determine our sharing strategy for the resource in question.
295+
D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
296+
ThrowIfFailed(m_devices[Secondary]->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, reinterpret_cast<void*>(&options), sizeof(options)));
297+
m_crossAdapterTextureSupport = options.CrossAdapterRowMajorTextureSupported;
298+
299+
UINT64 textureSize = 0;
300+
D3D12_RESOURCE_DESC crossAdapterDesc;
301+
302+
if (m_crossAdapterTextureSupport)
303+
{
304+
// If cross-adapter row-major textures are supported by the adapter,
305+
// then they can be sampled directly.
306+
crossAdapterDesc = renderTargetDesc;
307+
crossAdapterDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
308+
crossAdapterDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
309+
310+
D3D12_RESOURCE_ALLOCATION_INFO textureInfo = m_devices[Primary]->GetResourceAllocationInfo(0, 1, &crossAdapterDesc);
311+
textureSize = textureInfo.SizeInBytes;
312+
}
313+
else
314+
{
315+
// If cross-adapter row-major textures are not supported by the adapter,
316+
// then they will be shared as buffers and then copied to a destination
317+
// texture on the secondary adapter.
318+
319+
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
320+
m_devices[Primary]->GetCopyableFootprints(&renderTargetDesc, 0, 1, 0, &layout, nullptr, nullptr, nullptr);
321+
textureSize = Align(layout.Footprint.RowPitch * layout.Footprint.Height);
322+
323+
// Create a buffer with the same layout as the render target texture.
324+
crossAdapterDesc = CD3DX12_RESOURCE_DESC::Buffer(textureSize, D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER);
325+
}
326+
327+
// Create a heap that will be shared by both adapters.
328+
CD3DX12_HEAP_DESC heapDesc(
329+
textureSize * FrameCount,
330+
D3D12_HEAP_TYPE_DEFAULT,
331+
0,
332+
D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER);
333+
334+
ThrowIfFailed(m_devices[Primary]->CreateHeap(&heapDesc, IID_PPV_ARGS(&m_crossAdapterResourceHeaps[Primary])));
335+
336+
HANDLE heapHandle = nullptr;
337+
ThrowIfFailed(m_devices[Primary]->CreateSharedHandle(
338+
m_crossAdapterResourceHeaps[Primary].Get(),
339+
nullptr,
340+
GENERIC_ALL,
341+
nullptr,
342+
&heapHandle));
343+
344+
HRESULT openSharedHandleResult = m_devices[Secondary]->OpenSharedHandle(heapHandle, IID_PPV_ARGS(&m_crossAdapterResourceHeaps[Secondary]));
294345

346+
// We can close the handle after opening the cross-adapter shared resource.
347+
CloseHandle(heapHandle);
348+
349+
ThrowIfFailed(openSharedHandleResult);
350+
351+
// Create placed resources for each frame per adapter in the shared heap.
295352
for (UINT n = 0; n < FrameCount; n++)
296353
{
297-
ThrowIfFailed(m_devices[Primary]->CreateCommittedResource(
298-
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
299-
D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER,
354+
ThrowIfFailed(m_devices[Primary]->CreatePlacedResource(
355+
m_crossAdapterResourceHeaps[Primary].Get(),
356+
textureSize * n,
300357
&crossAdapterDesc,
301358
D3D12_RESOURCE_STATE_COPY_DEST,
302359
nullptr,
303360
IID_PPV_ARGS(&m_crossAdapterResources[Primary][n])));
304361

305-
HANDLE heapHandle = nullptr;
306-
ThrowIfFailed(m_devices[Primary]->CreateSharedHandle(
307-
m_crossAdapterResources[Primary][n].Get(),
308-
nullptr,
309-
GENERIC_ALL,
362+
ThrowIfFailed(m_devices[Secondary]->CreatePlacedResource(
363+
m_crossAdapterResourceHeaps[Secondary].Get(),
364+
textureSize * n,
365+
&crossAdapterDesc,
366+
m_crossAdapterTextureSupport ? D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE : D3D12_RESOURCE_STATE_COPY_SOURCE,
310367
nullptr,
311-
&heapHandle));
368+
IID_PPV_ARGS(&m_crossAdapterResources[Secondary][n])));
312369

313-
HRESULT openSharedHandleResult = m_devices[Secondary]->OpenSharedHandle(heapHandle, IID_PPV_ARGS(&m_crossAdapterResources[Secondary][n]));
314-
315-
// We can close the handle after opening the cross-adapter shared resource.
316-
CloseHandle(heapHandle);
317-
318-
ThrowIfFailed(openSharedHandleResult);
370+
if (!m_crossAdapterTextureSupport)
371+
{
372+
// If the primary adapter's render target must be shared as a buffer,
373+
// create a texture resource to copy it into on the secondary adapter.
374+
ThrowIfFailed(m_devices[Secondary]->CreateCommittedResource(
375+
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
376+
D3D12_HEAP_FLAG_NONE,
377+
&renderTargetDesc,
378+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
379+
nullptr,
380+
IID_PPV_ARGS(&m_secondaryAdapterTextures[n])));
381+
}
319382
}
320383
}
321384

@@ -335,12 +398,13 @@ void D3D12HeterogeneousMultiadapter::LoadPipeline()
335398
m_devices[Secondary]->CreateRenderTargetView(m_intermediateBlurRenderTarget.Get(), nullptr, rtvHandle);
336399
}
337400

338-
// Create a SRV for the cross-adapter resources and intermediate render target on the secondary adapter.
401+
// Create SRVs for the shared resources and intermediate render target on the secondary adapter.
339402
{
340403
CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(m_cbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart());
341404
for (UINT n = 0; n < FrameCount; n++)
342405
{
343-
m_devices[Secondary]->CreateShaderResourceView(m_crossAdapterResources[Secondary][n].Get(), nullptr, srvHandle);
406+
ID3D12Resource* pSrvResource = m_crossAdapterTextureSupport ? m_crossAdapterResources[Secondary][n].Get() : m_secondaryAdapterTextures[n].Get();
407+
m_devices[Secondary]->CreateShaderResourceView(pSrvResource, nullptr, srvHandle);
344408
srvHandle.Offset(m_srvDescriptorSizes[Secondary]);
345409
}
346410

@@ -691,7 +755,7 @@ void D3D12HeterogeneousMultiadapter::LoadAssets()
691755

692756
// Fence used by the primary adapter to signal its copy queue that it has completed rendering.
693757
// When this is signaled, the primary adapter's copy queue can begin copying to the cross-adapter shared resource.
694-
ThrowIfFailed(m_devices[Primary]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_renderFence)));
758+
ThrowIfFailed(m_devices[Primary]->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_renderFence)));
695759

696760
// Cross-adapter shared fence used by both adapters.
697761
// Used by the primary adapter to signal the secondary adapter that it has completed copying to the cross-adapter shared resource.
@@ -1006,8 +1070,35 @@ void D3D12HeterogeneousMultiadapter::PopulateCommandLists()
10061070
ThrowIfFailed(m_copyCommandAllocators[m_frameIndex]->Reset());
10071071
ThrowIfFailed(m_copyCommandList->Reset(m_copyCommandAllocators[m_frameIndex].Get(), nullptr));
10081072

1009-
// Copy the resource to the cross-adapter shared resource
1010-
m_copyCommandList->CopyResource(m_crossAdapterResources[adapter][m_frameIndex].Get(), m_renderTargets[adapter][m_frameIndex].Get());
1073+
// Copy the intermediate render target to the cross-adapter shared resource.
1074+
// Transition barriers are not required since there are fences guarding against
1075+
// concurrent read/write access to the shared heap.
1076+
if (m_crossAdapterTextureSupport)
1077+
{
1078+
// If cross-adapter row-major textures are supported by the adapter,
1079+
// simply copy the texture into the cross-adapter texture.
1080+
m_copyCommandList->CopyResource(m_crossAdapterResources[adapter][m_frameIndex].Get(), m_renderTargets[adapter][m_frameIndex].Get());
1081+
}
1082+
else
1083+
{
1084+
// If cross-adapter row-major textures are not supported by the adapter,
1085+
// the texture will be copied over as a buffer so that the texture row
1086+
// pitch can be explicitly managed.
1087+
1088+
// Copy the intermediate render target into the shared buffer using the
1089+
// memory layout prescribed by the render target.
1090+
D3D12_RESOURCE_DESC renderTargetDesc = m_renderTargets[adapter][m_frameIndex]->GetDesc();
1091+
D3D12_PLACED_SUBRESOURCE_FOOTPRINT renderTargetLayout;
1092+
1093+
m_devices[adapter]->GetCopyableFootprints(&renderTargetDesc, 0, 1, 0, &renderTargetLayout, nullptr, nullptr, nullptr);
1094+
1095+
CD3DX12_TEXTURE_COPY_LOCATION dest(m_crossAdapterResources[adapter][m_frameIndex].Get(), renderTargetLayout);
1096+
CD3DX12_TEXTURE_COPY_LOCATION src(m_renderTargets[adapter][m_frameIndex].Get(), 0);
1097+
CD3DX12_BOX box(0, 0, m_width, m_height);
1098+
1099+
m_copyCommandList->CopyTextureRegion(&dest, 0, 0, 0, &src, &box);
1100+
}
1101+
10111102
ThrowIfFailed(m_copyCommandList->Close());
10121103
}
10131104

@@ -1025,6 +1116,34 @@ void D3D12HeterogeneousMultiadapter::PopulateCommandLists()
10251116
// re-recording.
10261117
ThrowIfFailed(m_directCommandLists[adapter]->Reset(m_directCommandAllocators[adapter][m_frameIndex].Get(), m_blurPipelineStates[0].Get()));
10271118

1119+
if (!m_crossAdapterTextureSupport)
1120+
{
1121+
// Copy the buffer in the shared heap into a texture that the secondary
1122+
// adapter can sample from.
1123+
D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(
1124+
m_secondaryAdapterTextures[m_frameIndex].Get(),
1125+
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
1126+
D3D12_RESOURCE_STATE_COPY_DEST);
1127+
m_directCommandLists[adapter]->ResourceBarrier(1, &barrier);
1128+
1129+
// Copy the shared buffer contents into the texture using the memory
1130+
// layout prescribed by the texture.
1131+
D3D12_RESOURCE_DESC secondaryAdapterTexture = m_secondaryAdapterTextures[m_frameIndex]->GetDesc();
1132+
D3D12_PLACED_SUBRESOURCE_FOOTPRINT textureLayout;
1133+
1134+
m_devices[adapter]->GetCopyableFootprints(&secondaryAdapterTexture, 0, 1, 0, &textureLayout, nullptr, nullptr, nullptr);
1135+
1136+
CD3DX12_TEXTURE_COPY_LOCATION dest(m_secondaryAdapterTextures[m_frameIndex].Get(), 0);
1137+
CD3DX12_TEXTURE_COPY_LOCATION src(m_crossAdapterResources[adapter][m_frameIndex].Get(), textureLayout);
1138+
CD3DX12_BOX box(0, 0, m_width, m_height);
1139+
1140+
m_directCommandLists[adapter]->CopyTextureRegion(&dest, 0, 0, 0, &src, &box);
1141+
1142+
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
1143+
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
1144+
m_directCommandLists[adapter]->ResourceBarrier(1, &barrier);
1145+
}
1146+
10281147
// Get a timestamp at the start of the command list.
10291148
const UINT timestampHeapIndex = 2 * m_frameIndex;
10301149
m_directCommandLists[adapter]->EndQuery(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex);
@@ -1062,7 +1181,6 @@ void D3D12HeterogeneousMultiadapter::PopulateCommandLists()
10621181
{
10631182
m_directCommandLists[adapter]->SetPipelineState(m_blurPipelineStates[1].Get());
10641183

1065-
// Indicate that the intermediate render target will be used as a shader resource.
10661184
// Indicate that the back buffer will be used as a render target and the
10671185
// intermediate render target will be used as a SRV.
10681186
D3D12_RESOURCE_BARRIER barriers[] = {

Samples/Desktop/D3D12HeterogeneousMultiadapter/src/D3D12HeterogeneousMultiadapter.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ class D3D12HeterogeneousMultiadapter : public DXSample
157157
WorkloadConstantBufferData* m_pWorkloadCbvDataBegin;
158158
WorkloadConstantBufferData m_blurWorkloadConstantBufferData;
159159
WorkloadConstantBufferData* m_pBlurWorkloadCbvDataBegin;
160+
ComPtr<ID3D12Heap> m_crossAdapterResourceHeaps[GraphicsAdaptersCount];
160161
ComPtr<ID3D12Resource> m_crossAdapterResources[GraphicsAdaptersCount][FrameCount];
162+
BOOL m_crossAdapterTextureSupport;
163+
ComPtr<ID3D12Resource> m_secondaryAdapterTextures[FrameCount]; // Only used if cross adapter texture support is unavailable.
161164
ComPtr<ID3D12Resource> m_renderTargets[GraphicsAdaptersCount][FrameCount];
162165
ComPtr<ID3D12Resource> m_intermediateBlurRenderTarget;
163166
ComPtr<ID3D12QueryHeap> m_timestampQueryHeaps[GraphicsAdaptersCount];
@@ -172,4 +175,9 @@ class D3D12HeterogeneousMultiadapter : public DXSample
172175
void UpdateWindowTitle();
173176
void WaitForGpu(GraphicsAdapter adapter);
174177
void MoveToNextFrame();
175-
};
178+
179+
static inline UINT Align(UINT size, UINT alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT)
180+
{
181+
return (size + alignment - 1) & ~(alignment - 1);
182+
}
183+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Small Resources Sample
2+
This sample demonstrates the use of small placed resources in Direct3D 12. The sample allocates a number of small textures using 4K resource alignment and shows the potential memory savings gained by using placed resources over committed and reserved resources which use 64K resource alignments. The resource type and current GPU memory usage are displayed in the window's title bar.
3+
### Controls
4+
SPACE bar - toggles between using placed and committed resources.

0 commit comments

Comments
 (0)