「 DirectX11 」一覧


Windows Server 2016 で RemoteFX GPU の実験


Windows Server 2016 で個人的に魅力的に感じている RemoteFX 仮想 GPU について実験してみました。

Windows Server 2016側の準備

Hyper-V の役割だけでなく、リモートデスクトップ仮想化ホスト の役割もインストールして RemoteFX を使えるようにします。
今回の環境では Intel HD Graphics のドライバがうまく適用できなかったので、
Radeon 7750 を装着して DirectX, OpenGL が動くようにしました。
ちなみに最近のドライバをインストールしましたが、 WHQL 非取得でしたが、 7750 でも Vulkan も動きました。
(vulkaninfo を実行できて、情報が色々と表示されました)。

第2世代仮想マシンでは RemoteFX GPU が使えないという情報があったので、
仕方なく第1世代仮想マシンを作成し、 Windows10 Pro をインストールしました。

ちなみに 第2世代仮想マシンで RemoteFX GPU がちゃんと動いたという情報もあるのですが、
現時点においては正式なサポートというわけでもないようなので、まずは第1世代で試したというわけです。
続きを読む


BC7の圧縮ノイズについて調べてみた


優秀だという BC7 圧縮の品質がどんなものか調べてみました。
そのためにはそこそこの品質以上の画像データが必要だったので友人に協力してもらい画像を使わせてもらっています。
この場を借りてお礼申し上げます。

BC7への圧縮については Codeplex からダウンロードできる Microsoft の TexConv を使用しています。この最高品質となる CPU で処理した結果ではなく、 GPU を用いた速度とのバランスがとれているであろうモードを選択しています。

比較

いきなりですが圧縮前後の画像を比較してみます。
左が圧縮前、右が圧縮後のデータです。圧縮ノイズなどは確認できるでしょうか?自分では等倍でぱっと見た感じわかりませんでした。心持ち髪の毛曲線部とアルファの部分でノイズが気になるかも程度です。
compare_std_bc7_sample01
compare_std_bc7_sample02

続きを読む


DirectX11の場合のシステムメモリとVRAM消費について


今までは OpenGL の場合を調査してきました。今回は DirectX11の場合を調べてみようと思います。ドライバが一緒ならきっと同じ傾向を示すんじゃないかなと予想して実験をスタートです。

実験

DirectX11のプログラムとして、100フレームごとに頂点バッファ 32MB を確保し、次フレーム以降はこのデータを使って描画するプログラムを作成しました。
各フレームでの各メモリの使用状況を取得して、グラフ化しました。

実験は以下の環境で行いました

  • GTX750Ti Windows 7 347.09
  • RADEON HD 5450 Windows 7
  • RADEON HD 5450 Windows 8

結果

それぞれの実験結果のグラフを以下に示します。

nvidia_memory_graph_dx11_win7

radeon_memoy_graph_dx11_win7

radeon_memoy_graph_dx11_win8

NVIDIA も AMD も同じような挙動を示す結果となりました。また VRAM が使用可能な状態であれば、追加のシステムメモリの消費もなく良好といえそうです。(とはいっても追加のメモリを要求されたのは NVIDIA OpenGL の場合のみでしたが)。さすが仕様が決まっている DirectX といえるかなと思います。
 ちなみに RADEON のほうのグラフ末尾がおかしなことになっていますが、このときアプリは相変わらずフリーズ状態になってしまいました。ですので、システムメモリを VRAM リソースとして使用始めたらやや注意が必要になっていきそうです。ビデオメモリ仮想化が入ったといわれる現時点においても、なるべく搭載量を超えないようにするのはマナーとしておいたほうがよさそうです。


DirectX11で複数ウィンドウを使ってみる


最近Mach-Oの調査ばっかりやっているので、DirectX11とか触ってるとほっとします。

昨今では2つのディスプレイが繋がっていることも珍しくないと思います。
それぞれに対してDirectXアプリケーションのフルスクリーンやりたいとか、独立した複数ウィンドウでDirectXの描画やりたいとかそういうときにどうしたらよいかを実験してみました。

結論から言えば、複数のデバイスコンテキストを作る必要すら無く、レンダーターゲットビューとスワップチェインを複数持つことでこれらを実現出来ることがわかりました。デバイスが独立ではないのでリソースも共有出来ます。

初期化

DirectX11の初期化部分を説明します。
D3D11CreateDeviceAndSwapChain関数を使用して初期化することは出来ないようで、必要なオブジェクトを順番に作成していく必要があります。まずは D3D11CreateDevice関数でデバイスの初期化、続いて必要な数のスワップチェインの作成となります。
スワップチェインの作成はデバイスから直で出来ず、DXGIのオブジェクトを数回経由する必要があります。

これらの処理をざっくりと以下に示します。

スワップチェインを作成できたら、それぞれのウィンドウ(場合によってはディスプレイ)に対してのバックバッファを作成しておきます。
これはpSwapChain[0]->CreateRenderTargetViewでいつも通りに作成する感じです。必要ならデプスステンシルも作成しておきます。

描画

描画の方は何も難しいことはありません。複数のレンダーターゲットを扱ったことがある人なら意識するような違いがないです。コードを以下に示します。

まとめ

マルチウィンドウにすることでどのくらい2重でデータ持ちしないといけないかと心配しましたが、結構楽に実現出来ることがわかりました。スワップチェインが個別という程度で、他はマルチレンダーターゲットやっているときと変わらない感じです。

今回試してみたプログラムでは以下のようにリソースも1つでそれぞれに描画してみました。

dx11_multi_window


DirectX11でMSAA


DirectX11でMSAA(Multi Sampling Antialias)を試してみました。
検索でよく見つかるのが、プライマリのバッファをMSAA使用する例はよくみかけるのですが、テクスチャレンダリングする場合においてMSAA有効でレンダリングするというサンプルを見つけることはできませんでした。
そんなに難しい話ではないのですが、サンプルプログラムが見つからなかったので今回作成してみました。

まずは結果です。テクスチャを描画先(レンダーターゲット)として三角形を描画しています。その結果をテクスチャとして取得して、四角形のポリゴンに貼り付けて表示しています。
result-msaa

結果を見てもよくわからないので、MSAA OFFの場合の結果を以下に表示します。

msaa-off

これでもよくわからないかもしれません。そこで両者を比較して拡大したものを示してみます。これならば違いがわかるでしょうか?MSAAが有効なものについては、ポリゴン境界がなめらかに見えるように色が補間された結果が見えています。

msaa-comp

手順について

レンダーターゲットとしてテクスチャを使う方法についてはここでは説明しません。
ここではMSAAテクスチャを作成する方法と、それをテクスチャとして使う方法の2つを説明したいと思います。

MSAAテクスチャの生成

描画先となるテクスチャを作成する際に、MSAA用のパラメーターを設定します。
D3D11_TEXTURE2D_DESC 構造体の SampleDesc内のパラメータが該当するのですが、ここにパラメータを指定します。

これらのパラメータの設定がよくわかりませんでしたが、下記に示すように CheckMultisampleQualityLevels から取得できる Quality値を指定しておけばよいようです。

この例だとおそらく 4x の MSAA が有効となるようです。

MSAAテクスチャとして使う

上記の pRenderTargetにたいして描画行われた後でテクスチャとして使用するためにはResolve処理を行わなくてはなりません。またこのときに、Resolve結果格納先として別のテクスチャが必要になります。
普通はこのResolveされたのテクスチャを他の描画で使用します(正確にはこのテクスチャのShaderResourceViewを、ですが)。

まずはそのResolveテクスチャの作成についてはこんな感じになります。

Resolve処理

簡単ですが、D3DDeviceContextについて以下のAPIを呼ぶだけです。

レンダーテクスチャを使う際の注意点といいますかお作法として、
レンダーテクスチャ(RenderTargetViewとして)セットする前に、そのテクスチャがShaderResourceViewとしてセットされていないか確認し、すでにセットされているならば解除しておくことが望ましいようです。
D3Dのデバッグレイヤー有効にするとわかるのですが、シェーダーリソースとして設定されているものをレンダーターゲットとして設定した際に、警告メッセージが表示されます。これはそのシェーダーリソースがシェーダーで使用されていなくても警告がでますので要注意です。

サンプルプログラム

今回のサンプルプログラム全体です。VisualStudio2012で作成しています。
SampleMSAA11サンプルプログラム(Zip)

まとめ

意外と使われないのか、テクスチャに対するMSAAをやってみました。


Draw Indirect 系を調べてみた (OpenGL vs DirectX)


OpenGL では Draw Indirect 系が充実しているとの情報があったので、DirectXとどのように違うのかを調べてみました。

DirectX 11 では、 DrawInstancedIndirect(), DrawIndexedInstancedIndirect() の2つの関数が DrawIndirect系として使用可能です。DirectX10では DrawAuto() という関数が存在して、DirectX11ではこれを汎用化して上記の関数群となったようです。

上記の関数はインデックスバッファ有・無しの違いで分かれているだけで、インスタンス描画を考慮するもののそれ以上の機能は持っていないようです。

一方で OpenGL の Draw Indirect 系は次の関数が用意されています。

  • glDrawArraysIndirect()
  • glDrawElementsIndirect()
  • glMultiDrawArraysIndirect()
  • glMultiDrawElementsIndirect()

ちなみに、glMultiDrawArraysIndirect() は、複数回の glDrawInstancedIndirect() を1回の呼び出しとするようなものです。また glDrawArraysIndirect() が DrawInstancedIndirect() に相当するようです。Indirectのバッファの中には、インスタンス数を指定する項目も含まれるようです。

複数回の描画を束ねられる glMultiDrawArraysIndirect ですが、結局のところ CPU 側に描画数を通知しておく必要があります。そこが何ともうまくないところですが、ARB_indirect_parameters という拡張でこの対策がおこなわれているようです。
 ARB_indirect_parameters では、インスタンス数を格納しておくためのバッファが追加サポートされるようになります。そのバッファが GL_PARAMETER_BUFFER というもので、GLsizei のデータを入れておく入れ物となっています。関数としては、glMultiDrawArraysIndirectCount, glMultiDrawElementsIndirectCount となっています。


DirectX11で旧シェーダーコード(HLSL)を使う


DirectX11(DX11) は DirectX9(DX9) に対応したハードでも一応動かすことが出来ます。このとき、DX9 にのみ対応ハードで動かす場合、DX11 の機能は当然使えません。シェーダーに関しても同様で、頂点シェーダー、ピクセルシェーダーのみを使用することになります。

fxcや関連するドキュメントをみると、そういった DX9 ハード用のシェーダープロファイルとして、次のものを使用するようになっています。

  • vs_4_0_level_9_0
  • vs_4_0_level_9_1
  • vs_4_0_level_9_3
  • ps_4_0_level_9_1
  • ps_4_0_level_9_3

確かに、DirectX11 の仕様を守って新規にシェーダーファイルを作って行く場合には何の問題も無いのですが、昔からのコードを現世代で動くようにと作業している場合、これだけの指定では足りないのです。

例えば、以下のようなシェーダーファイルのコードがあったとして、これを上記のプロファイルに従い、 vs_4_0_level_9_3 でコンパイルしたとします。

これをコンパイルすると次のようにエラーが表示されます。

fxc /T vs_4_0_level_9_3 vs.hlsl

error X4541: vertex shader must minimally write all four components of SV_Position
compilation failed; no code produced

これをエラー無く、かつ、シェーダーコードを修正することなくシェーダーコンパイルを成功させるためには、/Gec オプションを指定します。

fxc /T vs_4_0_level_9_3 /Gec vs.hlsl

これで vs_4_0 系のタイプでシェーダーをコンパイルすることが出来、DirectX11 のプログラム上で使用することが可能になります。
内部的には、出力セマンティクスのPOSITION を SV_POSITION として勝手に扱ってくれるようです。コマンドラインでコンパイルした結果を見るとそんな感じに見えます。

なお、D3DX11ShaderCompileFromFile で、この “Gec” オプションに相当するものは、 D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY となるようです。

感想

意外と DirectX11 で古いシェーダーコードをそのまま使うという話はないのかな?と思いました。
調べてみても情報はほとんど出てきませんでした。
確かにDirectX11 は初心者にはちょっと手間な部分も多いですし、ある程度までなら DirectX9 を使ってしまった方が楽で、やりたいことを実現できますし。
それでもどこかで、同じように悩んだ人に、この記事が役立ってくれるといいなと思います。


DirectX11とDirectX9比較


DirectX11(D3D11)はDirectX9ハードウェア上でも動きます。
そういう場合に、DirectX11とDirectX9ではどちらを選択すべきだろうか、と思ってちょっと比較をしてみようかと思います。

チェック環境

  • RADEON HD 5450(DX11対応ハード)
  • Geforce9600GT
  • Geforce6800GT

サンプルプログラムとしてBasicHLSL11というSDK付属の物を使います。
これを実行してFPSの計測を行います。

チェックしてみる項目は以下の通り

  • D3D11デバイスでD3D_FEATURE_LEVEL_11_0
  • D3D11デバイスでD3D_FEATURE_LEVEL_10_0
  • D3D11デバイスでD3D_FEATURE_LEVEL_9_3
  • D3D9デバイス

結果

それぞれの場合でFPSを計測すると以下のようになりました。
(解像度は800×600)

条件 FPS値(5450) FPS値(9800GT) FPS値(GF6800)
D3D11+D3D_FEATURE_LEVEL_11_0 1170
D3D11+D3D_FEATURE_LEVEL_10_0 3625
D3D11+D3D_FEATURE_LEVEL_9_3 1220 4183 1604
D3D9 965 1367 1201

D3D9 vs D3D11では、圧倒的にD3D11の方が高速に動作しているようです。
そして貧弱なハードウェアだからか、レベルを落とした方が若干高速でした。
この結果を見ると、DX9とDX11(9_3レベル)を悩むならDX11のほうがよいと言えます。


DirectX11始めました -第3回-


今回はプログラムを修正して4角形にしたうえで、テクスチャを貼ってみます。

今回のプログラムの流れ

準備段階

第2回のものに加え、以下の準備を行います。

  1. テクスチャの準備
  2. サンプラーオブジェクトの準備

また以下の修正を行います。

  1. 頂点データの修正
    1. TEXCOORDの追加
  2. シェーダーの変更
  3. 頂点入力レイアウトを変更

メッセージループ

画面クリア処理の後、以下の設定を行います。

  1. バッファのセット
    1. 頂点バッファのセット
    2. 入力頂点の情報オブジェクトをセット
  2. シェーダーのセット
  3. テクスチャのセット
  4. サンプラーオブジェクトのセット
  5. 描画命令を発行

テクスチャの準備

今回はD3DXの関数を使って楽にテクスチャを作成します。

シェーダーから使うテクスチャは ID3D11ShaderResourceViewとして表現されます。
D3DX11には便利な関数が用意されていて、D3DX11CreateShaderResourceViewFromFile というものを使うと、ファイル名を指定するとこのID3D11ShaderResourceViewを作成してくれます。

サンプラーオブジェクトの準備

D3D11_SAMPLER_DESCの構造体に値を代入し、CreateSamperStateメソッドにてサンプラーオブジェクトを作成します。

頂点バッファの修正

このような感じで、頂点データおよび頂点バッファの作成部分を修正します。

シェーダーの修正

テクスチャを使うようにシェーダーファイルを修正します。

頂点シェーダー

ピクセルシェーダー

頂点入力レイアウトの修正

TEXCOORDのセマンティクスが追加されているので、それにあうように修正します。

描画処理

シェーダーのセットしたあたりで、テクスチャとサンプラーオブジェクトをセットします。

感想

DirectX10のサンプルを書いていたときには、テクスチャの作成がもう少し手間でした。
一旦ID3D10Texture2D作って、そこからシェーダーリソースビューを作っていました。
今回は、D3DXのAPIの中に便利なものがあったのでそれを使ってみました。1行でシェーダーリソースビューが取得できてしまうので便利です。
とはいえ、DirectX9のときには、D3DXCreateTextureFromFileが使えたので、それと同じことだったりします。

HelloDX11_3 ソースコード