Requêtes de prédicat

L’exemple D3D12PredicationQueries illustre l’élimination d’occlusion à l’aide de tas et de prédicats de requête DirectX 12. La procédure pas à pas décrit le code supplémentaire nécessaire pour étendre l’exemple HelloConstBuffer afin de gérer les requêtes de prédicat.

Créer un tas de descripteur de stencil de profondeur et un tas de requêtes d’occlusion

Dans la méthode LoadPipeline , créez un tas de descripteur de stencil de profondeur.

              // Describe and create a depth stencil view (DSV) descriptor heap.
              D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc = {};
              dsvHeapDesc.NumDescriptors = 1;
              dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
              dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
              ThrowIfFailed(m_device->CreateDescriptorHeap(&dsvHeapDesc, IID_PPV_ARGS(&m_dsvHeap)));
Workflow d’appel Paramètres
D3D12_DESCRIPTOR_HEAP_DESC
D3D12_DESCRIPTOR_HEAP_TYPE
[D3D12_DESCRIPTOR_HEAP_FLAG] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_descriptor_heap_flags)
CreateDescriptorHeap

Dans la méthode LoadAssets , créez un tas pour les requêtes d’occlusion.

     // Describe and create a heap for occlusion queries.
              D3D12_QUERY_HEAP_DESC queryHeapDesc = {};
              queryHeapDesc.Count = 1;
              queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_OCCLUSION;
              ThrowIfFailed(m_device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_queryHeap)));
Workflow d’appel Paramètres
Description du tas de la _ requête D3D12 _ _ _Type de _ segment de requête D3D12 _
CreateQueryHeap

Activer la fusion alpha

Cet exemple dessine deux Quad et illustre une requête d’occlusion binaire. Le quadruple au premier plan s’anime à travers l’écran, et celui à l’arrière sera parfois bloqués. Dans la méthode LoadAssets , la fusion alpha est activée pour cet exemple afin que nous puissions voir à quel point D3D prend en compte les quadruples bloqués.

     // Enable alpha blending so we can visualize the occlusion query results.
              CD3DX12_BLEND_DESC blendDesc(CD3DX12_DEFAULT);
              blendDesc.RenderTarget[0] =
              {
                     TRUE, FALSE,
                     D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD,
                     D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
                     D3D12_LOGIC_OP_NOOP,
                     D3D12_COLOR_WRITE_ENABLE_ALL,
              };
Workflow d’appel Paramètres
CD3DX12_BLEND_DESC
CD3DX12_DEFAULT
[D3D12_BLEND] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_blend)
[D3D12_BLEND_OP] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_blend_op)
[D3D12_LOGIC_OP] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_logic_op)
[D3D12_COLOR_WRITE_ENABLE] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_color_write_enable)

Désactiver les écritures de couleur et de profondeur

La requête d’occlusion est effectuée en rendant un quadruple qui couvre la même zone que le quadruple dont vous souhaitez tester la visibilité. Dans des scènes plus complexes, la requête serait probablement un volume englobant, plutôt qu’un simple quadruple. Dans les deux cas, un nouvel état de pipeline est créé, ce qui désactive l’écriture dans la cible de rendu et la mémoire tampon z afin que la requête d’occlusion proprement dite n’affecte pas la sortie visible de la passe de rendu.

Dans la méthode LoadAssets , désactivez les écritures de couleur et les écritures de profondeur pour l’état de la requête d’occlusion.

 // Disable color writes and depth writes for the occlusion query's state.
              psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = 0;
              psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;

              ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_queryState)));
Workflow d’appel Paramètres
Description de l' _ _ État du pipeline GRAPHICs D3D12 _ _ _Masque d' _ écriture de profondeur D3D12 _
CreateGraphicsPipelineState

Créer une mémoire tampon pour stocker les résultats de la requête

Dans la méthode LoadAssets , une mémoire tampon doit être créée pour stocker les résultats de la requête. Chaque requête nécessite 8 octets d’espace dans la mémoire du GPU. Cet exemple exécute une seule requête et, pour des raisons de simplicité et de lisibilité, crée une mémoire tampon exactement de cette taille (même si cet appel de fonction allouera une page de 64 Ko de mémoire GPU, la plupart des applications réelles créeraient probablement une mémoire tampon plus grande).

 // Create the query result buffer.
              CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT);
              auto queryBufferDesc = CD3DX12_RESOURCE_DESC::Buffer(8);
              ThrowIfFailed(m_device->CreateCommittedResource(
                     &heapProps,
                     D3D12_HEAP_FLAG_NONE,
                     &queryBufferDesc,
                     D3D12_RESOURCE_STATE_GENERIC_READ,
                     nullptr,
                     IID_PPV_ARGS(&m_queryResult)
                     ));
Workflow d’appel Paramètres
CreateCommittedResource
CD3DX12_HEAP_PROPERTIES
[D3D12_HEAP_TYPE] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_heap_type)
[D3D12_HEAP_FLAG] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_heap_flags)
[CD3DX12_RESOURCE_DESC] (cd3dx12-resource-desc.md)
[D3D12_RESOURCE_STATES] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_resource_states)

Dessinez les quatre cœurs et exécutez et résolvez la requête d’occlusion

Une fois l’installation terminée, la boucle principale est mise à jour dans la méthode PopulateCommandLists .

1. Dessinez les quadruples de l’arrière vers l’avant pour que l’effet de transparence fonctionne correctement. Le fait de redessiner le Quad à l’avant est prédicat sur le résultat de la requête du frame précédent et est une technique relativement courante. 2. Modifiez l’PSO pour désactiver les écritures de la cible de rendu et du stencil de profondeur. 3. Exécutez la requête d’occlusion. 4. Résolvez la requête d’occlusion.
       // 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.
              m_commandList->SetGraphicsRootDescriptorTable(0, cbvFarQuad);
              m_commandList->SetPredication(m_queryResult.Get(), 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
              m_commandList->DrawInstanced(4, 1, 0, 0);

              // Disable predication and always draw the near quad.
              m_commandList->SetPredication(nullptr, 0, D3D12_PREDICATION_OP_EQUAL_ZERO);
              m_commandList->SetGraphicsRootDescriptorTable(0, cbvNearQuad);
              m_commandList->DrawInstanced(4, 1, 4, 0);

              // Run the occlusion query with the bounding box quad.
              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);

              // 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_GENERIC_READ, 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_GENERIC_READ));
       }
Workflow d’appel Paramètres
CD3DX12_GPU_DESCRIPTOR_HANDLE GetGPUDescriptorHandleForHeapStart
IASetPrimitiveTopology D3D_PRIMITIVE_TOPOLOGY
IASetVertexBuffers
SetGraphicsRootDescriptorTable
SetPredication D3D12_PREDICATION_OP
DrawInstanced
SetPredication D3D12_PREDICATION_OP
SetGraphicsRootDescriptorTable
DrawInstanced
SetGraphicsRootDescriptorTable
SetPipelineState
BeginQuery D3D12_QUERY_TYPE
DrawInstanced
EndQuery D3D12_QUERY_TYPE
ResourceBarrier
CD3DX12_RESOURCE_BARRIER
[D3D12_RESOURCE_STATES] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_resource_states)
ResolveQueryData D3D12_QUERY_TYPE
ResourceBarrier
CD3DX12_RESOURCE_BARRIER
[D3D12_RESOURCE_STATES] (/Windows/Desktop/API/d3d12/ne-d3d12-d3d12_resource_states)

Exécution de l'exemple

Non bloqués :

deux zones non bloqués

Bloqués

bloqués entièrement

Bloqués partiel :

une seule zone partiellement bloqués

Walk-Throughs de code D3D12

Prédicat

Requêtes