次の方法で共有


ルート署名バージョン 1.1

ルート署名バージョン 1.1 の目的は、記述子ヒープ内の記述子が変更されないか、データ記述子が変更されない場合に、アプリケーションがドライバーに指示できるようにすることです。 これにより、ドライバーは、記述子または指すメモリが一定期間静的であることを認識できる可能性がある最適化を行うオプションを使用できます。

概要

ルート署名バージョン 1.0 では、記述子ヒープの内容と、それらを参照するコマンド リスト/バンドルが GPU 上で実行中である可能性がある場合に、それらを指すメモリをアプリケーションによって自由に変更できます。 ただし、多くの場合、アプリケーションは、記述子またはメモリを参照するコマンドが記録された後に変更する柔軟性を実際に必要としません。

多くの場合、アプリケーションは簡単に次のことが可能です。

  • コマンド リストまたはバンドルで記述子テーブルまたはルート記述子をバインドする前に、記述子 (およびそれらが指しているメモリ) を設定します。
  • これらの記述子を参照するコマンド リスト /bundle の実行が最後に完了するまで、これらの記述子が変更されないようにします。
  • 記述子が指すデータが同じ完全な期間変更されないようにします。

または、アプリケーションでは、そのデータが短い期間だけ変更されないことを尊重できる場合があります。 特定のデータは、ルート パラメーター バインド (記述子テーブルまたはルート記述子) が現在データを指している、コマンド リストの実行中に、時間枠内で静的である可能性があります。 言い換えると、アプリケーションは GPU タイムラインで実行を実行し、ルート パラメーターを使用して設定された期間の間にデータを更新し、それが設定されると静的であることを認識します。

記述子またはデータ記述子が変更されない場合、ドライバーが行う特定の最適化はハードウェア ベンダー固有であり、重要なのはパフォーマンスを向上させる以外の動作を変更しないことです。 アプリケーションの意図に関する知識を可能な限り保持しても、アプリケーションに負担をかけません。

最適化の 1 つは、多くのドライバーが、アプリケーションが記述子とデータの静的性について行うことができる約束を知っていれば、シェーダーによってより効率的なメモリ アクセスを生成できることです。 たとえば、ドライバーは、特定のハードウェアがルート引数のサイズに依存しない場合、それをルート記述子に変換することによって、ヒープ内の記述子にアクセスするための間接参照のレベルを削除できます。

バージョン 1.1 を使用する開発者向けの追加のタスクは、ドライバーが意味のある最適化を行えるように、可能な限りデータのボラティリティと静的性について約束することです。 開発者は、静的性について約束する必要はありません。

ルート署名バージョン 1.0 は引き続き変更されずに機能しますが、ルート署名を再コンパイルするアプリケーションは既定で Root Signature 1.1 になります (必要に応じてバージョン 1.0 を強制するオプションがあります)。

静的フラグと揮発性フラグ

次のフラグはルート署名の一部であり、ドライバーは、個々のルート引数を設定するときに最適に処理する方法の戦略を選択できます。また、ルート署名は PSO の一部であるため、最初にコンパイルされたときに同じ前提条件をパイプライン状態オブジェクト (PSO) に埋め込むことができます。

次のフラグはアプリによって設定され、記述子またはデータに適用されます。

typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS
{
    D3D12_DESCRIPTOR_RANGE_FLAG_NONE    = 0,
    D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE    = 0x1,
    D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE   = 0x2,
    D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE    = 0x4,
    D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8
} D3D12_DESCRIPTOR_RANGE_FLAGS;

typedef enum D3D12_ROOT_DESCRIPTOR_FLAGS
{
    D3D12_ROOT_DESCRIPTOR_FLAG_NONE = 0,
    D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE    = 0x2,
    D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
    D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC  = 0x8
} D3D12_ROOT_DESCRIPTOR_FLAGS;

DESCRIPTORS_VOLATILE

このフラグを設定すると、ルート記述子テーブルが指す記述子ヒープ内の記述子は、記述子テーブルをバインドするコマンド・リスト/バンドルが送信され、実行が完了していない場合を除き、アプリケーションによっていつでも変更できます。 たとえば、コマンド リストを記録してから記述子ヒープ内の記述子を変更すると、実行のためにコマンド リストを送信 前に が参照されます。 これは、Root Signature バージョン 1.0 でサポートされている唯一の動作です。

DESCRIPTORS_VOLATILE フラグが 設定されていない 場合、記述子は静的です。 このモードにはフラグがありません。 静的記述子とは、ルート記述子テーブルが指す記述子ヒープ内の記述子が、(記録中に) コマンド・リスト/バンドルに記述子テーブルが設定された時点までに初期化されたことを意味し、最後にコマンド・リスト/バンドルの実行が完了するまで記述子を変更することはできません。 ルート署名バージョン 1.1 の場合、静的記述子は既定の前提条件であり、必要に応じ、アプリケーションで DESCRIPTORS_VOLATILE フラグを指定する必要があります。

静的記述子を持つ記述子テーブルを使用するバンドルの場合、記述子はバンドルが (バンドルが呼び出されたときではなく) 記録された時点から開始する準備ができている必要があり、バンドルの最後の実行が完了するまで変更されません。 静的記述子を指す記述子テーブルは、バンドルの記録中に設定する必要があり、バンドルに継承されません。 バンドルに設定され、コマンド・リストに戻された静的記述子を持つ記述子テーブルをコマンド・リストで使用することは有効です。

記述子が静的な場合は、DESCRIPTORS_VOLATILE フラグを設定する必要がある動作に別の変更があります。 (Texture1D/2D/3D/Cube ビューとは対照的に) バッファー ビューへの境界外アクセスは無効であり、読み取りまたは書き込みの削除の既定値を返すのではなく、デバイスリセットの可能性を含む未定義の結果が生成されます。 アプリケーションがハードウェアの境界外アクセス チェックに依存する機能を削除する目的は、ドライバーが、より効率的であると判断された場合に、静的記述子アクセスをルート記述子アクセスに昇格することを選択できるようにすることです。 ルート記述子は、範囲外のチェックをサポートしていません。

記述子にアクセスするときに、アプリケーションが安全な範囲外のメモリ アクセス動作に依存している場合は、それらの記述子にアクセスする記述子範囲をDESCRIPTORS_VOLATILEとしてマークする必要があります。

DATA_VOLATILE

このフラグを設定すると、記述子テーブルをバインドするコマンド リスト/バンドルが送信され、実行が完了していない場合を除き、CPU によって指されるデータはいつでも CPU によって変更できます。 これは、Root Signature バージョン 1.0 でサポートされている唯一の動作です。

このフラグは、記述子範囲フラグとルート記述子フラグの両方で使用できます。

DATA_STATIC_WHILE_SET_AT_EXECUTE

このフラグを設定すると、GPU タイムラインでの実行中に、基になるルート記述子または記述子テーブルがコマンド リスト/バンドルに設定され、後続の描画/ディスパッチでデータが参照されなくなると、記述子によって指されるデータは変更できません。

GPU でルート記述子または記述子テーブルが設定される前に、このデータ は、同じコマンド リスト/バンドルによっても変更。 データは、参照する描画/ディスパッチが完了している限り、そのデータを指すルート記述子または記述子テーブルがコマンド リスト/バンドルに設定されている間も変更できます。 ただし、これを行うには、次にルート記述子または記述子テーブルが逆参照される前に、記述子テーブルをコマンド リストに再バインドする必要があります。 これにより、ドライバーは、ルート記述子または記述子テーブルによって指されているデータが変更されたことを認識できます。

DATA_STATIC_WHILE_SET_AT_EXECUTEとDATA_VOLATILEの基本的な違いは、ドライバーがコマンド リスト内のデータ コピーによって記述子が指すデータが追加の状態追跡を行わずに変更されたかどうかをドライバーが判断できないDATA_VOLATILE点です。 そのため、たとえば、ドライバーが任意の種類のデータプリフェッチ コマンドをコマンド リストに挿入できる場合 (たとえば、既知のデータへのシェーダー アクセスをより効率的にするために) DATA_STATIC_WHILE_SET_AT_EXECUTE、SetGraphicsRootDescriptorTableを使用して設定された時点でデータプリフェッチを実行するだけで済むをドライバーに知らせます。 SetComputeRootDescriptorTableまたは定数バッファー ビュー、シェーダー リソース ビュー、または順序指定されていないアクセス ビューを設定するメソッドの 1 つをします。

バンドルの場合、実行時に設定されている間にデータが静的であるという保証は、バンドルの各実行に一意に適用されます。

このフラグは、記述子範囲フラグとルート記述子フラグの両方で使用できます。

DATA_STATIC

このフラグが設定されている場合、記述子が指すデータは、記録中にメモリーを参照するルート記述子または記述子テーブルがコマンド・リスト/バンドルに設定された時点までに初期化され、最後にコマンド・リスト/バンドルの実行が完了するまでデータを変更することはできません。

バンドルの場合、静的期間は、呼び出し元のコマンド リストの記録ではなく、バンドルの記録中にルート記述子または記述子テーブルの設定から開始されます。 さらに、静的データを指す記述子テーブルは、バンドルに設定する必要があり、継承されません。 バンドルに設定され、コマンド・リストに戻された静的データを指す記述子テーブルをコマンド・リストで使用することは有効です。

このフラグは、記述子範囲フラグとルート記述子フラグの両方で使用できます。

フラグの組み合わせ

サンプラーがデータを指していないため、DATA フラグをまったくサポートしないサンプラー記述子範囲を除き、最大で 1 つの DATA フラグを一度に指定できます。

SRV および CBV 記述子範囲に DATA フラグが存在しない場合は、既定のDATA_STATIC_WHILE_SET_AT_EXECUTE動作が想定されていることを意味します。 この既定値がDATA_STATICではなく選択される理由は、ほとんどの場合、DATA_STATIC_WHILE_SET_AT_EXECUTEが安全な既定値になる可能性が高い一方で、既定のDATA_VOLATILEよりも最適化の機会が得られる可能性が高いということです。

UAV 記述子範囲に DATA フラグが存在しない場合は、通常、UAV が書き込まれる場合に、既定のDATA_VOLATILE動作が想定されていることを意味します。

DESCRIPTORS_VOLATILE DATA_STATICと組み合わせることはできませんが、は他の DATA フラグと組み合わせ。 DESCRIPTORS_VOLATILE DATA_STATIC_WHILE_SET_AT_EXECUTEと組み合わせることができる理由は、揮発性記述子ではコマンド リスト/バンドルの実行中に記述子の準備が必要であり、DATA_STATIC_WHILE_SET_AT_EXECUTEはコマンド リスト/バンドル実行のサブセット内の静的性についてのみ約束を行う必要があるということです。

フラグの概要

次の表は、使用される可能性があるフラグの組み合わせをまとめたものです。

有効なD3D12_DESCRIPTOR_RANGE_FLAGS設定 形容
フラグが設定されていません 記述子は静的です (既定値)。 データの既定の前提条件: SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE、UAV: DATA_VOLATILE。 SRV/CBV のこれらの既定値は、大部分のルート署名の使用パターンに安全に適合します。
DATA_STATIC 記述子とデータはどちらも静的です。 これにより、ドライバーの最適化の可能性が最大になります。
DATA_VOLATILE 記述子は静的であり、データは揮発性です。
DATA_STATIC_WHILE_SET_AT_EXECUTE 記述子は静的であり、実行時に設定されている間はデータは静的です。
DESCRIPTORS_VOLATILE 記述子は揮発性であり、SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTEと UAV: DATA_VOLATILEのデータに関する既定の前提条件が行われます。
DESCRIPTORS_VOLATILE |DATA_VOLATILE 記述子とデータはどちらも揮発性であり、ルート署名 1.0 と同等です。
DESCRIPTORS_VOLATILE |DATA_STATIC_WHILE_SET_AT_EXECUTE 記述子は揮発性ですが、コマンド リストの実行中に変更することはできません。 そのため、実行時にルート記述子テーブルを介して設定されている間にデータが静的であるという追加の宣言を組み合わせることが有効です。基になる記述子は、データが静的であると約束されているよりも長い間、実質的に静的です。

 

有効なD3D12_ROOT_DESCRIPTOR_FLAGS設定 形容
フラグが設定されていません データの既定の前提条件: SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE、UAV: DATA_VOLATILE。 SRV/CBV のこれらの既定値は、大部分のルート署名の使用パターンに安全に適合します。
DATA_STATIC データは静的であり、ドライバーの最適化に最適な可能性があります。
DATA_STATIC_WHILE_SET_AT_EXECUTE 実行時に設定されている間、データは静的です。
DATA_VOLATILE ルート署名 1.0 と同等です。

 

バージョン 1.1 API の概要

次の API 呼び出しでは、バージョン 1.1 が有効になります。

列挙型

これらの列挙型には、記述子とデータの揮発性を指定するためのキー フラグが含まれています。

構造

更新された構造体 (バージョン 1.0 以降) には、ボラティリティ/静的フラグへの参照が含まれています。

関数

ここに記載されているメソッドは、元の D3D12SerializeRootSignatureD3D12CreateRootSignatureDeserializer 関数よりも優先されます。これは、任意のバージョンのルート署名で動作するように設計されているためです。 シリアル化されたフォームは、CreateRootSignature API に渡されます。 シェーダーがルート署名を使用して作成されている場合、コンパイルされたシェーダーには既にシリアル化されたルート署名が含まれます。

メソッド

ルート署名データ構造を逆シリアル化するために、ID3D12VersionedRootSignatureDeserializer インターフェイスが作成されます。

ヘルパー構造体

一部のバージョン 1.1 構造体の初期化に役立つヘルパー構造体が追加されました。

  • CD3DX12_DESCRIPTOR_RANGE1
  • CD3DX12_ROOT_PARAMETER1
  • CD3DX12_STATIC_SAMPLER1
  • CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC

D3D12 のヘルパー構造体と関数のを参照してください。

静的フラグに違反した結果

上記で説明した記述子フラグとデータ フラグ (および特定のフラグが存在しないことによって示される既定値) は、アプリケーションによるドライバーの動作に関する約束を定義します。 アプリケーションが Promise に違反した場合、これは無効な動作です。結果は未定義であり、異なるドライバーとハードウェア間で異なる可能性があります。

デバッグ レイヤーには、フラグを設定せずにルート署名バージョン 1.1 を使用する既定の約束など、アプリケーションが約束を守っていることを検証するためのオプションがあります。

バージョン管理

シェーダーにアタッチされたルート署名をコンパイルする場合、新しい HLSL コンパイラでは既定でルート署名がバージョン 1.1 でコンパイルされますが、古い HLSL コンパイラでは 1.0 のみがサポートされます。 ルート署名 1.1 をサポートしていない OS では、1.1 ルート署名は機能しないことに注意してください。

シェーダーでコンパイルされたルート署名バージョンは、/force_rootsig_ver <version>を使用して特定のバージョンに強制できます。 コンパイラが強制バージョンでコンパイルされているルート署名の動作を保持できる場合(たとえば、最適化目的でのみ機能するが動作には影響しないルート署名にサポートされていないフラグをドロップするなど)、バージョンの強制は成功します。

この方法で、アプリケーションは、たとえば、アプリケーションをビルドするときに 1.0 と 1.1 の両方に 1.1 ルート署名をコンパイルし、OS サポートのレベルに応じて実行時に適切なバージョンを選択できます。 ただし、アプリケーションがシェーダーとは別にルート署名を個別にコンパイルする (特に複数のバージョンが必要な場合) には、最もスペース効率が高いでしょう。 シェーダーが最初にルート署名をアタッチしてコンパイルされていない場合でも、/verifyrootsignature コンパイラ オプションを使用して、シェーダーとのルート署名の互換性に関するコンパイラ検証の利点を保持できます。 後で実行時に、必要なルート署名 (OS でサポートされている適切なバージョン) を別のパラメーターとして渡しながら、ルート署名を持たないシェーダーを使用して PSO を作成できます。

ルート署名 の作成の

ルート署名

HLSL でのルート署名の指定の