ID3D12GraphicsCommandList
COM公式ドキュメント
レンダリング用のグラフィックスコマンドのリストをカプセル化します。コマンドリストの実行を計測するための API や、パイプラインステートの設定・クリアを行う API を含みます。
解説(Remarks)
このインターフェイスは D3D12 で新たに追加されたもので、ID3D11CommandList インターフェイスの機能の多くをカプセル化し、さらに レンダリング で説明されている新機能を含みます。
例
D3D12nBodyGravity サンプルでは、ID3D12GraphicsCommandList を次のように使用しています。
パイプラインオブジェクトを宣言します。
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;
コマンドリストへの記録を行います。
// Fill the command list with all the render commands and dependent state.
void D3D12nBodyGravity::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_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_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
// Set necessary state.
m_commandList->SetPipelineState(m_pipelineState.Get());
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
m_commandList->SetGraphicsRootConstantBufferView(RootParameterCB, m_constantBufferGS->GetGPUVirtualAddress() + m_frameIndex * sizeof(ConstantBufferGS));
ID3D12DescriptorHeap* ppHeaps[] = { m_srvUavHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
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.0f, 0.1f, 0.0f };
m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
// Render the particles.
float viewportHeight = static_cast<float>(static_cast<UINT>(m_viewport.Height) / m_heightInstances);
float viewportWidth = static_cast<float>(static_cast<UINT>(m_viewport.Width) / m_widthInstances);
for (UINT n = 0; n < ThreadCount; n++)
{
const UINT srvIndex = n + (m_srvIndex[n] == 0 ? SrvParticlePosVelo0 : SrvParticlePosVelo1);
D3D12_VIEWPORT viewport;
viewport.TopLeftX = (n % m_widthInstances) * viewportWidth;
viewport.TopLeftY = (n / m_widthInstances) * viewportHeight;
viewport.Width = viewportWidth;
viewport.Height = viewportHeight;
viewport.MinDepth = D3D12_MIN_DEPTH;
viewport.MaxDepth = D3D12_MAX_DEPTH;
m_commandList->RSSetViewports(1, &viewport);
CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle(m_srvUavHeap->GetGPUDescriptorHandleForHeapStart(), srvIndex, m_srvUavDescriptorSize);
m_commandList->SetGraphicsRootDescriptorTable(RootParameterSRV, srvHandle);
m_commandList->DrawInstanced(ParticleCount, 1, 0, 0);
}
m_commandList->RSSetViewports(1, &m_viewport);
// 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 リファレンスのサンプルコード を参照してください。
メソッド 51
vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。
コマンドリストへの記録が完了したことを示します。(ID3D12GraphicsCommandList.Close)
戻り値
型: HRESULT
成功した場合は S_OK を返します。それ以外の場合は、次のいずれかの値を返します。
- E_FAIL: コマンドリストが既にクローズされている場合、またはコマンドリストへの記録中に無効な API が呼び出された場合。
- E_OUTOFMEMORY: 記録中にオペレーティングシステムのメモリが不足した場合。
- E_INVALIDARG: 記録中にコマンドリスト API へ無効な引数が渡された場合。
解説(Remarks)
ランタイムは、コマンドリストが既にクローズされていないことを検証します。記録中にエラーが発生していた場合、そのエラーコードがここで返されます。この場合、ランタイムはクローズのデバイスドライバーインターフェイス (DDI) を呼び出しません。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::Close を次のように使用しています。
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::LoadAssets()
{
// Create an empty root signature.
{
CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc;
rootSignatureDesc.Init(0, nullptr, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
ComPtr<ID3DBlob> signature;
ComPtr<ID3DBlob> error;
ThrowIfFailed(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error));
ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
}
// Create the pipeline state, which includes compiling and loading shaders.
{
ComPtr<ID3DBlob> vertexShader;
ComPtr<ID3DBlob> pixelShader;
#if defined(_DEBUG)
// Enable better shader debugging with the graphics debugging tools.
UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#else
UINT compileFlags = 0;
#endif
ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "VSMain", "vs_5_0", compileFlags, 0, &vertexShader, nullptr));
ThrowIfFailed(D3DCompileFromFile(GetAssetFullPath(L"shaders.hlsl").c_str(), nullptr, nullptr, "PSMain", "ps_5_0", compileFlags, 0, &pixelShader, nullptr));
// Define the vertex input layout.
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
// Describe and create the graphics pipeline state object (PSO).
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) };
psoDesc.pRootSignature = m_rootSignature.Get();
psoDesc.VS = { reinterpret_cast<UINT8*>(vertexShader->GetBufferPointer()), vertexShader->GetBufferSize() };
psoDesc.PS = { reinterpret_cast<UINT8*>(pixelShader->GetBufferPointer()), pixelShader->GetBufferSize() };
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
psoDesc.DepthStencilState.DepthEnable = FALSE;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.SampleMask = UINT_MAX;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.NumRenderTargets = 1;
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
psoDesc.SampleDesc.Count = 1;
ThrowIfFailed(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState)));
}
// Create the command list.
ThrowIfFailed(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator.Get(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList)));
// Command lists are created in the recording state, but there is nothing
// to record yet. The main loop expects it to be closed, so close it now.
ThrowIfFailed(m_commandList->Close());
// Create the vertex buffer.
{
// Define the geometry for a triangle.
Vertex triangleVertices[] =
{
{ { 0.0f, 0.25f * m_aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
{ { 0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ { -0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
};
const UINT vertexBufferSize = sizeof(triangleVertices);
// Note: using upload heaps to transfer static data like vert buffers is not
// recommended. Every time the GPU needs it, the upload heap will be marshalled
// over. Please read up on Default Heap usage. An upload heap is used here for
// code simplicity and because there are very few verts to actually transfer.
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&m_vertexBuffer)));
// Copy the triangle data to the vertex buffer.
UINT8* pVertexDataBegin;
CD3DX12_RANGE readRange(0, 0); // We do not intend to read from this resource on the CPU.
ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
m_vertexBuffer->Unmap(0, nullptr);
// Initialize the vertex buffer view.
m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
m_vertexBufferView.StrideInBytes = sizeof(Vertex);
m_vertexBufferView.SizeInBytes = vertexBufferSize;
}
// Create synchronization objects and wait until assets have been uploaded to the GPU.
{
ThrowIfFailed(m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)));
m_fenceValue = 1;
// Create an event handle to use for frame synchronization.
m_fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
if (m_fenceEvent == nullptr)
{
ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
}
// Wait for the command list to execute; we are reusing the same command
// list in our main loop but for now, we just want to wait for setup to
// complete before continuing.
WaitForPreviousFrame();
}
}
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 リファレンスのサンプルコード を参照してください。
コマンドリストを、新しく作成された直後と同じ初期状態にリセットします。(ID3D12GraphicsCommandList.Reset)
| pAllocator | ID3D12CommandAllocator* | in | デバイスがコマンドリストを作成する元となる ID3D12CommandAllocator オブジェクトへのポインターです。 |
| pInitialState | ID3D12PipelineState* | inoptional | コマンドリストの初期パイプラインステートを保持する ID3D12PipelineState オブジェクトへのポインターです。これは省略可能で、NULL を指定できます。NULL の場合、ドライバーが未定義の状態を扱わずに済むよう、ランタイムがダミーの初期パイプラインステートを設定します。このオーバーヘッドは小さく、特にコマンドリストでは、コマンドリスト全体の記録コストが初期ステート設定 1 回分のコストを大きく上回るのが一般的です。したがって、初期パイプラインステートのパラメーターを設定するのが不都合であれば、設定しなくてもコストはほとんどありません。 一方、バンドルの場合は全体として小さく、頻繁に再利用される可能性が高いため、初期ステートのパラメーターを設定する方が合理的なことがあります。 |
戻り値
型: HRESULT
成功した場合は S_OK を返します。それ以外の場合は、次のいずれかの値を返します。
- E_FAIL: Reset の呼び出し時にコマンドリストが「クローズ」状態でなかった場合、またはデバイスごとの上限を超える場合。
- E_OUTOFMEMORY: オペレーティングシステムのメモリが不足した場合。
- E_INVALIDARG: 指定したアロケーターが「記録中」状態の別のコマンドリストで現在使用されている場合、または誤った型で作成されたアロケーターが指定された場合。
解説(Remarks)
Reset を使用すると、メモリ割り当てを行うことなくコマンドリストの追跡構造を再利用できます。ID3D12CommandAllocator::Reset とは異なり、ID3D12GraphicsCommandList::Reset はコマンドリストがまだ実行中であっても呼び出せます。
Reset は、ダイレクトコマンドリストとバンドルの両方に使用できます。
Reset に渡すコマンドアロケーターは、現在記録中の他のコマンドリストに関連付けられていてはなりません。アロケーターの種類 (ダイレクトコマンドリストまたはバンドル) は、作成するコマンドリストの種類と一致している必要があります。
バンドルがリソースヒープを指定しない場合、そのバンドルはバインドされる記述子テーブルを変更できません。いずれの場合も、バンドル内でリソースヒープを変更することはできません。バンドルにヒープを指定する場合、そのヒープは呼び出し元である「親」コマンドリストのヒープと一致している必要があります。
ランタイムによる検証
アプリが Reset を呼び出す前に、コマンドリストは「クローズ」状態になっている必要があります。コマンドリストが「クローズ」状態でない場合、Reset は失敗します。アプリはコマンドリストアロケーターを指定する必要があります。ランタイムは、1 つのアロケーターが同時に複数の記録中コマンドリストに関連付けられることがないよう保証します。
まだ送信されていないコマンドリストから参照されているバンドルに対しては、Reset は失敗します。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::Reset を次のように使用しています。
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 リファレンスのサンプルコード を参照してください。
ダイレクトコマンドリストの状態を、そのコマンドリストが作成された時点の状態にリセットします。(ID3D12GraphicsCommandList.ClearState)
| pPipelineState | ID3D12PipelineState* | inoptional | コマンドリストの初期パイプラインステートを保持する ID3D12PipelineState オブジェクトへのポインターです。 |
解説(Remarks)
バンドルに対して ClearState を呼び出すことは無効です。アプリがバンドルに対して ClearState を呼び出した場合、Close の呼び出しは E_FAIL を返します。
ClearState を呼び出すと、現在バインドされているすべてのリソースがアンバインドされます。プリミティブトポロジは D3D_PRIMITIVE_TOPOLOGY_UNDEFINED に設定されます。ビューポート、シザー矩形、ステンシル参照値、ブレンドファクターは空の値 (すべてゼロ) に設定されます。プレディケーションは無効になります。
アプリが指定したパイプラインステートオブジェクトが、現在設定されているパイプラインステートオブジェクトとしてバインドされます。
非インデックス付きのインスタンス化されたプリミティブを描画します。
| VertexCountPerInstance | DWORD | in | 描画する頂点の数です。 |
| InstanceCount | DWORD | in | 描画するインスタンスの数です。 |
| StartVertexLocation | DWORD | in | 最初の頂点のインデックスです。 |
| StartInstanceLocation | DWORD | in | 頂点バッファーからインスタンスごとのデータを読み取る前に、各インデックスに加算される値です。 |
解説(Remarks)
描画 API は、レンダリングパイプラインに処理を送信します。
インスタンシングを使うと、同じジオメトリを再利用してシーン内の複数のオブジェクトを描画できるため、パフォーマンスが向上する場合があります。インスタンシングの例としては、同じオブジェクトを異なる位置と色で描画することが挙げられます。
インスタンス描画呼び出しの頂点データは、通常はパイプラインにバインドされた頂点バッファーから供給されます。ただし、システム値セマンティクス (SV_InstanceID) で識別されるインスタンスデータを持つシェーダーから頂点データを供給することもできます。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::DrawInstanced を次のように使用しています。
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 リファレンスのサンプルコード を参照してください。
インデックス付きのインスタンス化されたプリミティブを描画します。
| IndexCountPerInstance | DWORD | in | インスタンスごとにインデックスバッファーから読み取るインデックスの数です。 |
| InstanceCount | DWORD | in | 描画するインスタンスの数です。 |
| StartIndexLocation | DWORD | in | GPU がインデックスバッファーから読み取る最初のインデックスの位置です。 |
| BaseVertexLocation | INT | in | 頂点バッファーから頂点を読み取る前に、各インデックスに加算される値です。 |
| StartInstanceLocation | DWORD | in | 頂点バッファーからインスタンスごとのデータを読み取る前に、各インデックスに加算される値です。 |
解説(Remarks)
描画 API は、レンダリングパイプラインに処理を送信します。
インスタンシングを使うと、同じジオメトリを再利用してシーン内の複数のオブジェクトを描画できるため、パフォーマンスが向上する場合があります。インスタンシングの例としては、同じオブジェクトを異なる位置と色で描画することが挙げられます。インスタンシングには複数の頂点バッファーが必要です。少なくとも 1 つは頂点ごとのデータ用、もう 1 つはインスタンスごとのデータ用です。
例
D3D12Bundles サンプルでは、ID3D12GraphicsCommandList::DrawIndexedInstanced を次のように使用しています。
void FrameResource::PopulateCommandList(ID3D12GraphicsCommandList* pCommandList, ID3D12PipelineState* pPso1, ID3D12PipelineState* pPso2,
UINT frameResourceIndex, UINT numIndices, D3D12_INDEX_BUFFER_VIEW* pIndexBufferViewDesc, D3D12_VERTEX_BUFFER_VIEW* pVertexBufferViewDesc,
ID3D12DescriptorHeap* pCbvSrvDescriptorHeap, UINT cbvSrvDescriptorSize, ID3D12DescriptorHeap* pSamplerDescriptorHeap, ID3D12RootSignature* pRootSignature)
{
// If the root signature matches the root signature of the caller, then
// bindings are inherited, otherwise the bind space is reset.
pCommandList->SetGraphicsRootSignature(pRootSignature);
ID3D12DescriptorHeap* ppHeaps[] = { pCbvSrvDescriptorHeap, pSamplerDescriptorHeap };
pCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
pCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
pCommandList->IASetIndexBuffer(pIndexBufferViewDesc);
pCommandList->IASetVertexBuffers(0, 1, pVertexBufferViewDesc);
pCommandList->SetGraphicsRootDescriptorTable(0, pCbvSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
pCommandList->SetGraphicsRootDescriptorTable(1, pSamplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
// Calculate the descriptor offset due to multiple frame resources.
// 1 SRV + how many CBVs we have currently.
UINT frameResourceDescriptorOffset = 1 + (frameResourceIndex * m_cityRowCount * m_cityColumnCount);
CD3DX12_GPU_DESCRIPTOR_HANDLE cbvSrvHandle(pCbvSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), frameResourceDescriptorOffset, cbvSrvDescriptorSize);
BOOL usePso1 = TRUE;
for (UINT i = 0; i < m_cityRowCount; i++)
{
for (UINT j = 0; j < m_cityColumnCount; j++)
{
// Alternate which PSO to use; the pixel shader is different on
// each just as a PSO setting demonstration.
pCommandList->SetPipelineState(usePso1 ? pPso1 : pPso2);
usePso1 = !usePso1;
// Set this city's CBV table and move to the next descriptor.
pCommandList->SetGraphicsRootDescriptorTable(2, cbvSrvHandle);
cbvSrvHandle.Offset(cbvSrvDescriptorSize);
pCommandList->DrawIndexedInstanced(numIndices, 1, 0, 0, 0);
}
}
}
D3D12 リファレンスのサンプルコード を参照してください。
スレッドグループ上でコンピュートシェーダーを実行します。
| ThreadGroupCountX | DWORD | in | x 方向にディスパッチされるグループの数です。ThreadGroupCountX は D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION (65535) 以下である必要があります。 |
| ThreadGroupCountY | DWORD | in | y 方向にディスパッチされるグループの数です。ThreadGroupCountY は D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION (65535) 以下である必要があります。 |
| ThreadGroupCountZ | DWORD | in | z 方向にディスパッチされるグループの数です。ThreadGroupCountZ は D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION (65535) 以下である必要があります。 機能レベル 10 では、ThreadGroupCountZ の値は 1 でなければなりません。 |
解説(Remarks)
コンピュートシェーダー内のコマンドを実行するには Dispatch メソッドを呼び出します。コンピュートシェーダーは、スレッドグループ内の多数のスレッド上で並列に実行できます。スレッドグループ内の個々のスレッドは、(x,y,z) で与えられる 3 次元ベクトルでインデックス指定します。
例
D3D12nBodyGravity サンプルでは、ID3D12GraphicsCommandList::Dispatch を次のように使用しています。
// Run the particle simulation using the compute shader.
void D3D12nBodyGravity::Simulate(UINT threadIndex)
{
ID3D12GraphicsCommandList* pCommandList = m_computeCommandList[threadIndex].Get();
UINT srvIndex;
UINT uavIndex;
ID3D12Resource *pUavResource;
if (m_srvIndex[threadIndex] == 0)
{
srvIndex = SrvParticlePosVelo0;
uavIndex = UavParticlePosVelo1;
pUavResource = m_particleBuffer1[threadIndex].Get();
}
else
{
srvIndex = SrvParticlePosVelo1;
uavIndex = UavParticlePosVelo0;
pUavResource = m_particleBuffer0[threadIndex].Get();
}
pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(pUavResource, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
pCommandList->SetPipelineState(m_computeState.Get());
pCommandList->SetComputeRootSignature(m_computeRootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_srvUavHeap.Get() };
pCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle(m_srvUavHeap->GetGPUDescriptorHandleForHeapStart(), srvIndex + threadIndex, m_srvUavDescriptorSize);
CD3DX12_GPU_DESCRIPTOR_HANDLE uavHandle(m_srvUavHeap->GetGPUDescriptorHandleForHeapStart(), uavIndex + threadIndex, m_srvUavDescriptorSize);
pCommandList->SetComputeRootConstantBufferView(RootParameterCB, m_constantBufferCS->GetGPUVirtualAddress());
pCommandList->SetComputeRootDescriptorTable(RootParameterSRV, srvHandle);
pCommandList->SetComputeRootDescriptorTable(RootParameterUAV, uavHandle);
pCommandList->Dispatch(static_cast<int>(ceil(ParticleCount / 128.0f)), 1, 1);
pCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(pUavResource, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
}
D3D12 リファレンスのサンプルコード を参照してください。
バッファーの領域をあるリソースから別のリソースへコピーします。
| pDstBuffer | ID3D12Resource* | in | コピー先の ID3D12Resource を指定します。 |
| DstOffset | ULONGLONG | in | コピー先リソース内のオフセット (バイト単位、UINT64) を指定します。 |
| pSrcBuffer | ID3D12Resource* | in | コピー元の ID3D12Resource を指定します。 |
| SrcOffset | ULONGLONG | in | コピーを開始するコピー元リソース内のオフセット (バイト単位、UINT64) を指定します。 |
| NumBytes | ULONGLONG | in | コピーするバイト数を指定します。 |
解説(Remarks)
リソース全体をコピーする場合は CopyResource メソッドの使用を検討してください。本メソッドは、リソースの一部の領域をコピーする用途に使用します。
CopyBufferRegion は、同じヒープメモリをエイリアスするリソースの初期化に使用できます。詳細については CreatePlacedResource を参照してください。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::CopyBufferRegion を次のように使用しています。
inline UINT64 UpdateSubresources(
_In_ ID3D12GraphicsCommandList* pCmdList,
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
UINT64 RequiredSize,
_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
_In_reads_(NumSubresources) const UINT* pNumRows,
_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)
{
// Minor validation
D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();
D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();
if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
RequiredSize > (SIZE_T)-1 ||
(DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
(FirstSubresource != 0 || NumSubresources != 1)))
{
return 0;
}
BYTE* pData;
HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));
if (FAILED(hr))
{
return 0;
}
for (UINT i = 0; i < NumSubresources; ++i)
{
if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;
D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };
MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);
}
pIntermediate->Unmap(0, NULL);
if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );
pCmdList->CopyBufferRegion(
pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
}
else
{
for (UINT i = 0; i < NumSubresources; ++i)
{
CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);
CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);
pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
}
}
return RequiredSize;
}
D3D12 リファレンスのサンプルコード を参照してください。
このメソッドは、GPU を使用して 2 つの位置の間でテクスチャデータをコピーします。コピー元とコピー先はいずれも、バッファーリソース内またはテクスチャリソース内に配置されたテクスチャデータを参照できます。
| pDst | D3D12_TEXTURE_COPY_LOCATION* | in | コピー先の D3D12_TEXTURE_COPY_LOCATION を指定します。参照されるサブリソースは D3D12_RESOURCE_STATE_COPY_DEST 状態である必要があります。 |
| DstX | DWORD | in | コピー先領域の左上隅の x 座標です。 |
| DstY | DWORD | in | コピー先領域の左上隅の y 座標です。1D サブリソースの場合は 0 でなければなりません。 |
| DstZ | DWORD | in | コピー先領域の左上隅の z 座標です。1D または 2D サブリソースの場合は 0 でなければなりません。 |
| pSrc | D3D12_TEXTURE_COPY_LOCATION* | in | コピー元の D3D12_TEXTURE_COPY_LOCATION を指定します。 参照されるサブリソースは D3D12_RESOURCE_STATE_COPY_SOURCE 状態である必要があります。 |
| pSrcBox | D3D12_BOX* | inoptional | コピーするコピー元テクスチャのサイズを指定する、省略可能な D3D12_BOX を指定します。 |
解説(Remarks)
コピー元のボックスは、コピー元リソースのサイズの範囲内でなければなりません。コピー先のオフセット (x、y、z) により、コピー先リソースへ書き込む際にコピー元ボックスをずらして配置できますが、コピー元ボックスの寸法とオフセットはリソースのサイズの範囲内である必要があります。コピー先リソースの外側へコピーしようとしたり、コピー元リソースより大きいコピー元ボックスを指定したりした場合、CopyTextureRegion の動作は未定義です。デバッグレイヤー をサポートするデバイスを作成している場合、この無効な CopyTextureRegion 呼び出しに対してデバッグ出力にエラーが報告されます。CopyTextureRegion に無効なパラメーターを渡すと動作が未定義となり、レンダリング結果の不正、クリッピング、コピーが行われない、さらにはレンダリングデバイスの削除といった結果を招く可能性があります。
リソースがバッファーの場合、すべての座標はバイト単位です。リソースがテクスチャの場合、すべての座標はテクセル単位です。
CopyTextureRegion は GPU 上でコピーを実行します (CPU による memcpy に相当します)。そのため、コピー元とコピー先のリソースは次の条件を満たす必要があります。
- 異なるサブリソースであること (同一リソース内のサブリソース同士でも構いません)。
- 互換性のある DXGI_FORMAT であること (同一であるか、同じ型グループに属していること)。たとえば、DXGI_FORMAT_R32G32B32_FLOAT のテクスチャは DXGI_FORMAT_R32G32B32_UINT のテクスチャへコピーできます。どちらの形式も DXGI_FORMAT_R32G32B32_TYPELESS グループに属しているためです。CopyTextureRegion は、いくつかの形式の型の間でコピーできます。詳細については Direct3D 10.1 を使用した形式変換 を参照してください。
なお、深度ステンシルバッファーでは、深度プレーンとステンシルプレーンはバッファー内の 別個のサブリソース です。
サブリソースの一部の領域ではなくリソース全体をコピーする場合は、代わりに CopyResource を使用することをお勧めします。
例
次のコードスニペットは、コピー元テクスチャ内のボックス ((120,100),(200,220) に位置する) を、コピー先テクスチャ内の領域 (10,20),(90,140) へコピーします。D3D12_BOX sourceRegion;
sourceRegion.left = 120;
sourceRegion.top = 100;
sourceRegion.right = 200;
sourceRegion.bottom = 220;
sourceRegion.front = 0;
sourceRegion.back = 1;
pCmdList -> CopyTextureRegion(pDestTexture, 10, 20, 0, pSourceTexture, &sourceRegion);
2D テクスチャの場合、front と back はそれぞれ 0 と 1 に設定される点に注意してください。
例
HelloTriangle サンプルでは、ID3D12GraphicsCommandList::CopyTextureRegion を次のように使用しています。
inline UINT64 UpdateSubresources(
_In_ ID3D12GraphicsCommandList* pCmdList,
_In_ ID3D12Resource* pDestinationResource,
_In_ ID3D12Resource* pIntermediate,
_In_range_(0,D3D12_REQ_SUBRESOURCES) UINT FirstSubresource,
_In_range_(0,D3D12_REQ_SUBRESOURCES-FirstSubresource) UINT NumSubresources,
UINT64 RequiredSize,
_In_reads_(NumSubresources) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
_In_reads_(NumSubresources) const UINT* pNumRows,
_In_reads_(NumSubresources) const UINT64* pRowSizesInBytes,
_In_reads_(NumSubresources) const D3D12_SUBRESOURCE_DATA* pSrcData)
{
// Minor validation
D3D12_RESOURCE_DESC IntermediateDesc = pIntermediate->GetDesc();
D3D12_RESOURCE_DESC DestinationDesc = pDestinationResource->GetDesc();
if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
RequiredSize > (SIZE_T)-1 ||
(DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
(FirstSubresource != 0 || NumSubresources != 1)))
{
return 0;
}
BYTE* pData;
HRESULT hr = pIntermediate->Map(0, NULL, reinterpret_cast<void**>(&pData));
if (FAILED(hr))
{
return 0;
}
for (UINT i = 0; i < NumSubresources; ++i)
{
if (pRowSizesInBytes[i] > (SIZE_T)-1) return 0;
D3D12_MEMCPY_DEST DestData = { pData + pLayouts[i].Offset, pLayouts[i].Footprint.RowPitch, pLayouts[i].Footprint.RowPitch * pNumRows[i] };
MemcpySubresource(&DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth);
}
pIntermediate->Unmap(0, NULL);
if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
{
CD3DX12_BOX SrcBox( UINT( pLayouts[0].Offset ), UINT( pLayouts[0].Offset + pLayouts[0].Footprint.Width ) );
pCmdList->CopyBufferRegion(
pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width);
}
else
{
for (UINT i = 0; i < NumSubresources; ++i)
{
CD3DX12_TEXTURE_COPY_LOCATION Dst(pDestinationResource, i + FirstSubresource);
CD3DX12_TEXTURE_COPY_LOCATION Src(pIntermediate, pLayouts[i]);
pCmdList->CopyTextureRegion(&Dst, 0, 0, 0, &Src, nullptr);
}
}
return RequiredSize;
}
D3D12 リファレンスのサンプルコード を参照してください。
コピー元リソースの内容全体をコピー先リソースへコピーします。
| pDstResource | ID3D12Resource* | in | コピー先リソースを表す ID3D12Resource インターフェイスへのポインターです。 |
| pSrcResource | ID3D12Resource* | in | コピー元リソースを表す ID3D12Resource インターフェイスへのポインターです。 |
解説(Remarks)
CopyResource の処理は GPU 上で実行されるため、コピーするデータのサイズに比例して CPU 負荷が大きくなることはありません。
CopyResource は、同じヒープメモリをエイリアスするリソースの初期化に使用できます。詳細については CreatePlacedResource を参照してください。
デバッグレイヤー
コピー元のサブリソースが D3D12_RESOURCE_STATE_COPY_SOURCE 状態でない場合、デバッグレイヤーはエラーを発行します。
コピー先のサブリソースが D3D12_RESOURCE_STATE_COPY_DEST 状態でない場合、デバッグレイヤーはエラーを発行します。
制限事項
このメソッドには、パフォーマンス向上のためのいくつかの制限があります。たとえば、コピー元とコピー先のリソースは次の条件を満たす必要があります。
- 異なるリソースであること。
- 同じ型であること。
- 合計サイズ (バイト数) が同じであること。
- 寸法 (幅、高さ、深度) が同一であるか、互換性のある 再解釈コピー であること。
- 互換性のある DXGI 形式 であること。すなわち、形式が同一であるか、少なくとも同じ型グループに属している必要があります。たとえば、DXGI_FORMAT_R32G32B32_FLOAT のテクスチャは DXGI_FORMAT_R32G32B32_UINT のテクスチャへコピーできます。どちらの形式も DXGI_FORMAT_R32G32B32_TYPELESS グループに属しているためです。CopyResource は、いくつかの形式の型の間でコピーできます (再解釈コピー を参照)。
- 現在マップされていないこと。
CopyResource はコピーのみをサポートし、拡大縮小、カラーキー、ブレンドはサポートしません。
CopyResource は、いくつかの形式の型の間でリソースデータを再解釈できます。詳細については、以下の 再解釈コピー を参照してください。
深度ステンシル リソースは、コピー元・コピー先のいずれとしても使用できます。マルチサンプリング機能付きで作成されたリソース (DXGI_SAMPLE_DESC を参照) は、コピー元とコピー先の両方でマルチサンプルの数と品質が同一である場合にのみ、コピー元・コピー先として使用できます。コピー元とコピー先でマルチサンプルの数や品質が異なる場合、あるいは一方がマルチサンプルでもう一方がマルチサンプルでない場合、CopyResource の呼び出しは失敗します。マルチサンプルリソースを非マルチサンプルのリソースへ解決するには、ResolveSubresource を使用してください。
このメソッドは非同期呼び出しであり、コマンドバッファーのキューに追加される場合があります。これにより、データのコピー時に発生しうるパイプラインのストールを排除しようとします。詳細については パフォーマンスに関する考慮事項 を参照してください。
リソース内のデータの一部のみをコピーする必要がある場合は、CopyTextureRegion または CopyBufferRegion の使用を検討してください。
再解釈コピー
次の表は、再解釈型の形式変換で使用できるコピー元とコピー先の形式の組み合わせを示しています。基になるデータ値は変換も圧縮・展開もされないため、再解釈が期待どおりに機能するには、データが適切にエンコードされている必要があります。詳細については Direct3D 10.1 を使用した形式変換 を参照してください。
DXGI_FORMAT_R9G9B9E5_SHAREDEXP の場合、幅と高さは等しくなければなりません (ブロックあたり 1 テクセル)。
ブロック圧縮リソースの幅と高さは、非圧縮リソースの幅と高さの 4 倍でなければなりません (ブロックあたり 16 テクセル)。たとえば、非圧縮の 256x256 の DXGI_FORMAT_R32G32B32A32_UINT テクスチャは、1024x1024 の DXGI_FORMAT_BC5_UNORM 圧縮テクスチャに対応します。
例
D3D12HeterogeneousMultiadapter サンプルでは、CopyResource を次のように使用しています。
// Command list to copy the render target to the shared heap on the primary adapter.
{
const GraphicsAdapter adapter = Primary;
// Reset the copy command allocator and command list.
ThrowIfFailed(m_copyCommandAllocators[m_frameIndex]->Reset());
ThrowIfFailed(m_copyCommandList->Reset(m_copyCommandAllocators[m_frameIndex].Get(), nullptr));
// Copy the intermediate render target to the cross-adapter shared resource.
// Transition barriers are not required since there are fences guarding against
// concurrent read/write access to the shared heap.
if (m_crossAdapterTextureSupport)
{
// If cross-adapter row-major textures are supported by the adapter,
// simply copy the texture into the cross-adapter texture.
m_copyCommandList->CopyResource(m_crossAdapterResources[adapter][m_frameIndex].Get(), m_renderTargets[adapter][m_frameIndex].Get());
}
else
{
// If cross-adapter row-major textures are not supported by the adapter,
// the texture will be copied over as a buffer so that the texture row
// pitch can be explicitly managed.
// Copy the intermediate render target into the shared buffer using the
// memory layout prescribed by the render target.
D3D12_RESOURCE_DESC renderTargetDesc = m_renderTargets[adapter][m_frameIndex]->GetDesc();
D3D12_PLACED_SUBRESOURCE_FOOTPRINT renderTargetLayout;
m_devices[adapter]->GetCopyableFootprints(&renderTargetDesc, 0, 1, 0, &renderTargetLayout, nullptr, nullptr, nullptr);
CD3DX12_TEXTURE_COPY_LOCATION dest(m_crossAdapterResources[adapter][m_frameIndex].Get(), renderTargetLayout);
CD3DX12_TEXTURE_COPY_LOCATION src(m_renderTargets[adapter][m_frameIndex].Get(), 0);
CD3DX12_BOX box(0, 0, m_width, m_height);
m_copyCommandList->CopyTextureRegion(&dest, 0, 0, 0, &src, &box);
}
ThrowIfFailed(m_copyCommandList->Close());
}
バッファーからタイルリソースへ、またはその逆方向にタイルをコピーします。(ID3D12GraphicsCommandList.CopyTiles)
| pTiledResource | ID3D12Resource* | in | タイルリソースへのポインターです。 |
| pTileRegionStartCoordinate | D3D12_TILED_RESOURCE_COORDINATE* | in | タイルリソースの開始座標を記述する D3D12_TILED_RESOURCE_COORDINATE 構造体へのポインターです。 |
| pTileRegionSize | D3D12_TILE_REGION_SIZE* | in | タイル領域のサイズを記述する D3D12_TILE_REGION_SIZE 構造体へのポインターです。 |
| pBuffer | ID3D12Resource* | in | デフォルト、ダイナミック、またはステージングのバッファーを表す ID3D12Resource へのポインターです。 |
| BufferStartOffsetInBytes | ULONGLONG | in | 処理を開始する、pBuffer のバッファー内のオフセット (バイト単位) です。 |
| Flags | D3D12_TILE_COPY_FLAGS | in | タイルをどのようにコピーするかを指定する、ビット単位の OR 演算で組み合わせた D3D12_TILE_COPY_FLAGS 型の値の組み合わせです。 |
解説(Remarks)
CopyTiles は、マップされていない領域への書き込み操作を破棄し、マップされていない領域からの読み取り操作を処理します (ただし Tier_1 のタイルリソースでは、マップされていない領域の読み書きは無効です。D3D12_TILED_RESOURCES_TIER を参照してください)。
コピー先リソース内の複数の位置が同じタイルメモリにマップされているために、同じメモリ位置へ複数回書き込むコピー操作となる場合、 多重マップされたタイルへの書き込み結果は非決定的かつ再現性がありません。すなわち、タイルメモリへのアクセスは、ハードウェアがコピー操作を実行する順序に依存します。
コピー操作の対象となるタイルには、パックされたミップマップを含むタイルを含めることはできません。含めた場合、コピー操作の結果は未定義です。 ハードウェアが 1 つ以上のタイルにパックしたミップマップとの間でデータを転送するには、 CopyTextureRegion のような標準の (すなわちタイル専用でない) コピー API を使用する必要があります。
CopyTiles は、標準のコピーメソッドとは少し異なるパターンでデータをコピーします。
コピー操作のうち非タイルバッファーリソース側のタイルのメモリレイアウトは、64 KB のタイル内でメモリ上リニアになっており、タイルリソースとの間で転送する際に、ハードウェアとドライバーがタイルごとに適宜スウィズル・デスウィズルします。マルチサンプルアンチエイリアシング (MSAA) サーフェスの場合、ハードウェアとドライバーは各ピクセルのサンプルをサンプルインデックス順にたどってから次のピクセルへ進みます。右端で部分的にしか埋まらないタイル (幅がタイル幅 (ピクセル単位) の倍数でないサーフェスの場合) では、1 行下へ移動するためのピッチおよびストライドは、タイルが完全に埋まっている場合にタイルの横方向に収まるピクセル数分のバイトサイズ全体になります。したがって、メモリ上でピクセルの各行の間に隙間が生じることがあります。タイルより小さいミップマップは、このリニアレイアウトでは互いにパックされません。メモリ領域の無駄に見えるかもしれませんが、前述のとおり、ハードウェアがパックするミップマップへのコピーに CopyTiles を使用することはできません。小さなミップマップを個別にコピーするには、CopyTextureRegion のような汎用のコピー API を使用してください。
マルチサンプルリソースを非マルチサンプルリソースへコピーします。
| pDstResource | ID3D12Resource* | in | コピー先リソースです。D3D12_HEAP_TYPE_DEFAULT ヒープ上に作成され、かつシングルサンプルである必要があります。ID3D12Resource を参照してください。 |
| DstSubresource | DWORD | in | コピー先のサブリソースを識別する 0 から始まるインデックスです。親リソースが複雑な構成の場合は、D3D12CalcSubresource を使用してサブリソースインデックスを計算してください。 |
| pSrcResource | ID3D12Resource* | in | コピー元リソースです。マルチサンプルである必要があります。 |
| SrcSubresource | DWORD | in | コピー元リソースのうち、対象となるサブリソースです。 |
| Format | DXGI_FORMAT | in | マルチサンプルリソースをシングルサンプルリソースへどのように解決するかを示す DXGI_FORMAT です。解説を参照してください。 |
解説(Remarks)
デバッグレイヤー
コピー元ビューが参照するサブリソースが D3D12_RESOURCE_STATE_RESOLVE_SOURCE 状態でない場合、デバッグレイヤーはエラーを発行します。コピー先バッファーが D3D12_RESOURCE_STATE_RESOLVE_DEST 状態でない場合、デバッグレイヤーはエラーを発行します。
コピー元とコピー先のリソースは同じリソース型であり、同じ寸法を持つ必要があります。さらに、互換性のある形式である必要があります。これには次の 3 つのケースがあります。
| ケース | 要件 |
|---|---|
| コピー元とコピー先の両方が構造化済みかつ型付き | コピー元とコピー先の形式が同一であり、その形式を Format パラメーターに指定する必要があります。 |
| 一方が構造化済みかつ型付きで、もう一方が構造化済みかつ型なし | 型付きリソースは、型なしリソースと互換性のある形式である必要があります (たとえば型付きリソースが DXGI_FORMAT_R32_FLOAT で、型なしリソースが DXGI_FORMAT_R32_TYPELESS の場合)。型付きリソースの形式を Format パラメーターに指定する必要があります。 |
| コピー元とコピー先の両方が構造化済みかつ型なし | コピー元とコピー先が同じ型なし形式である必要があり (たとえば両方が DXGI_FORMAT_R32_TYPELESS)、Format パラメーターにはコピー元およびコピー先と互換性のある形式を指定する必要があります (たとえば両方が DXGI_FORMAT_R32_TYPELESS の場合、Format パラメーターには DXGI_FORMAT_R32_FLOAT を指定できます)。
たとえば、DXGI_FORMAT_R16G16B16A16_TYPELESS 形式の場合は次のようになります。
|
入力アセンブラーステージへの入力データを記述する、プリミティブの種類とデータの順序に関する情報をバインドします。(ID3D12GraphicsCommandList.IASetPrimitiveTopology)
| PrimitiveTopology | D3D_PRIMITIVE_TOPOLOGY | in | プリミティブの種類とプリミティブデータの順序です (D3D_PRIMITIVE_TOPOLOGY を参照)。 |
ビューポートの配列をパイプラインのラスタライザーステージにバインドします。(ID3D12GraphicsCommandList.RSSetViewports)
| NumViewports | DWORD | in | バインドするビューポートの数です。 有効な値の範囲は (0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) です。 |
| pViewports | D3D12_VIEWPORT* | in | デバイスにバインドする D3D12_VIEWPORT 構造体の配列です。 |
解説(Remarks)
すべてのビューポートは、1 つの操作としてアトミックに設定する必要があります。呼び出しで定義されなかったビューポートは無効になります。
どのビューポートを使用するかは、ジオメトリシェーダーが出力する SV_ViewportArrayIndex セマンティクスによって決まります。ジオメトリシェーダーがこのセマンティクスを指定しない場合、Direct3D は配列内の最初のビューポートを使用します。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::RSSetViewports を次のように使用しています。
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 リファレンスのサンプルコード を参照してください。
シザー矩形の配列をラスタライザーステージにバインドします。
| NumRects | DWORD | in | バインドするシザー矩形の数です。 |
| pRects | RECT* | in | シザー矩形の配列です。 |
解説(Remarks)
すべてのシザー矩形は、1 つの操作としてアトミックに設定する必要があります。呼び出しで定義されなかったシザー矩形は無効になります。
どのシザー矩形を使用するかは、ジオメトリシェーダーが出力する SV_ViewportArrayIndex セマンティクスによって決まります (シェーダーセマンティクスの構文を参照)。ジオメトリシェーダーが SV_ViewportArrayIndex セマンティクスを使用しない場合、Direct3D は配列内の最初のシザー矩形を使用します。
配列内の各シザー矩形は、ビューポート配列内のビューポートに対応します (RSSetViewports を参照)。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::RSSetScissorRects を次のように使用しています。
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;
// 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 リファレンスのサンプルコード を参照してください。
ピクセルシェーダー、レンダーターゲット、またはその両方の値を変調するブレンドファクターを設定します。
| BlendFactor | FLOAT* | inoptional | RGBA の各コンポーネントに 1 つずつ対応するブレンドファクターの配列です。 |
解説(Remarks)
ブレンドステートオブジェクトを D3D12_BLEND_BLEND_FACTOR または D3D12_BLEND_INV_BLEND_FACTOR で作成した場合、ブレンドステージは NULL でないブレンドファクターの配列を使用します。それ以外の場合、ブレンドステージは NULL でないブレンドファクターの配列を使用せず、ランタイムがブレンドファクターを保持します。
NULL を渡した場合、ランタイムは { 1, 1, 1, 1 } に等しいブレンドファクターを使用または保持します。
深度ステンシルテストの参照値を設定します。
| StencilRef | DWORD | in | 深度ステンシルテストを行う際に比較対象とする参照値です。 |
すべてのシェーダーを設定し、グラフィックスプロセッシングユニット (GPU) パイプラインの固定機能ステートの大部分をプログラムします。
| pPipelineState | ID3D12PipelineState* | in | パイプラインステートのデータを保持する ID3D12PipelineState へのポインターです。 |
リソースへの複数のアクセスを同期する必要があることをドライバーに通知します。(ID3D12GraphicsCommandList.ResourceBarrier)
| NumBarriers | DWORD | in | 送信するバリア記述の数です。 |
| pBarriers | D3D12_RESOURCE_BARRIER* | in | バリア記述の配列へのポインターです。 |
解説(Remarks)
D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE 状態で使用するリソースは、その状態で作成する必要があり、その後その状態から遷移させてはなりません。また、その状態で作成されなかったリソースをその状態へ遷移させることもできません。詳細については、GitHub 上の DirectX レイトレーシング (DXR) 機能仕様の Acceleration structure memory restrictions を参照してください。
バリア記述には次の 3 種類があります。
- D3D12_RESOURCE_TRANSITION_BARRIER - 遷移バリアは、一連のサブリソースが異なる用途の間で遷移することを示します。呼び出し元は、サブリソースの 遷移前 と 遷移後 の用途を指定する必要があります。リソース内のすべてのサブリソースを同時に遷移させるには、D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES フラグを使用します。
- D3D12_RESOURCE_ALIASING_BARRIER - エイリアシングバリアは、同じヒープにマッピングされた 2 つの異なるリソースの用途間の遷移を示します。アプリケーションは遷移前と遷移後の両方のリソースを指定できます。なお、いずれか一方または両方のリソースを NULL にすることもできます (任意のタイルリソースがエイリアシングを引き起こしうることを示します)。
- D3D12_RESOURCE_UAV_BARRIER - アンオーダードアクセスビューバリアは、特定のリソースに対するすべての UAV アクセス (読み取りまたは書き込み) が、以降の UAV アクセス (読み取りまたは書き込み) の開始前に完了しなければならないことを示します。指定するリソースは NULL でも構いません。UAV の読み取りのみを行う 2 つの描画呼び出しやディスパッチ呼び出しの間に UAV バリアを挿入する必要はありません。また、同じ UAV へ書き込む 2 つの描画呼び出しやディスパッチ呼び出しであっても、UAV アクセスを任意の順序で実行しても安全であるとアプリケーションが分かっている場合は、UAV バリアを挿入する必要はありません。リソースは NULL にできます (任意の UAV アクセスがバリアを必要としうることを示します)。
サブリソースが取りうる用途の状態については、D3D12_RESOURCE_STATES 列挙型および Direct3D 12 におけるリソースバリアを使用したリソース状態の同期 のセクションを参照してください。
ID3D12GraphicsCommandList::DiscardResource を呼び出す際、リソース内のすべてのサブリソースは、レンダーターゲットの場合は RENDER_TARGET 状態、深度ステンシルリソースの場合は DEPTH_WRITE 状態になっている必要があります。
バックバッファーをプレゼントする際、そのバックバッファーは D3D12_RESOURCE_STATE_PRESENT 状態になっている必要があります。PRESENT 状態でないリソースに対して IDXGISwapChain1::Present1 が呼び出された場合、デバッグレイヤーの警告が発行されます。
リソースの用途を表すビットは、読み取り専用と読み書きの 2 つのカテゴリに分類されます。
次の用途ビットは読み取り専用です。
- 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
ある時点において、サブリソースはちょうど 1 つの状態にあります (一連のフラグによって決まります)。アプリケーションは、一連の ResourceBarrier 呼び出しを行う際に状態が整合するようにしなければなりません。言い換えると、連続する ResourceBarrier 呼び出しにおける遷移前と遷移後の状態は一致している必要があります。
リソース内のすべてのサブリソースを遷移させるには、アプリケーションはサブリソースインデックスに D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES を設定できます。これはすべてのサブリソースが変更されることを意味します。
パフォーマンス向上のため、アプリケーションは分割バリアを使用してください ( マルチエンジンの同期 を参照)。また、可能な限り複数の遷移を 1 回の呼び出しにまとめてください。
ランタイムによる検証
ランタイムは、バリアの種類の値が D3D12_RESOURCE_BARRIER_TYPE 列挙型の有効なメンバーであることを検証します。さらに、ランタイムは次の点を確認します。
- リソースポインターが NULL でないこと。
- サブリソースインデックスが有効であること。
- 遷移前と遷移後の状態が、リソースの D3D12_RESOURCE_BINDING_TIER および D3D12_RESOURCE_FLAGS フラグでサポートされていること。
- 状態マスクの予約ビットが設定されていないこと。
- 遷移前と遷移後の状態が異なること。
- 遷移前と遷移後の状態のビットの組み合わせが有効であること。
- D3D12_RESOURCE_STATE_RESOLVE_SOURCE ビットが設定されている場合、リソースのサンプル数が 1 より大きいこと。
- D3D12_RESOURCE_STATE_RESOLVE_DEST ビットが設定されている場合、リソースのサンプル数が 1 であること。
UAV バリアについては、リソースが NULL でない場合、そのリソースに D3D12_RESOURCE_STATE_UNORDERED_ACCESS バインドフラグが設定されていることをランタイムが検証します。
検証に失敗すると、ID3D12GraphicsCommandList::Close は E_INVALIDARG を返します。
デバッグレイヤー
デバッグレイヤーは、通常、ランタイムの検証に失敗する場合にエラーを発行します。- コマンドリスト内のサブリソースの遷移が、同一コマンドリスト内の以前の遷移と整合しない場合。
- リソースを正しい状態にするための ResourceBarrier を先に呼び出さずにリソースを使用した場合。
- リソースを読み取りと書き込みに同時に不正にバインドした場合。
- ResourceBarrier に渡された 遷移前 の状態が、以前の ResourceBarrier 呼び出しの 遷移後 の状態と一致しない場合 (エイリアシングの場合を含む)。
デバッグレイヤーは、次の場合に警告を発行します。
- D3D12 デバッグレイヤーが ID3D12GraphicsCommandList::ResourceBarrier に対して警告を発行するすべての場合。
- リソースに D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE 用途ビットが設定されている状態で、深度バッファーを読み取り専用でないモードで使用した場合。
例
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 リファレンスのサンプルコード を参照してください。
バンドルを実行します。
| pCommandList | ID3D12GraphicsCommandList* | in | 実行するバンドルを決定する ID3D12GraphicsCommandList を指定します。 |
解説(Remarks)
バンドルは、パイプラインステートオブジェクトとプリミティブトポロジを除き、ExecuteBundle を呼び出した親コマンドリストのすべてのステートを継承します。 バンドル内で設定されたステートはすべて、親コマンドリストのステートに影響します。 なお、ExecuteBundle はプレディケーション対象の操作ではありません。
ランタイムによる検証
ランタイムは、「呼び出される側」がバンドルであり、「呼び出す側」がダイレクトコマンドリストであることを検証します。また、バンドルがクローズされていることも検証します。この取り決めに違反した場合、ランタイムは呼び出しを黙って破棄します。 検証に失敗すると、Close は E_INVALIDARG を返します。デバッグレイヤー
デバッグレイヤーは、ランタイムが失敗するのと同じ場合に警告を発行します。 また、ExecuteCommandList の呼び出し時にプレディケートが設定されている場合にも警告を発行します。 さらに、コマンドリストが参照するリソースが破棄されていることを検出した場合はエラーを発行します。デバッグレイヤーは、コマンドリストに対して Close が呼び出されて以降、そのバンドルに関連付けられたコマンドアロケーターがリセットされていないことも検証します。この検証は ExecuteBundle の時点と、親コマンドリストがコマンドキュー上で実行される時点で行われます。
例
D3D12Bundles サンプルでは、ID3D12GraphicsCommandList::ExecuteBundle を次のように使用しています。
void D3D12Bundles::PopulateCommandList(FrameResource* pFrameResource)
{
// 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_pCurrentFrameResource->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_pCurrentFrameResource->m_commandAllocator.Get(), m_pipelineState1.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvHeap.Get(), m_samplerHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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(m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
if (UseBundles)
{
// Execute the prebuilt bundle.
m_commandList->ExecuteBundle(pFrameResource->m_bundle.Get());
}
else
{
// Populate a new command list.
pFrameResource->PopulateCommandList(m_commandList.Get(), m_pipelineState1.Get(), m_pipelineState2.Get(), m_currentFrameResourceIndex, m_numIndices, &m_indexBufferView,
&m_vertexBufferView, m_cbvSrvHeap.Get(), m_cbvSrvDescriptorSize, m_samplerHeap.Get(), m_rootSignature.Get());
}
// 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 リファレンスのサンプルコード を参照してください。
コマンドリストに関連付けられた、現在バインドされている記述子ヒープを変更します。
| NumDescriptorHeaps | DWORD | in | バインドする記述子ヒープの数です。 |
| ppDescriptorHeaps | ID3D12DescriptorHeap** | in | コマンドリストに設定するヒープを表す ID3D12DescriptorHeap オブジェクトの配列へのポインターです。 バインドできる記述子ヒープの種類は D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV と D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER のみです。 各種類につき一度に設定できる記述子ヒープは 1 つだけです。つまり、一度に設定できるヒープは最大 2 つ (サンプラー 1 つ、CBV/SRV/UAV 1 つ) です。 |
解説(Remarks)
SetDescriptorHeaps はバンドルに対しても呼び出せますが、バンドルの記述子ヒープは呼び出し元のコマンドリストの記述子ヒープと一致している必要があります。バンドルの制限の詳細については、コマンドリストとバンドルの作成および記録 を参照してください。
この呼び出しにより、以前に設定されたヒープはすべて解除されます。1 回の呼び出しで設定できるのは、シェーダーから参照可能な種類ごとに最大 1 つのヒープです。
記述子ヒープの変更は、一部のハードウェアではパイプラインのフラッシュを引き起こす可能性があります。そのため、バインドする記述子ヒープを頻繁に変更するのではなく、種類ごとにシェーダーから参照可能なヒープを 1 つ用意し、フレームごとに一度だけ設定することを推奨します。その代わりに、レンダリング中に必要に応じて ID3D12Device::CopyDescriptors や ID3D12Device::CopyDescriptorsSimple を使用して、シェーダーから参照できないヒープから、その単一のシェーダー参照可能ヒープへ必要な記述子をコピーしてください。
例
D3D12Bundles サンプルでは、ID3D12GraphicsCommandList::SetDescriptorHeaps を次のように使用しています。
void D3D12Bundles::PopulateCommandList(FrameResource* pFrameResource)
{
// 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_pCurrentFrameResource->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_pCurrentFrameResource->m_commandAllocator.Get(), m_pipelineState1.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvHeap.Get(), m_samplerHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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(m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
if (UseBundles)
{
// Execute the prebuilt bundle.
m_commandList->ExecuteBundle(pFrameResource->m_bundle.Get());
}
else
{
// Populate a new command list.
pFrameResource->PopulateCommandList(m_commandList.Get(), m_pipelineState1.Get(), m_pipelineState2.Get(), m_currentFrameResourceIndex, m_numIndices, &m_indexBufferView,
&m_vertexBufferView, m_cbvSrvHeap.Get(), m_cbvSrvDescriptorSize, m_samplerHeap.Get(), m_rootSignature.Get());
}
// 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 リファレンスのサンプルコード を参照してください。
コンピュート用ルートシグネチャのレイアウトを設定します。
| pRootSignature | ID3D12RootSignature* | inoptional | ID3D12RootSignature オブジェクトへのポインターです。 |
グラフィックス用ルートシグネチャのレイアウトを設定します。
| pRootSignature | ID3D12RootSignature* | inoptional | ID3D12RootSignature オブジェクトへのポインターです。 |
コンピュート用ルートシグネチャに記述子テーブルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BaseDescriptor | D3D12_GPU_DESCRIPTOR_HANDLE | in | 設定する基準となる記述子の GPU 記述子ハンドルオブジェクトです。 |
グラフィックス用ルートシグネチャに記述子テーブルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BaseDescriptor | D3D12_GPU_DESCRIPTOR_HANDLE | in | 設定する基準となる記述子の GPU 記述子ハンドルオブジェクトです。 |
コンピュート用ルートシグネチャに定数を設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| SrcData | DWORD | in | 設定する定数のソースデータです。 |
| DestOffsetIn32BitValues | DWORD | in | ルートシグネチャ内で定数を設定する位置のオフセットです (32 ビット値単位)。 |
グラフィックス用ルートシグネチャに定数を設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| SrcData | DWORD | in | 設定する定数のソースデータです。 |
| DestOffsetIn32BitValues | DWORD | in | ルートシグネチャ内で定数を設定する位置のオフセットです (32 ビット値単位)。 |
コンピュート用ルートシグネチャに定数のグループを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| Num32BitValuesToSet | DWORD | in | ルートシグネチャに設定する定数の数です。 |
| pSrcData | void* | in | 設定する定数グループのソースデータです。 |
| DestOffsetIn32BitValues | DWORD | in | ルートシグネチャ内でグループの最初の定数を設定する位置のオフセットです (32 ビット値単位)。 |
グラフィックス用ルートシグネチャに定数のグループを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| Num32BitValuesToSet | DWORD | in | ルートシグネチャに設定する定数の数です。 |
| pSrcData | void* | in | 設定する定数グループのソースデータです。 |
| DestOffsetIn32BitValues | DWORD | in | ルートシグネチャ内でグループの最初の定数を設定する位置のオフセットです (32 ビット値単位)。 |
コンピュート用ルートシグネチャに、定数バッファーの CPU 記述子ハンドルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BufferLocation | ULONGLONG | in | 定数バッファーの D3D12_GPU_VIRTUAL_ADDRESS を指定します。 |
グラフィックス用ルートシグネチャに、定数バッファーの CPU 記述子ハンドルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BufferLocation | ULONGLONG | in | 定数バッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。 |
コンピュート用ルートシグネチャに、シェーダーリソースの CPU 記述子ハンドルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BufferLocation | ULONGLONG | in | バッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。 |
グラフィックス用ルートシグネチャに、シェーダーリソースの CPU 記述子ハンドルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BufferLocation | ULONGLONG | in | バッファーの GPU 仮想アドレスです。 テクスチャはサポートされません。D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。 |
コンピュート用ルートシグネチャに、アンオーダードアクセスビューのリソースの CPU 記述子ハンドルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BufferLocation | ULONGLONG | in | バッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。 |
グラフィックス用ルートシグネチャに、アンオーダードアクセスビューのリソースの CPU 記述子ハンドルを設定します。
| RootParameterIndex | DWORD | in | バインドするスロット番号です。 |
| BufferLocation | ULONGLONG | in | バッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。 |
インデックスバッファーのビューを設定します。
| pView | D3D12_INDEX_BUFFER_VIEW* | inoptional | このビューは、D3D12_INDEX_BUFFER_VIEW 構造体へのポインターとして、インデックスバッファーのアドレス、サイズ、DXGI_FORMAT を指定します。 |
解説(Remarks)
グラフィックスパイプラインに同時にバインドできるインデックスバッファーは 1 つだけです。
例
D3D12Bundles サンプルでは、ID3D12GraphicsCommandList::IASetIndexBuffer を次のように使用しています。
void FrameResource::PopulateCommandList(ID3D12GraphicsCommandList* pCommandList, ID3D12PipelineState* pPso1, ID3D12PipelineState* pPso2,
UINT frameResourceIndex, UINT numIndices, D3D12_INDEX_BUFFER_VIEW* pIndexBufferViewDesc, D3D12_VERTEX_BUFFER_VIEW* pVertexBufferViewDesc,
ID3D12DescriptorHeap* pCbvSrvDescriptorHeap, UINT cbvSrvDescriptorSize, ID3D12DescriptorHeap* pSamplerDescriptorHeap, ID3D12RootSignature* pRootSignature)
{
// If the root signature matches the root signature of the caller, then
// bindings are inherited, otherwise the bind space is reset.
pCommandList->SetGraphicsRootSignature(pRootSignature);
ID3D12DescriptorHeap* ppHeaps[] = { pCbvSrvDescriptorHeap, pSamplerDescriptorHeap };
pCommandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
pCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
pCommandList->IASetIndexBuffer(pIndexBufferViewDesc);
pCommandList->IASetVertexBuffers(0, 1, pVertexBufferViewDesc);
pCommandList->SetGraphicsRootDescriptorTable(0, pCbvSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
pCommandList->SetGraphicsRootDescriptorTable(1, pSamplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
// Calculate the descriptor offset due to multiple frame resources.
// 1 SRV + how many CBVs we have currently.
UINT frameResourceDescriptorOffset = 1 + (frameResourceIndex * m_cityRowCount * m_cityColumnCount);
CD3DX12_GPU_DESCRIPTOR_HANDLE cbvSrvHandle(pCbvSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), frameResourceDescriptorOffset, cbvSrvDescriptorSize);
BOOL usePso1 = TRUE;
for (UINT i = 0; i < m_cityRowCount; i++)
{
for (UINT j = 0; j < m_cityColumnCount; j++)
{
// Alternate which PSO to use; the pixel shader is different on
// each just as a PSO setting demonstration.
pCommandList->SetPipelineState(usePso1 ? pPso1 : pPso2);
usePso1 = !usePso1;
// Set this city's CBV table and move to the next descriptor.
pCommandList->SetGraphicsRootDescriptorTable(2, cbvSrvHandle);
cbvSrvHandle.Offset(cbvSrvDescriptorSize);
pCommandList->DrawIndexedInstanced(numIndices, 1, 0, 0, 0);
}
}
}
D3D12 リファレンスのサンプルコード を参照してください。
頂点バッファーの CPU 記述子ハンドルを設定します。
| StartSlot | DWORD | in | 頂点バッファーの設定を開始する、デバイスの 0 から始まる配列内のインデックスです。 |
| NumViews | DWORD | in | pViews 配列内のビューの数です。 |
| pViews | D3D12_VERTEX_BUFFER_VIEW* | inoptional | D3D12_VERTEX_BUFFER_VIEW 構造体の配列で頂点バッファービューを指定します。 |
ストリーム出力バッファーのビューを設定します。
| StartSlot | DWORD | in | ストリーム出力バッファーの設定を開始する、デバイスの 0 から始まる配列内のインデックスです。 |
| NumViews | DWORD | in | pViews 配列内のエントリの数です。 |
| pViews | D3D12_STREAM_OUTPUT_BUFFER_VIEW* | inoptional | D3D12_STREAM_OUTPUT_BUFFER_VIEW 構造体の配列を指定します。 |
レンダーターゲットおよび深度ステンシルの CPU 記述子ハンドルを設定します。
| NumRenderTargetDescriptors | DWORD | in | pRenderTargetDescriptors 配列内のエントリの数です (0 から D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT の範囲)。このパラメーターが 0 以外の場合、pRenderTargetDescriptors が指す配列のエントリ数は、このパラメーターの値と等しくなければなりません。 |
| pRenderTargetDescriptors | D3D12_CPU_DESCRIPTOR_HANDLE* | inoptional | レンダーターゲット記述子のヒープの先頭を表す CPU 記述子ハンドルを記述する D3D12_CPU_DESCRIPTOR_HANDLE 構造体の配列を指定します。このパラメーターが NULL で、かつ NumRenderTargetDescriptors が 0 の場合、レンダーターゲットはバインドされません。 |
| RTsSingleHandleToDescriptorRange | BOOL | in | True は、渡されたハンドルが NumRenderTargetDescriptors 個の記述子が連続して並ぶ範囲へのポインターであることを意味します。バインドする記述子の集合がもともとメモリ上で連続している場合に有用です (先頭の 1 つへのハンドルだけで済みます)。たとえば NumRenderTargetDescriptors が 3 の場合、メモリレイアウトは次のように解釈されます。
この場合、ドライバーはハンドルを参照解決し、そのポインターが指すメモリをインクリメントしていきます。
False は、そのハンドルが NumRenderTargetDescriptors 個のハンドルからなる配列の先頭であることを意味します。false の場合、アプリケーションは異なる場所にある記述子の集合を一度にバインドできます。同じく NumRenderTargetDescriptors が 3 の場合、メモリレイアウトは次のように解釈されます。
この場合、ドライバーはメモリ上で互いに隣接していることが期待される 3 つのハンドルを参照解決します。 |
| pDepthStencilDescriptor | D3D12_CPU_DESCRIPTOR_HANDLE* | inoptional | 深度ステンシル記述子を保持するヒープの先頭を表す CPU 記述子ハンドルを記述する D3D12_CPU_DESCRIPTOR_HANDLE 構造体へのポインターです。このパラメーターが NULL の場合、深度ステンシル記述子はバインドされません。 |
深度ステンシルリソースをクリアします。(ID3D12GraphicsCommandList.ClearDepthStencilView)
| DepthStencilView | D3D12_CPU_DESCRIPTOR_HANDLE | in | クリア対象の深度ステンシル用ヒープの先頭を表す CPU 記述子ハンドルを記述します。 |
| ClearFlags | D3D12_CLEAR_FLAGS | in | ビット単位の OR 演算で組み合わせた D3D12_CLEAR_FLAGS 値の組み合わせです。結果の値により、クリアするデータの種類 (深度バッファー、ステンシルバッファー、またはその両方) が決まります。 |
| Depth | FLOAT | in | 深度バッファーをクリアする際に使用する値です。この値は 0 から 1 の範囲にクランプされます。 |
| Stencil | BYTE | in | ステンシルバッファーをクリアする際に使用する値です。 |
| NumRects | DWORD | in | pRects パラメーターで指定する配列内の矩形の数です。 |
| pRects | RECT* | inoptional | リソースビュー内でクリアする矩形を表す D3D12_RECT 構造体の配列です。NULL の場合、ClearDepthStencilView はリソースビュー全体をクリアします。 |
解説(Remarks)
この操作をサポートするのは、ダイレクトコマンドリストとバンドルのみです。
ClearDepthStencilView は、同じヒープメモリをエイリアスするリソースの初期化に使用できます。詳細については CreatePlacedResource を参照してください。
ランタイムによる検証
浮動小数点の入力については、ランタイムは非正規化数の値を 0 に設定します (NaN は保持されます)。検証に失敗すると、Close の呼び出しは E_INVALIDARG を返します。
デバッグレイヤー
入力された色が非正規化数の場合、デバッグレイヤーはエラーを発行します。ビューが参照するサブリソースが適切な状態でない場合、デバッグレイヤーはエラーを発行します。 ClearDepthStencilView の場合、状態は D3D12_RESOURCE_STATE_DEPTH_WRITE でなければなりません。
例
D3D12Bundles サンプルでは、ID3D12GraphicsCommandList::ClearDepthStencilView を次のように使用しています。
// Pipeline objects.
D3D12_VIEWPORT m_viewport;
ComPtr<IDXGISwapChain3> m_swapChain;
ComPtr<ID3D12Device> m_device;
ComPtr<ID3D12Resource> m_renderTargets[FrameCount];
ComPtr<ID3D12Resource> m_depthStencil;
ComPtr<ID3D12CommandAllocator> m_commandAllocator;
ComPtr<ID3D12GraphicsCommandList> m_commandList;
ComPtr<ID3D12CommandQueue> m_commandQueue;
ComPtr<ID3D12RootSignature >m_rootSignature;
ComPtr<ID3D12DescriptorHeap> m_rtvHeap;
ComPtr<ID3D12DescriptorHeap> m_cbvSrvHeap;
ComPtr<ID3D12DescriptorHeap> m_dsvHeap;
ComPtr<ID3D12DescriptorHeap> m_samplerHeap;
ComPtr<ID3D12PipelineState> m_pipelineState1;
ComPtr<ID3D12PipelineState> m_pipelineState2;
D3D12_RECT m_scissorRect;
void D3D12Bundles::PopulateCommandList(FrameResource* pFrameResource)
{
// 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_pCurrentFrameResource->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_pCurrentFrameResource->m_commandAllocator.Get(), m_pipelineState1.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvSrvHeap.Get(), m_samplerHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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(m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
if (UseBundles)
{
// Execute the prebuilt bundle.
m_commandList->ExecuteBundle(pFrameResource->m_bundle.Get());
}
else
{
// Populate a new command list.
pFrameResource->PopulateCommandList(m_commandList.Get(), m_pipelineState1.Get(), m_pipelineState2.Get(), m_currentFrameResourceIndex, m_numIndices, &m_indexBufferView,
&m_vertexBufferView, m_cbvSrvHeap.Get(), m_cbvSrvDescriptorSize, m_samplerHeap.Get(), m_rootSignature.Get());
}
// 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());
}
D3D12Multithreading サンプルでは、ID3D12GraphicsCommandList::ClearDepthStencilView を次のように使用しています。
void FrameResource::Init()
{
// Reset the command allocators and lists for the main thread.
for (int i = 0; i < CommandListCount; i++)
{
ThrowIfFailed(m_commandAllocators[i]->Reset());
ThrowIfFailed(m_commandLists[i]->Reset(m_commandAllocators[i].Get(), m_pipelineState.Get()));
}
// Clear the depth stencil buffer in preparation for rendering the shadow map.
m_commandLists[CommandListPre]->ClearDepthStencilView(m_shadowDepthView, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
// Reset the worker command allocators and lists.
for (int i = 0; i < NumContexts; i++)
{
ThrowIfFailed(m_shadowCommandAllocators[i]->Reset());
ThrowIfFailed(m_shadowCommandLists[i]->Reset(m_shadowCommandAllocators[i].Get(), m_pipelineStateShadowMap.Get()));
ThrowIfFailed(m_sceneCommandAllocators[i]->Reset());
ThrowIfFailed(m_sceneCommandLists[i]->Reset(m_sceneCommandAllocators[i].Get(), m_pipelineState.Get()));
}
}
// Assemble the CommandListPre command list.
void D3D12Multithreading::BeginFrame()
{
m_pCurrentFrameResource->Init();
// Indicate that the back buffer will be used as a render target.
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
// Clear the render target and depth stencil.
const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ClearDepthStencilView(m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
ThrowIfFailed(m_pCurrentFrameResource->m_commandLists[CommandListPre]->Close());
}
// Assemble the CommandListMid command list.
void D3D12Multithreading::MidFrame()
{
// Transition our shadow map from the shadow pass to readable in the scene pass.
m_pCurrentFrameResource->SwapBarriers();
ThrowIfFailed(m_pCurrentFrameResource->m_commandLists[CommandListMid]->Close());
}
Direct3D 12 リファレンスのサンプルコード を参照してください。
レンダーターゲット内のすべての要素を 1 つの値に設定します。
| RenderTargetView | D3D12_CPU_DESCRIPTOR_HANDLE | in | クリア対象のレンダーターゲット用ヒープの先頭を表す CPU 記述子ハンドルを記述する D3D12_CPU_DESCRIPTOR_HANDLE 構造体を指定します。 |
| ColorRGBA | FLOAT* | in | レンダーターゲットを塗りつぶす色を表す 4 要素の配列です。 |
| NumRects | DWORD | in | pRects パラメーターで指定する配列内の矩形の数です。 |
| pRects | RECT* | inoptional | リソースビュー内でクリアする矩形を表す D3D12_RECT 構造体の配列です。NULL の場合、ClearRenderTargetView はリソースビュー全体をクリアします。 |
解説(Remarks)
ClearRenderTargetView は、同じヒープメモリをエイリアスするリソースの初期化に使用できます。詳細については CreatePlacedResource を参照してください。
ランタイムによる検証
浮動小数点の入力については、ランタイムは非正規化数の値を 0 に設定します (NaN は保持されます)。検証に失敗すると、Close の呼び出しは E_INVALIDARG を返します。
デバッグレイヤー
入力された色が非正規化数の場合、デバッグレイヤーはエラーを発行します。ビューが参照するサブリソースが適切な状態でない場合、デバッグレイヤーはエラーを発行します。 ClearRenderTargetView の場合、状態は D3D12_RESOURCE_STATE_RENDER_TARGET でなければなりません。
例
D3D12HelloTriangle サンプルでは、ID3D12GraphicsCommandList::ClearRenderTargetView を次のように使用しています。
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());
}
D3D12Multithreading サンプルでは、ID3D12GraphicsCommandList::ClearRenderTargetView を次のように使用しています。
// Frame resources.
FrameResource* m_frameResources[FrameCount];
FrameResource* m_pCurrentFrameResource;
int m_currentFrameResourceIndex;
// Assemble the CommandListPre command list.
void D3D12Multithreading::BeginFrame()
{
m_pCurrentFrameResource->Init();
// Indicate that the back buffer will be used as a render target.
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_renderTargets[m_frameIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
// Clear the render target and depth stencil.
const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
m_pCurrentFrameResource->m_commandLists[CommandListPre]->ClearDepthStencilView(m_dsvHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
ThrowIfFailed(m_pCurrentFrameResource->m_commandLists[CommandListPre]->Close());
}
// Assemble the CommandListMid command list.
void D3D12Multithreading::MidFrame()
{
// Transition our shadow map from the shadow pass to readable in the scene pass.
m_pCurrentFrameResource->SwapBarriers();
ThrowIfFailed(m_pCurrentFrameResource->m_commandLists[CommandListMid]->Close());
}
D3D12 リファレンスのサンプルコード を参照してください。
アンオーダードアクセスビュー (UAV) 内のすべての要素を、指定した整数値に設定します。
| ViewGPUHandleInCurrentHeap | D3D12_GPU_DESCRIPTOR_HANDLE | in | クリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する D3D12_GPU_DESCRIPTOR_HANDLE です。この記述子は、シェーダーから参照可能な記述子ヒープ内にある必要があり、そのヒープは SetDescriptorHeaps によってコマンドリストに設定されている必要があります。 |
| ViewCPUHandle | D3D12_CPU_DESCRIPTOR_HANDLE | in | クリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する、シェーダーから参照できない記述子ヒープ内の D3D12_CPU_DESCRIPTOR_HANDLE です。 重要
この記述子は、シェーダーから参照可能な記述子ヒープ内にあってはなりません。これは、クリアを (ディスパッチではなく) 固定機能のハードウェア操作として実装するドライバーが、記述子を効率よく読み取れるようにするためです。シェーダーから参照可能なヒープは WRITE_COMBINE メモリ (D3D12_HEAP_TYPE_UPLOAD ヒープ型と同様) に作成される場合があり、この種のメモリからの CPU 読み取りは非常に低速です。 |
| pResource | ID3D12Resource* | in | クリア対象のアンオーダードアクセスビュー (UAV) リソースを表す ID3D12Resource インターフェイスへのポインターです。 |
| Values | DWORD* | in | アンオーダードアクセスビューのリソースを埋める値を格納した 4 要素の配列です。 |
| NumRects | DWORD | in | pRects パラメーターで指定する配列内の矩形の数です。 |
| pRects | RECT* | in | リソースビュー内でクリアする矩形を表す D3D12_RECT 構造体の配列です。NULL の場合、ClearUnorderedAccessViewUint はリソースビュー全体をクリアします。 |
解説(Remarks)
ランタイムによる検証
検証に失敗すると、ID3D12GraphicsCommandList::Close の呼び出しは E_INVALIDARG を返します。
デバッグレイヤー
入力値が正規化された範囲外の場合、デバッグレイヤーはエラーを発行します。
ビューが参照するサブリソースが適切な状態でない場合、デバッグレイヤーはエラーを発行します。ClearUnorderedAccessViewUint の場合、状態は D3D12_RESOURCE_STATE_UNORDERED_ACCESS でなければなりません。
アンオーダードアクセスビュー内のすべての要素を、指定した浮動小数点値に設定します。
| ViewGPUHandleInCurrentHeap | D3D12_GPU_DESCRIPTOR_HANDLE | in | クリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する D3D12_GPU_DESCRIPTOR_HANDLE です。この記述子は、シェーダーから参照可能な記述子ヒープ内にある必要があり、そのヒープは SetDescriptorHeaps によってコマンドリストに設定されている必要があります。 |
| ViewCPUHandle | D3D12_CPU_DESCRIPTOR_HANDLE | in | クリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する、シェーダーから参照できない記述子ヒープ内の D3D12_CPU_DESCRIPTOR_HANDLE です。 重要
この記述子は、シェーダーから参照可能な記述子ヒープ内にあってはなりません。これは、クリアを (ディスパッチではなく) 固定機能のハードウェア操作として実装するドライバーが、記述子を効率よく読み取れるようにするためです。シェーダーから参照可能なヒープは WRITE_COMBINE メモリ (D3D12_HEAP_TYPE_UPLOAD ヒープ型と同様) に作成される場合があり、この種のメモリからの CPU 読み取りは非常に低速です。 |
| pResource | ID3D12Resource* | in | クリア対象のアンオーダードアクセスビュー (UAV) リソースを表す ID3D12Resource インターフェイスへのポインターです。 |
| Values | FLOAT* | in | アンオーダードアクセスビューのリソースを埋める値を格納した 4 要素の配列です。 |
| NumRects | DWORD | in | pRects パラメーターで指定する配列内の矩形の数です。 |
| pRects | RECT* | in | リソースビュー内でクリアする矩形を表す D3D12_RECT 構造体の配列です。NULL の場合、ClearUnorderedAccessViewFloat はリソースビュー全体をクリアします。 |
解説(Remarks)
ランタイムによる検証
浮動小数点の入力については、ランタイムは非正規化数の値を 0 に設定します (NaN は保持されます)。
特定のビットパターンで UAV をクリアしたい場合は、ID3D12GraphicsCommandList::ClearUnorderedAccessViewUint の使用を検討してください。
検証に失敗すると、ID3D12GraphicsCommandList::Close の呼び出しは E_INVALIDARG を返します。
デバッグレイヤー
入力値が正規化された範囲外の場合、デバッグレイヤーはエラーを発行します。
ビューが参照するサブリソースが適切な状態でない場合、デバッグレイヤーはエラーを発行します。ClearUnorderedAccessViewFloat の場合、状態は D3D12_RESOURCE_STATE_UNORDERED_ACCESS でなければなりません。
リソースを破棄します。
| pResource | ID3D12Resource* | in | 破棄するリソースの ID3D12Resource インターフェイスへのポインターです。 |
| pRegion | D3D12_DISCARD_REGION* | inoptional | リソース破棄操作の詳細を記述する D3D12_DISCARD_REGION 構造体へのポインターです。 |
解説(Remarks)
DiscardResource のセマンティクスは、コマンドリストの種類によって変わります。
D3D12_COMMAND_LIST_TYPE_DIRECT の場合、次の 2 つの規則が適用されます。
- リソースに D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET フラグが設定されている場合、破棄対象のサブリソース領域が D3D12_RESOURCE_STATE_RENDER_TARGET のリソースバリア状態にあるときに DiscardResource を呼び出す必要があります。
- リソースに D3D12_RESOURCE_FLAG _ALLOW_DEPTH_STENCIL フラグが設定されている場合、破棄対象のサブリソース領域が D3D12_RESOURCE_STATE_DEPTH_WRITE の状態にあるときに DiscardResource を呼び出す必要があります。
- リソースに D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS フラグが設定されている必要があり、破棄対象のサブリソース領域が D3D12_RESOURCE_STATE_UNORDERED_ACCESS のリソースバリア状態にあるときに DiscardResource を呼び出す必要があります。
クエリの実行を開始します。(ID3D12GraphicsCommandList.BeginQuery)
| pQueryHeap | ID3D12QueryHeap* | in | クエリを保持する ID3D12QueryHeap を指定します。 |
| Type | D3D12_QUERY_TYPE | in | D3D12_QUERY_TYPE のいずれかのメンバーを指定します。 |
| Index | DWORD | in | クエリヒープ内におけるクエリのインデックスを指定します。 |
解説(Remarks)
D3D12 のクエリの詳細については クエリ を参照してください。
例
D3D12PredicationQueries サンプルでは、 ID3D12GraphicsCommandList::BeginQuery を次のように使用しています。
// Fill the command list with all the render commands and dependent state.
void D3D12PredicationQueries::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_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_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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);
// 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_PREDICATION, 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_PREDICATION));
}
// 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 リファレンスのサンプルコード を参照してください。
実行中のクエリを終了します。
| pQueryHeap | ID3D12QueryHeap* | in | クエリを保持する ID3D12QueryHeap を指定します。 |
| Type | D3D12_QUERY_TYPE | in | D3D12_QUERY_TYPE のいずれかのメンバーを指定します。 |
| Index | DWORD | in | クエリヒープ内におけるクエリのインデックスを指定します。 |
解説(Remarks)
D3D12 のクエリの詳細については クエリ を参照してください。
例
D3D12PredicationQueries サンプルでは、ID3D12GraphicsCommandList::EndQuery を次のように使用しています。
// Fill the command list with all the render commands and dependent state.
void D3D12PredicationQueries::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_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_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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);
// 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_PREDICATION, 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_PREDICATION));
}
// 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 リファレンスのサンプルコード を参照してください。
クエリからデータを取り出します。ResolveQueryData はすべてのヒープ型 (デフォルト、アップロード、リードバック) で動作します。ResolveQueryData はすべてのヒープ型 (デフォルト、アップロード、リードバック) で動作します。
| pQueryHeap | ID3D12QueryHeap* | in | 解決対象のクエリを保持する ID3D12QueryHeap を指定します。 |
| Type | D3D12_QUERY_TYPE | in | クエリの種類を、D3D12_QUERY_TYPE のメンバーの 1 つとして指定します。 |
| StartIndex | DWORD | in | 解決する最初のクエリのインデックスを指定します。 |
| NumQueries | DWORD | in | 解決するクエリの数を指定します。 |
| pDestinationBuffer | ID3D12Resource* | in | コピー先バッファーとなる ID3D12Resource を指定します。このバッファーは D3D12_RESOURCE_STATE_COPY_DEST 状態でなければなりません。 |
| AlignedDestinationBufferOffset | ULONGLONG | in | コピー先バッファー内のアラインメントされたオフセットを指定します。 8 バイトの倍数でなければなりません。 |
解説(Remarks)
ResolveQueryData は、クエリデータをコピー先バッファーへ書き込むバッチ処理を実行します。クエリデータはコピー先バッファーへ連続して書き込まれます。
ResolveQueryData は、アプリケーションから内容が不透明なクエリヒープ内の、同じく不透明なクエリデータを、アプリケーションで利用できるアダプター非依存の値へ変換します。完了していないクエリ (ID3D12GraphicsCommandList::BeginQuery は呼び出されたが ID3D12GraphicsCommandList::EndQuery が呼び出されていないクエリ) や、未初期化のクエリをヒープ内で解決すると、動作は未定義となり、デバイスのハングや削除を引き起こす可能性があります。未完了または未初期化のクエリをアプリケーションが解決したことを検出した場合、デバッグレイヤーはエラーを発行します。
未完了または未初期化のクエリの解決が未定義動作であるのは、ドライバーが未解決のクエリ内部に GPU 仮想アドレスやその他のデータを内部的に格納している可能性があるためです。そのため、未初期化のデータに対してこれらのクエリを解決しようとすると、ページフォールトやデバイスのハングを引き起こす可能性があります。以前のバージョンのデバッグレイヤーは、この動作を検証していませんでした。
バイナリオクルージョンクエリは、クエリごとに 64 ビットを書き込みます。最下位ビットは 0 (オブジェクトが完全に遮蔽されていた) または 1 (オブジェクトの少なくとも 1 サンプルが描画されたはず) のいずれかです。残りのビットは 0 です。オクルージョンクエリは、クエリごとに 64 ビットを書き込みます。その値は、テストに合格したサンプル数です。タイムスタンプクエリは、クエリごとに 64 ビットを書き込みます。これはティック値であり、対応するコマンドキューの周波数と比較する必要があります (タイミング を参照)。
パイプライン統計クエリは、クエリごとに D3D12_QUERY_DATA_PIPELINE_STATISTICS 構造体を書き込みます。ストリーム出力統計クエリはすべて、クエリごとに D3D12_QUERY_DATA_SO_STATISTICS 構造体を書き込みます。
コアランタイムは次の点を検証します。
- StartIndex と NumQueries が範囲内であること。
- AlignedDestinationBufferOffset が 8 バイトの倍数であること。
- DestinationBuffer がバッファーであること。
- 書き込まれるデータが出力バッファーをオーバーフローしないこと。
- クエリの種類がコマンドリストの種類でサポートされていること。
- クエリの種類がクエリヒープでサポートされていること。
コピー先バッファーが D3D12_RESOURCE_STATE_COPY_DEST 状態でない場合、または解決対象のクエリのいずれかに対して ID3D12GraphicsCommandList::EndQuery が呼び出されていない場合、デバッグレイヤーは警告を発行します。
例
D3D12PredicationQueries サンプルでは、ID3D12GraphicsCommandList::ResolveQueryData を次のように使用しています。
// Fill the command list with all the render commands and dependent state.
void D3D12PredicationQueries::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_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_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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);
// 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_PREDICATION, 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_PREDICATION));
}
// 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 リファレンスのサンプルコード を参照してください。
レンダリングプレディケートを設定します。
| pBuffer | ID3D12Resource* | inoptional | ID3D12Resource としてのバッファーです。D3D12_RESOURCE_STATE_PREDICATION または D3D21_RESOURCE_STATE_INDIRECT_ARGUMENT 状態でなければなりません (両者の値は同一で、分かりやすさのために別名として提供されています)。プレディケーションを無効にするには NULL を指定します。 |
| AlignedBufferOffset | ULONGLONG | in | アラインメントされたバッファーオフセット (UINT64) です。 |
| Operation | D3D12_PREDICATION_OP | in | D3D12_PREDICATION_OP_EQUAL_ZERO や D3D12_PREDICATION_OP_NOT_EQUAL_ZERO などの D3D12_PREDICATION_OP を指定します。 |
解説(Remarks)
このメソッドを使用すると、プレディケートの結果データが指定した演算と一致する場合に、以降のレンダリングおよびリソース操作コマンドを実際には実行しないよう指定できます。
Direct3D 11 とは異なり、Direct3D 12 ではプレディケーションの状態はダイレクトコマンドリストに継承されず、プレディケーションは常に尊重されます (プレディケーションのヒントは存在しません)。 すべてのダイレクトコマンドリストは、プレディケーションが無効な状態で開始されます。 一方、バンドルはプレディケーションの状態を継承します。 同じプレディケートを複数回バインドすることは正当です。
不正な API 呼び出しを行うと、Close がエラーを返すか、 ID3D12CommandQueue::ExecuteCommandLists がコマンドリストを破棄してデバイスを削除します。
ランタイムの検証に失敗した場合、デバッグレイヤーはエラーを発行します。
詳細については プレディケーション を参照してください。
例
D3D12PredicationQueries サンプルでは、ID3D12GraphicsCommandList::SetPredication を次のように使用しています。
// Fill the command list with all the render commands and dependent state.
void D3D12PredicationQueries::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_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_commandList->Reset(m_commandAllocators[m_frameIndex].Get(), m_pipelineState.Get()));
// Set necessary state.
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
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);
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);
// 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_PREDICATION, 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_PREDICATION));
}
// 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 リファレンスのサンプルコード を参照してください。
直接呼び出すことは意図されていません。コマンドリストにイベントを挿入するには PIX イベントランタイムを使用してください。(ID3D12GraphicsCommandList.SetMarker)
| Metadata | DWORD | in | 内部用です。 |
| pData | void* | inoptional | 内部用です。 |
| Size | DWORD | in | 内部用です。 |
解説(Remarks)
これは PIX イベントランタイムが内部的に使用するサポート用メソッドです。直接呼び出すことは意図されていません。
D3D12 コマンドリスト内の現在位置に計測用マーカーを挿入するには、PIXSetMarker 関数を使用してください。これは WinPixEventRuntime NuGet パッケージで提供されています。
直接呼び出すことは意図されていません。コマンドリストにイベントを挿入するには PIX イベントランタイムを使用してください。(ID3D12GraphicsCommandList.BeginEvent)
| Metadata | DWORD | in | 内部用です。 |
| pData | void* | inoptional | 内部用です。 |
| Size | DWORD | in | 内部用です。 |
解説(Remarks)
これは PIX イベントランタイムが内部的に使用するサポート用メソッドです。直接呼び出すことは意図されていません。
D3D12 コマンドリスト内の現在位置で計測領域の開始を示すには、PIXBeginEvent 関数または PIXScopedEvent マクロを使用してください。これらは WinPixEventRuntime NuGet パッケージで提供されています。
直接呼び出すことは意図されていません。コマンドリストにイベントを挿入するには PIX イベントランタイムを使用してください。(ID3D12GraphicsCommandList.EndEvent)
解説(Remarks)
これは PIX イベントランタイムが内部的に使用するサポート用メソッドです。直接呼び出すことは意図されていません。
D3D12 コマンドリスト内の現在位置で計測領域の終了を示すには、PIXEndEvent 関数または PIXScopedEvent マクロを使用してください。これらは WinPixEventRuntime NuGet パッケージで提供されています。
アプリケーションは、ExecuteIndirect メソッドを使用して間接描画・間接ディスパッチを実行します。
| pCommandSignature | ID3D12CommandSignature* | in | ID3D12CommandSignature を指定します。pArgumentBuffer が参照するデータは、コマンドシグネチャの内容に応じて解釈されます。コマンドシグネチャの作成に使用する API については 間接描画 を参照してください。 |
| MaxCommandCount | DWORD | in | コマンド数の指定方法には次の 2 通りがあります。
|
| pArgumentBuffer | ID3D12Resource* | in | コマンド引数を格納した 1 つ以上の ID3D12Resource オブジェクトを指定します。 |
| ArgumentBufferOffset | ULONGLONG | in | 最初のコマンド引数を特定するための、pArgumentBuffer 内のオフセットを指定します。 |
| pCountBuffer | ID3D12Resource* | inoptional | ID3D12Resource へのポインターを指定します。 |
| CountBufferOffset | ULONGLONG | in | 引数の個数を特定するための、pCountBuffer 内のオフセットを表す UINT64 を指定します。 |
解説(Remarks)
この API のセマンティクスは、次の擬似コードで定義されます。
pCountBuffer が NULL でない場合:
// 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();
}
pCountBuffer が NULL の場合:
// 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();
}
カウントバッファーまたは引数バッファーのいずれかが D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT 状態でない場合、デバッグレイヤーはエラーを発行します。コアランタイムは次の点を検証します。
- CountBufferOffset と ArgumentBufferOffset が 4 バイト境界にアラインメントされていること。
- pCountBuffer と pArgumentBuffer がバッファーリソースであること (ヒープの種類は問いません)。
- MaxCommandCount、ArgumentBufferOffset、および描画プログラムのストライドから導かれるオフセットが、pArgumentBuffer の範囲を超えないこと (カウントバッファーについても同様)。
- コマンドリストがダイレクトコマンドリストまたはコンピュートコマンドリストであること (コピーコマンドリストや JPEG デコードコマンドリストではないこと)。
- コマンドリストのルートシグネチャが、コマンドシグネチャのルートシグネチャと一致すること。
DrawInstancedIndirect と DrawIndexedInstancedIndirect の機能は、ExecuteIndirect に包含されています。
バンドル
ID3D12GraphicsCommandList::ExecuteIndirect をバンドルのコマンドリスト内で使用できるのは、次の条件がすべて満たされる場合のみです。- CountBuffer が NULL であること (CPU 側で指定したカウントのみ)。
- コマンドシグネチャに含まれる操作がちょうど 1 つであること。これは、コマンドシグネチャにルート引数の変更や VB/IB のバインド変更が含まれないことを意味します。
バッファーの仮想アドレスの取得
ID3D12Resource::GetGPUVirtualAddress メソッドを使用すると、アプリケーションはバッファーの GPU 仮想アドレスを取得できます。アプリケーションは、間接引数バッファーに仮想アドレスを格納する前に、任意のバイトオフセットを適用しても構いません。ただし、その結果得られる GPU 仮想アドレスにも、VB/IB/CB に関する D3D12 のアラインメント要件がすべて適用される点に注意してください。
例
D3D12ExecuteIndirect サンプルでは、ID3D12GraphicsCommandList::ExecuteIndirect を次のように使用しています。
// Data structure to match the command signature used for ExecuteIndirect.
struct IndirectCommand
{
D3D12_GPU_VIRTUAL_ADDRESS cbv;
D3D12_DRAW_ARGUMENTS drawArguments;
};
ExecuteIndirect の呼び出しは、このコードの末尾近く、コメント「Draw the triangles that have not been culled.」の下にあります。
// 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());
}
}
D3D12 リファレンスのサンプルコード を参照してください。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_ID3D12GraphicsCommandList "{5B160D0F-AC1B-4185-8BA8-B3AE42A5A455}" #usecom global ID3D12GraphicsCommandList IID_ID3D12GraphicsCommandList "{}" #comfunc global ID3D12GraphicsCommandList_Close 9 #comfunc global ID3D12GraphicsCommandList_Reset 10 sptr,sptr #comfunc global ID3D12GraphicsCommandList_ClearState 11 sptr #comfunc global ID3D12GraphicsCommandList_DrawInstanced 12 int,int,int,int #comfunc global ID3D12GraphicsCommandList_DrawIndexedInstanced 13 int,int,int,int,int #comfunc global ID3D12GraphicsCommandList_Dispatch 14 int,int,int #comfunc global ID3D12GraphicsCommandList_CopyBufferRegion 15 sptr,int64,sptr,int64,int64 #comfunc global ID3D12GraphicsCommandList_CopyTextureRegion 16 var,int,int,int,var,var #comfunc global ID3D12GraphicsCommandList_CopyResource 17 sptr,sptr #comfunc global ID3D12GraphicsCommandList_CopyTiles 18 sptr,var,var,sptr,int64,int #comfunc global ID3D12GraphicsCommandList_ResolveSubresource 19 sptr,int,sptr,int,int #comfunc global ID3D12GraphicsCommandList_IASetPrimitiveTopology 20 int #comfunc global ID3D12GraphicsCommandList_RSSetViewports 21 int,var #comfunc global ID3D12GraphicsCommandList_RSSetScissorRects 22 int,var #comfunc global ID3D12GraphicsCommandList_OMSetBlendFactor 23 var #comfunc global ID3D12GraphicsCommandList_OMSetStencilRef 24 int #comfunc global ID3D12GraphicsCommandList_SetPipelineState 25 sptr #comfunc global ID3D12GraphicsCommandList_ResourceBarrier 26 int,var #comfunc global ID3D12GraphicsCommandList_ExecuteBundle 27 sptr #comfunc global ID3D12GraphicsCommandList_SetDescriptorHeaps 28 int,sptr #comfunc global ID3D12GraphicsCommandList_SetComputeRootSignature 29 sptr #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootSignature 30 sptr #comfunc global ID3D12GraphicsCommandList_SetComputeRootDescriptorTable 31 int,int #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable 32 int,int #comfunc global ID3D12GraphicsCommandList_SetComputeRoot32BitConstant 33 int,int,int #comfunc global ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant 34 int,int,int #comfunc global ID3D12GraphicsCommandList_SetComputeRoot32BitConstants 35 int,int,sptr,int #comfunc global ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants 36 int,int,sptr,int #comfunc global ID3D12GraphicsCommandList_SetComputeRootConstantBufferView 37 int,int64 #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView 38 int,int64 #comfunc global ID3D12GraphicsCommandList_SetComputeRootShaderResourceView 39 int,int64 #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView 40 int,int64 #comfunc global ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView 41 int,int64 #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootUnorderedAccessView 42 int,int64 #comfunc global ID3D12GraphicsCommandList_IASetIndexBuffer 43 var #comfunc global ID3D12GraphicsCommandList_IASetVertexBuffers 44 int,int,var #comfunc global ID3D12GraphicsCommandList_SOSetTargets 45 int,int,var #comfunc global ID3D12GraphicsCommandList_OMSetRenderTargets 46 int,var,int,var #comfunc global ID3D12GraphicsCommandList_ClearDepthStencilView 47 int,int,float,int,int,var #comfunc global ID3D12GraphicsCommandList_ClearRenderTargetView 48 int,var,int,var #comfunc global ID3D12GraphicsCommandList_ClearUnorderedAccessViewUint 49 int,int,sptr,var,int,var #comfunc global ID3D12GraphicsCommandList_ClearUnorderedAccessViewFloat 50 int,int,sptr,var,int,var #comfunc global ID3D12GraphicsCommandList_DiscardResource 51 sptr,var #comfunc global ID3D12GraphicsCommandList_BeginQuery 52 sptr,int,int #comfunc global ID3D12GraphicsCommandList_EndQuery 53 sptr,int,int #comfunc global ID3D12GraphicsCommandList_ResolveQueryData 54 sptr,int,int,int,sptr,int64 #comfunc global ID3D12GraphicsCommandList_SetPredication 55 sptr,int64,int #comfunc global ID3D12GraphicsCommandList_SetMarker 56 int,sptr,int #comfunc global ID3D12GraphicsCommandList_BeginEvent 57 int,sptr,int #comfunc global ID3D12GraphicsCommandList_EndEvent 58 #comfunc global ID3D12GraphicsCommandList_ExecuteIndirect 59 sptr,int,sptr,int64,sptr,int64 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。#define global IID_ID3D12GraphicsCommandList "{5B160D0F-AC1B-4185-8BA8-B3AE42A5A455}" #usecom global ID3D12GraphicsCommandList IID_ID3D12GraphicsCommandList "{}" #comfunc global ID3D12GraphicsCommandList_Close 9 #comfunc global ID3D12GraphicsCommandList_Reset 10 sptr,sptr #comfunc global ID3D12GraphicsCommandList_ClearState 11 sptr #comfunc global ID3D12GraphicsCommandList_DrawInstanced 12 int,int,int,int #comfunc global ID3D12GraphicsCommandList_DrawIndexedInstanced 13 int,int,int,int,int #comfunc global ID3D12GraphicsCommandList_Dispatch 14 int,int,int #comfunc global ID3D12GraphicsCommandList_CopyBufferRegion 15 sptr,int64,sptr,int64,int64 #comfunc global ID3D12GraphicsCommandList_CopyTextureRegion 16 sptr,int,int,int,sptr,sptr #comfunc global ID3D12GraphicsCommandList_CopyResource 17 sptr,sptr #comfunc global ID3D12GraphicsCommandList_CopyTiles 18 sptr,sptr,sptr,sptr,int64,int #comfunc global ID3D12GraphicsCommandList_ResolveSubresource 19 sptr,int,sptr,int,int #comfunc global ID3D12GraphicsCommandList_IASetPrimitiveTopology 20 int #comfunc global ID3D12GraphicsCommandList_RSSetViewports 21 int,sptr #comfunc global ID3D12GraphicsCommandList_RSSetScissorRects 22 int,sptr #comfunc global ID3D12GraphicsCommandList_OMSetBlendFactor 23 sptr #comfunc global ID3D12GraphicsCommandList_OMSetStencilRef 24 int #comfunc global ID3D12GraphicsCommandList_SetPipelineState 25 sptr #comfunc global ID3D12GraphicsCommandList_ResourceBarrier 26 int,sptr #comfunc global ID3D12GraphicsCommandList_ExecuteBundle 27 sptr #comfunc global ID3D12GraphicsCommandList_SetDescriptorHeaps 28 int,sptr #comfunc global ID3D12GraphicsCommandList_SetComputeRootSignature 29 sptr #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootSignature 30 sptr #comfunc global ID3D12GraphicsCommandList_SetComputeRootDescriptorTable 31 int,int #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable 32 int,int #comfunc global ID3D12GraphicsCommandList_SetComputeRoot32BitConstant 33 int,int,int #comfunc global ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstant 34 int,int,int #comfunc global ID3D12GraphicsCommandList_SetComputeRoot32BitConstants 35 int,int,sptr,int #comfunc global ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants 36 int,int,sptr,int #comfunc global ID3D12GraphicsCommandList_SetComputeRootConstantBufferView 37 int,int64 #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView 38 int,int64 #comfunc global ID3D12GraphicsCommandList_SetComputeRootShaderResourceView 39 int,int64 #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootShaderResourceView 40 int,int64 #comfunc global ID3D12GraphicsCommandList_SetComputeRootUnorderedAccessView 41 int,int64 #comfunc global ID3D12GraphicsCommandList_SetGraphicsRootUnorderedAccessView 42 int,int64 #comfunc global ID3D12GraphicsCommandList_IASetIndexBuffer 43 sptr #comfunc global ID3D12GraphicsCommandList_IASetVertexBuffers 44 int,int,sptr #comfunc global ID3D12GraphicsCommandList_SOSetTargets 45 int,int,sptr #comfunc global ID3D12GraphicsCommandList_OMSetRenderTargets 46 int,sptr,int,sptr #comfunc global ID3D12GraphicsCommandList_ClearDepthStencilView 47 int,int,float,int,int,sptr #comfunc global ID3D12GraphicsCommandList_ClearRenderTargetView 48 int,sptr,int,sptr #comfunc global ID3D12GraphicsCommandList_ClearUnorderedAccessViewUint 49 int,int,sptr,sptr,int,sptr #comfunc global ID3D12GraphicsCommandList_ClearUnorderedAccessViewFloat 50 int,int,sptr,sptr,int,sptr #comfunc global ID3D12GraphicsCommandList_DiscardResource 51 sptr,sptr #comfunc global ID3D12GraphicsCommandList_BeginQuery 52 sptr,int,int #comfunc global ID3D12GraphicsCommandList_EndQuery 53 sptr,int,int #comfunc global ID3D12GraphicsCommandList_ResolveQueryData 54 sptr,int,int,int,sptr,int64 #comfunc global ID3D12GraphicsCommandList_SetPredication 55 sptr,int64,int #comfunc global ID3D12GraphicsCommandList_SetMarker 56 int,sptr,int #comfunc global ID3D12GraphicsCommandList_BeginEvent 57 int,sptr,int #comfunc global ID3D12GraphicsCommandList_EndEvent 58 #comfunc global ID3D12GraphicsCommandList_ExecuteIndirect 59 sptr,int,sptr,int64,sptr,int64 ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。
この場合、ドライバーはハンドルを参照解決し、そのポインターが指すメモリをインクリメントしていきます。
この場合、ドライバーはメモリ上で互いに隣接していることが期待される 3 つのハンドルを参照解決します。