Prädikationsabfragen

Das D3D12PredicationQueries-Beispiel veranschaulicht die Okklusionskulling mithilfe von DirectX 12-Abfrageheaps und Prädication. In der exemplarischen Vorgehensweise wird der zusätzliche Code beschrieben, der zum Erweitern des HelloConstBuffer-Beispiels zur Behandlung von Prädicationabfragen erforderlich ist.

Erstellen eines Tiefenschablonendeskriptors heap und eines Abfrageheaps mit Okklusion

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)));
Anrufverlauf 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 in der 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)));
Anrufverlauf Parameter
D3D12_QUERY_HEAP_DESC D3D12_QUERY_HEAP_TYPE
CreateQueryHeap

 

Aktivieren der Alphamischung

Dieses Beispiel zeichnet zwei Quads und veranschaulicht eine Abfrage mit binärer Okklusion. Das Viereck vorne animiert über den Bildschirm, und das quad hinten wird gelegentlich verworren. In der LoadAssets-Methode ist die Alphamischung für dieses Beispiel aktiviert, sodass wir sehen können, an welchem Punkt D3D das Quad in back als verworren 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,
              };
Anrufverlauf 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 durch Rendern eines Quads ausgeführt, das denselben Bereich wie das Quad abdeckt, dessen Sichtbarkeit wir testen möchten. In komplexeren Szenen würde es sich bei der Abfrage wahrscheinlich um ein begrenzungsierendes Volume und nicht um ein einfaches Quad handeln. In beiden Fällen wird ein neuer Pipelinezustand erstellt, der das Schreiben in das Renderziel und den z-Puffer deaktiviert, sodass die Okklusionsabfrage selbst keine Auswirkungen auf die sichtbare Ausgabe des Renderingdurchlaufs hat.

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)));
Anrufverlauf 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 Bytes Speicherplatz im GPU-Arbeitsspeicher. In diesem Beispiel wird nur eine Abfrage ausgeführt, und aus Gründen der Einfachheit und Lesbarkeit wird ein Puffer genau in dieser Größe erstellt (auch wenn dieser Funktionsaufruf eine 64K-Seite GPU-Speicher zuordnet – 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)
                     ));
Anrufverlauf 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 Sie die Quads, und führen Sie die Okklusionsabfrage aus, und lösen Sie sie auf.

Nach dem Setup wird die Standard-Schleife in der PopulateCommandLists-Methode aktualisiert.

1. Zeichnen Sie die Quads von hinten nach vorne, damit der Transparenzeffekt ordnungsgemäß funktioniert. Das Zeichnen des Quads von hinten nach vorne basiert auf dem Ergebnis der Abfrage des vorherigen Frames und ist eine ziemlich gängige Technik dafür. 2. Ändern Sie den PSO, um Renderziel- und Tiefenschablonenschreibvorgänge zu deaktivieren. 3. Führen Sie die Okklusionsabfrage aus. 4. Lösen Sie die Okklusionsabfrage auf.
       // 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));
       }
Anrufverlauf 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 verschließen

Verdeckt:

eine Box vollständig verschließen

Teilweise verworren:

ein Feld teilweise verschließen

Exemplarische Vorgehensweisen zu D3D12-Code

Prädikation

Abfragen