DirectX一覧

BC7について段階的にデコードしてみた

BC7のCPUデコーダーを作っている過程でおもしろいものが確認できたので記事にしてみました。当たり前の話ではあるのですが、視覚化されたケースって無いようなので。
BC7 はいわゆる第2世代のテクスチャ圧縮技術で、各ブロックごとに最適なモードを選択してデータを圧縮しています。このブロックがどんな風に割り当てられているかを、ブロックごとの色分けで塗ってみたら以下のような結果を得られました。

image_partition

この段階でも各ブロックの特徴によってモード選択されているのが確認できます。そのためおおよその画像の検討が付く程度にはなっています。これらのブロック種別を順番に展開してみます。 続きを読む


DirectX9 と DirectX9Ex の違いをテクスチャの観点から

DirectX 9.0Ex では D3DPOOL_MANAGED が使えなくなりましたが、基本的にはデバイスロストが発生しなくなりました。そのため D3DPOOL_DEFAULT を使ってリソースを作成しても問題がなくなりました。もっとも D3DPOOL_DEFAULT でなければリソース生成に失敗してしまいますが。こんな便利になった DirectX 9.0Ex があまり注目を浴びていなかったようなのと、ちょっとした差異があるようだったので記事にしてみました。以降、 DirectX9 を DX9, DirectX9.0Ex を DX9EX と表現します。

基本的にはより厳密な制御を求められるようになった感じです。
従来の DX9 で D3DPOOL_MANAGED でリソースを作成し、何も気にせず Lock メソッドを使った場合、システムがよろしく制御を行ってくれました。パフォーマンスロスなどは発生しますが、動作はしていました。これもデバッグランタイムを使用していれば警告メッセージ等は出ていたかと思います。しかし、 DX9EX ではこれらについてエラーとなるようです。

ここではテクスチャについて見ていきます。

これは DirectX 9.0 では問題が発生しなかったコードです。しかし D3D9EX では、CreateTexture で失敗してしまいます。先ほど述べたように D3DPOOL_MANAGED が使えないためです。ここを D3DPOOL_DEFAULT にしてみると、テクスチャの生成には成功しますが、後続の LockRect で失敗します。このときのエラーメッセージは以下のように表示されました。

というわけでLockで書き込む際には D3DUSAGE_DYNAMIC が必要なようです。このことは、 D3DPOOL_MANAGED で作成し、LockRect にてテクスチャからの読み込みのコードを書いていた場合に失敗するということを意味しています。頻繁な読み書きをする場合には D3DUSAGE_DYNAMIC が必須という感じです。
 恐ろしいことに、D3D9 において Lockのフラグで D3DLOCK_READONLY をつけて読み込みロックをしていた場合でも D3DPOOL_MANAGED では書き込みすることが出来てしまいました。しかもそれが反映されるケースもありました。 D3D9EX では書き込み結果は反映されません。正しい挙動をしているといえます。

D3D9EX でテクスチャをCPUで読み書きする場合には、 D3DUSAGE_DYNAMIC フラグが必要といえると思います。このフラグさえ設定しておけば D3D9 のコードと他の部分は違いはなく動作できそうです。
逆に初期化だけで使えるスタティカルなテクスチャはどう作成するかを考えてみたところ、CPU上でのスステージングテクスチャを作成して、それを転送するという方法が考えられます。手順の擬似コードとしては以下のようになります。

まとめ

頂点およびインデックスバッファも同様ですが、一番違いの影響を受けそうなテクスチャについて調査してみました。

DirectX 9.0 Ex のよい点はデバイスロストからの解放だけでなく、フルスクリーンで自分のプログラムを動かした際に、他のプログラムに対してもデバイスロストを発生させないというのもあります。他のプログラムが DirectX 9.0だったとしても自分のプログラムが 9.0Ex でフルスクリーン化しても向こうもデバイスロストにならないのです。


DirectX12 で画面クリアまで (祝)

DirectX12 (D3D12) を使ってようやく画面のクリアだけエラーも起こらず動作させることができるようになりました。そもそも SDK が正式版ではないので、今後変更されることもあると思います。それでも気になる人のために、コードをさらしてみたいと思います。Windows8.x以降、 Win32 アプリケーションは肩身が狭くなってきた感がありますが、ここでのサンプルは相変わらず Win32アプリケーションで作成してみました。
以下の内容は既に古くなっています。以下のコードでも動きますが、よりコード量の少なくなったこちらの記事を参考にどうぞ
本内容は既に最新環境では正常にコンパイルできません。ご注意ください 2015/5

必要なもの

VisualStudio 2013 でも作業できそうに思いますが、すべて最新の状況で作業しました。作業している最中に Windows10 は 10049 に上がっちゃいましたが。以下のものをインストールしました。

  • VisualStudio 2015 CTP6
  • VisualStudio Tools for Windows10 Technical Preview
  • Windows10 Technical Preview 10041

d3d12_clear

とりあえず上記のように画面のクリア処理がうまく動くようになりました。結構手間取ったので喜びもひとしおです! 続きを読む


Direct3D9Exでフルスクリーン

DirectX9 でのフルスクリーンのサンプルはそこそこ見かけるのですが、DirectX9Ex でのフルスクリーンのサンプルってほとんど見かけないので作ってみました。通常の DirectX9 とほとんど同じで、違う箇所は初期化のところだけだったのでその部分だけを本記事では紹介したいと思います。

DirectX9Exの初期化

Direct3DCreate9 の代わりに Direct3DCreate9Ex を使用します。引数がちょっと変わっています。
そして定番の D3DPRESENT_PARAMETERS を設定します。本来はもうちょっとモニタの設定とか確認したりエラーチェック入れたりする必要があるのですが、サンプルなので省略してます。

ここでのポイントは特にないと思います。続いて CreateDeviceEx を呼び出してデバイスを作成するのですが、こちらの方には気をつけるポイントが存在します。まずはコードを示します。

ポイントとは、Windowモードの時には D3DDISPLAYMODEEX を設定してはならない点、フルスクリーンのときには設定が必須となる点が1つです。もう1つは D3DPRESENT_PARAMETERS のリフレッシュレート設定と DISPLAYMODEEX のリフレッシュ設定を同じにしなくてはならない点です。適当にゼロを入れておくのでは関数が失敗となります。

この関数が成功したらあとは通常の DirectX9 と変わらないです。

今回は不遇の扱いをされているDirectX9Ex のしかもほとんど情報がなさそうなフルスクリーンをやってみました。通常の DirectX9 と違い DirectX9Ex ではデバイスロストの問題も発生しないですし、割と使いやすいものだと思います。 Vista 以降を必須とする点はちょっとマイナスかもしれませんが、毛嫌いするほど出来が悪いとも思えないんですよね~


DirectX9 on Windows 7 でメモリの消費調査

今回は DirectX 9.0 を用いた場合ではどんな感じになるのかを調べてみました。環境は Windows 7 (x64) です。また DirectX 9.0 と表記していますが、実際のところは DirectX 9.0 EX のことを指すものとします。

Windows XP までの頃は VRAM の仮想化というものがなく、デバイスロスト発生のためのケアが必要になっていました。その代わり VRAM にデータを送ってしまい、メインメモリは消費しないということができたように思います。(もしかするとできていなかったのかもしれませんが、今更検証価値も低そうなので手元でテストしていないです・・・。)
一方で Windows 7 になってVRAM仮想化が導入され、VRAMの空き容量など取得が難しくなってきました。 DirectX 9.0 は動くものの、その挙動は XP のころとはまた違ったものになっていると予想されます。それなのに検証をしていないままだったので、 VRAMの情報取得という武器ができた今、調べてみようと思ったわけです。

NVIDIA (Geforce9800) の場合

安定状態になってから頂点バッファ 32MB を D3DPOOL_DEFAULT にて作成しました.

状態 メモリ(MB) Dedicate(MB) 共有メモリ(MB)
定常状態 1054.6 47 13
VertexBuffer作成 1回目 1086.7 80 13
VertexBuffer作成 2回目 1119.3 112 13

どの場合においてもメインメモリ 32MB 程度消費し、Dedicate のメモリ 32MB ほど消費している結果となりました。

AMD (RADEON) の場合

状態 メモリ(MB) Dedicate(MB) 共有メモリ(MB)
定常状態 1028.9 45 22
VertexBuffer作成 1回目 1061.1 77 22
VertexBuffer作成 2回目 1093.8 109 22

こちらの場合においてもメインメモリ 32MB 程度消費し、Dedicate のメモリ 32MB ほど消費している結果となりました。

実験その2

描画フレームを回しながら、 100 フレームごとに頂点バッファを確保し描画するという定番のプログラムで実験してみました。
上記の消費メモリが永続的なものではなくテンポラリ扱いならば、相当の数のバッファが作れるはずです。

しかし予想外の結果になりました。

メインメモリの消費が、自分のプロセスに対して発生していました。どうやら D3DPOOL_DEFAULT では自プロセスのどこかにバックアップのバッファが存在するようです。

GTX 750Ti 2GB の状態で普通の 32bit アプリケーションで実行の場合には、x64環境といえども、 1プロセスで使えるサイズは 2GB まで。そのため VRAM 使用量が 1GB 程度のところで DirectX がバッファの作成に失敗しました、とエラーを出しました。このときのプロセスの状況を調べてみましたが、消費されている仮想アドレスが 2GB 近かったです。
 一方で、 32bit アプリで LAA オプションをつけて再実行してみると、今度は VRAM 使用量は 1.7GB 程度にまでなり、プロセスの仮想アドレス使用量は 4GB 近くにまでなっていました。

※ このプロセス内での状況を知るのに VMMap というツールは便利です。

まとめ

DirectX 9.0 の場合においては NVIDIA も AMD も同じような挙動となることを確認できました。またどちらの場合においても使用するリソース分、メインメモリも消費していることが確認できました。これはこれで挙動把握さえできてしまえば、扱いやすそうです。
ただ注意が必要であると感じたのが、自分のプロセスの仮想アドレス空間にバックアップ先を確保するため、メモリ不足よりも自身の仮想アドレス空間を枯渇させてしまうのが早そうに思います。 64bit 環境を必須とするなら 32bit アプリケーションの場合、 LAA 必須といってもいいレベルだと思いました。
 この場合、よいビデオボードを使っていて 「 4GB の VRAM 全部使いきる DirectX 9.0 アプリケーションを開発してやるぞ。 ただし 32bit アプリケーションだけどなっ」 という夢はかなわないことが判明しました。そんな人は少数派だとは思いますが・・・。


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 リソースとして使用始めたらやや注意が必要になっていきそうです。ビデオメモリ仮想化が入ったといわれる現時点においても、なるべく搭載量を超えないようにするのはマナーとしておいたほうがよさそうです。


XInputの注意事項

最近になってゲームパッドのコーナーを見てみると、純正XBOX 360パッド以外でもたくさんの XINPUTの対応パッドが並んでいることに気付きました。これはXINPUT無視できないなーと感じました。また多くのパッドが DirectInput との切り替えスイッチを持っていて、両対応できるようになっていました。
 これはアプリケーション側も両対応しておいたほうが何かと都合良さそうな感じです。

ひとつ注意事項があります。
VisualStudio 2012など使っていると DirectXSDKが統合されたこともあり、XInputのインクルードやライブラリのリンクについてちょちょいとやってしまえるのですが、ここに罠があります。
 VisualStudio 2012 では標準の対象 OS が Windows8 であることを想定しているため、XInput も Windows8のものをリンクするようになっています(XInput.lib指定時)。これを回避して、Windows7やWindows8で動くようにするためには、リンクするライブラリを “Xinput9_1_0.lib” に変更します。これで Windows7の環境でも動作させることが出来るようになります。ただ古いバージョンになるため使用できるAPIに制限が出来てしまいますので、注意が必要です。

参考: XInput Versions(MSDN)


OpenGLとDirectX11で、あと何が足りてないか

ここ1ヶ月ほどは主に最近のOpenGLについて勉強しているわけですが、DirectX11と比べてまだ何が足りていないかまとめてみます。

やったこと

  • テクスチャ配列 (DX10だけど)
  • ジオメトリシェーダーでストリームアウト&ポイントスプライト (DX10だけど)
  • ハードウェアでのインスタンシング描画
  • テセレーションのシェーダーについて(TCS, TES)
  • シェーダーの実行関数の動的切替(DX11でいうところのDynamic Shader Linkage)
  • インダイレクト描画

まだやれていないこと

  • Texture Buffer (なんかよくわかっていない)
  • コンピュートシェーダー(OpenGL4.3で入った)
  • UAV関連(↑のコンピュートシェーダーの範疇かも)
  • NVIDIA の DirectX と OpenGL の inteop
  • NVIDIA の bindless 色々(GL4.4では標準化されてGL_ARB_bindless_texture).
  • Tiled Resource (DirectX11.2の機能らしい. GLではGL_ARB_sparse_textureだとか)

VisualStudio 2013をインストールしてみた

MSDNのほうではVisualStudio 2013がRTMになってダウンロード可能となったのでインストールしてみました。
今回はその記録です。

まず素のWindows7にインストールしようとしたら、セットアップできませんでした。
InternetExplorer10 を要求するようです。
DirectX SDKを使って開発している場合にはこれが少々問題になって、IE10インストール後はPiX for Windowsが使用できなくなるようです(詳しくはこちら)。
IE10のインストール後は、VisualStudio2012の付属のツールを使って調査して下さい、ということのようです。
・・・でもこれだとDirectX9が非対応のようで残念なのですが。時代的にもうDirectX9は積極的なサポートのほうは終了という意思の表れのように感じます。

ランタイムで気になった物のバージョンを調べてみました。

  • .NET Framework 4.5.1
  • VCランタイム 12.00.21005.1
  • Windows Kitsフォルダ内には 8.0 と 8.1 の両方のファイルが存在
    • d3dcompilerもそれぞれにあった。d3dcompiler_46/47.dll, d3dcsx_46/47.dll となっていて、これらは再配布可能フォルダにあった。

Windows8 RTMでは .NET Framework 4.5 だったのでわずかに上がってます。Windows7 SP1のころでは、.NET Frameworkは 3.5.1だったので、4がスキップされてますね。

続きを読む


DDSのRGB 10bitフォーマットの罠

今更といえば今更な話なのですが、あまり情報がないようにみえたのでここにメモしておきます。DDSフォーマットの A2R10G10B10 や A2B10G10R10 の並びの画像データについて罠というか、マイクロソフトも承知のバグが潜んでいました。具体的には、チャンネルのマスクビットが逆転しています・・・。

続きを読む