void WorldObjectEffect::beginBulkUpdate() { if (inThreadOperation) return; int frameIndex = xapp().getCurrentBackBufferIndex(); inBulkOperation = true; ThrowIfFailed(commandAllocators[frameIndex]->Reset()); ThrowIfFailed(commandLists[frameIndex]->Reset(commandAllocators[frameIndex].Get(), pipelineState.Get())); // Set necessary state. commandLists[frameIndex]->SetGraphicsRootSignature(rootSignature.Get()); // TODO check //commandLists[frameIndex]->RSSetViewports(1, &vr_eyes.viewports[eyeNum]); //commandLists[frameIndex]->RSSetScissorRects(1, &vr_eyes.scissorRects[eyeNum]); //commandLists[frameIndex]->RSSetViewports(1, xapp().vr.getViewport()); //commandLists[frameIndex]->RSSetScissorRects(1, xapp().vr.getScissorRect()); // Set CBVs //commandLists[frameIndex]->SetGraphicsRootConstantBufferView(0, cbvResource->GetGPUVirtualAddress() + cbvAlignedSize); commandLists[frameIndex]->SetGraphicsRootConstantBufferView(1, xapp().lights.cbvResource->GetGPUVirtualAddress()); // Indicate that the back buffer will be used as a render target. // commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(renderTargets[frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); //CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(xapp().rtvHeap->GetCPUDescriptorHandleForHeapStart(), frameIndex, xapp().rtvDescriptorSize); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle = xapp().getRTVHandle(frameIndex); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(xapp().dsvHeaps[frameIndex]->GetCPUDescriptorHandleForHeapStart()); //m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); commandLists[frameIndex]->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); xapp().handleRTVClearing(commandLists[frameIndex].Get(), rtvHandle, dsvHandle); }
D3D12_CPU_DESCRIPTOR_HANDLE QD3D12Window::extraDepthStencilCPUHandle(int idx) const { Q_D(const QD3D12Window); Q_ASSERT(idx >= 0 && idx < d->extraRenderTargetCount); D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle(d->dsvHeap->GetCPUDescriptorHandleForHeapStart()); dsvHandle.ptr += (1 + idx) * d->dsvStride; return dsvHandle; }
void D3D12DynamicIndexing::PopulateCommandList(FrameResource* pFrameResource) { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(m_pCurrentFrameResource->m_commandAllocator->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(m_commandList->Reset(m_pCurrentFrameResource->m_commandAllocator.Get(), m_pipelineState.Get())); // Set necessary state. m_commandList->SetGraphicsRootSignature(m_rootSignature.Get()); ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvHeap.Get(), m_samplerHeap.Get() }; m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps); m_commandList->RSSetViewports(1, &m_viewport); m_commandList->RSSetScissorRects(1, &m_scissorRect); // Indicate that the back buffer will be used as a render target. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); // Record commands. const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f }; m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); m_commandList->ClearDepthStencilView(m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); if (UseBundles) { // Execute the prebuilt bundle. m_commandList->ExecuteBundle(pFrameResource->m_bundle.Get()); } else { // Populate a new command list. pFrameResource->PopulateCommandList(m_commandList.Get(), m_pipelineState.Get(), m_currentFrameResourceIndex, m_numIndices, &m_indexBufferView, &m_vertexBufferView, m_cbvSrvHeap.Get(), m_cbvSrvDescriptorSize, m_samplerHeap.Get(), m_rootSignature.Get()); } // Indicate that the back buffer will now be used to present. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); ThrowIfFailed(m_commandList->Close()); }
void WorldObjectEffect::preDraw(DrawInfo &di) { // last frame must have been finished before we run here!!! int frameIndex = xapp().getCurrentBackBufferIndex(); if (!inBulkOperation) { //auto &f = frameData[xapp().lastPresentedFrame]; //waitForSyncPoint(f); //auto &f = frameData[frameIndex]; //waitForSyncPoint(f); // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(commandAllocators[frameIndex]->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(commandLists[frameIndex]->Reset(commandAllocators[frameIndex].Get(), pipelineState.Get())); // Set necessary state. commandLists[frameIndex]->SetGraphicsRootSignature(rootSignature.Get()); commandLists[frameIndex]->RSSetViewports(1, &vr_eyes.viewports[di.eyeNum]); commandLists[frameIndex]->RSSetScissorRects(1, &vr_eyes.scissorRects[di.eyeNum]); // Set CBVs commandLists[frameIndex]->SetGraphicsRootConstantBufferView(0, cbvResource->GetGPUVirtualAddress()/* + cbvAlignedSize*/); commandLists[frameIndex]->SetGraphicsRootConstantBufferView(1, xapp().lights.cbvResource->GetGPUVirtualAddress()); // Indicate that the back buffer will be used as a render target. // commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(renderTargets[frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); //CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(xapp().rtvHeap->GetCPUDescriptorHandleForHeapStart(), frameIndex, xapp().rtvDescriptorSize); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle = xapp().getRTVHandle(frameIndex); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(xapp().dsvHeaps[frameIndex]->GetCPUDescriptorHandleForHeapStart()); //m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); commandLists[frameIndex]->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); xapp().handleRTVClearing(commandLists[frameIndex].Get(), rtvHandle, dsvHandle); return; } commandLists[frameIndex]->SetGraphicsRootConstantBufferView(0, getCBVVirtualAddress(frameIndex, 0, di.objectNum, 0)); }
// Worker thread body. workerIndex is an integer from 0 to NumContexts // describing the worker's thread index. void D3D12Multithreading::WorkerThread(LPVOID workerIndex) { int threadIndex = reinterpret_cast<int>(workerIndex); assert(threadIndex >= 0); assert(threadIndex < NumContexts); #if !SINGLETHREADED while (threadIndex >= 0 && threadIndex < NumContexts) { // Wait for main thread to tell us to draw. WaitForSingleObject(m_workerBeginRenderFrame[threadIndex], INFINITE); #endif ID3D12GraphicsCommandList* pShadowCommandList = m_pCurrentFrameResource->m_shadowCommandLists[threadIndex].Get(); ID3D12GraphicsCommandList* pSceneCommandList = m_pCurrentFrameResource->m_sceneCommandLists[threadIndex].Get(); // // Shadow pass // // Populate the command list. SetCommonPipelineState(pShadowCommandList); m_pCurrentFrameResource->Bind(pShadowCommandList, FALSE, nullptr, nullptr); // No need to pass RTV or DSV descriptor heap. // Set null SRVs for the diffuse/normal textures. pShadowCommandList->SetGraphicsRootDescriptorTable(0, m_cbvSrvHeap->GetGPUDescriptorHandleForHeapStart()); // Distribute objects over threads by drawing only 1/NumContexts // objects per worker (i.e. every object such that objectnum % // NumContexts == threadIndex). PIXBeginEvent(pShadowCommandList, 0, L"Worker drawing shadow pass..."); for (int j = threadIndex; j < _countof(SampleAssets::Draws); j += NumContexts) { SampleAssets::DrawParameters drawArgs = SampleAssets::Draws[j]; pShadowCommandList->DrawIndexedInstanced(drawArgs.IndexCount, 1, drawArgs.IndexStart, drawArgs.VertexBase, 0); } PIXEndEvent(pShadowCommandList); ThrowIfFailed(pShadowCommandList->Close()); #if !SINGLETHREADED // Submit shadow pass. SetEvent(m_workerFinishShadowPass[threadIndex]); #endif // // Scene pass // // Populate the command list. These can only be sent after the shadow // passes for this frame have been submitted. SetCommonPipelineState(pSceneCommandList); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); m_pCurrentFrameResource->Bind(pSceneCommandList, TRUE, &rtvHandle, &dsvHandle); PIXBeginEvent(pSceneCommandList, 0, L"Worker drawing scene pass..."); D3D12_GPU_DESCRIPTOR_HANDLE cbvSrvHeapStart = m_cbvSrvHeap->GetGPUDescriptorHandleForHeapStart(); const UINT cbvSrvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); const UINT nullSrvCount = 2; for (int j = threadIndex; j < _countof(SampleAssets::Draws); j += NumContexts) { SampleAssets::DrawParameters drawArgs = SampleAssets::Draws[j]; // Set the diffuse and normal textures for the current object. CD3DX12_GPU_DESCRIPTOR_HANDLE cbvSrvHandle(cbvSrvHeapStart, nullSrvCount + drawArgs.DiffuseTextureIndex, cbvSrvDescriptorSize); pSceneCommandList->SetGraphicsRootDescriptorTable(0, cbvSrvHandle); pSceneCommandList->DrawIndexedInstanced(drawArgs.IndexCount, 1, drawArgs.IndexStart, drawArgs.VertexBase, 0); } PIXEndEvent(pSceneCommandList); ThrowIfFailed(pSceneCommandList->Close()); #if !SINGLETHREADED // Tell main thread that we are done. SetEvent(m_workerFinishedRenderFrame[threadIndex]); } #endif }
// Fill the command list with all the render commands and dependent state. void D3D12HeterogeneousMultiadapter::PopulateCommandLists() { // Command list to render target the triangles on the primary adapter. { const GraphicsAdapter adapter = Primary; // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(m_directCommandAllocators[adapter][m_frameIndex]->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(m_directCommandLists[adapter]->Reset(m_directCommandAllocators[adapter][m_frameIndex].Get(), m_pipelineState.Get())); // Get a timestamp at the start of the command list. const UINT timestampHeapIndex = 2 * m_frameIndex; m_directCommandLists[adapter]->EndQuery(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex); // Set necessary state. m_directCommandLists[adapter]->SetGraphicsRootSignature(m_rootSignature.Get()); m_directCommandLists[adapter]->RSSetViewports(1, &m_viewport); m_directCommandLists[adapter]->RSSetScissorRects(1, &m_scissorRect); // Indicate that the render target will be used as a render target. m_directCommandLists[adapter]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[adapter][m_frameIndex].Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeaps[adapter]->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSizes[adapter]); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); m_directCommandLists[adapter]->OMSetRenderTargets(1, &rtvHandle, false, &dsvHandle); // Record commands. m_directCommandLists[adapter]->ClearRenderTargetView(rtvHandle, ClearColor, 0, nullptr); m_directCommandLists[adapter]->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Draw the triangles. m_directCommandLists[adapter]->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_directCommandLists[adapter]->IASetVertexBuffers(0, 1, &m_vertexBufferView); m_directCommandLists[adapter]->SetGraphicsRootConstantBufferView(1, m_workloadConstantBuffer->GetGPUVirtualAddress() + (m_frameIndex * sizeof(WorkloadConstantBufferData))); const D3D12_GPU_VIRTUAL_ADDRESS cbVirtualAddress = m_constantBuffer->GetGPUVirtualAddress(); for (UINT n = 0; n < m_triangleCount; n++) { const D3D12_GPU_VIRTUAL_ADDRESS cbLocation = cbVirtualAddress + (m_frameIndex * MaxTriangleCount * sizeof(ConstantBufferData)) + (n * sizeof(ConstantBufferData)); m_directCommandLists[adapter]->SetGraphicsRootConstantBufferView(0, cbLocation); m_directCommandLists[adapter]->DrawInstanced(3, 1, 0, 0); } // Indicate that the render target will now be used to copy. m_directCommandLists[adapter]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[adapter][m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE)); // Get a timestamp at the end of the command list and resolve the query data. m_directCommandLists[adapter]->EndQuery(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex + 1); m_directCommandLists[adapter]->ResolveQueryData(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex, 2, m_timestampResultBuffers[adapter].Get(), timestampHeapIndex * sizeof(UINT64)); ThrowIfFailed(m_directCommandLists[adapter]->Close()); } // Command list to copy the render target to the shared heap on the primary adapter. { const GraphicsAdapter adapter = Primary; // Reset the copy command allocator and command list. ThrowIfFailed(m_copyCommandAllocators[m_frameIndex]->Reset()); ThrowIfFailed(m_copyCommandList->Reset(m_copyCommandAllocators[m_frameIndex].Get(), nullptr)); // Copy the resource to the cross-adapter shared resource m_copyCommandList->CopyResource(m_crossAdapterResources[adapter][m_frameIndex].Get(), m_renderTargets[adapter][m_frameIndex].Get()); ThrowIfFailed(m_copyCommandList->Close()); } // Command list to blur the render target and present. { const GraphicsAdapter adapter = Secondary; // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(m_directCommandAllocators[adapter][m_frameIndex]->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(m_directCommandLists[adapter]->Reset(m_directCommandAllocators[adapter][m_frameIndex].Get(), m_blurPipelineStates[0].Get())); // Get a timestamp at the start of the command list. const UINT timestampHeapIndex = 2 * m_frameIndex; m_directCommandLists[adapter]->EndQuery(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex); // Set necessary state. m_directCommandLists[adapter]->SetGraphicsRootSignature(m_blurRootSignature.Get()); ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() }; m_directCommandLists[adapter]->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps); m_directCommandLists[adapter]->RSSetViewports(1, &m_viewport); m_directCommandLists[adapter]->RSSetScissorRects(1, &m_scissorRect); // Indicate that the intermediate render target will be used as a render target. m_directCommandLists[adapter]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_intermediateBlurRenderTarget.Get(), D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET)); // Record commands. m_directCommandLists[adapter]->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_directCommandLists[adapter]->IASetVertexBuffers(0, 1, &m_fullscreenQuadVertexBufferView); m_directCommandLists[adapter]->SetGraphicsRootConstantBufferView(0, m_blurConstantBuffer->GetGPUVirtualAddress()); m_directCommandLists[adapter]->SetGraphicsRootConstantBufferView(2, m_blurWorkloadConstantBuffer->GetGPUVirtualAddress() + (m_frameIndex * sizeof(WorkloadConstantBufferData))); // Draw the fullscreen quad - Blur pass #1. { CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle(m_cbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(), m_frameIndex, m_srvDescriptorSizes[adapter]); m_directCommandLists[adapter]->SetGraphicsRootDescriptorTable(1, srvHandle); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeaps[adapter]->GetCPUDescriptorHandleForHeapStart(), FrameCount, m_rtvDescriptorSizes[adapter]); m_directCommandLists[adapter]->OMSetRenderTargets(1, &rtvHandle, false, nullptr); m_directCommandLists[adapter]->DrawInstanced(4, 1, 0, 0); } // Draw the fullscreen quad - Blur pass #2. { m_directCommandLists[adapter]->SetPipelineState(m_blurPipelineStates[1].Get()); // Indicate that the intermediate render target will be used as a shader resource. // Indicate that the back buffer will be used as a render target and the // intermediate render target will be used as a SRV. D3D12_RESOURCE_BARRIER barriers[] = { CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[adapter][m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET), CD3DX12_RESOURCE_BARRIER::Transition(m_intermediateBlurRenderTarget.Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) }; m_directCommandLists[adapter]->ResourceBarrier(_countof(barriers), barriers); CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle(m_cbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(), FrameCount, m_srvDescriptorSizes[adapter]); m_directCommandLists[adapter]->SetGraphicsRootDescriptorTable(1, srvHandle); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeaps[adapter]->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSizes[adapter]); m_directCommandLists[adapter]->OMSetRenderTargets(1, &rtvHandle, false, nullptr); m_directCommandLists[adapter]->DrawInstanced(4, 1, 0, 0); } // Indicate that the back buffer will now be used to present. m_directCommandLists[adapter]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[adapter][m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); // Get a timestamp at the end of the command list and resolve the query data. m_directCommandLists[adapter]->EndQuery(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex + 1); m_directCommandLists[adapter]->ResolveQueryData(m_timestampQueryHeaps[adapter].Get(), D3D12_QUERY_TYPE_TIMESTAMP, timestampHeapIndex, 2, m_timestampResultBuffers[adapter].Get(), timestampHeapIndex * sizeof(UINT64)); ThrowIfFailed(m_directCommandLists[adapter]->Close()); } }
// Fill the command list with all the render commands and dependent state. void D3D12PredicationQueries::PopulateCommandList() { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get())); // Set necessary state. m_commandList->SetGraphicsRootSignature(m_rootSignature.Get()); ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() }; m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps); m_commandList->RSSetViewports(1, &m_viewport); m_commandList->RSSetScissorRects(1, &m_scissorRect); // Indicate that the back buffer will be used as a render target. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); // Record commands. const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f }; m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); // Draw the quads and perform the occlusion query. { CD3DX12_GPU_DESCRIPTOR_HANDLE cbvFarQuad(m_cbvHeap->GetGPUDescriptorHandleForHeapStart(), m_frameIndex * CbvCountPerFrame, m_cbvSrvDescriptorSize); CD3DX12_GPU_DESCRIPTOR_HANDLE cbvNearQuad(cbvFarQuad, m_cbvSrvDescriptorSize); m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); // Draw the far quad conditionally based on the result of the occlusion query // from the previous frame. PIXBeginEvent(m_commandList.Get(), 0, L"Draw potentially occluded geometry"); m_commandList->SetGraphicsRootDescriptorTable(0, cbvFarQuad); m_commandList->SetPredication(m_queryResult.Get(), 0, D3D12_PREDICATION_OP_EQUAL_ZERO); m_commandList->DrawInstanced(4, 1, 0, 0); PIXEndEvent(m_commandList.Get()); // Disable predication and always draw the near quad. PIXBeginEvent(m_commandList.Get(), 0, L"Draw animating geometry"); m_commandList->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO); m_commandList->SetGraphicsRootDescriptorTable(0, cbvNearQuad); m_commandList->DrawInstanced(4, 1, 4, 0); PIXEndEvent(m_commandList.Get()); // Run the occlusion query with the bounding box quad. PIXBeginEvent(m_commandList.Get(), 0, L"Execute occlusion query"); m_commandList->SetGraphicsRootDescriptorTable(0, cbvFarQuad); m_commandList->SetPipelineState(m_queryState.Get()); m_commandList->BeginQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, 0); m_commandList->DrawInstanced(4, 1, 8, 0); m_commandList->EndQuery(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, 0); PIXEndEvent(m_commandList.Get()); // Resolve the occlusion query and store the results in the query result buffer // to be used on the subsequent frame. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_queryResult.Get(), D3D12_RESOURCE_STATE_PREDICATION, D3D12_RESOURCE_STATE_COPY_DEST)); m_commandList->ResolveQueryData(m_queryHeap.Get(), D3D12_QUERY_TYPE_BINARY_OCCLUSION, 0, 1, m_queryResult.Get(), 0); m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_queryResult.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PREDICATION)); } // Indicate that the back buffer will now be used to present. m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); ThrowIfFailed(m_commandList->Close()); }
// Fill the command list with all the render commands and dependent state. void D3D12ExecuteIndirect::PopulateCommandLists() { // Command list allocators can only be reset when the associated // command lists have finished execution on the GPU; apps should use // fences to determine GPU execution progress. ThrowIfFailed(m_computeCommandAllocators[m_frameIndex]->Reset()); ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset()); // However, when ExecuteCommandList() is called on a particular command // list, that command list can then be reset at any time and must be before // re-recording. ThrowIfFailed(m_computeCommandList->Reset(m_computeCommandAllocators[m_frameIndex].Get(), m_computeState.Get())); ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get())); // Record the compute commands that will cull triangles and prevent them from being processed by the vertex shader. if (m_enableCulling) { UINT frameDescriptorOffset = m_frameIndex * CbvSrvUavDescriptorCountPerFrame; D3D12_GPU_DESCRIPTOR_HANDLE cbvSrvUavHandle = m_cbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart(); m_computeCommandList->SetComputeRootSignature(m_computeRootSignature.Get()); ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() }; m_computeCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps); m_computeCommandList->SetComputeRootDescriptorTable( SrvUavTable, CD3DX12_GPU_DESCRIPTOR_HANDLE(cbvSrvUavHandle, CbvSrvOffset + frameDescriptorOffset, m_cbvSrvUavDescriptorSize)); m_computeCommandList->SetComputeRoot32BitConstants(RootConstants, 4, reinterpret_cast<void*>(&m_csRootConstants), 0); // Reset the UAV counter for this frame. m_computeCommandList->CopyBufferRegion(m_processedCommandBuffers[m_frameIndex].Get(), CommandBufferSizePerFrame, m_processedCommandBufferCounterReset.Get(), 0, sizeof(UINT)); D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_processedCommandBuffers[m_frameIndex].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); m_computeCommandList->ResourceBarrier(1, &barrier); m_computeCommandList->Dispatch(static_cast<UINT>(ceil(TriangleCount / float(ComputeThreadBlockSize))), 1, 1); } ThrowIfFailed(m_computeCommandList->Close()); // Record the rendering commands. { // Set necessary state. m_commandList->SetGraphicsRootSignature(m_rootSignature.Get()); ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() }; m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps); m_commandList->RSSetViewports(1, &m_viewport); m_commandList->RSSetScissorRects(1, m_enableCulling ? &m_cullingScissorRect : &m_scissorRect); // Indicate that the command buffer will be used for indirect drawing // and that the back buffer will be used as a render target. D3D12_RESOURCE_BARRIER barriers[2] = { CD3DX12_RESOURCE_BARRIER::Transition( m_enableCulling ? m_processedCommandBuffers[m_frameIndex].Get() : m_commandBuffer.Get(), m_enableCulling ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT), CD3DX12_RESOURCE_BARRIER::Transition( m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET) }; m_commandList->ResourceBarrier(_countof(barriers), barriers); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart()); m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); // Record commands. const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f }; m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); if (m_enableCulling) { // Draw the triangles that have not been culled. m_commandList->ExecuteIndirect( m_commandSignature.Get(), TriangleCount, m_processedCommandBuffers[m_frameIndex].Get(), 0, m_processedCommandBuffers[m_frameIndex].Get(), CommandBufferSizePerFrame); } else { // Draw all of the triangles. m_commandList->ExecuteIndirect( m_commandSignature.Get(), TriangleCount, m_commandBuffer.Get(), CommandBufferSizePerFrame * m_frameIndex, nullptr, 0); } // Indicate that the command buffer may be used by the compute shader // and that the back buffer will now be used to present. barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; barriers[0].Transition.StateAfter = m_enableCulling ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; m_commandList->ResourceBarrier(_countof(barriers), barriers); ThrowIfFailed(m_commandList->Close()); } }
void WorldObjectEffect::updateTask(BulkDivideInfo bi, int threadIndex, const vector<unique_ptr<WorldObject>> *grp, WorldObjectEffect *effect) { effect->workerThreadsCreated++; //ComPtr<ID3D12GraphicsCommandList> commandList; //ComPtr<ID3D12CommandAllocator> commandAllocator; int frameIndex; while (true) { { unique_lock<mutex> lock(effect->multiRenderLock); effect->waiting_for_rendering++; effect->render_start.notify_one(); effect->render_wait.wait(lock); if (effect->allThreadsShouldEnd) break; // jump out of while loop } // now running outside lock so that all worker threads run in parallel //if (threadIndex > 0) Sleep(10); //Log("rendering " << this_thread::get_id() << endl); //this_thread::sleep_for(1s); //Log("rendering ended " << this_thread::get_id() << endl); frameIndex = xapp().getCurrentBackBufferIndex(); if (!threadLocal.initialized) { threadLocal.initialized = true; Log(" obj bulk update thread " << std::hex << this_thread::get_id() << " " << bi.start << endl); //Log(" obj bulk update thread " << bi.start << endl); this_thread::sleep_for(4s); ThrowIfFailed(xapp().device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&threadLocal.commandAllocator))); ThrowIfFailed(xapp().device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, threadLocal.commandAllocator.Get(), effect->pipelineState.Get(), IID_PPV_ARGS(&threadLocal.commandList))); } else { threadLocal.commandAllocator->Reset(); threadLocal.commandList->Reset(threadLocal.commandAllocator.Get(), effect->pipelineState.Get()); } //Log(" obj bulk update thread " << bi.end << " complete" << endl); threadLocal.commandList->SetGraphicsRootSignature(effect->rootSignature.Get()); // TODO check //threadLocal.commandList->RSSetViewports(1, xapp().vr.getViewport()); //threadLocal.commandList->RSSetScissorRects(1, xapp().vr.getScissorRect()); // Set CBVs //commandLists[frameIndex]->SetGraphicsRootConstantBufferView(0, cbvResource->GetGPUVirtualAddress() + cbvAlignedSize); //threadLocal.commandList->SetGraphicsRootConstantBufferView(1, xapp().lights.cbvResource->GetGPUVirtualAddress()); // Indicate that the back buffer will be used as a render target. // commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(renderTargets[frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle = xapp().getRTVHandle(frameIndex); CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(xapp().dsvHeaps[frameIndex]->GetCPUDescriptorHandleForHeapStart()); threadLocal.commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle); threadLocal.commandList->SetGraphicsRootConstantBufferView(0, effect->getCBVVirtualAddress(frameIndex, threadIndex, 0, 0)); for (auto i = bi.start; i <= bi.end; i++) { WorldObject *w = grp->at(i).get(); //commandList->SetGraphicsRootConstantBufferView(0, effect->getCBVVirtualAddress(frameIndex, w->objectNum)); w->threadNum = threadIndex; //if (threadIndex == 1) this_thread::sleep_for(30ms); //Log(" obj draw" << w->objectNum << endl); w->draw(); //Log(" obj end" << w->objectNum << endl); //Log(" pos" << w->objectNum << endl) //auto & w = grp[i]; //w.->draw(); } ThrowIfFailed(threadLocal.commandList->Close()); // Execute the command list. ID3D12CommandList* ppCommandLists[] = { threadLocal.commandList.Get() }; xapp().commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists); { unique_lock<mutex> lock(effect->multiRenderLock); effect->finished_rendering++; effect->render_ended.notify_one(); } } effect->workerThreadsCreated--; }