ID3D12GraphicsCommandList::ResourceBarrier 方法 (d3d12.h)

通知驅動程式需要同步處理資源的多個存取。

語法

void ResourceBarrier(
  [in] UINT                         NumBarriers,
  [in] const D3D12_RESOURCE_BARRIER *pBarriers
);

參數

[in] NumBarriers

類型: UINT

提交的屏障描述數目。

[in] pBarriers

類型:const D3D12_RESOURCE_BARRIER*

屏障描述陣列的指標。

傳回值

備註

注意

要用於 D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE 狀態的資源必須以該狀態建立,然後永遠不會從中轉換。 也不會有建立的資源未處於該狀態,而無法轉換成該資源。 如需詳細資訊,請參閱 GitHub 上 DirectX 光線追蹤 (DXR) 功能規格中的 加速結構記憶體限制

屏障描述有三種類型:

  • D3D12_RESOURCE_TRANSITION_BARRIER - 轉換屏障表示一組子資源在不同的使用方式之間轉換。 呼叫端必須指定子資源使用前後的 。 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES旗標可用來同時轉換資源中的所有子資源。
  • D3D12_RESOURCE_ALIASING_BARRIER - 別名屏障表示兩個不同資源使用量之間的轉換,這些資源會對應到相同的堆積。 應用程式可以同時指定資源前後的 。 請注意,一或兩個資源可以是 Null (,表示任何磚資源都可能導致別名) 。
  • D3D12_RESOURCE_UAV_BARRIER - 未排序的存取檢視屏障表示所有 UAV 存取 (讀取或寫入特定資源) 必須先完成, (才能開始讀取或寫入) 。 指定的資源可以是 Null。 不需要在兩個繪製或分派唯讀取 UAV 的呼叫之間插入 UAV 屏障。 此外,如果應用程式知道以任何循序執行 UAV 存取,則不需要在兩個繪製或分派呼叫之間插入 UAV 屏障,以寫入相同的 UAV。 資源可以是 Null (,表示任何 UAV 存取可能需要屏障) 。
ID3D12GraphicsCommandList::ResourceBarrier 傳遞資源屏障描述的陣列時,API 的行為就如同每個陣列) 元素 (1 次 (1,依指定的順序。 轉換應該盡可能批次處理成單一 API 呼叫,以作為效能優化。

如需子資源可以位於的使用狀態原因,請參閱 D3D12_RESOURCE_STATES 列舉和 使用資源屏障在 Direct3D 12 中同步處理資源狀態 一節。

呼叫 ID3D12GraphicsCommandList::D iscardResource 時,資源中的所有子資源都必須處於RENDER_TARGET狀態或DEPTH_WRITE狀態,才能分別轉譯目標/深度樣板資源。

出現後端緩衝區時,它必須處於D3D12_RESOURCE_STATE_PRESENT狀態。 如果在不在 PRESENT 狀態的資源上呼叫 IDXGISwapChain1::P resent1 ,將會發出偵錯層警告。

資源使用量位分為兩個類別:唯讀和讀取/寫入。

下列使用位是唯讀的:

  • D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER
  • D3D12_RESOURCE_STATE_INDEX_BUFFER
  • D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE
  • D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE
  • D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT
  • D3D12_RESOURCE_STATE_COPY_SOURCE
  • D3D12_RESOURCE_STATE_DEPTH_READ
下列使用位是讀取/寫入:
  • D3D12_RESOURCE_STATE_UNORDERED_ACCESS
  • D3D12_RESOURCE_STATE_DEPTH_WRITE
下列使用方式位是唯讀的:
  • D3D12_RESOURCE_STATE_COPY_DEST
  • D3D12_RESOURCE_STATE_RENDER_TARGET
  • D3D12_RESOURCE_STATE_STREAM_OUT
最多可以設定一個寫入位。 如果已設定任何寫入位,則不會設定任何讀取位。 如果未設定寫入位,則可以設定任意數目的讀取位。

在任何指定的時間,子資源都只處於一種狀態, (由一組旗標所決定) 。 應用程式必須在進行一連串 的 ResourceBarrier 呼叫時,確保狀態相符。 換句話說, 連續呼叫 ResourceBarrier 的前後狀態必須同意。

若要轉換資源內的所有子資源,應用程式可以將子資源索引設定為 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,這表示所有子資源都會變更。

為了提升效能,應用程式應該使用分割屏障 (參考 多引擎同步 處理) 。 您的應用程式也應該盡可能將多個轉換批次處理成單一呼叫。

執行時間驗證

執行時間會驗證屏障類型值是否為 D3D12_RESOURCE_BARRIER_TYPE 列舉的有效成員。

此外,執行時間會檢查下列各項:

  • 資源指標為非 Null。
  • 子資源索引有效
  • 資源 D3D12_RESOURCE_BINDING_TIERD3D12_RESOURCE_FLAGS 旗標支援狀態前後的 。
  • 未設定狀態遮罩中的保留位。
  • 之前和之後的狀態不同。
  • 狀態前後的位集合有效。
  • 如果已設定D3D12_RESOURCE_STATE_RESOLVE_SOURCE位,則資源樣本計數必須大於 1。
  • 如果已設定D3D12_RESOURCE_STATE_RESOLVE_DEST位,則資源範例計數必須等於 1。
針對別名屏障,執行時間會驗證如果任一資源指標為非 Null,則會參考磚資源。

針對 UAV 屏障,執行時間會驗證資源是否為非 Null,則資源已設定D3D12_RESOURCE_STATE_UNORDERED_ACCESS系結旗標。

驗證失敗會導致 ID3D12GraphicsCommandList::Close 傳回E_INVALIDARG。

偵錯層

偵錯層通常會發出運行時驗證失敗的錯誤:
  • 如果命令清單中的子資源轉換與相同命令清單中的先前轉換不一致。
  • 如果使用資源而不先呼叫 ResourceBarrier ,將資源放入正確的狀態。
  • 如果資源不合法地同時系結讀取和寫入。
  • 如果傳遞至ResourceBarrier之前的狀態不符合先前呼叫ResourceBarrier的後置狀態,包括別名案例。
雖然偵錯層會嘗試驗證執行時間規則,但會以保守方式運作,讓偵錯層錯誤是真正的錯誤,在某些情況下,實際錯誤可能不會產生偵錯層錯誤。

偵錯層會在下列情況下發出警告:

範例

D3D12HelloTriangle範例使用ID3D12GraphicsCommandList::ResourceBarrier,如下所示:

D3D12_VIEWPORT m_viewport;
D3D12_RECT m_scissorRect;
ComPtr<IDXGISwapChain3> m_swapChain;
ComPtr<ID3D12Device> m_device;
ComPtr<ID3D12Resource> m_renderTargets[FrameCount];
ComPtr<ID3D12CommandAllocator> m_commandAllocator;
ComPtr<ID3D12CommandQueue> m_commandQueue;
ComPtr<ID3D12RootSignature> m_rootSignature;
ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
ComPtr<ID3D12PipelineState> m_pipelineState;
ComPtr<ID3D12GraphicsCommandList> m_commandList;
UINT m_rtvDescriptorSize;

void D3D12HelloTriangle::PopulateCommandList()
{
    // 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_commandAllocator->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_commandList->Reset(m_commandAllocator.Get(), m_pipelineState.Get()));

    // Set necessary state.
    m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
    m_commandList->RSSetViewports(1, &m_viewport);
    m_commandList->RSSetScissorRects(1, &m_scissorRect);

    // Indicate that the back buffer will be used as a render target.
    m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));

    CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
    m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);

    // Record commands.
    const float clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
    m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
    m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
    m_commandList->DrawInstanced(3, 1, 0, 0);

    // Indicate that the back buffer will now be used to present.
    m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));

    ThrowIfFailed(m_commandList->Close());
}

請參閱 D3D12 參考中的範例程式碼

需求

   
目標平台 Windows
標頭 d3d12.h
程式庫 D3d12.lib
Dll D3d12.dll

另請參閱

ID3D12GraphicsCommandList

在 Direct3D 12 中使用資源屏障同步處理資源狀態