|
12 | 12 | #include "stdafx.h" |
13 | 13 | #include "D3D12ExecuteIndirect.h" |
14 | 14 |
|
| 15 | +const UINT D3D12ExecuteIndirect::CommandBufferSizePerFrame = TriangleCount * sizeof(IndirectCommand); |
15 | 16 | const float D3D12ExecuteIndirect::TriangleHalfWidth = 0.05f; |
16 | 17 | const float D3D12ExecuteIndirect::TriangleDepth = 1.0f; |
17 | 18 | const float D3D12ExecuteIndirect::CullingCutoff = 0.5f; |
@@ -354,7 +355,7 @@ void D3D12ExecuteIndirect::LoadAssets() |
354 | 355 | m_constantBufferData[n].velocity = XMFLOAT4(GetRandomFloat(0.01f, 0.02f), 0.0f, 0.0f, 0.0f); |
355 | 356 | m_constantBufferData[n].offset = XMFLOAT4(GetRandomFloat(-5.0f, -1.5f), GetRandomFloat(-1.0f, 1.0f), GetRandomFloat(0.0f, 2.0f), 0.0f); |
356 | 357 | m_constantBufferData[n].color = XMFLOAT4(GetRandomFloat(0.5f, 1.0f), GetRandomFloat(0.5f, 1.0f), GetRandomFloat(0.5f, 1.0f), 1.0f); |
357 | | - m_constantBufferData[n].projection = XMMatrixTranspose(XMMatrixPerspectiveFovLH(XM_PIDIV4, m_aspectRatio, 0.01f, 20.0f)); |
| 358 | + XMStoreFloat4x4(&m_constantBufferData[n].projection, XMMatrixTranspose(XMMatrixPerspectiveFovLH(XM_PIDIV4, m_aspectRatio, 0.01f, 20.0f))); |
358 | 359 |
|
359 | 360 | for (int frame = 0; frame < FrameCount; frame++) |
360 | 361 | { |
@@ -410,7 +411,7 @@ void D3D12ExecuteIndirect::LoadAssets() |
410 | 411 | { |
411 | 412 | std::vector<IndirectCommand> commands; |
412 | 413 | commands.resize(TriangleResourceCount); |
413 | | - const UINT commandBufferSize = TriangleResourceCount * sizeof(IndirectCommand); |
| 414 | + const UINT commandBufferSize = CommandBufferSizePerFrame * FrameCount; |
414 | 415 |
|
415 | 416 | ThrowIfFailed(m_device->CreateCommittedResource( |
416 | 417 | &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), |
@@ -477,46 +478,48 @@ void D3D12ExecuteIndirect::LoadAssets() |
477 | 478 | CD3DX12_CPU_DESCRIPTOR_HANDLE processedCommandsHandle(m_cbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart(), ProcessedCommandsOffset, m_cbvSrvUavDescriptorSize); |
478 | 479 | for (UINT frame = 0; frame < FrameCount; frame++) |
479 | 480 | { |
480 | | - // Allocate a buffer large enough to hold all of the indirect commands. |
| 481 | + // Allocate a buffer large enough to hold all of the indirect commands |
| 482 | + // for a single frame as well as a UAV counter. |
481 | 483 | ThrowIfFailed(m_device->CreateCommittedResource( |
482 | 484 | &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), |
483 | 485 | D3D12_HEAP_FLAG_NONE, |
484 | | - &CD3DX12_RESOURCE_DESC::Buffer(commandBufferSize / FrameCount, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS), |
485 | | - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, |
| 486 | + &CD3DX12_RESOURCE_DESC::Buffer(CommandBufferSizePerFrame + sizeof(UINT), D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS), |
| 487 | + D3D12_RESOURCE_STATE_COPY_DEST, |
486 | 488 | nullptr, |
487 | 489 | IID_PPV_ARGS(&m_processedCommandBuffers[frame]))); |
488 | 490 |
|
489 | | - // Allocate a counter for the UAV. |
490 | | - ThrowIfFailed(m_device->CreateCommittedResource( |
491 | | - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), |
492 | | - D3D12_HEAP_FLAG_NONE, |
493 | | - &CD3DX12_RESOURCE_DESC::Buffer(sizeof(UINT)), |
494 | | - D3D12_RESOURCE_STATE_GENERIC_READ, |
495 | | - nullptr, |
496 | | - IID_PPV_ARGS(&m_processedCommandBufferCounters[frame]))); |
497 | | - |
498 | 491 | D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; |
499 | 492 | uavDesc.Format = DXGI_FORMAT_UNKNOWN; |
500 | 493 | uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; |
501 | 494 | uavDesc.Buffer.FirstElement = 0; |
502 | 495 | uavDesc.Buffer.NumElements = TriangleCount; |
503 | 496 | uavDesc.Buffer.StructureByteStride = sizeof(IndirectCommand); |
504 | | - uavDesc.Buffer.CounterOffsetInBytes = 0; |
| 497 | + uavDesc.Buffer.CounterOffsetInBytes = CommandBufferSizePerFrame; |
505 | 498 | uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE; |
506 | 499 |
|
507 | 500 | m_device->CreateUnorderedAccessView( |
508 | 501 | m_processedCommandBuffers[frame].Get(), |
509 | | - m_processedCommandBufferCounters[frame].Get(), |
| 502 | + m_processedCommandBuffers[frame].Get(), |
510 | 503 | &uavDesc, |
511 | 504 | processedCommandsHandle); |
512 | 505 |
|
513 | | - // Map the UAV counters. We don't unmap these until the app closes. |
514 | | - // Keeping things mapped for the lifetime of the resource is okay. |
515 | | - ThrowIfFailed(m_processedCommandBufferCounters[frame]->Map(0, nullptr, reinterpret_cast<void**>(&m_pMappedUavCounters[frame]))); |
516 | | - ZeroMemory(m_pMappedUavCounters[frame], sizeof(UINT)); |
517 | | - |
518 | 506 | processedCommandsHandle.Offset(CbvSrvUavDescriptorCountPerFrame, m_cbvSrvUavDescriptorSize); |
519 | 507 | } |
| 508 | + |
| 509 | + // Allocate a buffer that can be used to reset the UAV counters and initialize |
| 510 | + // it to 0. |
| 511 | + ThrowIfFailed(m_device->CreateCommittedResource( |
| 512 | + &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), |
| 513 | + D3D12_HEAP_FLAG_NONE, |
| 514 | + &CD3DX12_RESOURCE_DESC::Buffer(sizeof(UINT)), |
| 515 | + D3D12_RESOURCE_STATE_GENERIC_READ, |
| 516 | + nullptr, |
| 517 | + IID_PPV_ARGS(&m_processedCommandBufferCounterReset))); |
| 518 | + |
| 519 | + UINT8* pMappedCounterReset = nullptr; |
| 520 | + ThrowIfFailed(m_processedCommandBufferCounterReset->Map(0, nullptr, reinterpret_cast<void**>(&pMappedCounterReset))); |
| 521 | + ZeroMemory(pMappedCounterReset, sizeof(UINT)); |
| 522 | + m_processedCommandBufferCounterReset->Unmap(0, nullptr); |
520 | 523 | } |
521 | 524 |
|
522 | 525 | // Close the command list and execute it to begin the vertex buffer copy into |
@@ -571,8 +574,6 @@ void D3D12ExecuteIndirect::OnUpdate() |
571 | 574 |
|
572 | 575 | UINT8* destination = m_pCbvDataBegin + (TriangleCount * m_frameIndex * sizeof(ConstantBufferData)); |
573 | 576 | memcpy(destination, &m_constantBufferData[0], TriangleCount * sizeof(ConstantBufferData)); |
574 | | - |
575 | | - ZeroMemory(m_pMappedUavCounters[m_frameIndex], sizeof(UINT)); |
576 | 577 | } |
577 | 578 |
|
578 | 579 | // Render the scene. |
@@ -655,6 +656,12 @@ void D3D12ExecuteIndirect::PopulateCommandLists() |
655 | 656 |
|
656 | 657 | m_computeCommandList->SetComputeRoot32BitConstants(RootConstants, 4, reinterpret_cast<void*>(&m_csRootConstants), 0); |
657 | 658 |
|
| 659 | + // Reset the UAV counter for this frame. |
| 660 | + m_computeCommandList->CopyBufferRegion(m_processedCommandBuffers[m_frameIndex].Get(), CommandBufferSizePerFrame, m_processedCommandBufferCounterReset.Get(), 0, sizeof(UINT)); |
| 661 | + |
| 662 | + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_processedCommandBuffers[m_frameIndex].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); |
| 663 | + m_computeCommandList->ResourceBarrier(1, &barrier); |
| 664 | + |
658 | 665 | m_computeCommandList->Dispatch(static_cast<UINT>(ceil(TriangleCount / float(ComputeThreadBlockSize))), 1, 1); |
659 | 666 | } |
660 | 667 |
|
@@ -698,19 +705,33 @@ void D3D12ExecuteIndirect::PopulateCommandLists() |
698 | 705 | m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); |
699 | 706 | m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView); |
700 | 707 |
|
701 | | - // Draw the triangles that have not been culled. |
702 | | - m_commandList->ExecuteIndirect( |
703 | | - m_commandSignature.Get(), |
704 | | - TriangleCount, |
705 | | - m_enableCulling ? m_processedCommandBuffers[m_frameIndex].Get() : m_commandBuffer.Get(), |
706 | | - m_enableCulling ? 0 : TriangleCount * m_frameIndex * sizeof(IndirectCommand), |
707 | | - m_enableCulling ? m_processedCommandBufferCounters[m_frameIndex].Get() : nullptr, |
708 | | - 0); |
| 708 | + if (m_enableCulling) |
| 709 | + { |
| 710 | + // Draw the triangles that have not been culled. |
| 711 | + m_commandList->ExecuteIndirect( |
| 712 | + m_commandSignature.Get(), |
| 713 | + TriangleCount, |
| 714 | + m_processedCommandBuffers[m_frameIndex].Get(), |
| 715 | + 0, |
| 716 | + m_processedCommandBuffers[m_frameIndex].Get(), |
| 717 | + CommandBufferSizePerFrame); |
| 718 | + } |
| 719 | + else |
| 720 | + { |
| 721 | + // Draw all of the triangles. |
| 722 | + m_commandList->ExecuteIndirect( |
| 723 | + m_commandSignature.Get(), |
| 724 | + TriangleCount, |
| 725 | + m_commandBuffer.Get(), |
| 726 | + CommandBufferSizePerFrame * m_frameIndex, |
| 727 | + nullptr, |
| 728 | + 0); |
| 729 | + } |
709 | 730 |
|
710 | 731 | // Indicate that the command buffer may be used by the compute shader |
711 | 732 | // and that the back buffer will now be used to present. |
712 | 733 | barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; |
713 | | - barriers[0].Transition.StateAfter = m_enableCulling ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; |
| 734 | + barriers[0].Transition.StateAfter = m_enableCulling ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; |
714 | 735 | barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; |
715 | 736 | barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; |
716 | 737 |
|
|
0 commit comments