Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Apps führen indirekte Ziehungen/Verteiler mithilfe der ExecuteIndirect-Methode aus.
Syntax
void ExecuteIndirect(
[in] ID3D12CommandSignature *pCommandSignature,
[in] UINT MaxCommandCount,
[in] ID3D12Resource *pArgumentBuffer,
[in] UINT64 ArgumentBufferOffset,
[in, optional] ID3D12Resource *pCountBuffer,
[in] UINT64 CountBufferOffset
);
Parameter
[in] pCommandSignature
Typ: ID3D12CommandSignature*
Gibt eine ID3D12CommandSignaturean. Die daten, auf die von pArgumentBuffer verwiesen wird, werden je nach Inhalt der Befehlssignatur interpretiert. Informationen zu indirekten Zeichnungs- für die APIs, die zum Erstellen einer Befehlssignatur verwendet werden.
[in] MaxCommandCount
Typ: UINT-
Es gibt zwei Möglichkeiten, wie Befehlsanzahlen angegeben werden können:
- Wenn pCountBuffer- nicht NULL ist, gibt MaxCommandCount die maximale Anzahl von Vorgängen an, die ausgeführt werden. Die tatsächliche Anzahl der auszuführenden Vorgänge wird durch das Minimum dieses Werts definiert, und eine 32-Bit-ganzzahl ohne Vorzeichen, die in pCountBuffer- enthalten ist (im byte-Offset durch CountBufferOffsetangegeben).
- Wenn pCountBuffer- NULL ist, gibt die MaxCommandCount- die genaue Anzahl der Vorgänge an, die ausgeführt werden.
[in] pArgumentBuffer
Typ: ID3D12Resource-*
Gibt ein oder mehrere ID3D12Resource- Objekte an, die die Befehlsargumente enthalten.
[in] ArgumentBufferOffset
Typ: UINT64-
Gibt einen Offset in pArgumentBuffer- an, um das erste Befehlsargument zu identifizieren.
[in, optional] pCountBuffer
Typ: ID3D12Resource-*
Gibt einen Zeiger auf eine ID3D12Resource-an.
[in] CountBufferOffset
Typ: UINT64-
Gibt einen UINT64-Wert an, der der Offset in pCountBuffer-ist und die Argumentanzahl identifiziert.
Rückgabewert
Nichts
Bemerkungen
Die Semantik dieser API wird mit dem folgenden Pseudocode definiert:
Non-NULL pCountBuffer:
// Read draw count out of count buffer
UINT CommandCount = pCountBuffer->ReadUINT32(CountBufferOffset);
CommandCount = min(CommandCount, MaxCommandCount)
// Get pointer to first Commanding argument
BYTE* Arguments = pArgumentBuffer->GetBase() + ArgumentBufferOffset;
for(UINT CommandIndex = 0; CommandIndex < CommandCount; CommandIndex++)
{
// Interpret the data contained in *Arguments
// according to the command signature
pCommandSignature->Interpret(Arguments);
Arguments += pCommandSignature->GetByteStride();
}
NULL pCountBuffer:
// Get pointer to first Commanding argument
BYTE* Arguments = pArgumentBuffer->GetBase() + ArgumentBufferOffset;
for(UINT CommandIndex = 0; CommandIndex < MaxCommandCount; CommandIndex++)
{
// Interpret the data contained in *Arguments
// according to the command signature
pCommandSignature->Interpret(Arguments);
Arguments += pCommandSignature->GetByteStride();
}
Die Debugebene gibt einen Fehler aus, wenn sich der Anzahlpuffer oder der Argumentpuffer nicht im D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT Zustand befinden. Die Kernlaufzeit überprüft Folgendes:
- CountBufferOffset- und ArgumentBufferOffset- 4-Byte ausgerichtet sind
- pCountBuffer- und pArgumentBuffer- sind Pufferressourcen (beliebiger Heap-Typ)
- Der durch MaxCommandCount, ArgumentBufferOffsetimplizierte Offset und der Zeichenprogramm-Stride überschreiten nicht die Grenzen pArgumentBuffer- (ähnlich für den Anzahlpuffer)
- Die Befehlsliste ist eine direkte Befehlsliste oder eine Computebefehlsliste (keine Kopier- oder JPEG-Decodierungsbefehlsliste)
- Die Stammsignatur der Befehlsliste entspricht der Stammsignatur der Befehlssignatur.
DrawInstancedIndirect und DrawIndexedInstancedIndirect, umfasst ExecuteIndirect.
Bundles
ID3D12GraphicsCommandList::ExecuteIndirect ist nur innerhalb von Bundle-Befehlslisten zulässig, wenn alle folgenden Werte zutreffen:- CountBuffer ist NULL (nur CPU-angegebene Anzahl).
- Die Befehlssignatur enthält genau einen Vorgang. Dies bedeutet, dass die Befehlssignatur keine Stammargumentänderungen enthält oder VB/IB-Bindungsänderungen enthält.
Abrufen virtueller Pufferadressen
Mit der ID3D12Resource::GetGPUVirtualAddress-Methode kann eine App die virtuelle GPU-Adresse eines Puffers abrufen.Apps können Byte-Offsets auf virtuelle Adressen anwenden, bevor sie in einen indirekten Argumentpuffer platziert werden. Beachten Sie, dass alle D3D12-Ausrichtungsanforderungen für VB/IB/CB weiterhin für die resultierende virtuelle GPU-Adresse gelten.
Beispiele
Im beispiel D3D12ExecuteIndirect wird ID3D12GraphicsCommandList::ExecuteIndirect wie folgt verwendet:
// Data structure to match the command signature used for ExecuteIndirect.
struct IndirectCommand
{
D3D12_GPU_VIRTUAL_ADDRESS cbv;
D3D12_DRAW_ARGUMENTS drawArguments;
};
Der Aufruf von ExecuteIndirect befindet sich am Ende dieser Auflistung unter dem Kommentar "Zeichnen Sie die Dreiecke, die nicht gekullt wurden."
// Fill the command list with all the render commands and dependent state.
void D3D12ExecuteIndirect::PopulateCommandLists()
{
// Command list allocators can only be reset when the associated
// command lists have finished execution on the GPU; apps should use
// fences to determine GPU execution progress.
ThrowIfFailed(m_computeCommandAllocators[m_frameIndex]->Reset());
ThrowIfFailed(m_commandAllocators[m_frameIndex]->Reset());
// However, when ExecuteCommandList() is called on a particular command
// list, that command list can then be reset at any time and must be before
// re-recording.
ThrowIfFailed(m_computeCommandList->Reset(m_computeCommandAllocators[m_frameIndex].Get(), m_computeState.Get()));
ThrowIfFailed(m_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
// Record the compute commands that will cull triangles and prevent them from being processed by the vertex shader.
if (m_enableCulling)
{
UINT frameDescriptorOffset = m_frameIndex * CbvSrvUavDescriptorCountPerFrame;
D3D12_GPU_DESCRIPTOR_HANDLE cbvSrvUavHandle = m_cbvSrvUavHeap->GetGPUDescriptorHandleForHeapStart();
m_computeCommandList->SetComputeRootSignature(m_computeRootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() };
m_computeCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
m_computeCommandList->SetComputeRootDescriptorTable(
SrvUavTable,
CD3DX12_GPU_DESCRIPTOR_HANDLE(cbvSrvUavHandle, CbvSrvOffset + frameDescriptorOffset, m_cbvSrvUavDescriptorSize));
m_computeCommandList->SetComputeRoot32BitConstants(RootConstants, 4, reinterpret_cast<void*>(&m_csRootConstants), 0);
// Reset the UAV counter for this frame.
m_computeCommandList->CopyBufferRegion(m_processedCommandBuffers[m_frameIndex].Get(), CommandBufferSizePerFrame, m_processedCommandBufferCounterReset.Get(), 0, sizeof(UINT));
D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(m_processedCommandBuffers[m_frameIndex].Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
m_computeCommandList->ResourceBarrier(1, &barrier);
m_computeCommandList->Dispatch(static_cast<UINT>(ceil(TriangleCount / float(ComputeThreadBlockSize))), 1, 1);
}
ThrowIfFailed(m_computeCommandList->Close());
// Record the rendering commands.
{
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvUavHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
m_commandList->RSSetViewports(1, &m_viewport);
m_commandList->RSSetScissorRects(1, m_enableCulling ? &m_cullingScissorRect : &m_scissorRect);
// Indicate that the command buffer will be used for indirect drawing
// and that the back buffer will be used as a render target.
D3D12_RESOURCE_BARRIER barriers[2] = {
CD3DX12_RESOURCE_BARRIER::Transition(
m_enableCulling ? m_processedCommandBuffers[m_frameIndex].Get() : m_commandBuffer.Get(),
m_enableCulling ? D3D12_RESOURCE_STATE_UNORDERED_ACCESS : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT),
CD3DX12_RESOURCE_BARRIER::Transition(
m_renderTargets[m_frameIndex].Get(),
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET)
};
m_commandList->ResourceBarrier(_countof(barriers), barriers);
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(m_dsvHeap->GetCPUDescriptorHandleForHeapStart());
m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
// Record commands.
const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
m_commandList->ClearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
if (m_enableCulling)
{
// Draw the triangles that have not been culled.
m_commandList->ExecuteIndirect(
m_commandSignature.Get(),
TriangleCount,
m_processedCommandBuffers[m_frameIndex].Get(),
0,
m_processedCommandBuffers[m_frameIndex].Get(),
CommandBufferSizePerFrame);
}
else
{
// Draw all of the triangles.
m_commandList->ExecuteIndirect(
m_commandSignature.Get(),
TriangleCount,
m_commandBuffer.Get(),
CommandBufferSizePerFrame * m_frameIndex,
nullptr,
0);
}
// Indicate that the command buffer may be used by the compute shader
// and that the back buffer will now be used to present.
barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
barriers[0].Transition.StateAfter = m_enableCulling ? D3D12_RESOURCE_STATE_COPY_DEST : D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
m_commandList->ResourceBarrier(_countof(barriers), barriers);
ThrowIfFailed(m_commandList->Close());
}
}
Siehe Beispielcode in der D3D12-Referenz.
Anforderungen
| Anforderung | Wert |
|---|---|
| Zielplattform- | Fenster |
| Header- | d3d12.h |
| Library | D3d12.lib |
| DLL- | D3d12.dll |