Freigeben über


Vorababfragen

Das D3D12PredicationQueries Beispiel veranschaulicht die Okklusions-Culling mithilfe von DirectX 12-Abfrage heaps und -prädication. In der exemplarischen Vorgehensweise wird der zusätzliche Code beschrieben, der zum Erweitern des HelloConstBuffer- Beispiels zur Behandlung von Vorababfragen erforderlich ist.

Erstellen eines Tiefenschablonendeskriptor-Heaps und eines Heaps für okklusionsabfragen

Erstellen Sie in der LoadPipeline- Methode einen Tiefenschablonendeskriptor heap.

              // 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)));
Anruffluss Parameter
D3D12_DESCRIPTOR_HEAP_DESC
D3D12_DESCRIPTOR_HEAP_TYPE
[D3D12_DESCRIPTOR_HEAP_FLAG](/windows/desktop/api/d3d12/ne-d3d12-d3d12_descriptor_heap_flags)
CreateDescriptorHeap-

 

Erstellen Sie im LoadAssets Methode einen Heap für Okklusionsabfragen.

     // 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)));
Anruffluss Parameter
D3D12_QUERY_HEAP_DESC D3D12_QUERY_HEAP_TYPE
CreateQueryHeap-

 

Aktivieren der Alphamischung

In diesem Beispiel werden zwei Quads gezeichnet und eine binäre Okklusionsabfrage veranschaulicht. Das Quad vorn wird über den Bildschirm animiert, und die in der Rückseite wird gelegentlich verdeckt. In der LoadAssets-Methode ist die Alphamischung für dieses Beispiel aktiviert, sodass wir sehen können, an welchem Punkt D3D das Quad im Hintergrund betrachtet.

     // 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,
              };
Anruffluss Parameter
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)

 

Deaktivieren von Farb- und Tiefenschreibvorgängen

Die Okklusionsabfrage wird ausgeführt, indem ein Quad gerendert wird, das denselben Bereich wie das Quad abdeckt, dessen Sichtbarkeit wir testen möchten. In komplexeren Szenen wäre die Abfrage wahrscheinlich ein Begrenzungsvolumen anstelle eines einfachen Quads. In beiden Fällen wird ein neuer Pipelinestatus erstellt, der das Schreiben in das Renderziel und den Z-Puffer deaktiviert, sodass sich die Okklusionsabfrage selbst nicht auf die sichtbare Ausgabe des Renderingdurchlaufs auswirkt.

Deaktivieren Sie in der LoadAssets--Methode Farb- und Tiefenschreibvorgänge für den Zustand der Okklusionsabfrage.

 // 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)));
Anruffluss Parameter
D3D12_GRAPHICS_PIPELINE_STATE_DESC D3D12_DEPTH_WRITE_MASK
CreateGraphicsPipelineState

 

Erstellen eines Puffers zum Speichern der Ergebnisse der Abfrage

In der LoadAssets Methode muss ein Puffer erstellt werden, um die Ergebnisse der Abfrage zu speichern. Jede Abfrage benötigt 8 Byte Speicherplatz im GPU-Speicher. In diesem Beispiel wird nur eine Abfrage ausgeführt, und aus Gründen der Einfachheit und Lesbarkeit wird ein Puffer genau dieser Größe erstellt (auch wenn dieser Funktionsaufruf eine 64K-Seite des GPU-Speichers zuweist – die meisten echten Apps würden wahrscheinlich einen größeren Puffer erstellen).

 // 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)
                     ));
Anruffluss Parameter
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)

 

Zeichnen Der Quads und Ausführen und Auflösen der Okklusionsabfrage

Nach Abschluss des Setups wird die Hauptschleife in der PopulateCommandLists-Methode aktualisiert.

1. Zeichnen Sie die Quads von hinten nach vorne, damit der Transparenzeffekt ordnungsgemäß funktioniert. Das Zeichnen des Quads in den Vordergrund wird auf das Ergebnis der Abfrage des vorherigen Frames prädiziert und ist dafür eine ziemlich häufige Technik. 2. Ändern Sie die PSO, um Renderziel- und Tiefenschablonenschreibvorgänge zu deaktivieren. 3. Ausführen der Okklusionsabfrage. 4. Auflösen der Okklusionsabfrage.
       // 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));
       }
Anruffluss Parameter
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)

 

Ausführen des Beispiels

Nicht verdeckt:

zwei Felder nicht verdeckt

Verdeckt:

ein Feld vollständig verdeckt

Teilweise verdeckt:

ein Feld teilweise verdeckt

D3D12 Code Walk-Throughs

Prädication-

Abfragen