Partilhar via


Consultas de predicação

O exemplo de D3D12PredicationQueries demonstra o abate de oclusão usando heaps de consulta e predicação do DirectX 12. O passo a passo descreve o código adicional necessário para estender o HelloConstBuffer exemplo para lidar com consultas de predicação.

Criar um heap descritor de estêncil de profundidade e um heap de consulta de oclusão

No método LoadPipeline, crie um heap de descritor de estêncil de profundidade.

              // 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)));
Fluxo de chamadas Parâmetros
D3D12_DESCRIPTOR_HEAP_DESC
D3D12_DESCRIPTOR_HEAP_TYPE
[D3D12_DESCRIPTOR_HEAP_FLAG](/windows/desktop/api/d3d12/ne-d3d12-d3d12_descriptor_heap_flags)
CreateDescriptorHeap

 

No método LoadAssets, crie um heap para consultas de oclusão.

     // 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)));
Fluxo de chamadas Parâmetros
D3D12_QUERY_HEAP_DESC D3D12_QUERY_HEAP_TYPE
CreateQueryHeap

 

Ativar a mistura alfa

Este exemplo desenha dois quads e ilustra uma consulta de oclusão binária. O quad na frente anima através da tela, e o de trás ocasionalmente será ocluído. No método LoadAssets, a mistura alfa é habilitada para este exemplo para que possamos ver em que ponto o D3D considera o quad na parte traseira ocluído.

     // 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,
              };
Fluxo de chamadas Parâmetros
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)

 

Desativar gravações de cor e profundidade

A consulta de oclusão é realizada renderizando um quad que cobre a mesma área que o quad cuja visibilidade queremos testar. Em cenas mais complexas, a consulta provavelmente seria um volume limitador, em vez de um simples quad. Em ambos os casos, um novo estado de pipeline é criado que desabilita a gravação no destino de renderização e no buffer z para que a consulta de oclusão em si não afete a saída visível do passo de renderização.

No método LoadAssets, desative as gravações coloridas e as gravações de profundidade para o estado da consulta de oclusão.

 // 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)));
Fluxo de chamadas Parâmetros
D3D12_GRAPHICS_PIPELINE_STATE_DESC D3D12_DEPTH_WRITE_MASK
CreateGraphicsPipelineState

 

Criar um buffer para armazenar os resultados da consulta

No método LoadAssets, um buffer precisa ser criado para armazenar os resultados da consulta. Cada consulta requer 8 bytes de espaço na memória da GPU. Este exemplo executa apenas uma consulta e, para simplicidade e legibilidade, cria um buffer exatamente desse tamanho (mesmo que essa chamada de função aloque uma página de 64K de memória GPU - a maioria dos aplicativos reais provavelmente criaria um buffer maior).

 // 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)
                     ));
Fluxo de chamadas Parâmetros
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)

 

Desenhe os quadriciclos e execute e resolva a consulta de oclusão

Depois de fazer a configuração, o loop principal é atualizado no método PopulateCommandLists.

1. Desenhe os quadriciclos de trás para a frente para fazer com que o efeito de transparência funcione corretamente. Desenhar o quad de trás para a frente é baseado no resultado da consulta do quadro anterior e é uma técnica bastante comum para isso. 2. Altere o PSO para desativar as gravações de estêncil de profundidade e destino de renderização. 3. Execute a consulta de oclusão. 4. Resolva a consulta de oclusão.
       // 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));
       }
Fluxo de chamadas Parâmetros
CD3DX12_GPU_DESCRIPTOR_HANDLE GetGPUDescriptorHandleForHeapStart
de topologia 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)

 

Executar o exemplo

Não ocluído:

duas caixas não ocluídas

Ocluído:

uma caixa totalmente ocluída

Parcialmente ocluído:

uma caixa parcialmente ocluída

Código D3D12 Passo a passo

Predicação

Consultas