透過緩衝區讀取資料
例如,若要從 GPU (讀取資料,若要擷取螢幕擷取畫面) ,請使用讀取回堆積。 這項技術與 透過緩衝區上傳紋理資料有關,但有一些差異。
- 若要讀取回資料,您可以建立堆積,並將 D3D12_HEAP_TYPE 設定為 D3D12_HEAP_TYPE_READBACK,而不是 D3D12_HEAP_TYPE_UPLOAD。
- 讀取後堆積上的資源一律必須是 D3D12_RESOURCE_DIMENSION_BUFFER。
- 當您完成將資料寫入輸出緩衝區時,您可以使用柵欄來偵測 GPU 何時完成處理框架 () 。 這很重要,因為 ID3D12Resource::Map 方法不會相反地與 GPU 同步處理 (,因此 Direct3D 11 對等專案 會 同步處理) 。 Direct3D 12 對應 呼叫的行為就像您呼叫 Direct3D 11 與 NO_OVERWRITE 旗標相等。
- 資料準備好 (包括任何必要的資源屏障) 之後,請呼叫 ID3D12Resource::Map ,讓 CPU 可以看到回寫資料。
程式碼範例
下列程式碼範例顯示透過緩衝區將 GPU 資料讀取回 CPU 之程式的一般大綱。
// The output buffer (created below) is on a default heap, so only the GPU can access it.
D3D12_HEAP_PROPERTIES defaultHeapProperties{ CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT) };
D3D12_RESOURCE_DESC outputBufferDesc{ CD3DX12_RESOURCE_DESC::Buffer(outputBufferSize, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) };
winrt::com_ptr<::ID3D12Resource> outputBuffer;
winrt::check_hresult(d3d12Device->CreateCommittedResource(
&defaultHeapProperties,
D3D12_HEAP_FLAG_NONE,
&outputBufferDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
__uuidof(outputBuffer),
outputBuffer.put_void()));
// The readback buffer (created below) is on a readback heap, so that the CPU can access it.
D3D12_HEAP_PROPERTIES readbackHeapProperties{ CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK) };
D3D12_RESOURCE_DESC readbackBufferDesc{ CD3DX12_RESOURCE_DESC::Buffer(outputBufferSize) };
winrt::com_ptr<::ID3D12Resource> readbackBuffer;
winrt::check_hresult(d3d12Device->CreateCommittedResource(
&readbackHeapProperties,
D3D12_HEAP_FLAG_NONE,
&readbackBufferDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
__uuidof(readbackBuffer),
readbackBuffer.put_void()));
{
D3D12_RESOURCE_BARRIER outputBufferResourceBarrier
{
CD3DX12_RESOURCE_BARRIER::Transition(
outputBuffer.get(),
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_COPY_SOURCE)
};
commandList->ResourceBarrier(1, &outputBufferResourceBarrier);
}
commandList->CopyResource(readbackBuffer.get(), outputBuffer.get());
// Code goes here to close, execute (and optionally reset) the command list, and also
// to use a fence to wait for the command queue.
// The code below assumes that the GPU wrote FLOATs to the buffer.
D3D12_RANGE readbackBufferRange{ 0, outputBufferSize };
FLOAT * pReadbackBufferData{};
winrt::check_hresult(
readbackBuffer->Map
(
0,
&readbackBufferRange,
reinterpret_cast<void**>(&pReadbackBufferData)
)
);
// Code goes here to access the data via pReadbackBufferData.
D3D12_RANGE emptyRange{ 0, 0 };
readbackBuffer->Unmap
(
0,
&emptyRange
);
如需讀取轉譯目標紋理的螢幕擷取畫面常式的完整實作,並將它寫入磁片作為檔案,請參閱適用于 DX12 的ScreenGrab的DirectX 工具組。