Win32 API 日本語リファレンス
ホームGraphics.Direct3D12 › ID3D12GraphicsCommandList

ID3D12GraphicsCommandList

COM
IID5b160d0f-ac1b-4185-8ba8-b3ae42a5a455継承元ID3D12CommandList自前メソッド開始 vtbl9

公式ドキュメント

レンダリング用のグラフィックスコマンドのリストをカプセル化します。コマンドリストの実行を計測するための 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。

vtbl 9 HRESULT Close()

コマンドリストへの記録が完了したことを示します。(ID3D12GraphicsCommandList.Close)

戻り値

型: HRESULT

成功した場合は S_OK を返します。それ以外の場合は、次のいずれかの値を返します。

その他の戻り値については、Direct3D 12 のリターンコード を参照してください。

解説(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 リファレンスのサンプルコード を参照してください。

vtbl 10 HRESULT Reset(ID3D12CommandAllocator* pAllocator, ID3D12PipelineState* pInitialState)

コマンドリストを、新しく作成された直後と同じ初期状態にリセットします。(ID3D12GraphicsCommandList.Reset)

pAllocatorID3D12CommandAllocator*inデバイスがコマンドリストを作成する元となる ID3D12CommandAllocator オブジェクトへのポインターです。
pInitialStateID3D12PipelineState*inoptional

コマンドリストの初期パイプラインステートを保持する ID3D12PipelineState オブジェクトへのポインターです。これは省略可能で、NULL を指定できます。NULL の場合、ドライバーが未定義の状態を扱わずに済むよう、ランタイムがダミーの初期パイプラインステートを設定します。このオーバーヘッドは小さく、特にコマンドリストでは、コマンドリスト全体の記録コストが初期ステート設定 1 回分のコストを大きく上回るのが一般的です。したがって、初期パイプラインステートのパラメーターを設定するのが不都合であれば、設定しなくてもコストはほとんどありません。

一方、バンドルの場合は全体として小さく、頻繁に再利用される可能性が高いため、初期ステートのパラメーターを設定する方が合理的なことがあります。

戻り値

型: HRESULT

成功した場合は S_OK を返します。それ以外の場合は、次のいずれかの値を返します。

その他の戻り値については、Direct3D 12 のリターンコード を参照してください。

解説(Remarks)

Reset を使用すると、メモリ割り当てを行うことなくコマンドリストの追跡構造を再利用できます。ID3D12CommandAllocator::Reset とは異なり、ID3D12GraphicsCommandList::Reset はコマンドリストがまだ実行中であっても呼び出せます。

Reset は、ダイレクトコマンドリストとバンドルの両方に使用できます。

Reset に渡すコマンドアロケーターは、現在記録中の他のコマンドリストに関連付けられていてはなりません。アロケーターの種類 (ダイレクトコマンドリストまたはバンドル) は、作成するコマンドリストの種類と一致している必要があります。

バンドルがリソースヒープを指定しない場合、そのバンドルはバインドされる記述子テーブルを変更できません。いずれの場合も、バンドル内でリソースヒープを変更することはできません。バンドルにヒープを指定する場合、そのヒープは呼び出し元である「親」コマンドリストのヒープと一致している必要があります。

ランタイムによる検証

アプリが Reset を呼び出す前に、コマンドリストは「クローズ」状態になっている必要があります。コマンドリストが「クローズ」状態でない場合、Reset は失敗します。
メモ ID3D12GraphicsCommandList::Close の呼び出しが失敗した場合、そのコマンドリストは二度とリセットできません。Reset を呼び出すと、ID3D12GraphicsCommandList::Close が返したものと同じエラーが返されます。
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 リファレンスのサンプルコード を参照してください。

vtbl 11 void ClearState(ID3D12PipelineState* pPipelineState)

ダイレクトコマンドリストの状態を、そのコマンドリストが作成された時点の状態にリセットします。(ID3D12GraphicsCommandList.ClearState)

pPipelineStateID3D12PipelineState*inoptionalコマンドリストの初期パイプラインステートを保持する ID3D12PipelineState オブジェクトへのポインターです。

解説(Remarks)

バンドルに対して ClearState を呼び出すことは無効です。アプリがバンドルに対して ClearState を呼び出した場合、Close の呼び出しは E_FAIL を返します。

ClearState を呼び出すと、現在バインドされているすべてのリソースがアンバインドされます。プリミティブトポロジは D3D_PRIMITIVE_TOPOLOGY_UNDEFINED に設定されます。ビューポート、シザー矩形、ステンシル参照値、ブレンドファクターは空の値 (すべてゼロ) に設定されます。プレディケーションは無効になります。

アプリが指定したパイプラインステートオブジェクトが、現在設定されているパイプラインステートオブジェクトとしてバインドされます。

vtbl 12 void DrawInstanced(DWORD VertexCountPerInstance, DWORD InstanceCount, DWORD StartVertexLocation, DWORD StartInstanceLocation)

非インデックス付きのインスタンス化されたプリミティブを描画します。

VertexCountPerInstanceDWORDin描画する頂点の数です。
InstanceCountDWORDin描画するインスタンスの数です。
StartVertexLocationDWORDin最初の頂点のインデックスです。
StartInstanceLocationDWORDin頂点バッファーからインスタンスごとのデータを読み取る前に、各インデックスに加算される値です。

解説(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 リファレンスのサンプルコード を参照してください。

vtbl 13 void DrawIndexedInstanced(DWORD IndexCountPerInstance, DWORD InstanceCount, DWORD StartIndexLocation, INT BaseVertexLocation, DWORD StartInstanceLocation)

インデックス付きのインスタンス化されたプリミティブを描画します。

IndexCountPerInstanceDWORDinインスタンスごとにインデックスバッファーから読み取るインデックスの数です。
InstanceCountDWORDin描画するインスタンスの数です。
StartIndexLocationDWORDinGPU がインデックスバッファーから読み取る最初のインデックスの位置です。
BaseVertexLocationINTin頂点バッファーから頂点を読み取る前に、各インデックスに加算される値です。
StartInstanceLocationDWORDin頂点バッファーからインスタンスごとのデータを読み取る前に、各インデックスに加算される値です。

解説(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 リファレンスのサンプルコード を参照してください。

vtbl 14 void Dispatch(DWORD ThreadGroupCountX, DWORD ThreadGroupCountY, DWORD ThreadGroupCountZ)

スレッドグループ上でコンピュートシェーダーを実行します。

ThreadGroupCountXDWORDinx 方向にディスパッチされるグループの数です。ThreadGroupCountXD3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION (65535) 以下である必要があります。
ThreadGroupCountYDWORDiny 方向にディスパッチされるグループの数です。ThreadGroupCountYD3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION (65535) 以下である必要があります。
ThreadGroupCountZDWORDinz 方向にディスパッチされるグループの数です。ThreadGroupCountZD3D11_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 リファレンスのサンプルコード を参照してください。

vtbl 15 void CopyBufferRegion(ID3D12Resource* pDstBuffer, ULONGLONG DstOffset, ID3D12Resource* pSrcBuffer, ULONGLONG SrcOffset, ULONGLONG NumBytes)

バッファーの領域をあるリソースから別のリソースへコピーします。

pDstBufferID3D12Resource*inコピー先の ID3D12Resource を指定します。
DstOffsetULONGLONGinコピー先リソース内のオフセット (バイト単位、UINT64) を指定します。
pSrcBufferID3D12Resource*inコピー元の ID3D12Resource を指定します。
SrcOffsetULONGLONGinコピーを開始するコピー元リソース内のオフセット (バイト単位、UINT64) を指定します。
NumBytesULONGLONGinコピーするバイト数を指定します。

解説(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 リファレンスのサンプルコード を参照してください。

vtbl 16 void CopyTextureRegion(D3D12_TEXTURE_COPY_LOCATION* pDst, DWORD DstX, DWORD DstY, DWORD DstZ, D3D12_TEXTURE_COPY_LOCATION* pSrc, D3D12_BOX* pSrcBox)

このメソッドは、GPU を使用して 2 つの位置の間でテクスチャデータをコピーします。コピー元とコピー先はいずれも、バッファーリソース内またはテクスチャリソース内に配置されたテクスチャデータを参照できます。

pDstD3D12_TEXTURE_COPY_LOCATION*inコピー先の D3D12_TEXTURE_COPY_LOCATION を指定します。参照されるサブリソースは D3D12_RESOURCE_STATE_COPY_DEST 状態である必要があります。
DstXDWORDinコピー先領域の左上隅の x 座標です。
DstYDWORDinコピー先領域の左上隅の y 座標です。1D サブリソースの場合は 0 でなければなりません。
DstZDWORDinコピー先領域の左上隅の z 座標です。1D または 2D サブリソースの場合は 0 でなければなりません。
pSrcD3D12_TEXTURE_COPY_LOCATION*inコピー元の D3D12_TEXTURE_COPY_LOCATION を指定します。 参照されるサブリソースは D3D12_RESOURCE_STATE_COPY_SOURCE 状態である必要があります。
pSrcBoxD3D12_BOX*inoptionalコピーするコピー元テクスチャのサイズを指定する、省略可能な D3D12_BOX を指定します。

解説(Remarks)

コピー元のボックスは、コピー元リソースのサイズの範囲内でなければなりません。コピー先のオフセット (x、y、z) により、コピー先リソースへ書き込む際にコピー元ボックスをずらして配置できますが、コピー元ボックスの寸法とオフセットはリソースのサイズの範囲内である必要があります。コピー先リソースの外側へコピーしようとしたり、コピー元リソースより大きいコピー元ボックスを指定したりした場合、CopyTextureRegion の動作は未定義です。デバッグレイヤー をサポートするデバイスを作成している場合、この無効な CopyTextureRegion 呼び出しに対してデバッグ出力にエラーが報告されます。CopyTextureRegion に無効なパラメーターを渡すと動作が未定義となり、レンダリング結果の不正、クリッピング、コピーが行われない、さらにはレンダリングデバイスの削除といった結果を招く可能性があります。

リソースがバッファーの場合、すべての座標はバイト単位です。リソースがテクスチャの場合、すべての座標はテクセル単位です。

CopyTextureRegion は GPU 上でコピーを実行します (CPU による memcpy に相当します)。そのため、コピー元とコピー先のリソースは次の条件を満たす必要があります。

CopyTextureRegion はコピーのみをサポートし、拡大縮小、カラーキー、ブレンドはサポートしません。CopyTextureRegion は、いくつかの形式の型の間でリソースデータを再解釈できます。

なお、深度ステンシルバッファーでは、深度プレーンとステンシルプレーンはバッファー内の 別個のサブリソース です。

サブリソースの一部の領域ではなくリソース全体をコピーする場合は、代わりに CopyResource を使用することをお勧めします。

メモ 深度ステンシルバッファーまたはマルチサンプルリソースに対して CopyTextureRegion を使用する場合は、サブリソースの矩形全体をコピーする必要があります。この場合、DstXDstYDstZ の各パラメーターには 0 を、pSrcBox パラメーターには NULL を渡す必要があります。さらに、pSrcResource および pDstResource パラメーターで表されるコピー元とコピー先のリソースは、同一のサンプル数を持つ必要があります。
CopyTextureRegion は、同じヒープメモリをエイリアスするリソースの初期化に使用できます。詳細については CreatePlacedResource を参照してください。

次のコードスニペットは、コピー元テクスチャ内のボックス ((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 リファレンスのサンプルコード を参照してください。

vtbl 17 void CopyResource(ID3D12Resource* pDstResource, ID3D12Resource* pSrcResource)

コピー元リソースの内容全体をコピー先リソースへコピーします。

pDstResourceID3D12Resource*inコピー先リソースを表す ID3D12Resource インターフェイスへのポインターです。
pSrcResourceID3D12Resource*inコピー元リソースを表す ID3D12Resource インターフェイスへのポインターです。

解説(Remarks)

CopyResource の処理は GPU 上で実行されるため、コピーするデータのサイズに比例して CPU 負荷が大きくなることはありません。

CopyResource は、同じヒープメモリをエイリアスするリソースの初期化に使用できます。詳細については CreatePlacedResource を参照してください。

デバッグレイヤー

コピー元のサブリソースが D3D12_RESOURCE_STATE_COPY_SOURCE 状態でない場合、デバッグレイヤーはエラーを発行します。

コピー先のサブリソースが D3D12_RESOURCE_STATE_COPY_DEST 状態でない場合、デバッグレイヤーはエラーを発行します。

制限事項

このメソッドには、パフォーマンス向上のためのいくつかの制限があります。たとえば、コピー元とコピー先のリソースは次の条件を満たす必要があります。

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 圧縮テクスチャに対応します。

ビット幅 非圧縮リソース ブロック圧縮リソース 幅・高さの比
32 DXGI_FORMAT_R32_UINT
DXGI_FORMAT_R32_SINT
DXGI_FORMAT_R9G9B9E5_SHAREDEXP 1:1
64 DXGI_FORMAT_R16G16B16A16_UINT
DXGI_FORMAT_R16G16B16A16_SINT
DXGI_FORMAT_R32G32_UINT
DXGI_FORMAT_R32G32_SINT
DXGI_FORMAT_BC1_UNORM[_SRGB]
DXGI_FORMAT_BC4_UNORM
DXGI_FORMAT_BC4_SNORM
1:4
128 DXGI_FORMAT_R32G32B32A32_UINT
DXGI_FORMAT_R32G32B32A32_SINT
DXGI_FORMAT_BC2_UNORM[_SRGB]
DXGI_FORMAT_BC3_UNORM[_SRGB]
DXGI_FORMAT_BC5_UNORM
DXGI_FORMAT_BC5_SNORM
1:4

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()); 
    } 
vtbl 18 void CopyTiles(ID3D12Resource* pTiledResource, D3D12_TILED_RESOURCE_COORDINATE* pTileRegionStartCoordinate, D3D12_TILE_REGION_SIZE* pTileRegionSize, ID3D12Resource* pBuffer, ULONGLONG BufferStartOffsetInBytes, D3D12_TILE_COPY_FLAGS Flags)

バッファーからタイルリソースへ、またはその逆方向にタイルをコピーします。(ID3D12GraphicsCommandList.CopyTiles)

pTiledResourceID3D12Resource*inタイルリソースへのポインターです。
pTileRegionStartCoordinateD3D12_TILED_RESOURCE_COORDINATE*inタイルリソースの開始座標を記述する D3D12_TILED_RESOURCE_COORDINATE 構造体へのポインターです。
pTileRegionSizeD3D12_TILE_REGION_SIZE*inタイル領域のサイズを記述する D3D12_TILE_REGION_SIZE 構造体へのポインターです。
pBufferID3D12Resource*inデフォルト、ダイナミック、またはステージングのバッファーを表す ID3D12Resource へのポインターです。
BufferStartOffsetInBytesULONGLONGin処理を開始する、pBuffer のバッファー内のオフセット (バイト単位) です。
FlagsD3D12_TILE_COPY_FLAGSinタイルをどのようにコピーするかを指定する、ビット単位の OR 演算で組み合わせた D3D12_TILE_COPY_FLAGS 型の値の組み合わせです。

解説(Remarks)

CopyTiles は、マップされていない領域への書き込み操作を破棄し、マップされていない領域からの読み取り操作を処理します (ただし Tier_1 のタイルリソースでは、マップされていない領域の読み書きは無効です。D3D12_TILED_RESOURCES_TIER を参照してください)。

コピー先リソース内の複数の位置が同じタイルメモリにマップされているために、同じメモリ位置へ複数回書き込むコピー操作となる場合、 多重マップされたタイルへの書き込み結果は非決定的かつ再現性がありません。すなわち、タイルメモリへのアクセスは、ハードウェアがコピー操作を実行する順序に依存します。

コピー操作の対象となるタイルには、パックされたミップマップを含むタイルを含めることはできません。含めた場合、コピー操作の結果は未定義です。 ハードウェアが 1 つ以上のタイルにパックしたミップマップとの間でデータを転送するには、 CopyTextureRegion のような標準の (すなわちタイル専用でない) コピー API を使用する必要があります。

CopyTiles は、標準のコピーメソッドとは少し異なるパターンでデータをコピーします。

コピー操作のうち非タイルバッファーリソース側のタイルのメモリレイアウトは、64 KB のタイル内でメモリ上リニアになっており、タイルリソースとの間で転送する際に、ハードウェアとドライバーがタイルごとに適宜スウィズル・デスウィズルします。マルチサンプルアンチエイリアシング (MSAA) サーフェスの場合、ハードウェアとドライバーは各ピクセルのサンプルをサンプルインデックス順にたどってから次のピクセルへ進みます。右端で部分的にしか埋まらないタイル (幅がタイル幅 (ピクセル単位) の倍数でないサーフェスの場合) では、1 行下へ移動するためのピッチおよびストライドは、タイルが完全に埋まっている場合にタイルの横方向に収まるピクセル数分のバイトサイズ全体になります。したがって、メモリ上でピクセルの各行の間に隙間が生じることがあります。タイルより小さいミップマップは、このリニアレイアウトでは互いにパックされません。メモリ領域の無駄に見えるかもしれませんが、前述のとおり、ハードウェアがパックするミップマップへのコピーに CopyTiles を使用することはできません。小さなミップマップを個別にコピーするには、CopyTextureRegion のような汎用のコピー API を使用してください。

vtbl 19 void ResolveSubresource(ID3D12Resource* pDstResource, DWORD DstSubresource, ID3D12Resource* pSrcResource, DWORD SrcSubresource, DXGI_FORMAT Format)

マルチサンプルリソースを非マルチサンプルリソースへコピーします。

pDstResourceID3D12Resource*inコピー先リソースです。D3D12_HEAP_TYPE_DEFAULT ヒープ上に作成され、かつシングルサンプルである必要があります。ID3D12Resource を参照してください。
DstSubresourceDWORDinコピー先のサブリソースを識別する 0 から始まるインデックスです。親リソースが複雑な構成の場合は、D3D12CalcSubresource を使用してサブリソースインデックスを計算してください。
pSrcResourceID3D12Resource*inコピー元リソースです。マルチサンプルである必要があります。
SrcSubresourceDWORDinコピー元リソースのうち、対象となるサブリソースです。
FormatDXGI_FORMATinマルチサンプルリソースをシングルサンプルリソースへどのように解決するかを示す 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 形式の場合は次のようになります。
vtbl 20 void IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology)

入力アセンブラーステージへの入力データを記述する、プリミティブの種類とデータの順序に関する情報をバインドします。(ID3D12GraphicsCommandList.IASetPrimitiveTopology)

PrimitiveTopologyD3D_PRIMITIVE_TOPOLOGYinプリミティブの種類とプリミティブデータの順序です (D3D_PRIMITIVE_TOPOLOGY を参照)。
vtbl 21 void RSSetViewports(DWORD NumViewports, D3D12_VIEWPORT* pViewports)

ビューポートの配列をパイプラインのラスタライザーステージにバインドします。(ID3D12GraphicsCommandList.RSSetViewports)

NumViewportsDWORDinバインドするビューポートの数です。 有効な値の範囲は (0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) です。
pViewportsD3D12_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 リファレンスのサンプルコード を参照してください。

vtbl 22 void RSSetScissorRects(DWORD NumRects, RECT* pRects)

シザー矩形の配列をラスタライザーステージにバインドします。

NumRectsDWORDinバインドするシザー矩形の数です。
pRectsRECT*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 リファレンスのサンプルコード を参照してください。

vtbl 23 void OMSetBlendFactor(FLOAT* BlendFactor)

ピクセルシェーダー、レンダーターゲット、またはその両方の値を変調するブレンドファクターを設定します。

BlendFactorFLOAT*inoptionalRGBA の各コンポーネントに 1 つずつ対応するブレンドファクターの配列です。

解説(Remarks)

ブレンドステートオブジェクトを D3D12_BLEND_BLEND_FACTOR または D3D12_BLEND_INV_BLEND_FACTOR で作成した場合、ブレンドステージは NULL でないブレンドファクターの配列を使用します。それ以外の場合、ブレンドステージは NULL でないブレンドファクターの配列を使用せず、ランタイムがブレンドファクターを保持します。

NULL を渡した場合、ランタイムは { 1, 1, 1, 1 } に等しいブレンドファクターを使用または保持します。

vtbl 24 void OMSetStencilRef(DWORD StencilRef)

深度ステンシルテストの参照値を設定します。

StencilRefDWORDin深度ステンシルテストを行う際に比較対象とする参照値です。
vtbl 25 void SetPipelineState(ID3D12PipelineState* pPipelineState)

すべてのシェーダーを設定し、グラフィックスプロセッシングユニット (GPU) パイプラインの固定機能ステートの大部分をプログラムします。

pPipelineStateID3D12PipelineState*inパイプラインステートのデータを保持する ID3D12PipelineState へのポインターです。
vtbl 26 void ResourceBarrier(DWORD NumBarriers, D3D12_RESOURCE_BARRIER* pBarriers)

リソースへの複数のアクセスを同期する必要があることをドライバーに通知します。(ID3D12GraphicsCommandList.ResourceBarrier)

NumBarriersDWORDin送信するバリア記述の数です。
pBarriersD3D12_RESOURCE_BARRIER*inバリア記述の配列へのポインターです。

解説(Remarks)

メモ

D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE 状態で使用するリソースは、その状態で作成する必要があり、その後その状態から遷移させてはなりません。また、その状態で作成されなかったリソースをその状態へ遷移させることもできません。詳細については、GitHub 上の DirectX レイトレーシング (DXR) 機能仕様の Acceleration structure memory restrictions を参照してください。

バリア記述には次の 3 種類があります。

ID3D12GraphicsCommandList::ResourceBarrier にリソースバリア記述の配列を渡した場合、この API は指定された順序で N 回 (配列要素ごとに 1 回) 呼び出されたかのように動作します。 パフォーマンス最適化のため、可能な場合は複数の遷移を 1 回の API 呼び出しにまとめてください。

サブリソースが取りうる用途の状態については、D3D12_RESOURCE_STATES 列挙型および Direct3D 12 におけるリソースバリアを使用したリソース状態の同期 のセクションを参照してください。

ID3D12GraphicsCommandList::DiscardResource を呼び出す際、リソース内のすべてのサブリソースは、レンダーターゲットの場合は RENDER_TARGET 状態、深度ステンシルリソースの場合は DEPTH_WRITE 状態になっている必要があります。

バックバッファーをプレゼントする際、そのバックバッファーは D3D12_RESOURCE_STATE_PRESENT 状態になっている必要があります。PRESENT 状態でないリソースに対して IDXGISwapChain1::Present1 が呼び出された場合、デバッグレイヤーの警告が発行されます。

リソースの用途を表すビットは、読み取り専用と読み書きの 2 つのカテゴリに分類されます。

次の用途ビットは読み取り専用です。

次の用途ビットは読み書き可能です。 次の用途ビットは書き込み専用です。 書き込みビットは最大でも 1 つしか設定できません。 いずれかの書き込みビットが設定されている場合、読み取りビットを設定することはできません。 書き込みビットが設定されていない場合は、任意の数の読み取りビットを設定できます。

ある時点において、サブリソースはちょうど 1 つの状態にあります (一連のフラグによって決まります)。アプリケーションは、一連の ResourceBarrier 呼び出しを行う際に状態が整合するようにしなければなりません。言い換えると、連続する ResourceBarrier 呼び出しにおける遷移前と遷移後の状態は一致している必要があります。

リソース内のすべてのサブリソースを遷移させるには、アプリケーションはサブリソースインデックスに D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES を設定できます。これはすべてのサブリソースが変更されることを意味します。

パフォーマンス向上のため、アプリケーションは分割バリアを使用してください ( マルチエンジンの同期 を参照)。また、可能な限り複数の遷移を 1 回の呼び出しにまとめてください。

ランタイムによる検証

ランタイムは、バリアの種類の値が D3D12_RESOURCE_BARRIER_TYPE 列挙型の有効なメンバーであることを検証します。

さらに、ランタイムは次の点を確認します。

エイリアシングバリアについては、いずれかのリソースポインターが NULL でない場合、それがタイルリソースを指していることをランタイムが検証します。

UAV バリアについては、リソースが NULL でない場合、そのリソースに D3D12_RESOURCE_STATE_UNORDERED_ACCESS バインドフラグが設定されていることをランタイムが検証します。

検証に失敗すると、ID3D12GraphicsCommandList::CloseE_INVALIDARG を返します。

デバッグレイヤー

デバッグレイヤーは、通常、ランタイムの検証に失敗する場合にエラーを発行します。 デバッグレイヤーはランタイムの規則を検証しようとしますが、保守的に動作します。そのため、デバッグレイヤーのエラーは実際のエラーですが、場合によっては実際のエラーであってもデバッグレイヤーのエラーが発生しないことがあります。

デバッグレイヤーは、次の場合に警告を発行します。

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 リファレンスのサンプルコード を参照してください。

vtbl 27 void ExecuteBundle(ID3D12GraphicsCommandList* pCommandList)

バンドルを実行します。

pCommandListID3D12GraphicsCommandList*in実行するバンドルを決定する ID3D12GraphicsCommandList を指定します。

解説(Remarks)

バンドルは、パイプラインステートオブジェクトとプリミティブトポロジを除き、ExecuteBundle を呼び出した親コマンドリストのすべてのステートを継承します。 バンドル内で設定されたステートはすべて、親コマンドリストのステートに影響します。 なお、ExecuteBundle はプレディケーション対象の操作ではありません。

ランタイムによる検証

ランタイムは、「呼び出される側」がバンドルであり、「呼び出す側」がダイレクトコマンドリストであることを検証します。また、バンドルがクローズされていることも検証します。この取り決めに違反した場合、ランタイムは呼び出しを黙って破棄します。 検証に失敗すると、CloseE_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 リファレンスのサンプルコード を参照してください。

vtbl 28 void SetDescriptorHeaps(DWORD NumDescriptorHeaps, ID3D12DescriptorHeap** ppDescriptorHeaps)

コマンドリストに関連付けられた、現在バインドされている記述子ヒープを変更します。

NumDescriptorHeapsDWORDinバインドする記述子ヒープの数です。
ppDescriptorHeapsID3D12DescriptorHeap**in

コマンドリストに設定するヒープを表す ID3D12DescriptorHeap オブジェクトの配列へのポインターです。

バインドできる記述子ヒープの種類は D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAVD3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER のみです。

各種類につき一度に設定できる記述子ヒープは 1 つだけです。つまり、一度に設定できるヒープは最大 2 つ (サンプラー 1 つ、CBV/SRV/UAV 1 つ) です。

解説(Remarks)

SetDescriptorHeaps はバンドルに対しても呼び出せますが、バンドルの記述子ヒープは呼び出し元のコマンドリストの記述子ヒープと一致している必要があります。バンドルの制限の詳細については、コマンドリストとバンドルの作成および記録 を参照してください。

この呼び出しにより、以前に設定されたヒープはすべて解除されます。1 回の呼び出しで設定できるのは、シェーダーから参照可能な種類ごとに最大 1 つのヒープです。

記述子ヒープの変更は、一部のハードウェアではパイプラインのフラッシュを引き起こす可能性があります。そのため、バインドする記述子ヒープを頻繁に変更するのではなく、種類ごとにシェーダーから参照可能なヒープを 1 つ用意し、フレームごとに一度だけ設定することを推奨します。その代わりに、レンダリング中に必要に応じて ID3D12Device::CopyDescriptorsID3D12Device::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 リファレンスのサンプルコード を参照してください。

vtbl 29 void SetComputeRootSignature(ID3D12RootSignature* pRootSignature)

コンピュート用ルートシグネチャのレイアウトを設定します。

pRootSignatureID3D12RootSignature*inoptionalID3D12RootSignature オブジェクトへのポインターです。
vtbl 30 void SetGraphicsRootSignature(ID3D12RootSignature* pRootSignature)

グラフィックス用ルートシグネチャのレイアウトを設定します。

pRootSignatureID3D12RootSignature*inoptionalID3D12RootSignature オブジェクトへのポインターです。
vtbl 31 void SetComputeRootDescriptorTable(DWORD RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor)

コンピュート用ルートシグネチャに記述子テーブルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BaseDescriptorD3D12_GPU_DESCRIPTOR_HANDLEin設定する基準となる記述子の GPU 記述子ハンドルオブジェクトです。
vtbl 32 void SetGraphicsRootDescriptorTable(DWORD RootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor)

グラフィックス用ルートシグネチャに記述子テーブルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BaseDescriptorD3D12_GPU_DESCRIPTOR_HANDLEin設定する基準となる記述子の GPU 記述子ハンドルオブジェクトです。
vtbl 33 void SetComputeRoot32BitConstant(DWORD RootParameterIndex, DWORD SrcData, DWORD DestOffsetIn32BitValues)

コンピュート用ルートシグネチャに定数を設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
SrcDataDWORDin設定する定数のソースデータです。
DestOffsetIn32BitValuesDWORDinルートシグネチャ内で定数を設定する位置のオフセットです (32 ビット値単位)。
vtbl 34 void SetGraphicsRoot32BitConstant(DWORD RootParameterIndex, DWORD SrcData, DWORD DestOffsetIn32BitValues)

グラフィックス用ルートシグネチャに定数を設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
SrcDataDWORDin設定する定数のソースデータです。
DestOffsetIn32BitValuesDWORDinルートシグネチャ内で定数を設定する位置のオフセットです (32 ビット値単位)。
vtbl 35 void SetComputeRoot32BitConstants(DWORD RootParameterIndex, DWORD Num32BitValuesToSet, void* pSrcData, DWORD DestOffsetIn32BitValues)

コンピュート用ルートシグネチャに定数のグループを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
Num32BitValuesToSetDWORDinルートシグネチャに設定する定数の数です。
pSrcDatavoid*in設定する定数グループのソースデータです。
DestOffsetIn32BitValuesDWORDinルートシグネチャ内でグループの最初の定数を設定する位置のオフセットです (32 ビット値単位)。
vtbl 36 void SetGraphicsRoot32BitConstants(DWORD RootParameterIndex, DWORD Num32BitValuesToSet, void* pSrcData, DWORD DestOffsetIn32BitValues)

グラフィックス用ルートシグネチャに定数のグループを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
Num32BitValuesToSetDWORDinルートシグネチャに設定する定数の数です。
pSrcDatavoid*in設定する定数グループのソースデータです。
DestOffsetIn32BitValuesDWORDinルートシグネチャ内でグループの最初の定数を設定する位置のオフセットです (32 ビット値単位)。
vtbl 37 void SetComputeRootConstantBufferView(DWORD RootParameterIndex, ULONGLONG BufferLocation)

コンピュート用ルートシグネチャに、定数バッファーの CPU 記述子ハンドルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BufferLocationULONGLONGin定数バッファーの D3D12_GPU_VIRTUAL_ADDRESS を指定します。
vtbl 38 void SetGraphicsRootConstantBufferView(DWORD RootParameterIndex, ULONGLONG BufferLocation)

グラフィックス用ルートシグネチャに、定数バッファーの CPU 記述子ハンドルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BufferLocationULONGLONGin定数バッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。
vtbl 39 void SetComputeRootShaderResourceView(DWORD RootParameterIndex, ULONGLONG BufferLocation)

コンピュート用ルートシグネチャに、シェーダーリソースの CPU 記述子ハンドルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BufferLocationULONGLONGinバッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。
vtbl 40 void SetGraphicsRootShaderResourceView(DWORD RootParameterIndex, ULONGLONG BufferLocation)

グラフィックス用ルートシグネチャに、シェーダーリソースの CPU 記述子ハンドルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BufferLocationULONGLONGinバッファーの GPU 仮想アドレスです。 テクスチャはサポートされません。D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。
vtbl 41 void SetComputeRootUnorderedAccessView(DWORD RootParameterIndex, ULONGLONG BufferLocation)

コンピュート用ルートシグネチャに、アンオーダードアクセスビューのリソースの CPU 記述子ハンドルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BufferLocationULONGLONGinバッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。
vtbl 42 void SetGraphicsRootUnorderedAccessView(DWORD RootParameterIndex, ULONGLONG BufferLocation)

グラフィックス用ルートシグネチャに、アンオーダードアクセスビューのリソースの CPU 記述子ハンドルを設定します。

RootParameterIndexDWORDinバインドするスロット番号です。
BufferLocationULONGLONGinバッファーの GPU 仮想アドレスです。 D3D12_GPU_VIRTUAL_ADDRESS は UINT64 の typedef された別名です。
vtbl 43 void IASetIndexBuffer(D3D12_INDEX_BUFFER_VIEW* pView)

インデックスバッファーのビューを設定します。

pViewD3D12_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 リファレンスのサンプルコード を参照してください。

vtbl 44 void IASetVertexBuffers(DWORD StartSlot, DWORD NumViews, D3D12_VERTEX_BUFFER_VIEW* pViews)

頂点バッファーの CPU 記述子ハンドルを設定します。

StartSlotDWORDin頂点バッファーの設定を開始する、デバイスの 0 から始まる配列内のインデックスです。
NumViewsDWORDinpViews 配列内のビューの数です。
pViewsD3D12_VERTEX_BUFFER_VIEW*inoptionalD3D12_VERTEX_BUFFER_VIEW 構造体の配列で頂点バッファービューを指定します。
vtbl 45 void SOSetTargets(DWORD StartSlot, DWORD NumViews, D3D12_STREAM_OUTPUT_BUFFER_VIEW* pViews)

ストリーム出力バッファーのビューを設定します。

StartSlotDWORDinストリーム出力バッファーの設定を開始する、デバイスの 0 から始まる配列内のインデックスです。
NumViewsDWORDinpViews 配列内のエントリの数です。
pViewsD3D12_STREAM_OUTPUT_BUFFER_VIEW*inoptionalD3D12_STREAM_OUTPUT_BUFFER_VIEW 構造体の配列を指定します。
vtbl 46 void OMSetRenderTargets(DWORD NumRenderTargetDescriptors, D3D12_CPU_DESCRIPTOR_HANDLE* pRenderTargetDescriptors, BOOL RTsSingleHandleToDescriptorRange, D3D12_CPU_DESCRIPTOR_HANDLE* pDepthStencilDescriptor)

レンダーターゲットおよび深度ステンシルの CPU 記述子ハンドルを設定します。

NumRenderTargetDescriptorsDWORDinpRenderTargetDescriptors 配列内のエントリの数です (0 から D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT の範囲)。このパラメーターが 0 以外の場合、pRenderTargetDescriptors が指す配列のエントリ数は、このパラメーターの値と等しくなければなりません。
pRenderTargetDescriptorsD3D12_CPU_DESCRIPTOR_HANDLE*inoptionalレンダーターゲット記述子のヒープの先頭を表す CPU 記述子ハンドルを記述する D3D12_CPU_DESCRIPTOR_HANDLE 構造体の配列を指定します。このパラメーターが NULL で、かつ NumRenderTargetDescriptors が 0 の場合、レンダーターゲットはバインドされません。
RTsSingleHandleToDescriptorRangeBOOLin

True は、渡されたハンドルが NumRenderTargetDescriptors 個の記述子が連続して並ぶ範囲へのポインターであることを意味します。バインドする記述子の集合がもともとメモリ上で連続している場合に有用です (先頭の 1 つへのハンドルだけで済みます)。たとえば NumRenderTargetDescriptors が 3 の場合、メモリレイアウトは次のように解釈されます。

パラメーターを true に設定した場合のメモリレイアウト この場合、ドライバーはハンドルを参照解決し、そのポインターが指すメモリをインクリメントしていきます。

False は、そのハンドルが NumRenderTargetDescriptors 個のハンドルからなる配列の先頭であることを意味します。false の場合、アプリケーションは異なる場所にある記述子の集合を一度にバインドできます。同じく NumRenderTargetDescriptors が 3 の場合、メモリレイアウトは次のように解釈されます。

パラメーターを false に設定した場合のメモリレイアウト この場合、ドライバーはメモリ上で互いに隣接していることが期待される 3 つのハンドルを参照解決します。
pDepthStencilDescriptorD3D12_CPU_DESCRIPTOR_HANDLE*inoptional深度ステンシル記述子を保持するヒープの先頭を表す CPU 記述子ハンドルを記述する D3D12_CPU_DESCRIPTOR_HANDLE 構造体へのポインターです。このパラメーターが NULL の場合、深度ステンシル記述子はバインドされません。
vtbl 47 void ClearDepthStencilView(D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView, D3D12_CLEAR_FLAGS ClearFlags, FLOAT Depth, BYTE Stencil, DWORD NumRects, RECT* pRects)

深度ステンシルリソースをクリアします。(ID3D12GraphicsCommandList.ClearDepthStencilView)

DepthStencilViewD3D12_CPU_DESCRIPTOR_HANDLEinクリア対象の深度ステンシル用ヒープの先頭を表す CPU 記述子ハンドルを記述します。
ClearFlagsD3D12_CLEAR_FLAGSinビット単位の OR 演算で組み合わせた D3D12_CLEAR_FLAGS 値の組み合わせです。結果の値により、クリアするデータの種類 (深度バッファー、ステンシルバッファー、またはその両方) が決まります。
DepthFLOATin深度バッファーをクリアする際に使用する値です。この値は 0 から 1 の範囲にクランプされます。
StencilBYTEinステンシルバッファーをクリアする際に使用する値です。
NumRectsDWORDinpRects パラメーターで指定する配列内の矩形の数です。
pRectsRECT*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 リファレンスのサンプルコード を参照してください。

vtbl 48 void ClearRenderTargetView(D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView, FLOAT* ColorRGBA, DWORD NumRects, RECT* pRects)

レンダーターゲット内のすべての要素を 1 つの値に設定します。

RenderTargetViewD3D12_CPU_DESCRIPTOR_HANDLEinクリア対象のレンダーターゲット用ヒープの先頭を表す CPU 記述子ハンドルを記述する D3D12_CPU_DESCRIPTOR_HANDLE 構造体を指定します。
ColorRGBAFLOAT*inレンダーターゲットを塗りつぶす色を表す 4 要素の配列です。
NumRectsDWORDinpRects パラメーターで指定する配列内の矩形の数です。
pRectsRECT*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 リファレンスのサンプルコード を参照してください。

vtbl 49 void ClearUnorderedAccessViewUint(D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap, D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle, ID3D12Resource* pResource, DWORD* Values, DWORD NumRects, RECT* pRects)

アンオーダードアクセスビュー (UAV) 内のすべての要素を、指定した整数値に設定します。

ViewGPUHandleInCurrentHeapD3D12_GPU_DESCRIPTOR_HANDLEinクリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する D3D12_GPU_DESCRIPTOR_HANDLE です。この記述子は、シェーダーから参照可能な記述子ヒープ内にある必要があり、そのヒープは SetDescriptorHeaps によってコマンドリストに設定されている必要があります。
ViewCPUHandleD3D12_CPU_DESCRIPTOR_HANDLEin

クリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する、シェーダーから参照できない記述子ヒープ内の D3D12_CPU_DESCRIPTOR_HANDLE です。

重要

この記述子は、シェーダーから参照可能な記述子ヒープ内にあってはなりません。これは、クリアを (ディスパッチではなく) 固定機能のハードウェア操作として実装するドライバーが、記述子を効率よく読み取れるようにするためです。シェーダーから参照可能なヒープは WRITE_COMBINE メモリ (D3D12_HEAP_TYPE_UPLOAD ヒープ型と同様) に作成される場合があり、この種のメモリからの CPU 読み取りは非常に低速です。

pResourceID3D12Resource*inクリア対象のアンオーダードアクセスビュー (UAV) リソースを表す ID3D12Resource インターフェイスへのポインターです。
ValuesDWORD*inアンオーダードアクセスビューのリソースを埋める値を格納した 4 要素の配列です。
NumRectsDWORDinpRects パラメーターで指定する配列内の矩形の数です。
pRectsRECT*inリソースビュー内でクリアする矩形を表す D3D12_RECT 構造体の配列です。NULL の場合、ClearUnorderedAccessViewUint はリソースビュー全体をクリアします。

解説(Remarks)

ランタイムによる検証

検証に失敗すると、ID3D12GraphicsCommandList::Close の呼び出しは E_INVALIDARG を返します。

デバッグレイヤー

入力値が正規化された範囲外の場合、デバッグレイヤーはエラーを発行します。

ビューが参照するサブリソースが適切な状態でない場合、デバッグレイヤーはエラーを発行します。ClearUnorderedAccessViewUint の場合、状態は D3D12_RESOURCE_STATE_UNORDERED_ACCESS でなければなりません。

vtbl 50 void ClearUnorderedAccessViewFloat(D3D12_GPU_DESCRIPTOR_HANDLE ViewGPUHandleInCurrentHeap, D3D12_CPU_DESCRIPTOR_HANDLE ViewCPUHandle, ID3D12Resource* pResource, FLOAT* Values, DWORD NumRects, RECT* pRects)

アンオーダードアクセスビュー内のすべての要素を、指定した浮動小数点値に設定します。

ViewGPUHandleInCurrentHeapD3D12_GPU_DESCRIPTOR_HANDLEinクリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する D3D12_GPU_DESCRIPTOR_HANDLE です。この記述子は、シェーダーから参照可能な記述子ヒープ内にある必要があり、そのヒープは SetDescriptorHeaps によってコマンドリストに設定されている必要があります。
ViewCPUHandleD3D12_CPU_DESCRIPTOR_HANDLEin

クリア対象のアンオーダードアクセスビュー (UAV) の初期化済み記述子を参照する、シェーダーから参照できない記述子ヒープ内の D3D12_CPU_DESCRIPTOR_HANDLE です。

重要

この記述子は、シェーダーから参照可能な記述子ヒープ内にあってはなりません。これは、クリアを (ディスパッチではなく) 固定機能のハードウェア操作として実装するドライバーが、記述子を効率よく読み取れるようにするためです。シェーダーから参照可能なヒープは WRITE_COMBINE メモリ (D3D12_HEAP_TYPE_UPLOAD ヒープ型と同様) に作成される場合があり、この種のメモリからの CPU 読み取りは非常に低速です。

pResourceID3D12Resource*inクリア対象のアンオーダードアクセスビュー (UAV) リソースを表す ID3D12Resource インターフェイスへのポインターです。
ValuesFLOAT*inアンオーダードアクセスビューのリソースを埋める値を格納した 4 要素の配列です。
NumRectsDWORDinpRects パラメーターで指定する配列内の矩形の数です。
pRectsRECT*inリソースビュー内でクリアする矩形を表す D3D12_RECT 構造体の配列です。NULL の場合、ClearUnorderedAccessViewFloat はリソースビュー全体をクリアします。

解説(Remarks)

ランタイムによる検証

浮動小数点の入力については、ランタイムは非正規化数の値を 0 に設定します (NaN は保持されます)。

特定のビットパターンで UAV をクリアしたい場合は、ID3D12GraphicsCommandList::ClearUnorderedAccessViewUint の使用を検討してください。

検証に失敗すると、ID3D12GraphicsCommandList::Close の呼び出しは E_INVALIDARG を返します。

デバッグレイヤー

入力値が正規化された範囲外の場合、デバッグレイヤーはエラーを発行します。

ビューが参照するサブリソースが適切な状態でない場合、デバッグレイヤーはエラーを発行します。ClearUnorderedAccessViewFloat の場合、状態は D3D12_RESOURCE_STATE_UNORDERED_ACCESS でなければなりません。

vtbl 51 void DiscardResource(ID3D12Resource* pResource, D3D12_DISCARD_REGION* pRegion)

リソースを破棄します。

pResourceID3D12Resource*in破棄するリソースの ID3D12Resource インターフェイスへのポインターです。
pRegionD3D12_DISCARD_REGION*inoptionalリソース破棄操作の詳細を記述する D3D12_DISCARD_REGION 構造体へのポインターです。

解説(Remarks)

DiscardResource のセマンティクスは、コマンドリストの種類によって変わります。

D3D12_COMMAND_LIST_TYPE_DIRECT の場合、次の 2 つの規則が適用されます。

D3D12_COMMAND_LIST_TYPE_COMPUTE の場合、次の規則が適用されます。 DiscardResource は、D3D12_COMMAND_LIST_TYPE_BUNDLE および D3D12_COMMAND_LIST_TYPE_COPY のコマンドリストではサポートされません。
vtbl 52 void BeginQuery(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, DWORD Index)

クエリの実行を開始します。(ID3D12GraphicsCommandList.BeginQuery)

pQueryHeapID3D12QueryHeap*inクエリを保持する ID3D12QueryHeap を指定します。
TypeD3D12_QUERY_TYPEinD3D12_QUERY_TYPE のいずれかのメンバーを指定します。
IndexDWORDinクエリヒープ内におけるクエリのインデックスを指定します。

解説(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 リファレンスのサンプルコード を参照してください。

vtbl 53 void EndQuery(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, DWORD Index)

実行中のクエリを終了します。

pQueryHeapID3D12QueryHeap*inクエリを保持する ID3D12QueryHeap を指定します。
TypeD3D12_QUERY_TYPEinD3D12_QUERY_TYPE のいずれかのメンバーを指定します。
IndexDWORDinクエリヒープ内におけるクエリのインデックスを指定します。

解説(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 リファレンスのサンプルコード を参照してください。

vtbl 54 void ResolveQueryData(ID3D12QueryHeap* pQueryHeap, D3D12_QUERY_TYPE Type, DWORD StartIndex, DWORD NumQueries, ID3D12Resource* pDestinationBuffer, ULONGLONG AlignedDestinationBufferOffset)

クエリからデータを取り出します。ResolveQueryData はすべてのヒープ型 (デフォルト、アップロード、リードバック) で動作します。ResolveQueryData はすべてのヒープ型 (デフォルト、アップロード、リードバック) で動作します。

pQueryHeapID3D12QueryHeap*in解決対象のクエリを保持する ID3D12QueryHeap を指定します。
TypeD3D12_QUERY_TYPEinクエリの種類を、D3D12_QUERY_TYPE のメンバーの 1 つとして指定します。
StartIndexDWORDin解決する最初のクエリのインデックスを指定します。
NumQueriesDWORDin解決するクエリの数を指定します。
pDestinationBufferID3D12Resource*inコピー先バッファーとなる ID3D12Resource を指定します。このバッファーは D3D12_RESOURCE_STATE_COPY_DEST 状態でなければなりません。
AlignedDestinationBufferOffsetULONGLONGinコピー先バッファー内のアラインメントされたオフセットを指定します。 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 構造体を書き込みます。

コアランタイムは次の点を検証します。

コピー先バッファーが 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 リファレンスのサンプルコード を参照してください。

vtbl 55 void SetPredication(ID3D12Resource* pBuffer, ULONGLONG AlignedBufferOffset, D3D12_PREDICATION_OP Operation)

レンダリングプレディケートを設定します。

pBufferID3D12Resource*inoptionalID3D12Resource としてのバッファーです。D3D12_RESOURCE_STATE_PREDICATION または D3D21_RESOURCE_STATE_INDIRECT_ARGUMENT 状態でなければなりません (両者の値は同一で、分かりやすさのために別名として提供されています)。プレディケーションを無効にするには NULL を指定します。
AlignedBufferOffsetULONGLONGinアラインメントされたバッファーオフセット (UINT64) です。
OperationD3D12_PREDICATION_OPinD3D12_PREDICATION_OP_EQUAL_ZEROD3D12_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 リファレンスのサンプルコード を参照してください。

vtbl 56 void SetMarker(DWORD Metadata, void* pData, DWORD Size)

直接呼び出すことは意図されていません。コマンドリストにイベントを挿入するには PIX イベントランタイムを使用してください。(ID3D12GraphicsCommandList.SetMarker)

MetadataDWORDin内部用です。
pDatavoid*inoptional内部用です。
SizeDWORDin内部用です。

解説(Remarks)

これは PIX イベントランタイムが内部的に使用するサポート用メソッドです。直接呼び出すことは意図されていません。

D3D12 コマンドリスト内の現在位置に計測用マーカーを挿入するには、PIXSetMarker 関数を使用してください。これは WinPixEventRuntime NuGet パッケージで提供されています。

vtbl 57 void BeginEvent(DWORD Metadata, void* pData, DWORD Size)

直接呼び出すことは意図されていません。コマンドリストにイベントを挿入するには PIX イベントランタイムを使用してください。(ID3D12GraphicsCommandList.BeginEvent)

MetadataDWORDin内部用です。
pDatavoid*inoptional内部用です。
SizeDWORDin内部用です。

解説(Remarks)

これは PIX イベントランタイムが内部的に使用するサポート用メソッドです。直接呼び出すことは意図されていません。

D3D12 コマンドリスト内の現在位置で計測領域の開始を示すには、PIXBeginEvent 関数または PIXScopedEvent マクロを使用してください。これらは WinPixEventRuntime NuGet パッケージで提供されています。

vtbl 58 void EndEvent()

直接呼び出すことは意図されていません。コマンドリストにイベントを挿入するには PIX イベントランタイムを使用してください。(ID3D12GraphicsCommandList.EndEvent)

解説(Remarks)

これは PIX イベントランタイムが内部的に使用するサポート用メソッドです。直接呼び出すことは意図されていません。

D3D12 コマンドリスト内の現在位置で計測領域の終了を示すには、PIXEndEvent 関数または PIXScopedEvent マクロを使用してください。これらは WinPixEventRuntime NuGet パッケージで提供されています。

vtbl 59 void ExecuteIndirect(ID3D12CommandSignature* pCommandSignature, DWORD MaxCommandCount, ID3D12Resource* pArgumentBuffer, ULONGLONG ArgumentBufferOffset, ID3D12Resource* pCountBuffer, ULONGLONG CountBufferOffset)

アプリケーションは、ExecuteIndirect メソッドを使用して間接描画・間接ディスパッチを実行します。

pCommandSignatureID3D12CommandSignature*inID3D12CommandSignature を指定します。pArgumentBuffer が参照するデータは、コマンドシグネチャの内容に応じて解釈されます。コマンドシグネチャの作成に使用する API については 間接描画 を参照してください。
MaxCommandCountDWORDin

コマンド数の指定方法には次の 2 通りがあります。

  • pCountBuffer が NULL でない場合、MaxCommandCount は実行される操作の最大数を指定します。実際に実行される操作の数は、この値と、pCountBuffer 内 (CountBufferOffset で指定されたバイトオフセット位置) に格納された 32 ビット符号なし整数のうち、小さい方になります。
  • pCountBuffer が NULL の場合、MaxCommandCount は実行される操作の正確な数を指定します。
pArgumentBufferID3D12Resource*inコマンド引数を格納した 1 つ以上の ID3D12Resource オブジェクトを指定します。
ArgumentBufferOffsetULONGLONGin最初のコマンド引数を特定するための、pArgumentBuffer 内のオフセットを指定します。
pCountBufferID3D12Resource*inoptionalID3D12Resource へのポインターを指定します。
CountBufferOffsetULONGLONGin引数の個数を特定するための、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 状態でない場合、デバッグレイヤーはエラーを発行します。コアランタイムは次の点を検証します。

以前のバージョンの Direct3D にあった 2 つの API、DrawInstancedIndirectDrawIndexedInstancedIndirect の機能は、ExecuteIndirect に包含されています。

バンドル

ID3D12GraphicsCommandList::ExecuteIndirect をバンドルのコマンドリスト内で使用できるのは、次の条件がすべて満たされる場合のみです。

バッファーの仮想アドレスの取得

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 の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
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 指定が可能。