Partager via


Requêtes de prédication

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

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

Dans la méthode LoadPipeline créez un tas de descripteur de gabarit 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)));
Flux d’appels 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)));
Flux d’appels Paramètres
D3D12_QUERY_HEAP_DESC D3D12_QUERY_HEAP_TYPE
CreateQueryHeap

 

Activer le mélange alpha

Cet exemple dessine deux quads et illustre une requête d’occlusion binaire. Le quad en face s’anime sur l’écran, et celui en arrière sera occasionnellement obstrué. Dans la méthode LoadAssets, le mélange alpha est activé pour cet exemple afin que nous puissions voir à quel point D3D considère le quad en arrière oblude.

     // 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,
              };
Flux d’appels 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 quad qui couvre la même zone que le quad dont nous voulons tester la visibilité. Dans des scènes plus complexes, la requête serait probablement un volume englobant plutôt qu’un quad simple. Dans les deux cas, un nouvel état de pipeline est créé qui désactive l’écriture sur la cible de rendu et la mémoire tampon z afin que la requête d’occlusion elle-même n’affecte pas la sortie visible du passage 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)));
Flux d’appels Paramètres
D3D12_GRAPHICS_PIPELINE_STATE_DESC D3D12_DEPTH_WRITE_MASK
CreateGraphicsPipelineState

 

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

Dans le LoadAssets méthode, 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 GPU. Cet exemple effectue uniquement une requête et, par souci de simplicité et de lisibilité, crée une mémoire tampon exactement cette taille (même si cet appel de fonction alloue une page de mémoire GPU de 64 Ko , 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)
                     ));
Flux d’appels 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)

 

Dessiner les quads et effectuer et résoudre la requête d’occlusion

Après avoir effectué la configuration, la boucle principale est mise à jour dans la méthode PopulateCommandLists.

1. Dessinez les quads de l’arrière vers l’avant pour que l’effet de transparence fonctionne correctement. Le dessin du quad à l’arrière est prédicé sur le résultat de la requête du cadre précédent et est une technique assez courante pour cela. 2. Modifiez l’authentification unique pour désactiver les écritures de gabarit de cible et de profondeur de rendu. 3. Effectuez 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));
       }
Flux d’appels 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écuter l’exemple

Non obstrué :

deux boîtes non obstruées

Obstrué:

une boîte entièrement obstruée

Partiellement obstrué :

une boîte partiellement obstruée

procédure pas à pas de code D3D12

de prédication

requêtes