|
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