void AppTest::InitBundles() { CHK(Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_BUNDLE, IID_PPV_ARGS(CommandBundleAllocator.GetAddressOf()))); for (unsigned int i = 0; i < BundleCount; i++) { const unsigned int bundlesPerThread = BundleCount / ThreadCount; const unsigned int threadID = i / bundlesPerThread; CHK(Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_BUNDLE, CommandBundleAllocator.Get(), PSO.Get(), IID_PPV_ARGS(CommandBundleArray[i].GetAddressOf()))); ID3D12GraphicsCommandList* commandBundle = CommandBundleArray[i].Get(); const unsigned int offset = ObjectsPerBundle * i; commandBundle->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); commandBundle->SetGraphicsRootSignature(RootSignature.Get()); if (UseRootLevelCBV) { for (unsigned int command = 0; command < ObjectsPerBundle; command++) { commandBundle->SetGraphicsRootConstantBufferView(0, PerObjectConstantBuffers.GetGPUHandle(offset + command)); commandBundle->DrawIndexedInstanced(IndexCount, 1, 0, 0, 0); } } else { D3D12_GPU_DESCRIPTOR_HANDLE descriptorHandle; ID3D12DescriptorHeap* descriptorHeap = ConstantBufferDescriptorHeap->GetBaseHeap(); commandBundle->SetDescriptorHeaps(1, &descriptorHeap); for (unsigned int command = 0; command < ObjectsPerBundle; command++) { descriptorHandle.ptr = ConstantBufferDescriptorHeap->GetDescriptorGPUHandle(offset + command); commandBundle->SetGraphicsRootDescriptorTable(0, descriptorHandle); commandBundle->DrawIndexedInstanced(IndexCount, 1, 0, 0, 0); } } commandBundle->Close(); } }
void DXMultiAdapterRenderer::PopulateCommandLists() { // Primary rendering command list { ComPtr<ID3D12Resource> curPrimaryRenderTarget = mDXDevices[Device_Primary]->mRenderTargets[mCurrentFrameIndex]; // Reset allocator and command list for current render target ThrowIfFailed(mDXDevices[Device_Primary]->mCommandAllocator->Reset()); // Only do this when all command lists have finished executing ID3D12GraphicsCommandList* primaryCommandList = mCommandLists[Primary_CommandList_Scene].Get(); ThrowIfFailed(primaryCommandList->Reset(mDXDevices[Device_Primary]->mCommandAllocator.Get(), nullptr)); primaryCommandList->RSSetViewports(1, &mViewport); primaryCommandList->RSSetScissorRects(1, &mScissorRect); ID3D12DescriptorHeap* descHeaps[] = { mDXDevices[Device_Primary]->mCbvSrvUavHeap.Get() }; primaryCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps); // Allow for rending to current render target primaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curPrimaryRenderTarget.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mDXDevices[Device_Primary]->mRtvHeap->GetCPUDescriptorHandleForHeapStart(), mCurrentFrameIndex, mDXDevices[Device_Primary]->mRtvDescriptorSize); primaryCommandList->OMSetRenderTargets(1, &rtvHandle, true, nullptr); primaryCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); primaryCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Primary_Quad_Top]); // Render top portion of scene on primary GPU primaryCommandList->SetGraphicsRootSignature(mRootSignatures[Primary_RootSignature_Scene].Get()); primaryCommandList->SetGraphicsRootDescriptorTable(0, mTimePrimaryCbvHandle); primaryCommandList->SetPipelineState(mPipelineStates[Primary_PipelineState_Scene].Get()); primaryCommandList->DrawInstanced(4, 1, 0, 0); // Indicate that render target will be used for copy primaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curPrimaryRenderTarget.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); ThrowIfFailed(mCommandLists[Primary_CommandList_Scene]->Close()); } // Copy command list - in DXCrossAdapterResources object { mCrossAdapterResources->PopulateCommandList(mCurrentFrameIndex); } // Reset command allocator for secondary device - used by all following command lists ThrowIfFailed(mDXDevices[Device_Secondary]->mCommandAllocator->Reset()); // Only do this when all command lists have finished executing // Secondary rendering command list { ID3D12GraphicsCommandList* secondaryCommandList = mCommandLists[Secondary_CommandList_Scene].Get(); ThrowIfFailed(secondaryCommandList->Reset(mDXDevices[Device_Secondary]->mCommandAllocator.Get(), nullptr)); secondaryCommandList->RSSetViewports(1, &mViewport); secondaryCommandList->RSSetScissorRects(1, &mScissorRect); ID3D12DescriptorHeap* descHeaps[] = { mDXDevices[Device_Secondary]->mCbvSrvUavHeap.Get() }; secondaryCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps); secondaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mTexture.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); secondaryCommandList->OMSetRenderTargets(1, &mTextureRtvHandle, true, nullptr); secondaryCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); secondaryCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Secondary_Quad_Bottom]); // Quad geometry // Render bottom portion of scene on secondary GPU secondaryCommandList->SetGraphicsRootSignature(mRootSignatures[Secondary_RootSignature_Scene].Get()); secondaryCommandList->SetGraphicsRootDescriptorTable(0, mTimeSecondaryCbvHandle); secondaryCommandList->SetPipelineState(mPipelineStates[Secondary_PipelineState_Scene].Get()); secondaryCommandList->DrawInstanced(4, 1, 0, 0); secondaryCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mTexture.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); ThrowIfFailed(mCommandLists[Secondary_CommandList_Scene]->Close()); } // Overlay Command List { ID3D12GraphicsCommandList* overlayCommandList = mCommandLists[Secondary_CommandList_Combine_Scene].Get(); ComPtr<ID3D12Resource> curSecondaryRenderTarget = mDXDevices[Device_Secondary]->mRenderTargets[mCurrentFrameIndex]; // Get secondary render target for current frame ThrowIfFailed(overlayCommandList->Reset(mDXDevices[Device_Secondary]->mCommandAllocator.Get(), nullptr)); overlayCommandList->RSSetViewports(1, &mViewport); overlayCommandList->RSSetScissorRects(1, &mScissorRect); ID3D12DescriptorHeap* descHeaps[] = { mDXDevices[Device_Secondary]->mCbvSrvUavHeap.Get() }; overlayCommandList->SetDescriptorHeaps(_countof(descHeaps), descHeaps); overlayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curSecondaryRenderTarget.Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(mDXDevices[Device_Secondary]->mRtvHeap->GetCPUDescriptorHandleForHeapStart(), mCurrentFrameIndex, mDXDevices[Device_Secondary]->mRtvDescriptorSize); overlayCommandList->OMSetRenderTargets(1, &rtvHandle, true, nullptr); static const float clearColor[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; overlayCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); overlayCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Render top quad with cross-adapter texture overlayCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Secondary_Quad_Combine_Top]); // Quad geometry CD3DX12_GPU_DESCRIPTOR_HANDLE crossAdapterSrvHandle(mDXDevices[Device_Secondary]->mCbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(), mCurrentFrameIndex, mDXDevices[Device_Secondary]->mCbvSrvUavDescriptorSize); overlayCommandList->SetGraphicsRootSignature(mRootSignatures[Secondary_RootSignature_CrossAdapter].Get()); overlayCommandList->SetPipelineState(mPipelineStates[Secondary_PipelineState_CrossAdapter].Get()); overlayCommandList->SetGraphicsRootDescriptorTable(0, mTransformTopCbvHandle); overlayCommandList->SetGraphicsRootDescriptorTable(1, crossAdapterSrvHandle); // Scale and translate quad to top of screen mConstantBufferTransformTopData.modelViewProjection = DirectX::XMMatrixIdentity(); mConstantBufferTransformTopData.modelViewProjection *= DirectX::XMMatrixTranslation(0.0, ((1.0f / mSharePercentage) - 1.0f) + 0.015f, 0.0); mConstantBufferTransformTopData.modelViewProjection *= DirectX::XMMatrixScaling(1.0, mSharePercentage, 1.0); UpdateConstantBuffer(mConstantBufferTransformTop, &mConstantBufferTransformTopData, sizeof(mConstantBufferTransformTopData)); overlayCommandList->DrawInstanced(4, 1, 0, 0); // Render bottom quad with texture from secondary GPU overlayCommandList->IASetVertexBuffers(0, 1, mVertexBufferViews[Secondary_Quad_Combine_Bottom]); // Quad geometry overlayCommandList->SetGraphicsRootDescriptorTable(0, mTransformBottomCbvHandle); overlayCommandList->SetGraphicsRootDescriptorTable(1, mTextureSrvHandle); // Scale and translate quad to bottom of screen mConstantBufferTransformBottomData.modelViewProjection = DirectX::XMMatrixIdentity(); mConstantBufferTransformBottomData.modelViewProjection *= DirectX::XMMatrixTranslation(0.0, -((1.0f / (1.0f - mSharePercentage)) - 1.0f) - 0.015f, 0.0); mConstantBufferTransformBottomData.modelViewProjection *= DirectX::XMMatrixScaling(1.0, (1.0f - mSharePercentage), 1.0); UpdateConstantBuffer(mConstantBufferTransformBottom, &mConstantBufferTransformBottomData, sizeof(mConstantBufferTransformBottomData)); overlayCommandList->DrawInstanced(4, 1, 0, 0); overlayCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(curSecondaryRenderTarget.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); ThrowIfFailed(mCommandLists[Secondary_CommandList_Combine_Scene]->Close()); } }
//-------------------------------------------------------------------------- void VeRenderWindowD3D12::Record(VeUInt32 u32Index) noexcept { VeRendererD3D12& kRenderer = *VeMemberCast( &VeRendererD3D12::m_kRenderWindowList, m_kNode.get_list()); VE_ASSERT(u32Index < m_kRecorderList.size()); Recorder& kRecorder = m_kRecorderList[u32Index]; FrameCache& kFrame = m_akFrameCache[m_u32FrameIndex]; ID3D12GraphicsCommandList* pkGCL = kFrame.m_kDirectCommandList[kRecorder.m_u32CommandIndex]; VE_ASSERT_GE(pkGCL->Reset(kFrame.m_pkDirectAllocator, nullptr), S_OK); ID3D12DescriptorHeap* ppHeaps[] = { kRenderer.m_kSRVHeap.Get() }; pkGCL->SetDescriptorHeaps(1, ppHeaps); for (auto& task : kRecorder.m_kTaskList) { switch (task->m_eType) { case REC_BARRIER: { auto& list = ((RecordBarrier*)task)->m_akBarrierList[m_u32FrameIndex]; pkGCL->ResourceBarrier((VeUInt32)list.size(), &list.front()); } break; case REC_CLEAR_RTV: { RecordClearRTV& rec = *((RecordClearRTV*)task); pkGCL->ClearRenderTargetView(rec.m_ahHandle[m_u32FrameIndex], (const FLOAT*)&(rec.m_kColor), 0, nullptr); } break; case REC_CLEAR_DSV: { RecordClearDSV& rec = *((RecordClearDSV*)task); pkGCL->ClearDepthStencilView(rec.m_ahHandle[m_u32FrameIndex], rec.m_eFlags, rec.m_f32Depth, rec.m_u8Stencil, 0, nullptr); } break; case REC_RENDER_TARGET: { RecordRenderTarget& rec = *((RecordRenderTarget*)task); pkGCL->OMSetRenderTargets((VeUInt32)rec.m_akRTVList[m_u32FrameIndex].size(), &rec.m_akRTVList[m_u32FrameIndex].front(), FALSE, rec.m_ahDSV[m_u32FrameIndex].ptr ? &rec.m_ahDSV[m_u32FrameIndex] : nullptr); } break; case REC_VIEWPORT: { RecordViewport& rec = *((RecordViewport*)task); pkGCL->RSSetViewports((VeUInt32)rec.m_kViewportList.size(), &rec.m_kViewportList.front()); } break; case REC_SCISSOR_RECT: { RecordScissorRect& rec = *((RecordScissorRect*)task); pkGCL->RSSetScissorRects((VeUInt32)rec.m_kScissorRectList.size(), &rec.m_kScissorRectList.front()); } break; case REC_RENDER_QUAD: { RecordRenderQuad& rec = *((RecordRenderQuad*)task); pkGCL->SetPipelineState(rec.m_pkPipelineState); pkGCL->SetGraphicsRootSignature(rec.m_pkRootSignature); for (auto& itTab : rec.m_kTable) { pkGCL->SetGraphicsRootDescriptorTable(itTab.first, itTab.second); } pkGCL->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); pkGCL->IASetVertexBuffers(0, 1, &kRenderer.m_kQuadVBV); pkGCL->DrawInstanced(4, 1, 0, 0); } break; default: break; } } VE_ASSERT_GE(pkGCL->Close(), S_OK); }