DirectXの新機能 - 機能レベル12_2

Claire Andrewsさんの[New in DirectX— Feature Level 12_2](https://devblogs.microsoft.com/directx/new-in-directx-feature-level-12_2/)を訳したのですが、ダメと言われてしまいました(見出しにしかない情報があるって？まぁいろいろありますよ)。

ただ、公式の仕様書([Feature Level 12_2](https://microsoft.github.io/DirectX-Specs/d3d/D3D12_FeatureLevel12_2.html))があって、こちらはオープンソースだから、こちらを使うのが良いよと、言われたので、こちらを訳してみました。

機能レベル 12_2 は、次の機能を含むかなり大きな機能追加で 個別の利用可能性を調べるのではなく、まとめて（いわばGPUの世代を）確認することができます。
- DirectX レイトレーシング
- メッシュシェーダ
- 可変解像度シェーディング
- サンプラーフィードバック

そして、DirectX 12 Ultimate の機能レベルでの呼び名です。

機能レベル 12_2 は、NVIDIA のRTX GPUや、AMDのRDNA 2のGPUが対応しています。[Windows Insider Program](https://insider.windows.com/)のビルドバージョン20170以降のSDKですでに利用可能だそうです。


---
こちらの記事は、[Feature Level 12_2](https://microsoft.github.io/DirectX-Specs/d3d/D3D12_FeatureLevel12_2.html) を訳したものです。
元仕様書は、[microsoft](https://github.com/microsoft) が著作権を持っており、CC4.0で公開されています。

# 機能レベル12_2

## 目的
機能レベル12_2は、Windowsプラットフォーム上のグラフィカルなゲームやアプリケーションでの顧客体験を向上させるために、GPUエコシステム全体で一連の機能を標準化するための手段として存在しています。

## クエリー と API
ランタイムは、他のフィーチャレベルのクエリーと同じ方法で、12_2機能レベルをグラフィックスドライバに問い合わせます。

> 備考
> 
>フィーチャーレベル12_2を、正しいCAPSセットが正しい値であることに基づいて推測することができますが、機能レベルの推測は既存の設計に反するため、ランタイムはこれを行いません。機能レベル12_2は、ドライバーによって明示的に報告されるものです。

12_2の列挙値は次のように表されます:

``` cpp
typedef
enum D3D_FEATURE_LEVEL
{
    // ...
	D3D_FEATURE_LEVEL_12_2 = 0xc200

} 	D3D_FEATURE_LEVEL;
```

機能レベル12_2は、他のフィーチャーレベルと同じように、例えばデバイスを作成するときに要求されます：

``` cpp
    ComPtr<ID3D12Device> device;
    D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_12_2;
    HRESULT hr = D3D12CreateDevice(nullptr, featureLevel, IID_PPV_ARGS(&m_spDevice));
    if (SUCCEEDED(hr))
    {
        // 機能レベルはディフォルトアダプターでサポートされている
    } 
```

## 機能
機能レベル12_2は、CheckFeatureSupportで直接問い合わせ可能な、機能と機能階層(tier)で表現されます。

デバイスが機能レベル12_2の場合、次のようになります。

|機能|12_2 での最低限	|公開仕様|
|:-----------|:------------|:------------:|
|要求ドライバーモデル|	WDDM 2.0	||
|シェーダモデル|	6.5	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/HLSL_ShaderModel6_5.html)|
|レイトレーシング階層|	Tier 1.1	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html)|
|可変シェーディングレート|	Tier 2	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/VariableRateShading.html)|
|メッシュシェーダ階層|	Tier 1	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html)|
|サンプラーフィードバック|	Tier 0.9	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html)|
|リソースバインディング階層|	Tier 3	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html#root-signature-version-11)|
|タイルリソース|	Tier 3	||
|保守的(Conservative)ラスタライズ|	Tier 3	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/ConservativeRasterization.html)|
|ルートシグネチャ階層|	1.1	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html)|
|深度境界テストサポート|	TRUE	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/DepthBoundsTest.html)|
|即時書き込みバッファサポートフラグ|Direct, Compute, Bundle	||
|リソース単位のGPU仮想アドレスビット最大値(MaxGPUVirtualAddressBitsPerResource)|	40	||
|プロセス単位のGPU仮想アドレスビット最大値(MaxGPUVirtualAddressBitsPerProcess)|	40||

さらに、次のフラグが設定されています。

|機能|12_2 での値|機能(英語)|
|:-----------|:------------|:------------|
|ウェーブ単位の操作|TRUE|WaveOps|
|出力合成でのロジック操作|TRUE|OutputMergerLogicOp|
|任意のシェーダからのVPとRTの配列インデックス、GSエミュレーションなしでラスタライザをサポート|TRUE|VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportWithoutGSEmulation|
|クエリーのタイムスタンプをコピーするクエリーのサポート | TRUE | CopyQueueTimestampQueriesSupported |
|完全に型指定された形式のキャストのサポート|TRUE|CastingFullyTypedFormatSupported|
|Int64シェーダ操作|TRUE|Int64ShaderOps|


> 備考
>
> 一部の仕様、特に2019年5月のアップデート以前の仕様はDirectX-Specsのリポジトリに移行されていません。

## DDI
Direct3D 12 UMD DDI には、機能レベルを説明するための列挙型 D3D12DDI_3DPIPELINELEVEL があります。この列挙型には、機能レベル 12.2 の値があります。


``` cpp
typedef enum D3D12DDI_3DPIPELINELEVEL
{
    // ...
    D3D12DDI_3DPIPELINELEVEL_12_2 = 14,
} D3D12DDI_3DPIPELINELEVEL;
```

ドライバーがサポートしている機能レベルを見つけるために、ランタイムはPFND3D12DDI_GETCAPSを次の設定で呼び出します。

* D3D12DDICAPS_TYPE_3DPIPELINESUPPORT, もしくは
* D3D12DDICAPS_TYPE_3DPIPELINESUPPORT1

この2つのGetCapsの使い方の違いは以下の通りです。

|セレクター            | データ解釈                                                              |有効な帰り値を与える機能レベル |
|:---|---|---|
|3DPIPELINESUPPORT    | D3D12DDI_3DPIPELINELEVEL, 簡単な出力値                                    |12.1 と、それ以前|
|3DPIPELINESUPPORT1   | D3D12DDI_3DPIPELINESUPPORT1_DATA_0081, 入力・出力フィールドを含む構造体  |すべて。12.2 と、それ以降を含む|

D3D12DDI_3DPIPELINESUPPORT1_DATA_0081の定義は以下の通りです。

``` cpp
typedef struct D3D12DDI_3DPIPELINESUPPORT1_DATA_0081
{
    D3D12DDI_3DPIPELINELEVEL HighestRuntimeSupportedFeatureLevel; // 入力
    D3D12DDI_3DPIPELINELEVEL MaximumDriverSupportedFeatureLevel;  // 出力
} D3D12DDI_3DPIPELINESUPPORT1_DATA_0081;
```

3DPIPELINESUPPORT1の場合、ランタイムはHighestRuntimeSupportedFeatureLevelの値を設定します。
ドライバーは、HighestRuntimeSupportedFeatureLevelを超えないMaximumDriverSupportedFeatureLevelの値を返します。

>#### 備考
> 実際には:
> 
> * Manganese (20H2)以前のOSに組み込まれたDirect3Dのバージョンでは、3DPIPELINESUPPORTを使用します。
> * Iron OS 以降に組み込まれたDirect3Dのバージョンでは、3DPIPELINESUPPORT1を使用し、失敗した場合は3DPIPELINESUPPORTに差し戻します。

### APIレベルとDDIレベルのレポート機能の不一致
D3D12_COMMAND_LIST_SUPPORT_FLAG_BUNDLE機能のWriteBufferImmediateSupportFlagsは、DDIレベルでD3D12DDI_COMMAND_QUEUE_FLAG_3Dを報告するドライバーのAPIレベルでオンになります。


## 検証

機能レベル12_2で作成されたDirect3D 12デバイスが少なくとも本ドキュメントの「機能」セクションで説明されている機能を満たすことを検証するためのDirect3D 12適合性テストがあります。これは、ドライバーではなくランタイムの動作を実行するため、HLKテストではなく適合性テストです。機能レベル 12_2 の特定のテストとは別に、CheckFeatureSupport の機能がデバイスの動作と適切に一致していることを確認するためのテストも行われています。

<!---
---
**DirectXの新機能 - 機能レベル12_2**
# 機能レベル(feature level)とは?
あなたがゲーム開発者で、コンピュータのハードウェア、もしくはハードウェアを操作するシミュレーションゲームと一緒に長い時間を過ごした人ならば、グラフィックカードがすべて同じものではないと知っているでしょう。差異があります。

全体的なパフォーマンス特性だけでなく、利用可能な機能の種類にも違いがあります。もちろん、Direct3D 12は、Windows上のDirect3D 12ドライバを搭載した**全て**のグラフィックカードで機能が保証されています。このような標準化は非常に価値があり、Windows上でグラフィカルなアプリケーションを作成するすべての人の生活を楽にしました。同時に、Direct3D 12は、特にテクノロジが向上し、進化するのに応じて、グラフィックカード間の差異をアプリケーションで管理しやすくする方法を提供してきました。アプリケーションは、クールな新しいハードウェア機能が利用可能になったときに活用できます。

Direct3Dにおける、「機能レベル」とは、グラフィックカードの一連の機能を表現するのに使われる名前です。「機能レベル」はグラフィックスカードのプロパティです。PCのお店に言ったり、友人から借りて、Windows 10デスクトップマシンと互換性のある2枚のグラフィックカードを見つけたとしましょう。しかし、それらは異なる機能レベルを持っている可能性があります。もしかすると、2つのGPUが異なるマルチGPUシステムを使用しているかもしれません。それらの間で機能レベルが異なる場合があります。ゲームとアプリケーションは、システムで使用可能な機能レベルを検出し、それに応じて一連の機能を使用するようにプログラムされることが期待されています。

機能レベルにより、新しいハードウェア機能の採用を奨励しながら、アプリケーションコードを合理化できます。 これらは、時間の経過とともに発生するGPUの世代ごとの改善をアプリケーションが理解するための便利な方法です。GPU機能の大まかなグループ化により、アプリケーションは、個々の機能の多くの組み合わせよりも簡単にレンダリングパラダイムのベースにのることができます。

連続する機能レベルは、機能のスーパーセットです。 たとえば、機能レベル12_1には、機能レベル12_0のすべての機能に加えて、いくつかの機能が含まれています。 そしてもちろん、機能レベル12_2にはそれ以前のもののすべての機能に加えて、いくつかの新しいものが含まれています。 正直に言うと、12_1から12_2へのジャンプは非常に大きなものです。

# なぜ新しいものが必要なの?

Direct3D 12には、機能レベルで表現するに値する重要なグラフィック機能がいくつかあります。これらの機能を使用したいアプリケーションを合理化し、すべてのゲーム環境でこれらの機能をサポートすることを容易にしたいという要望があります。これらの重要な項目は以下の通りです。

- DirectX レイトレーシング
- メッシュシェーダ
- 可変解像度シェーディング
- サンプラーフィードバック

さらに、機能レベル12_2には、以下に列挙する他の機能が含まれています。時間が経ち、より新しい機能レベルのグラフィックスカードがより広く利用できるようになると、面倒な機能チェックは単純な新しい機能レベルの存在に頼ることで削除できるため、アプリケーション開発者の生活はより楽になります。


## クエリー と API
アプリケーションであれば、他の機能レベルを要求するのと同じように、機能レベル12_2を要求します。これは、Direct3D 12デバイスを作成するときに行います。

``` cpp
    ComPtr<ID3D12Device> device;
    D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_12_2;
    HRESULT hr = D3D12CreateDevice(nullptr, featureLevel, IID_PPV_ARGS(&m_spDevice));
    if (SUCCEEDED(hr))
    {
        // 機能レベルはディフォルトアダプターでサポートされている
    }
```

より低い機能レベルでデバイスを作成した場合でも、CheckFeatureSupportを使って、デバイスに12_2が使えるかを問い合わせられます。 例えば：

``` cpp
    D3D12_FEATURE_DATA_FEATURE_LEVELS cap{};
    cap.NumFeatureLevels = 1;
    D3D_FEATURE_LEVEL requested = D3D_FEATURE_LEVEL_12_2;
    cap.pFeatureLevelsRequested = &requested;
    if (SUCCEEDED(device->CheckFeatureSupport(
        D3D12_FEATURE_FEATURE_LEVELS,
        &cap,
        sizeof(cap)))
        && cap.MaxSupportedFeatureLevel == requested)
    {
        // 機能レベルはこのデバイスでサポートされている
    }
```

ご覧の通り、12_2の列挙値は次のように表されます。

``` cpp
typedef
enum D3D_FEATURE_LEVEL
{
    // ...
    D3D_FEATURE_LEVEL_12_2 = 0xc200
} D3D_FEATURE_LEVEL;
```
簡単です。

## 機能

機能レベル12_2を構成するすべてのものは、CheckFeatureSupportを介して照会可能な機能と機能層として存在しています。 隠された機能などはありません。

デバイスが機能レベル12_2の場合、次のようになります。

|機能|12_2 での最低限	|公開仕様|
|:-----------|:------------|:------------:|
|要求ドライバーモデル|	WDDM 2.0	||
|シェーダモデル|	6.5	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/HLSL_ShaderModel6_5.html)|
|レイトレーシング段階|	Tier 1.1	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html)|
|可変シェーディングレート|	Tier 2	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/VariableRateShading.html)|
|メッシュシェーダ段階|	Tier 1	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/MeshShader.html)|
|サンプラーフィードバック|	Tier 0.9	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/SamplerFeedback.html)|
|リソースバインディング段階|	Tier 3	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html#root-signature-version-11)|
|タイルリソース|	Tier 3	||
|保守的(Conservative)ラスタライズ|	Tier 3	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/ConservativeRasterization.html)|
|ルートシグネチャ段階|	1.1	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/ResourceBinding.html)|
|深度境界テストサポート|	TRUE	|[Link](https://microsoft.github.io/DirectX-Specs/d3d/DepthBoundsTest.html)|
|即時書き込みバッファサポートフラグ|Direct, Compute, Bundle	||
|リソース単位のGPU仮想アドレスビット最大値|	40	||
|プロセス単位のGPU仮想アドレスビット最大値|	40||

さらに、次のフラグが設定されています


|機能|12_2 での値|英文|
|:-----------|:------------|:------------|
|ウェーブ単位の操作|TRUE|WaveOps|
|出力合成でのロジック操作|TRUE|OutputMergerLogicOp|
|任意のシェーダからのVPとRTの配列インデックス、GSエミュレーションなしでラスタライザをサポート|TRUE|VPAndRTArrayIndexFromAnyShaderFeedingRasterizerSupportWithoutGSEmulation|
|クエリーのタイムスタンプをコピーするクエリーのサポート | TRUE | CopyQueueTimestampQueriesSupported |
|完全に型指定された形式のキャストのサポート|TRUE|CastingFullyTypedFormatSupported|
|Int64シェーダ操作|TRUE|Int64ShaderOps|


# よくある質問(F.A.Q.)
## Q: グラフィックカードとドライバーが上記のすべての機能を報告する場合、グラフィックカードは自動的に機能レベル12_2になっていることになりますか?
A: 簡単な答え: 必ずしもそうではありませんが、ドライバの更新を取得するか、待つ必要がある場合があります。より長い答え: ドライバがDirect3D 12ランタイムと通信する際、ランタイムに機能レベルを伝えます。ドライバは、機能レベル12_2のサポートを明示的に報告する必要があり、ランタイムは自動的に機能レベルを推測することはありません。グラフィックスハードウェアメーカーは、それを報告するアップデートされたドライバを出荷しているかもしれません。これについて質問がある場合は、お使いのグラフィックカードのメーカーに問い合わせてください。

## Q: 機能レベル12_2で使うDirect3D APIは?
A: Direct3D 12でいいじゃん。今、私はあなたが何を考えているかわかります。「でも、過去の機能レベルによっては、Direct3D 11やDirect3D 12が使えたのに！？なんで12_2じゃないの？」 これは、前回の機能レベルから経過した時間の長さと、機能レベル12_2の内容がどれだけ大きなものであるかを物語っています。

12_2の機能、特に重要な機能は、Direct3D 11 APIで表に出ることはありません。例えば、Direct3D 11のプログラミングモデルでは、DirectXレイトレーシングなどの機能は利用できません。そのため、プログラミングモデルにアクセスできない機能を備えた機能レベルを要求することはほとんど意味がありません。一方、機能レベル 12_1 は、Windows 10 の最初のリリースと同時にリリースされました。この機能レベルには、Direct3D 11 と Direct3D 12 の両方のプログラミングモデルを通じて公開することに意味がある、理解しやすい機能が含まれていました。たとえば、タイルリソースを見てみましょう。これは、機能レベル 12_0 で保証されている機能です。11でリソースをタイル化し、12にリソースを割り当てました（「予約済みリソース」と呼ばれます）。保守的ラスタライズについても同様で、両方のプログラミングモデルで動作するように十分に広くスコープが設定されており、12_1に含まれていました。一方で、機能レベル 12_2 を構成する機能は膨大で、大きな API サーフェスを構成しています。Direct3D 12 プログラミングモデルとの緊密な統合によって、これらの機能は本当にうまく機能することができます。

詳細を一つ：Direct3D 11デバイスを作成するときに、順序付けされた機能レベルの配列を渡します。platform-availability-checkに成功した最初のフィーチャレベルが取得されます。そのリストに機能レベル12_2が含まれている場合、それを無視して次の機能レベルに移動します。呼び出し全体が失敗することはありません。

##  Q: 機能レベル12_2をサポートするハードウェアプラットフォームは?
A: 次のお知らせをできるのがうれしい:

- 機能レベル12_2は、NVIDIA GeForce RTXおよびNVIDIA Quadro RTX GPUでサポートされています。
- AMDの次期RDNA 2アーキテクチャベースのGPUには、フィーチャーレベル12_2の完全なサポートが含まれています。
- Intelのロードマップには、開発者が機能レベル12_2をフル活用できるディスクリートGPUが含まれています。
- Microsoftは、DirectX 機能レベル12_2のメリットをSnapdragonプラットフォームにもたらすようにQualcommと協力しています。

機能レベル12_2の強力な新機能は、ゲームやアプリケーション開発者にとって刺激的な新しい可能性を表しています。

##  Q: いつ機能レベル12_2の機能をプログラミングして、新しい機能レベルをSDKで確認できますか?
A: 朗報です。機能レベル 12_2 を構成する機能は、Windows May 2020 Update とその互換性のある SDK の [CheckFeatureSupport](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-checkfeaturesupport) を使用して、すでに個別に照会することができます。互換性のあるハードウェアがあれば、機能が表示され、すぐに準備ができます。

D3D_FEATURE_LEVEL_12_2自体については、機能レベルは[Windows Insider](https://insider.windows.com/)プログラム、SDK、ビルドバージョン**20170以降**で利用可能です。始めるには、プレビュー版のWindowsオペレーティングシステムとSDKの両方が必要です。低レベルの詳細については、GithubのDirectX-Specsレポジトリにある[Feature Level 12_2 仕様](https://microsoft.github.io/DirectX-Specs/d3d/D3D12_FeatureLevel12_2.html)をチェックしてみてください。ご意見をお聞かせください！[discord.gg/directx](https://devblogs.microsoft.com/directx/new-in-directx-feature-level-12_2/discord.gg/directx)のDiscordサーバーまでお気軽にお問い合わせください。
-->