「 2010年10月 」一覧

D3D10_TEXTURE2D_DESCのArraySize。テクスチャ配列の罠?

DirectX10でテクスチャ配列使ってみようと思い、
ソースコードを書いて試そうとした矢先に躓きました。D3D10_TEXTURE2D_DESCのArraySize = 2; として、
テクスチャを作成するも失敗。

なんていうエラーメッセージが出てくる始末。

いろいろと試行錯誤した結果、
D3D10_USAGE_DEFAULT で作成したもののみ、テクスチャ配列使えるみたい。
CPUから書き込める USAGE_DYNAMICでは使えなかった。

これらのことから、テクスチャ配列は作成時に値を確定させておく、
Immutableな使い方しか出来ない、ということなんだろうか。
D3D10CalcSubresourceなんていう位置計算してくれる補助関数あるのだから、
CPUからも書き込みできるようになっていると期待するのは間違いなんだろうか。


プログラマ的ご飯のおかずに…

この日記でコメントつけてくれましたしゅんぼーさんとご飯に行ってきました。
ご飯を食べながら、ライブラリの設計やその思想を語り合えたのは有意義でした。

  • パフォーマンス優先マルチプラットフォーム
  • 単一プラットフォームマルチAPI

という思想の違いでそれぞれの意見を交わせました。

DirectX10,11などで存在する機能(GS,DS,HS)に対するアクセスを、
DirectX9モードで使用するというような場合には、どうしようもないのですが、
後者の思想ではどのようにこれに対する結論を出すかがやはり難しいですね。

一定水準以上の機能を使った場合、同一コードでAPIを切り替えるのはやはり無理だ…

Device::getSpecificDevice10(); => DirectX10以上で使える機能はここからアクセス.
Device::getSpecificDevice11(); => DirectX11以上で使える機能はここからアクセス.

今のところこんな感じで想定してみました。

その他

話をしていて、参考になった項目の記録です。

  • ShaderResourceViewのビューの概念は意外と使えそう。
    • デバイスとかシェーダーにセットするのは、このビュー
  • テクスチャ配列の概念
    • ある単位の形状描画で使う(マルチ)テクスチャは、ほぼ一意に定まり、特定の要素のみ入れ替えるというのはほとんど無い。
    • そのためにこれらの集合を1つの単位で扱えると都合がいい
      • という解釈を聞いて、なるほど!と思いました。

HW ShadowMapのために。

HW ShadowMapのために最近の状況をしらべてみました。

  • NVIDIA
    • Geforce7x00くらいのころから搭載*1
    • テクスチャとしてUSAGE_DEPTHSTENCIL付きでD24S8フォーマットで作成可能
    • これをサンプリングするときに4近傍からの平均がとれてしまう。
  • AMD
    • fetch4
      • X1800以外のX1xxxシリーズで使用可能
      • このとき、DF24というフォーマットでテクスチャを作れる
      • このサンプリング時にfetch4機能で4サンプルとって、シェーダー内で平均算出
    • 通常のD24S8テクスチャ
      • RADEON 2000以上で使用可能になっているよう
      • サンプリング時に4近傍からの平均が求まってしまう。

このような相違があります。

では多くの環境でHWシャドウマップ技術を使うには、という点を考えてみます。

*1 : 6×00系ですでに使えたかも

多くの環境でHWシャドウマップ技術を適用するには

まず、環境がNVIDIAかAMDかで振り分けます。

NVIDIA時

D24S8形式のテクスチャ(USAGE_DEPTHSTENCIL付き)が使えるかを調べます。

もし使えないようならば、完全ソフトウェアのシャドウマップを使うしかありません。

AMD時

  1. D24S8形式のテクスチャが使えるかを調べます。
    1. これが使えるのはRADEON 2000以上です。PCFが有効でデプス値はサンプリングだけから求まります。
    2. 使えるならこれを使用します。使えない場合に以下に続きます。
  2. 続いてfetch4機能が使えるかを調べます。
    1. 使えるのは、RADEON X1x00以降です(1800を除く)。PCFはかからないので、自前で平均を計算します
    2. 使えるならこれを使用します。使えない場合に以下に続きます。
  3. 完全ソフトウェアのシャドウマップを使用します

このような感じで適用すべき機能が振り分けられると思います。
ここでいう完全ソフトウェアのシャドウマップとは、
D3DFMT_R32Fなどの単一要素のカラーとしてレンダーテクスチャを作成し、カラー値としてデプスを書き込む感じになります。

まとめ

これらの方針で一度実装してみようかと思います。
現在の多くの環境では、完全ソフトウェアのシャドウマップをやらなきゃいけないということはないと思われます。
DX10対応しているハードであれば、HWシャドウマップは使えるはずですし。
そうでないにしても、fetch4くらいは使える環境が多いのではないでしょうか。

個人的には、この記事を元に、マルペケつくろ~のIKDさんがサンプルおよび、ここよりわかりやすい解説に発展させてくれないかなと、密かに期待しております。


低レベルなDirectX9

ドライバーの内部エラーについて、ここに記載がちょっとありました。http://msdn.microsoft.com/ja-jp/library/ee417865%28VS.85%29.aspx

こんな仕組みになっているけど、デバイスの破棄および再生成で処理を復帰っていうことが、
果たしてどのくらい可能なんだろうか。ちょっと疑問に思います。

でも、IDirect3DDevice9::ValidateDevice というメソッドを DrawPrimitive系の直前に挿入して、
デバイス状態を確認するという手法はなかなか良さそうに思いました。
デバッグビルドとかフラグでそんなコードになるように、元々のコードに準備をしておくのは役立つかもしれません。

コマンドバッファな話

Direct3D API 呼び出しの正確なプロファイリング (Direct3D 9)と題して、MSDNに記載を発見。
以前はどこかのWeb記事でDirectXのコマンドバッファの話を読んだ気がしていましたが。
このドキュメントの本来の意味は、タイトル通りプロファイリングの話です。
しかし、アプリケーションから実デバイスまでに設定データ類がどのように伝達するか、というのが使用されている図と、プロファイリングの注意点より読み取ることが出来ます。

ドキュメントの後方にある構成の図はなかなかわかりやすいです。
結局デバイスに到達するときには、各設定はコマンドバッファというバッファに単純なコマンドとして記録された状態になっています。
GPUはそのバッファを順番に解釈し、実行しているだけに過ぎません。

もちろん、このやりとりにはデバイス制御があるため、
カーネルモードに遷移したりするのですが、この部分まできちんと説明があるため、
このドキュメントはよく出来ていると思いました。


Collada+DirectX

海外のサイトで、COLLADAとDirectXの話が書いてありました。
さらりと見てみましたが、COLLADA DOMとその中身にどうアクセスするか、
各種メッシュ(静的メッシュ、スキニングのような骨の親子構造を持つもの、モーフィング)の扱い方
これらについて丁寧に書いてありました。
ただし、英語で、ですが。ここに。→ http://thecansin.com/2010/10/collada-loading-for-directx/

ソースコードも同時に公開されているのでかなり参考にできそうです。

書籍を購入しました

ちょうどタイミングを同じくして、「MESH GURU」という書籍を購入しました。
まだざっくりとしか読めてないですが、その内容と今回の海外でのサイト情報とがほぼ一致してるような気がして、
急いで中身を見てみましたが、全く一緒と言うことはありませんでした。
用語が一緒で、ドキッとしたくらいですね。

.xやFBX,COLLADAとフォーマットをまたいでの知識であれば書籍を、
COLLADA特化なら上記の海外サイト情報がお勧めできそうです。

各種モデラーからデータを出す場合には、最近はCOLLADAがいいのですかねぇ・・・?
FBXも捨てがたいとは思うのですが。悩みどころのような気がします。


GLSLのデバッグ

GLSLをデバッグするのによいツールはないかと探してみたところ、
次のソフトウェアが見つかりました。

  • glslDevil
  • shader maker

これらについて書いてみます.

glslDevil

見た感じは、これが本命となりそうです。
手元で試してみたところ、OpenGLのAPIのトレースは行ってくれるのですが、
シェーダーのデバッグというのが行えませんでした。

最初 RADEON搭載機だから?と思い、Geforce 9800GTを搭載しているPCで試してみましたが、
こちらでも状況は変わりませんでした。(glslDevilは1.1.5を使用)

どちらの環境もNV_transform_feedbackをサポートしているので、
動作はしてくれると思ったのですが、どうにもこうにも動かずでした。

OpenGL APIを呼び出し後にInvalid Operationとなるようなものをキャッチしてくれたりするので、これ目的ではとりあえず使えそうです。
glslDevilのサイトでは、実装概念となる論文も掲載されていますし、
これを元に自作することも可能なのかなと思います。

Shader Maker

昔のDirectXのサンプルにあったEffectEditっぽい感じがします。
テキストエリアにシェーダーコードを入力して、ビルド。
そして、ビューの部分で結果を確認という感じです。

パラメータを設定する部分もGUIから出来ますし、
表示されるモデルもまた任意のものに入れ替え可能みたいなので、
シェーダーを作る、という点においてはこれでも何とかなるのかなと思います。

デバッガではないために、値を見るという部分は手作業で、カラーとして画面に出して確認、というような方法をやっていく必要があります。


shlwapi関連の罠

ファイルパス操作関連のAPIで便利なshlwapiがあります。
しかし今回はこれの操作で思いの外、はまってしまった。通常CreateFile等では、ファイルパスに””の代わりに”/”が設定されてもファイルを開くことが出来きます。
しかしながら、shlwapi系では、””で設定されていないと正常に動作できないという。

当然ながら、ファイルパスの区切りは、””で行うのが正解です。

このあたりに注意して、せめてコード中は””でパス区切りを行うようにしましょう。

ユーザー入力部では”/”にもなり得ることを想定して、
“/”を””に置換するようなコードが必要になると思います。
この際には、CharNext(),CharPrev()等の関数を用いて文字列を操作することがポイントです。


glGetActiveUniformの挙動 -その2-

先日の日記に書いたglGetActiveUniformの件についての続報です。早速辞書順に並ばない結果を取得できてしまったので、
やはり名前アクセスしたいときには辞書順ソートを自前でいれておくべきです。

(ユーザーの勝手な)思いこみは危険。


D3DPOOL_MANAGEDのデータ保存先について

D3DPOOL_MANAGEDについて。
どうやら生成元となったバイナリデータ列はユーザー空間に置かれる模様。そんな挙動のため、結局のところは使用メモリがどんどん増えていくように見える。
仮に256MBほどテクスチャがあったとすると、このフラグ付きで送った場合には結局メインメモリにも同じ容量だけメモリを使われていることになってしまう。

また先日作業用のメモリとって、必要に応じてUpdateTextureで転送すればいいと書いたけど、これも結局のところD3DPOOL_MANAGED相当を自前でやっているだけに過ぎない…。

意外といけてなかった。
もっとよりよい方法を考えてみることにします。