Guest User

D3D12ExecuteIndirect.cpp

a guest
Apr 21st, 2016
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 33.41 KB | None | 0 0
  1. //*********************************************************
  2. //
  3. // Copyright (c) Microsoft. All rights reserved.
  4. // This code is licensed under the MIT License (MIT).
  5. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  6. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  7. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  8. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  9. //
  10. //*********************************************************
  11.  
  12. #include "stdafx.h"
  13. #include "D3D12ExecuteIndirect.h"
  14.  
  15. const UINT D3D12ExecuteIndirect::CommandBufferSizePerFrame = TriangleCount * sizeof(IndirectCommand);
  16. const float D3D12ExecuteIndirect::TriangleHalfWidth = 0.05f;
  17. const float D3D12ExecuteIndirect::TriangleDepth = 1.0f;
  18. const float D3D12ExecuteIndirect::CullingCutoff = 0.5f;
  19.  
  20. D3D12ExecuteIndirect::D3D12ExecuteIndirect(UINT width, UINT height, std::wstring name) :
  21.     DXSample(width, height, name),
  22.     m_frameIndex(0),
  23.     m_viewport(),
  24.     m_scissorRect(),
  25.     m_cullingScissorRect(),
  26.     m_rtvDescriptorSize(0),
  27.     m_cbvSrvUavDescriptorSize(0),
  28.     m_csRootConstants(),
  29.     m_enableCulling(true)
  30. {
  31.     ZeroMemory(m_fenceValues, sizeof(m_fenceValues));
  32.     m_constantBufferData.resize(TriangleCount);
  33.  
  34.     m_csRootConstants.xOffset = TriangleHalfWidth;
  35.     m_csRootConstants.zOffset = TriangleDepth;
  36.     m_csRootConstants.cullOffset = CullingCutoff;
  37.     m_csRootConstants.commandCount = TriangleCount;
  38.  
  39.     m_viewport.Width = static_cast<float>(width);
  40.     m_viewport.Height = static_cast<float>(height);
  41.     m_viewport.MaxDepth = 1.0f;
  42.  
  43.     m_scissorRect.right = static_cast<LONG>(width);
  44.     m_scissorRect.bottom = static_cast<LONG>(height);
  45.  
  46.     float center = width / 2.0f;
  47.     m_cullingScissorRect.left = static_cast<LONG>(center - (center * CullingCutoff));
  48.     m_cullingScissorRect.right = static_cast<LONG>(center + (center * CullingCutoff));
  49.     m_cullingScissorRect.bottom = static_cast<LONG>(height);
  50. }
  51.  
  52. void D3D12ExecuteIndirect::OnInit()
  53. {
  54.     LoadPipeline();
  55.     LoadAssets();
  56. }
  57.  
  58. // Load the rendering pipeline dependencies.
  59. void D3D12ExecuteIndirect::LoadPipeline()
  60. {
  61. #if defined(_DEBUG)
  62.     // Enable the D3D12 debug layer.
  63.     {
  64.         ComPtr<ID3D12Debug> debugController;
  65.         if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
  66.         {
  67.             debugController->EnableDebugLayer();
  68.         }
  69.     }
  70. #endif
  71.  
  72.     ComPtr<IDXGIFactory4> factory;
  73.     ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&factory)));
  74.  
  75.     if (m_useWarpDevice)
  76.     {
  77.         ComPtr<IDXGIAdapter> warpAdapter;
  78.         ThrowIfFailed(factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));
  79.  
  80.         ThrowIfFailed(D3D12CreateDevice(
  81.             warpAdapter.Get(),
  82.             D3D_FEATURE_LEVEL_11_0,
  83.             IID_PPV_ARGS(&m_device)
  84.             ));
  85.     }
  86.     else
  87.     {
  88.         ComPtr<IDXGIAdapter1> hardwareAdapter;
  89.         GetHardwareAdapter(factory.Get(), &hardwareAdapter);
  90.  
  91.         ThrowIfFailed(D3D12CreateDevice(
  92.             hardwareAdapter.Get(),
  93.             D3D_FEATURE_LEVEL_11_0,
  94.             IID_PPV_ARGS(&m_device)
  95.             ));
  96.     }
  97.  
  98.     // Describe and create the command queues.
  99.     D3D12_COMMAND_QUEUE_DESC queueDesc = {};
  100.     queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
  101.     queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
  102.  
  103.     ThrowIfFailed(m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue)));
  104.     NAME_D3D12_OBJECT(m_commandQueue);
  105.  
  106.     D3D12_COMMAND_QUEUE_DESC computeQueueDesc = {};
  107.     computeQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
  108.     computeQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_COMPUTE;
  109.  
  110.     ThrowIfFailed(m_device->CreateCommandQueue(&computeQueueDesc, IID_PPV_ARGS(&m_computeCommandQueue)));
  111.     NAME_D3D12_OBJECT(m_computeCommandQueue);
  112.  
  113.     // Describe and create the swap chain.
  114.     DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
  115.     swapChainDesc.BufferCount = FrameCount;
  116.     swapChainDesc.Width = m_width;
  117.     swapChainDesc.Height = m_height;
  118.     swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  119.     swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  120.     swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
  121.     swapChainDesc.SampleDesc.Count = 1;
  122.  
  123.     ComPtr<IDXGISwapChain1> swapChain;
  124.     ThrowIfFailed(factory->CreateSwapChainForHwnd(
  125.         m_commandQueue.Get(),       // Swap chain needs the queue so that it can force a flush on it.
  126.         Win32Application::GetHwnd(),
  127.         &swapChainDesc,
  128.         nullptr,
  129.         nullptr,
  130.         &swapChain
  131.         ));
  132.  
  133.     // This sample does not support fullscreen transitions.
  134.     ThrowIfFailed(factory->MakeWindowAssociation(Win32Application::GetHwnd(), DXGI_MWA_NO_ALT_ENTER));
  135.  
  136.     ThrowIfFailed(swapChain.As(&m_swapChain));
  137.     m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
  138.  
  139.     // Create descriptor heaps.
  140.     {
  141.         // Describe and create a render target view (RTV) descriptor heap.
  142.         D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {};
  143.         rtvHeapDesc.NumDescriptors = FrameCount;
  144.         rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
  145.         rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  146.         ThrowIfFailed(m_device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_rtvHeap)));
  147.  
  148.         // Describe and create a depth stencil view (DSV) descriptor heap.
  149.         D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
  150.         dsvHeapDesc.NumDescriptors = 1;
  151.         dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
  152.         dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  153.         ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap)));
  154.  
  155.         // Describe and create a constant buffer view (CBV), Shader resource
  156.         // view (SRV), and unordered access view (UAV) descriptor heap.
  157.         D3D12_DESCRIPTOR_HEAP_DESC cbvSrvUavHeapDesc = {};
  158.         cbvSrvUavHeapDesc.NumDescriptors = CbvSrvUavDescriptorCountPerFrame * FrameCount;
  159.         cbvSrvUavHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  160.         cbvSrvUavHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  161.         ThrowIfFailed(m_device->CreateDescriptorHeap(&cbvSrvUavHeapDesc, IID_PPV_ARGS(&m_cbvSrvUavHeap)));
  162.         NAME_D3D12_OBJECT(m_cbvSrvUavHeap);
  163.  
  164.         m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
  165.         m_cbvSrvUavDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  166.     }
  167.  
  168.     // Create frame resources.
  169.     {
  170.         CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart());
  171.  
  172.         // Create a RTV and command allocators for each frame.
  173.         for (UINT n = 0; n < FrameCount; n++)
  174.         {
  175.             ThrowIfFailed(m_swapChain->GetBuffer(n, IID_PPV_ARGS(&m_renderTargets[n])));
  176.             m_device->CreateRenderTargetView(m_renderTargets[n].Get(), nullptr, rtvHandle);
  177.             rtvHandle.Offset(1, m_rtvDescriptorSize);
  178.  
  179.             WCHAR name[25];
  180.             if (swprintf_s(name, L"m_renderTargets[%u]", n) > 0)
  181.             {
  182.                 SetName(m_renderTargets[n].Get(), name);
  183.             }
  184.  
  185.             ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocators[n])));
  186.             ThrowIfFailed(m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COMPUTE, IID_PPV_ARGS(&m_computeCommandAllocators[n])));
  187.         }
  188.     }
  189. }
  190.  
  191. // Load the sample assets.
  192. void D3D12ExecuteIndirect::LoadAssets()
  193. {
  194.     // Create the root signatures.
  195.     {
  196.         CD3DX12_ROOT_PARAMETER rootParameters[GraphicsRootParametersCount];
  197.         rootParameters[Cbv].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_VERTEX);
  198.  
  199.         CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
  200.         rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  201.  
  202.         ComPtr<ID3DBlob> signature;
  203.         ComPtr<ID3DBlob> error;
  204.         ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
  205.         ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
  206.         NAME_D3D12_OBJECT(m_rootSignature);
  207.  
  208.         // Create compute signature.
  209.         CD3DX12_DESCRIPTOR_RANGE ranges[2];
  210.         ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0);
  211.         ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0);
  212.  
  213.         CD3DX12_ROOT_PARAMETER computeRootParameters[ComputeRootParametersCount];
  214.         computeRootParameters[SrvUavTable].InitAsDescriptorTable(2, ranges);
  215.         computeRootParameters[RootConstants].InitAsConstants(4, 0);
  216.  
  217.         CD3DX12_ROOT_SIGNATURE_DESC computeRootSignatureDesc;
  218.         computeRootSignatureDesc.Init(_countof(computeRootParameters), computeRootParameters);
  219.  
  220.         ThrowIfFailed(D3D12SerializeRootSignature(&computeRootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
  221.         ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_computeRootSignature)));
  222.         NAME_D3D12_OBJECT(m_computeRootSignature);
  223.     }
  224.  
  225.     // Create the pipeline state, which includes compiling and loading shaders.
  226.     {
  227.         ComPtr<ID3DBlob> vertexShader;
  228.         ComPtr<ID3DBlob> pixelShader;
  229.         ComPtr<ID3DBlob> computeShader;
  230.         ComPtr<ID3DBlob> error;
  231.  
  232. #if defined(_DEBUG)
  233.         // Enable better shader debugging with the graphics debugging tools.
  234.         UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
  235. #else
  236.         UINT compileFlags = 0;
  237. #endif
  238.  
  239.         ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, &error));
  240.         ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, &error));
  241.         ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"compute.hlsl").c_str(), nullptr, nullptr, "CSMain", "cs_5_0", compileFlags, 0, &computeShader, &error));
  242.  
  243.         // Define the vertex input layout.
  244.         D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
  245.         {
  246.             { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  247.         };
  248.  
  249.         // Describe and create the graphics pipeline state objects (PSO).
  250.         D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
  251.         psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
  252.         psoDesc.pRootSignature = m_rootSignature.Get();
  253.         psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShader.Get());
  254.         psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShader.Get());
  255.         psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  256.         psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  257.         psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  258.         psoDesc.SampleMask = UINT_MAX;
  259.         psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  260.         psoDesc.NumRenderTargets = 1;
  261.         psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
  262.         psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT;
  263.         psoDesc.SampleDesc.Count = 1;
  264.  
  265.         ThrowIfFailed( m_device->CreateGraphicsPipelineState( &psoDesc, IID_PPV_ARGS( &m_pipelineState0 ) ) );
  266.         ThrowIfFailed( m_device->CreateGraphicsPipelineState( &psoDesc, IID_PPV_ARGS( &m_pipelineState1 ) ) );
  267.         NAME_D3D12_OBJECT( m_pipelineState0 );
  268.         NAME_D3D12_OBJECT( m_pipelineState1 );
  269.  
  270.         // Describe and create the compute pipeline state object (PSO).
  271.         D3D12_COMPUTE_PIPELINE_STATE_DESC computePsoDesc = {};
  272.         computePsoDesc.pRootSignature = m_computeRootSignature.Get();
  273.         computePsoDesc.CS = CD3DX12_SHADER_BYTECODE(computeShader.Get());
  274.  
  275.         ThrowIfFailed(m_device->CreateComputePipelineState(&computePsoDesc, IID_PPV_ARGS(&m_computeState)));
  276.         NAME_D3D12_OBJECT(m_computeState);
  277.     }
  278.  
  279.     // Create the command list.
  280.     ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocators[m_frameIndex].Get(), m_pipelineState0.Get(), IID_PPV_ARGS(&m_commandList)));
  281.     ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COMPUTE, m_computeCommandAllocators[m_frameIndex].Get(), m_computeState.Get(), IID_PPV_ARGS(&m_computeCommandList)));
  282.     ThrowIfFailed(m_computeCommandList->Close());
  283.  
  284.     NAME_D3D12_OBJECT(m_commandList);
  285.     NAME_D3D12_OBJECT(m_computeCommandList);
  286.  
  287.     // Note: ComPtr's are CPU objects but these resources need to stay in scope until
  288.     // the command list that references them has finished executing on the GPU.
  289.     // We will flush the GPU at the end of this method to ensure the resources are not
  290.     // prematurely destroyed.
  291.     ComPtr<ID3D12Resource> vertexBufferUpload;
  292.     ComPtr<ID3D12Resource> commandBufferUpload;
  293.  
  294.     // Create the vertex buffer.
  295.     {
  296.         // Define the geometry for a triangle.
  297.         Vertex triangleVertices[] =
  298.         {
  299.             { { 0.0f, TriangleHalfWidth, TriangleDepth } },
  300.             { { TriangleHalfWidth, -TriangleHalfWidth, TriangleDepth } },
  301.             { { -TriangleHalfWidth, -TriangleHalfWidth, TriangleDepth } }
  302.         };
  303.  
  304.         const UINT vertexBufferSize = sizeof(triangleVertices);
  305.  
  306.         ThrowIfFailed(m_device->CreateCommittedResource(
  307.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  308.             D3D12_HEAP_FLAG_NONE,
  309.             &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
  310.             D3D12_RESOURCE_STATE_COPY_DEST,
  311.             nullptr,
  312.             IID_PPV_ARGS(&m_vertexBuffer)));
  313.  
  314.         ThrowIfFailed(m_device->CreateCommittedResource(
  315.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
  316.             D3D12_HEAP_FLAG_NONE,
  317.             &CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
  318.             D3D12_RESOURCE_STATE_GENERIC_READ,
  319.             nullptr,
  320.             IID_PPV_ARGS(&vertexBufferUpload)));
  321.  
  322.         NAME_D3D12_OBJECT(m_vertexBuffer);
  323.  
  324.         // Copy data to the intermediate upload heap and then schedule a copy
  325.         // from the upload heap to the vertex buffer.
  326.         D3D12_SUBRESOURCE_DATA vertexData = {};
  327.         vertexData.pData = reinterpret_cast<UINT8*>(triangleVertices);
  328.         vertexData.RowPitch = vertexBufferSize;
  329.         vertexData.SlicePitch = vertexData.RowPitch;
  330.  
  331.         UpdateSubresources<1>(m_commandList.Get(), m_vertexBuffer.Get(), vertexBufferUpload.Get(), 0, 0, 1, &vertexData);
  332.         m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
  333.  
  334.         // Initialize the vertex buffer view.
  335.         m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
  336.         m_vertexBufferView.StrideInBytes = sizeof(Vertex);
  337.         m_vertexBufferView.SizeInBytes = sizeof(triangleVertices);
  338.     }
  339.  
  340.     // Create the depth stencil view.
  341.     {
  342.         D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
  343.         depthStencilDesc.Format = DXGI_FORMAT_D32_FLOAT;
  344.         depthStencilDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
  345.         depthStencilDesc.Flags = D3D12_DSV_FLAG_NONE;
  346.  
  347.         D3D12_CLEAR_VALUE depthOptimizedClearValue = {};
  348.         depthOptimizedClearValue.Format = DXGI_FORMAT_D32_FLOAT;
  349.         depthOptimizedClearValue.DepthStencil.Depth = 1.0f;
  350.         depthOptimizedClearValue.DepthStencil.Stencil = 0;
  351.  
  352.         ThrowIfFailed(m_device->CreateCommittedResource(
  353.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  354.             D3D12_HEAP_FLAG_NONE,
  355.             &CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_D32_FLOAT, m_width, m_height, 1, 0, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
  356.             D3D12_RESOURCE_STATE_DEPTH_WRITE,
  357.             &depthOptimizedClearValue,
  358.             IID_PPV_ARGS(&m_depthStencil)
  359.             ));
  360.  
  361.         NAME_D3D12_OBJECT(m_depthStencil);
  362.  
  363.         m_device->CreateDepthStencilView(m_depthStencil.Get(), &depthStencilDesc, m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
  364.     }
  365.  
  366.     // Create the constant buffers.
  367.     {
  368.         const UINT constantBufferDataSize = TriangleResourceCount * sizeof(ConstantBufferData);
  369.  
  370.         ThrowIfFailed(m_device->CreateCommittedResource(
  371.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
  372.             D3D12_HEAP_FLAG_NONE,
  373.             &CD3DX12_RESOURCE_DESC::Buffer(constantBufferDataSize),
  374.             D3D12_RESOURCE_STATE_GENERIC_READ,
  375.             nullptr,
  376.             IID_PPV_ARGS(&m_constantBuffer)));
  377.  
  378.         NAME_D3D12_OBJECT(m_constantBuffer);
  379.  
  380.         D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
  381.         cbvDesc.SizeInBytes = sizeof(ConstantBufferData);
  382.  
  383.         // Create constant buffer views to access the upload buffer.
  384.         for (UINT n = 0; n < TriangleCount; n++)
  385.         {
  386.             m_constantBufferData[n].velocity = XMFLOAT4(GetRandomFloat(0.01f, 0.02f), 0.0f, 0.0f, 0.0f);
  387.             m_constantBufferData[n].offset = XMFLOAT4(GetRandomFloat(-5.0f, -1.5f), GetRandomFloat(-1.0f, 1.0f), GetRandomFloat(0.0f, 2.0f), 0.0f);
  388.             m_constantBufferData[n].color = XMFLOAT4(GetRandomFloat(0.5f, 1.0f), GetRandomFloat(0.5f, 1.0f), GetRandomFloat(0.5f, 1.0f), 1.0f);
  389.             XMStoreFloat4x4(&m_constantBufferData[n].projection, XMMatrixTranspose(XMMatrixPerspectiveFovLH(XM_PIDIV4, m_aspectRatio, 0.01f, 20.0f)));
  390.         }
  391.  
  392.         // Map the constant buffers. We don't unmap this until the app closes.
  393.         // Keeping things mapped for the lifetime of the resource is okay.
  394.         CD3DX12_RANGE readRange(0, 0);      // We do not intend to read from this resource on the CPU.
  395.         ThrowIfFailed(m_constantBuffer->Map(0, &readRange, reinterpret_cast<void**>(&m_pCbvDataBegin)));
  396.         memcpy(m_pCbvDataBegin, &m_constantBufferData[0], TriangleCount * sizeof(ConstantBufferData));
  397.  
  398.         // Create shader resource views (SRV) of the constant buffers for the
  399.         // compute shader to read from.
  400.         D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  401.         srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  402.         srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  403.         srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  404.         srvDesc.Buffer.NumElements = TriangleCount;
  405.         srvDesc.Buffer.StructureByteStride = sizeof(ConstantBufferData);
  406.         srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
  407.  
  408.         CD3DX12_CPU_DESCRIPTOR_HANDLE cbvSrvHandle(m_cbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart(), CbvSrvOffset, m_cbvSrvUavDescriptorSize);
  409.         for (UINT frame = 0; frame < FrameCount; frame++)
  410.         {
  411.             srvDesc.Buffer.FirstElement = frame * TriangleCount;
  412.             m_device->CreateShaderResourceView(m_constantBuffer.Get(), &srvDesc, cbvSrvHandle);
  413.             cbvSrvHandle.Offset(CbvSrvUavDescriptorCountPerFrame, m_cbvSrvUavDescriptorSize);
  414.         }
  415.     }
  416.  
  417.     // Create the command signature used for indirect drawing.
  418.     {
  419.         // Each command consists of a CBV update and a DrawInstanced call.
  420.         D3D12_INDIRECT_ARGUMENT_DESC argumentDescs[2] = {};
  421.         argumentDescs[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW;
  422.         argumentDescs[0].ConstantBufferView.RootParameterIndex = Cbv;
  423.         argumentDescs[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
  424.  
  425.         D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc = {};
  426.         commandSignatureDesc.pArgumentDescs = argumentDescs;
  427.         commandSignatureDesc.NumArgumentDescs = _countof(argumentDescs);
  428.         commandSignatureDesc.ByteStride = sizeof(IndirectCommand);
  429.  
  430.         ThrowIfFailed(m_device->CreateCommandSignature(&commandSignatureDesc, m_rootSignature.Get(), IID_PPV_ARGS(&m_commandSignature)));
  431.         NAME_D3D12_OBJECT(m_commandSignature);
  432.     }
  433.  
  434.     // Create the command buffers and UAVs to store the results of the compute work.
  435.     {
  436.         std::vector<IndirectCommand> commands;
  437.         commands.resize(TriangleResourceCount);
  438.         const UINT commandBufferSize = CommandBufferSizePerFrame * FrameCount;
  439.  
  440.         D3D12_RESOURCE_DESC commandBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(commandBufferSize);
  441.         ThrowIfFailed(m_device->CreateCommittedResource(
  442.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  443.             D3D12_HEAP_FLAG_NONE,
  444.             &commandBufferDesc,
  445.             D3D12_RESOURCE_STATE_COPY_DEST,
  446.             nullptr,
  447.             IID_PPV_ARGS(&m_commandBuffer)));
  448.  
  449.         ThrowIfFailed(m_device->CreateCommittedResource(
  450.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
  451.             D3D12_HEAP_FLAG_NONE,
  452.             &CD3DX12_RESOURCE_DESC::Buffer(commandBufferSize),
  453.             D3D12_RESOURCE_STATE_GENERIC_READ,
  454.             nullptr,
  455.             IID_PPV_ARGS(&commandBufferUpload)));
  456.  
  457.         NAME_D3D12_OBJECT(m_commandBuffer);
  458.  
  459.         D3D12_GPU_VIRTUAL_ADDRESS gpuAddress = m_constantBuffer->GetGPUVirtualAddress();
  460.         UINT commandIndex = 0;
  461.  
  462.         for (UINT frame = 0; frame < FrameCount; frame++)
  463.         {
  464.             for (UINT n = 0; n < TriangleCount; n++)
  465.             {
  466.                 commands[commandIndex].cbv = gpuAddress;
  467.                 commands[commandIndex].drawArguments.VertexCountPerInstance = 3;
  468.                 commands[commandIndex].drawArguments.InstanceCount = 1;
  469.                 commands[commandIndex].drawArguments.StartVertexLocation = 0;
  470.                 commands[commandIndex].drawArguments.StartInstanceLocation = 0;
  471.  
  472.                 commandIndex++;
  473.                 gpuAddress += sizeof(ConstantBufferData);
  474.             }
  475.         }
  476.  
  477.         // Copy data to the intermediate upload heap and then schedule a copy
  478.         // from the upload heap to the command buffer.
  479.         D3D12_SUBRESOURCE_DATA commandData = {};
  480.         commandData.pData = reinterpret_cast<UINT8*>(&commands[0]);
  481.         commandData.RowPitch = commandBufferSize;
  482.         commandData.SlicePitch = commandData.RowPitch;
  483.  
  484.         UpdateSubresources<1>(m_commandList.Get(), m_commandBuffer.Get(), commandBufferUpload.Get(), 0, 0, 1, &commandData);
  485.         m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_commandBuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
  486.  
  487.         // Create SRVs for the command buffers.
  488.         D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  489.         srvDesc.Format = DXGI_FORMAT_UNKNOWN;
  490.         srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
  491.         srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  492.         srvDesc.Buffer.NumElements = TriangleCount;
  493.         srvDesc.Buffer.StructureByteStride = sizeof(IndirectCommand);
  494.         srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
  495.  
  496.         CD3DX12_CPU_DESCRIPTOR_HANDLE commandsHandle(m_cbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart(), CommandsOffset, m_cbvSrvUavDescriptorSize);
  497.         for (UINT frame = 0; frame < FrameCount; frame++)
  498.         {
  499.             srvDesc.Buffer.FirstElement = frame * TriangleCount;
  500.             m_device->CreateShaderResourceView(m_commandBuffer.Get(), &srvDesc, commandsHandle);
  501.             commandsHandle.Offset(CbvSrvUavDescriptorCountPerFrame, m_cbvSrvUavDescriptorSize);
  502.         }
  503.  
  504.         // Create the unordered access views (UAVs) that store the results of the compute work.
  505.         CD3DX12_CPU_DESCRIPTOR_HANDLE processedCommandsHandle(m_cbvSrvUavHeap->GetCPUDescriptorHandleForHeapStart(), ProcessedCommandsOffset, m_cbvSrvUavDescriptorSize);
  506.         for (UINT frame = 0; frame < FrameCount; frame++)
  507.         {
  508.             // Allocate a buffer large enough to hold all of the indirect commands
  509.             // for a single frame as well as a UAV counter.
  510.             commandBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(CommandBufferSizePerFrame + sizeof(UINT), D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS);
  511.             ThrowIfFailed(m_device->CreateCommittedResource(
  512.                 &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
  513.                 D3D12_HEAP_FLAG_NONE,
  514.                 &commandBufferDesc,
  515.                 D3D12_RESOURCE_STATE_COPY_DEST,
  516.                 nullptr,
  517.                 IID_PPV_ARGS(&m_processedCommandBuffers[frame])));
  518.  
  519.             WCHAR name[35];
  520.             if (swprintf_s(name, L"m_processedCommandBuffers[%u]", frame) > 0)
  521.             {
  522.                 SetName(m_processedCommandBuffers[frame].Get(), name);
  523.             }
  524.  
  525.             D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
  526.             uavDesc.Format = DXGI_FORMAT_UNKNOWN;
  527.             uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
  528.             uavDesc.Buffer.FirstElement = 0;
  529.             uavDesc.Buffer.NumElements = TriangleCount;
  530.             uavDesc.Buffer.StructureByteStride = sizeof(IndirectCommand);
  531.             uavDesc.Buffer.CounterOffsetInBytes = CommandBufferSizePerFrame;
  532.             uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
  533.  
  534.             m_device->CreateUnorderedAccessView(
  535.                 m_processedCommandBuffers[frame].Get(),
  536.                 m_processedCommandBuffers[frame].Get(),
  537.                 &uavDesc,
  538.                 processedCommandsHandle);
  539.  
  540.             processedCommandsHandle.Offset(CbvSrvUavDescriptorCountPerFrame, m_cbvSrvUavDescriptorSize);
  541.         }
  542.  
  543.         // Allocate a buffer that can be used to reset the UAV counters and initialize
  544.         // it to 0.
  545.         ThrowIfFailed(m_device->CreateCommittedResource(
  546.             &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
  547.             D3D12_HEAP_FLAG_NONE,
  548.             &CD3DX12_RESOURCE_DESC::Buffer(sizeof(UINT)),
  549.             D3D12_RESOURCE_STATE_GENERIC_READ,
  550.             nullptr,
  551.             IID_PPV_ARGS(&m_processedCommandBufferCounterReset)));
  552.  
  553.         UINT8* pMappedCounterReset = nullptr;
  554.         CD3DX12_RANGE readRange(0, 0);      // We do not intend to read from this resource on the CPU.
  555.         ThrowIfFailed(m_processedCommandBufferCounterReset->Map(0, &readRange, reinterpret_cast<void**>(&pMappedCounterReset)));
  556.         ZeroMemory(pMappedCounterReset, sizeof(UINT));
  557.         m_processedCommandBufferCounterReset->Unmap(0, nullptr);
  558.     }
  559.  
  560.     // Close the command list and execute it to begin the vertex buffer copy into
  561.     // the default heap.
  562.     ThrowIfFailed(m_commandList->Close());
  563.     ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
  564.     m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
  565.  
  566.     // Create synchronization objects and wait until assets have been uploaded to the GPU.
  567.     {
  568.         ThrowIfFailed(m_device->CreateFence(m_fenceValues[m_frameIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
  569.         ThrowIfFailed(m_device->CreateFence(m_fenceValues[m_frameIndex], D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_computeFence)));
  570.         m_fenceValues[m_frameIndex]++;
  571.  
  572.         // Create an event handle to use for frame synchronization.
  573.         m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  574.         if (m_fenceEvent == nullptr)
  575.         {
  576.             ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
  577.         }
  578.  
  579.         // Wait for the command list to execute; we are reusing the same command
  580.         // list in our main loop but for now, we just want to wait for setup to
  581.         // complete before continuing.
  582.         WaitForGpu();
  583.     }
  584. }
  585.  
  586. // Get a random float value between min and max.
  587. float D3D12ExecuteIndirect::GetRandomFloat(float min, float max)
  588. {
  589.     float scale = static_cast<float>(rand()) / RAND_MAX;
  590.     float range = max - min;
  591.     return scale * range + min;
  592. }
  593.  
  594. // Update frame-based values.
  595. void D3D12ExecuteIndirect::OnUpdate()
  596. {
  597.     for (UINT n = 0; n < TriangleCount; n++)
  598.     {
  599.         const float offsetBounds = 2.5f;
  600.  
  601.         // Animate the triangles.
  602.         m_constantBufferData[n].offset.x += m_constantBufferData[n].velocity.x;
  603.         if (m_constantBufferData[n].offset.x > offsetBounds)
  604.         {
  605.             m_constantBufferData[n].velocity.x = GetRandomFloat(0.01f, 0.02f);
  606.             m_constantBufferData[n].offset.x = -offsetBounds;
  607.         }
  608.     }
  609.  
  610.     UINT8* destination = m_pCbvDataBegin + (TriangleCount * m_frameIndex * sizeof(ConstantBufferData));
  611.     memcpy(destination, &m_constantBufferData[0], TriangleCount * sizeof(ConstantBufferData));
  612. }
  613.  
  614. // Render the scene.
  615. void D3D12ExecuteIndirect::OnRender()
  616. {
  617.     // Record all the commands we need to render the scene into the command list.
  618.     PopulateCommandLists();
  619.  
  620.     // Execute the compute work.
  621.     if (m_enableCulling)
  622.     {
  623.         PIXBeginEvent(m_commandQueue.Get(), 0, L"Cull invisible triangles");
  624.  
  625.         ID3D12CommandList* ppCommandLists[] = { m_computeCommandList.Get() };
  626.         m_computeCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
  627.  
  628.         PIXEndEvent(m_commandQueue.Get());
  629.  
  630.         m_computeCommandQueue->Signal(m_computeFence.Get(), m_fenceValues[m_frameIndex]);
  631.  
  632.         // Execute the rendering work only when the compute work is complete.
  633.         m_commandQueue->Wait(m_computeFence.Get(), m_fenceValues[m_frameIndex]);
  634.     }
  635.  
  636.     PIXBeginEvent(m_commandQueue.Get(), 0, L"Render");
  637.  
  638.     // Execute the rendering work.
  639.     ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
  640.     m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
  641.  
  642.     PIXEndEvent(m_commandQueue.Get());
  643.  
  644.     // Present the frame.
  645.     ThrowIfFailed(m_swapChain->Present(1, 0));
  646.  
  647.     MoveToNextFrame();
  648. }
  649.  
  650. void D3D12ExecuteIndirect::OnDestroy()
  651. {
  652.     // Ensure that the GPU is no longer referencing resources that are about to be
  653.     // cleaned up by the destructor.
  654.     WaitForGpu();
  655.  
  656.     CloseHandle(m_fenceEvent);
  657. }
  658.  
  659. void D3D12ExecuteIndirect::OnKeyDown(UINT8 key)
  660. {
  661.     if (key == VK_SPACE)
  662.     {
  663.         m_enableCulling = !m_enableCulling;
  664.     }
  665. }
  666.  
  667. // Fill the command list with all the render commands and dependent state.
  668. void D3D12ExecuteIndirect::PopulateCommandLists()
  669. {
  670.     // Command list allocators can only be reset when the associated
  671.     // command lists have finished execution on the GPU; apps should use
  672.     // fences to determine GPU execution progress.
  673.     ThrowIfFailed(m_computeCommandAllocators[m_frameIndex]->Reset());
  674.     ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset());
  675.  
  676.     // However, when ExecuteCommandList() is called on a particular command
  677.     // list, that command list can then be reset at any time and must be before
  678.     // re-recording.
  679.     ThrowIfFailed(m_computeCommandList->Reset(m_computeCommandAllocators[m_frameIndex].Get(), m_computeState.Get()));
  680.     ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState0.Get()));
  681.  
  682.     // Record the compute commands that will cull triangles and prevent them from being processed by the vertex shader.
  683.     if (m_enableCulling)
  684.     {
  685.         UINT frameDescriptorOffset = m_frameIndex * CbvSrvUavDescriptorCountPerFrame;
  686.         D3D12_GPU_DESCRIPTOR_HANDLE cbvSrvUavHandle = m_cbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart();
  687.  
  688.         m_computeCommandList->SetComputeRootSignature(m_computeRootSignature.Get());
  689.  
  690.         ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() };
  691.         m_computeCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
  692.  
  693.         m_computeCommandList->SetComputeRootDescriptorTable(
  694.             SrvUavTable,
  695.             CD3DX12_GPU_DESCRIPTOR_HANDLE(cbvSrvUavHandle, CbvSrvOffset + frameDescriptorOffset, m_cbvSrvUavDescriptorSize));
  696.  
  697.         m_computeCommandList->SetComputeRoot32BitConstants(RootConstants, 4, reinterpret_cast<void*>(&m_csRootConstants), 0);
  698.  
  699.         // Reset the UAV counter for this frame.
  700.         m_computeCommandList->CopyBufferRegion(m_processedCommandBuffers[m_frameIndex].Get(), CommandBufferSizePerFrame, m_processedCommandBufferCounterReset.Get(), 0, sizeof(UINT));
  701.  
  702.         D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_processedCommandBuffers[m_frameIndex].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
  703.         m_computeCommandList->ResourceBarrier(1, &barrier);
  704.  
  705.         m_computeCommandList->Dispatch(static_cast<UINT>(ceil(TriangleCount / float(ComputeThreadBlockSize))), 1, 1);
  706.     }
  707.  
  708.     ThrowIfFailed(m_computeCommandList->Close());
  709.  
  710.     // Record the rendering commands.
  711.     {
  712.         // Set necessary state.
  713.         m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
  714.  
  715.         ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() };
  716.         m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
  717.  
  718.         m_commandList->RSSetViewports(1, &m_viewport);
  719.         m_commandList->RSSetScissorRects(1, m_enableCulling ? &m_cullingScissorRect : &m_scissorRect);
  720.  
  721.         // Indicate that the command buffer will be used for indirect drawing
  722.         // and that the back buffer will be used as a render target.
  723.         D3D12_RESOURCE_BARRIER barriers[2] = {
  724.             CD3DX12_RESOURCE_BARRIER::Transition(
  725.                 m_enableCulling ? m_processedCommandBuffers[m_frameIndex].Get() : m_commandBuffer.Get(),
  726.                 m_enableCulling ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
  727.                 D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT),
  728.             CD3DX12_RESOURCE_BARRIER::Transition(
  729.                 m_renderTargets[m_frameIndex].Get(),
  730.                 D3D12_RESOURCE_STATE_PRESENT,
  731.                 D3D12_RESOURCE_STATE_RENDER_TARGET)
  732.         };
  733.  
  734.         m_commandList->ResourceBarrier(_countof(barriers), barriers);
  735.  
  736.         CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
  737.         CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
  738.         m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
  739.  
  740.         // Record commands.
  741.         const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
  742.         m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
  743.         m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
  744.  
  745.         m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
  746.         m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
  747.  
  748.         // No triangles drawn
  749.         m_commandList->SetPipelineState( m_pipelineState0.Get() );
  750.         m_commandList->ExecuteIndirect(
  751.             m_commandSignature.Get(),
  752.             TriangleCount - 4,
  753.             m_commandBuffer.Get(),
  754.             CommandBufferSizePerFrame * m_frameIndex,
  755.             nullptr,
  756.             0 );
  757.  
  758.         // 4 triangles drawn
  759.         m_commandList->SetPipelineState( m_pipelineState1.Get() );
  760.         m_commandList->ExecuteIndirect(
  761.             m_commandSignature.Get(),
  762.             4,
  763.             m_commandBuffer.Get(),
  764.             CommandBufferSizePerFrame * m_frameIndex + ( TriangleCount - 4 ) * sizeof( IndirectCommand ),
  765.             nullptr,
  766.             0 );
  767.  
  768.         // Indicate that the command buffer may be used by the compute shader
  769.         // and that the back buffer will now be used to present.
  770.         barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
  771.         barriers[0].Transition.StateAfter = m_enableCulling ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
  772.         barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
  773.         barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
  774.  
  775.         m_commandList->ResourceBarrier(_countof(barriers), barriers);
  776.  
  777.         ThrowIfFailed(m_commandList->Close());
  778.     }
  779. }
  780.  
  781. // Wait for pending GPU work to complete.
  782. void D3D12ExecuteIndirect::WaitForGpu()
  783. {
  784.     // Schedule a Signal command in the queue.
  785.     ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), m_fenceValues[m_frameIndex]));
  786.  
  787.     // Wait until the fence has been processed.
  788.     ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent));
  789.     WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
  790.  
  791.     // Increment the fence value for the current frame.
  792.     m_fenceValues[m_frameIndex]++;
  793. }
  794.  
  795. // Prepare to render the next frame.
  796. void D3D12ExecuteIndirect::MoveToNextFrame()
  797. {
  798.     // Schedule a Signal command in the queue.
  799.     const UINT64 currentFenceValue = m_fenceValues[m_frameIndex];
  800.     ThrowIfFailed(m_commandQueue->Signal(m_fence.Get(), currentFenceValue));
  801.  
  802.     // Update the frame index.
  803.     m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
  804.  
  805.     // If the next frame is not ready to be rendered yet, wait until it is ready.
  806.     if (m_fence->GetCompletedValue() < m_fenceValues[m_frameIndex])
  807.     {
  808.         ThrowIfFailed(m_fence->SetEventOnCompletion(m_fenceValues[m_frameIndex], m_fenceEvent));
  809.         WaitForSingleObjectEx(m_fenceEvent, INFINITE, FALSE);
  810.     }
  811.  
  812.     // Set the fence value for the next frame.
  813.     m_fenceValues[m_frameIndex] = currentFenceValue + 1;
  814. }
Add Comment
Please, Sign In to add comment