다음을 통해 공유


조건자 쿼리

D3D12PredicationQueries 샘플은 DirectX 12 쿼리 힙 및 조건자를 사용하여 폐색 컬링을 보여 줍니다. 이 연습에서는 조건자 쿼리를 처리하기 위해 HelloConstBuffer 샘플을 확장하는 데 필요한 추가 코드를 설명합니다.

깊이 스텐실 설명자 힙 및 폐색 쿼리 힙 만들기

LoadPipeline 메서드에서 깊이 스텐실 설명자 힙을 만듭니다.

              // 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)));
통화 흐름 매개 변수
D3D12_DESCRIPTOR_HEAP_DESC
D3D12_DESCRIPTOR_HEAP_TYPE
[D3D12_DESCRIPTOR_HEAP_FLAG](/windows/desktop/api/d3d12/ne-d3d12-d3d12_descriptor_heap_flags)
CreateDescriptorHeap

 

LoadAssets 메서드에서 폐색 쿼리에 대한 힙을 만듭니다.

     // 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)));
통화 흐름 매개 변수
D3D12_QUERY_HEAP_DESC D3D12_QUERY_HEAP_TYPE
CreateQueryHeap

 

알파 혼합 사용

이 샘플에서는 두 개의 쿼드를 그리고 이진 폐색 쿼리를 보여 줍니다. 앞의 쿼드는 화면에 애니메이션 효과를 주며, 뒤쪽에 있는 쿼드는 때때로 폐색됩니다. LoadAssets 메서드에서 이 샘플에 대해 알파 혼합을 사용하도록 설정하여 D3D가 쿼드를 폐색된 것으로 간주하는 지점을 확인할 수 있습니다.

     // 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,
              };
통화 흐름 매개 변수
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)

 

색 및 깊이 쓰기 사용 안 함

폐색 쿼리는 테스트하려는 가시성이 있는 쿼드와 동일한 영역을 포함하는 쿼드를 렌더링하여 수행됩니다. 더 복잡한 장면에서 쿼리는 단순한 쿼드가 아닌 경계 볼륨일 수 있습니다. 두 경우 모두 폐색 쿼리 자체가 렌더링 패스의 표시되는 출력에 영향을 주지 않도록 렌더링 대상 및 z 버퍼에 쓰기를 사용하지 않도록 설정하는 새 파이프라인 상태가 만들어집니다.

LoadAssets 메서드에서 폐색 쿼리의 상태에 대한 색 쓰기 및 깊이 쓰기를 사용하지 않도록 설정합니다.

 // 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)));
통화 흐름 매개 변수
D3D12_GRAPHICS_PIPELINE_STATE_DESC D3D12_DEPTH_WRITE_MASK
CreateGraphicsPipelineState

 

쿼리 결과를 저장할 버퍼 만들기

LoadAssets 메서드에서 쿼리 결과를 저장하기 위해 버퍼를 만들어야 합니다. 각 쿼리에는 GPU 메모리에 8바이트의 공간이 필요합니다. 이 샘플은 하나의 쿼리만 수행하고 단순성과 가독성을 위해 정확히 해당 크기의 버퍼를 만듭니다(이 함수 호출은 GPU 메모리의 64K 페이지를 할당하더라도 대부분의 실제 앱은 더 큰 버퍼를 만들 수 있습니다).

 // 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)
                     ));
통화 흐름 매개 변수
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)

 

쿼드를 그리고 폐색 쿼리를 수행하고 해결합니다.

설치를 완료하면 기본 루프가 PopulateCommandLists 메서드에서 업데이트됩니다.

1. 투명도 효과가 제대로 작동하도록 쿼드를 뒤에서 앞쪽으로 그립니다. 쿼드를 앞면으로 그리는 것은 이전 프레임의 쿼리 결과를 기준으로 하며 이에 대한 매우 일반적인 기술입니다. 2. 렌더링 대상 및 깊이 스텐실 쓰기를 사용하지 않도록 PSO를 변경합니다. 3. 폐색 쿼리를 수행합니다. 4. 폐색 쿼리를 해결합니다.
       // 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));
       }
통화 흐름 매개 변수
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)

 

샘플 실행

폐색되지 않음:

폐색:

한 상자가 완전히 폐색된

부분적으로 폐색:

한 상자가 부분적으로 폐색된

D3D12 코드 연습

조건

쿼리