HRESULT STDMETHODCALLTYPE DXGIXAffinityCreateLDASwapChain( IDXGISwapChain3* pSwapChain, CD3DX12AffinityCommandQueue* pQueue, CD3DX12AffinityDevice* pDevice, DXGI_SWAP_CHAIN_DESC1* pDesc, CDXGIAffinitySwapChain** ppSwapChain) { CD3DX12AffinityCommandQueue* AffinityQueue = static_cast<CD3DX12AffinityCommandQueue*>(pQueue); CD3DX12AffinityDevice* AffinityDevice = static_cast<CD3DX12AffinityDevice*>(pDevice); ID3D12Device* HostDevice = AffinityDevice->GetChildObject(0); std::vector<CDXGIAffinitySwapChain::SDeviceContext> NodeContexts; NodeContexts.reserve(AffinityDevice->GetNodeCount()); for (UINT i = 0; i < AffinityDevice->GetNodeCount(); ++i) { NodeContexts.push_back(CDXGIAffinitySwapChain::SDeviceContext()); CDXGIAffinitySwapChain::SDeviceContext& NodeContext = NodeContexts.back(); NodeContext.mDevice = AffinityDevice->GetChildObject(0); //single device in LDA case NodeContext.mDisplayCommandQueue = AffinityQueue->GetChildObject(i); } CDXGIAffinitySwapChain* AffinityChain = new CDXGIAffinitySwapChain(AffinityDevice, AffinityQueue, &pSwapChain, 1); AffinityChain->mMode = EAffinitySwapChainMode::LDA; AffinityChain->mDeviceContexts = NodeContexts; AffinityChain->mNumBackBuffers = lcm(pDesc->BufferCount, AffinityDevice->GetNodeCount()); AffinityChain->mNumRequestedBackBuffers = pDesc->BufferCount; AffinityChain->mHostDevice = HostDevice; *ppSwapChain = AffinityChain; std::vector<IUnknown*> ppCommandQueues; std::vector<UINT> pCreationNodes; for (UINT i = 0; i < AffinityChain->mNumBackBuffers; ++i) { UINT node = i % AffinityDevice->GetNodeCount(); ppCommandQueues.push_back(AffinityQueue->GetChildObject(node)); pCreationNodes.push_back(AffinityDevice->AffinityIndexToNodeMask(node)); } pSwapChain->AddRef(); const HRESULT hr = pSwapChain->ResizeBuffers1(AffinityChain->mNumBackBuffers, pDesc->Width, pDesc->Height, pDesc->Format, pDesc->Flags, pCreationNodes.data(), ppCommandQueues.data()); return hr; }
HRESULT STDMETHODCALLTYPE DXGIXAffinityCreateSingleWindowSwapChain( IDXGISwapChain3* pSwapChain, CD3DX12AffinityCommandQueue* pQueue, CD3DX12AffinityDevice* pDevice, DXGI_SWAP_CHAIN_DESC1* pDesc, CDXGIAffinitySwapChain** ppSwapChain) { CD3DX12AffinityCommandQueue* AffinityQueue = static_cast<CD3DX12AffinityCommandQueue*>(pQueue); CD3DX12AffinityDevice* AffinityDevice = static_cast<CD3DX12AffinityDevice*>(pDevice); ID3D12Device* HostDevice = AffinityDevice->GetChildObject(0); std::vector<CDXGIAffinitySwapChain::SDeviceContext> DeviceContexts; DeviceContexts.reserve(AffinityDevice->GetDeviceCount()); for (UINT i = 0; i < AffinityDevice->GetDeviceCount(); ++i) { DeviceContexts.push_back(CDXGIAffinitySwapChain::SDeviceContext()); CDXGIAffinitySwapChain::SDeviceContext& DeviceContext = DeviceContexts.back(); DeviceContext.mDevice = AffinityDevice->GetChildObject(i); DeviceContext.mDisplayCommandQueue = AffinityQueue->GetChildObject(i); // Each device needs a command list and respective command allocator. // This list will be used for submitting resource barriers and copies from the "dummy" rendertarget. RETURN_IF_FAILED_WITH_ERROR_LOG( DeviceContext.mDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&DeviceContext.mDisplayCommandAllocator)), "Failed to create command allocator during affinity swap chain setup.", AffinityDevice); RETURN_IF_FAILED_WITH_ERROR_LOG( DeviceContext.mDevice->CreateCommandList( 0, D3D12_COMMAND_LIST_TYPE_DIRECT, DeviceContext.mDisplayCommandAllocator, nullptr, IID_PPV_ARGS(&DeviceContext.mDisplayCommandList)), "Failed to create command list during affinity swap chain setup.", AffinityDevice); // The device at index 0 is the "host" device, it uses it's own actual render targets // and presents from this device occur in the usual fashion. // // For all devices index 1 and up, we need to create some fences and intermediate buffers // to facilitate presents. { // Create the cross-adapter copy fence, used to control access to the cross-adapter copy buffer RETURN_IF_FAILED_WITH_ERROR_LOG( DeviceContext.mDevice->CreateFence( 0, D3D12_FENCE_FLAG_SHARED | D3D12_FENCE_FLAG_SHARED_CROSS_ADAPTER, IID_PPV_ARGS(&DeviceContext.mCrossAdapterCopyFence)), "Failed to create fence during affinity swap chain setup.", AffinityDevice); std::wstring Name = std::wstring(L"CrossAdapterCopyFence") + std::to_wstring(i); RETURN_IF_FAILED(DeviceContext.mCrossAdapterCopyFence->SetName(Name.c_str())); { HANDLE CrossAdapterCopyFenceSharedHandle = nullptr; RETURN_IF_FAILED_WITH_ERROR_LOG( DeviceContext.mDevice->CreateSharedHandle( DeviceContext.mCrossAdapterCopyFence, nullptr, GENERIC_ALL, Name.c_str(), &CrossAdapterCopyFenceSharedHandle), "Failed to create shared handle to cross adapter copy fence during affinity swap chain setup.", AffinityDevice); RETURN_IF_FAILED_WITH_ERROR_LOG( HostDevice->OpenSharedHandle(CrossAdapterCopyFenceSharedHandle, IID_PPV_ARGS(&DeviceContext.mCrossAdapterCopyFenceOnHost)), "Failed to open shared handle to cross adapter copy fence during affinity swap chain setup.", AffinityDevice); Name = std::wstring(L"CrossAdapterCopyFenceOnHost") + std::to_wstring(i); RETURN_IF_FAILED(DeviceContext.mCrossAdapterCopyFenceOnHost->SetName(L"CrossAdapterCopyFenceOnHost")); } // Create the "dummy" render targets and cross-adapter copy buffers. // For a swap chain with (n) back buffers, we create (n) render targets and (n) cross-adapter copy buffers. DeviceContext.mRenderTargets.reserve(pDesc->BufferCount); DeviceContext.mCrossAdapterCopyBuffers.reserve(pDesc->BufferCount); RETURN_IF_FAILED(CDXGIAffinitySwapChain::CreateDummyRenderTargetsAndCrossAdapterCopyBuffers( i, AffinityDevice, HostDevice, DeviceContext, pDesc->Width, pDesc->Height, pDesc->Format, pDesc->BufferCount )); } } pSwapChain->AddRef(); CDXGIAffinitySwapChain* AffinityChain = new CDXGIAffinitySwapChain(AffinityDevice, AffinityQueue, &pSwapChain, 1); if (AffinityDevice->GetAffinityMode() == EAffinityMode::LDA) { AffinityChain->mMode = EAffinitySwapChainMode::LDA; } else { AffinityChain->mMode = EAffinitySwapChainMode::SingleWindow; } AffinityChain->mDeviceContexts = DeviceContexts; AffinityChain->mNumBackBuffers = pDesc->BufferCount; AffinityChain->mHostDevice = HostDevice; *ppSwapChain = AffinityChain; return S_OK; }