「 2010年11月 」一覧

XenServer on VMware


VMware Workstation7 の仮想マシン環境で、
XenServer 5をインストールしてみました。

しかし、どうやら完全仮想化はサポートされない模様。
仮想マシン内で仮想マシンが正しく動くって言われているのは、
サポートリストにあるESXi4だけなのかも。

この環境では、Hyper-Vはそもそもインストール不可のため、
XenServerの場合はどこまで試せるかを実験してみたいと思います。

VMware上でXenServerをインストール

無事にインストールは完了。
途中で警告が出てきますが、これが完全仮想化使えないよって意味合いのメッセージでした。
わかりやすく”Windowsは使えないです”って文章が出てきたと思います。

この上にのせる仮想環境としてCentOSを考えているため、
linux用の追加ディスク(パッケージ)もインストールしておきます。

CentOSをインストール

仮想マシンにCentOS 5.2, 5.4 のそれぞれx64版をインストールしました。
インストール時にGUIが使えなく、テキストベースのインストールをする必要があります。

インストール後は問題も起きず、正常に起動出来ました。



RADEONドライバ誤作動-動画再生編-


問題点(不具合)

RADEON 5450搭載しているWindows7環境での話です。
エンコードしたムービーをメディアプレイヤー12で再生していると
画面がチラチラとちらついて表示される。

解決策

以下の設定を行うことで、ようやく正常に再生させることが出来ました。

  • Catalyst Control Center/”Avivoビデオ”
    • すべての設定
      • 高水準画質/”ダイナミックコントラストを有効にする” のチェックをOFF
      • ビデオ再生/”強制的になめらかなビデオ再生を実行する”のチェックをOFF

要は、ドライバの動画再生支援高画質化の処理で誤作動してしまった、
ということですね。

今のところは、これで問題なく動いていそうなので解決です。


パラメトリック曲線 -失敗編 その2-


調べてみてやっと分かりました。
やりたいことは、ベジェ曲線の3次を使えば出来そうです。接線角度が0のときはおおよそ一致するのですが、
角度設定や長さが設定されたときの挙動と計算についてまだまだ謎です。

うーん、むずかしい。


パラメトリック曲線 -失敗編-


カーブについていろいろと試行錯誤中。
SoftImage ModToolにあるようなアニメーションカーブエディタGUIを作ってみようかと思ってます。
↑まずはぬるくC#でと考え中です。しかし、同様の曲線が書けないところで躓いてます。
エルミートスプライン、ベジェ、どれにしてもうまくいかず。
接線ハンドルの値と実際の接線ベクタの値に何か係数があるのかなぁ。

フレーム 接線ハンドル値
1 0 左右とも角度は0, 長さは10.0
30 180 左右とも角度は0, 長さは10.0
60 0 左右とも角度は0, 長さは10.0

こんな設定で作ったSoftImage上のカーブ

エルミートスプラインで作ったカーブ(C#)

C#で作ったカーブでは、接線ベクタとしては
SoftImageに設定した長さ10という点から、(10.0f,0)という方向のベクタを設定しました。

みてわかる通り、形状がそもそも違ってしまっています。

  • カーブの種類選択が既に間違っている
  • 接線ハンドルの値と、実際にカーブ計算に使う値の間には補正係数がある

など考えられるかなぁと思っていますが、
詳しくは分からない状態です。

この日記を見たどなたか分かる人、どうか教えてください。

[追記]
→ 一部判明しました。
どうやら3次のベジェ曲線でうまく出来そうです。


D3DPOOLについて考える


今回はDirectX9でのD3DPOOLについて考えてみました。
最近はDX10の話だったので、ちょっと流れをぶち切ってしまいました。
以下の話は、すべてWindowsXP DirectX9での話となります。
Vista以降のDirectX9Exの話はまた異なるため、そのうちにでも。

説明

http://msdn.microsoft.com/ja-jp/library/ee418784%28v=VS.85%29.aspx
このページを見てしまってから思い悩むことになってしまいました。
今までは、以下の方針でリソース作成を行っておけばいいと思っていたのですが。

  • 途中で更新するデータである
    • → D3DPOOL_DEFAULT + DYNAMIC付き
  • 上記以外
    • → D3DPOOL_MANAGED

この背景には、D3DPOOL_MANAGEDであればデバイスロスト時の処理が楽になる点と、
実際にはVRAMへ転送済みであるということを想定していたからでした。

しかし、この理解は若干間違っているというのが、図によって分かりました。

  • D3DPOOL_DEFAULT
    • VRAM上かAGPメモリに配置される
    • DYNAMICリソースであればAGPメモリに配置される
  • D3DPOOL_MANAGED
    • VRAM上かAGPメモリ上、それとシステムメモリにバッキングストアとして配置される

このようになっていることが図から読み取れます。

理解が間違っていたのはD3DPOOL_DEFAULTは常にVRAMと思っていた点でした。

まとめ

さて、これらの点からどのようにリソースを配置していくべきかを考えてみました。

PC用と想定すれば、実際に動かされる環境はまちまちなので、ドライバに任せる部分は任せて、
多少の動作速度改善に向けた配置を心がけるのが良さそうです。

  • 途中で更新するデータ
    • 頂点orインデックスバッファなら D3DPOOL_DEFAULT + DYNAMIC付き
    • テクスチャなら D3DPOOL_DEFAULT + D3DPOOL_SYSTEMMEMの2重持ち
      • SYSTEMMEMに更新したいデータを埋めて、あとで転送する方式にします
  • データは最初から終わりまで不変
    • D3DPOOL_MANAGEDで配置。
    • D3DPOOL_MANAGEDはドライバによって実際に配置される場所が決定される。
    • この配置決定には、パフォーマンスや使用状況も考慮されるためお勧めの模様。

注意点としては、上記の動的なデータというのは限りなく少なくしておくべきという点でしょうか。
今回ドキュメントを読んで知ったのですが、MANAGEDとDEFAULTの混在はビデオメモリの断片化を招き、よろしくないとのことです。
DEFAULTを先に作成し終えてから、MANAGEDリソースを作るのが良いとのことです。

もしも対象としている動作環境が VRAM 256MB必須 としてしまい、それ以下の搭載メモリの状況では動作を保証しないというのであれば、
D3DPOOL_MANAGEDを使用する代わりにDEFAULTでもいいのかなと思います。
デバイスロストのときには、データを再度読み込むか、あるいは、SYSTEMMEMで最初から持っておくとかそういうようにして準備する必要はあると思います。
実際にDEFAULT+SYSTEMMEMの両方持っているという状況はOpenGLでは(実装の上では)このようにやっているように見えます。
(メモリの使用状況を見ていると、倍くらい使用メモリが多いので)。



DirectX10でテクスチャ配列を使用する例


前回の日記で書いた、DirectX10でテクスチャ配列を使用するサンプルができました。
いろいろとはまりどころはあったのですが、ようやく出来ました。
注意点はその都度説明します。今回のサンプルではテクスチャ配列を使う例ということで、
下の図のようなイメージで実装しました。

2枚のテクスチャをテクスチャ配列として、あたかも1つのテクスチャオブジェクトとして扱います。
それを、描画の際にはUVのUの値でブレンドさせて表示させてみるということを行っています。

シェーダーコード

頂点シェーダーは以前のものと変更していないので省略します。
以下にピクセルシェーダーのソースコードを貼り付けます。

前の説明にも書いたように、テクスチャ配列内でテクスチャを特定するのは取得するUV値の次の要素に配列内インデックス値を入れます。
つまり今回 xyにUVなので、z要素にそのインデックス値を入れています。

C++コード側

肝となるのはテクスチャ配列のデータの準備からデバイスに設定するまでだと思います。
そのためここではその部分に絞って説明します。

テクスチャ配列を作る

まず、2枚のテクスチャの準備を行います。
今回は2枚のddsファイルを用意してこれらを準備する段階で1つのテクスチャ配列に入れるということをします。

こんな感じでメモリ上にDDSファイルの中身を読み込んでおきます。
続いて、ID3D10Texture2Dのオブジェクトを作成します。
そのために次のように D3D10_TEXTURE2D_DESCを用意します。
ポイントとなるのは、ArraySize = 2と設定しているところですね。

また、この例ではDDSの中身を知っているため解析もせずに直接値を放り込んでいます。あくまで例ということでご注意ください。

そして、D3D10_USAGE_DEFAULT で作成する必要があったので、
データを放り込むためにはサブリソース情報を使わなくてはなりません。
また、ここがポイントですが2枚のテクスチャを1つのテクスチャ配列に入れるために、サブリソース情報は2つのサイズで作成します。

具体的には以下に示すような感じになります。
なお、DDSは128バイト目からが実データなので直接設定してしまっています。

これらの情報からテクスチャを作成します。

リソースビュー

このままではシェーダーにセットできないので、
ここからシェーダーリソースビューを作成します。
シェーダーからもテクスチャ配列として扱いたいので、それように作ります。

ポイントは、ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2DARRAY; と設定しているところと、
それにあわせてテクスチャの構造を記載している部分です。
(ベースレベルミップマップの番号とテクスチャそのものがもつミップマップ数とか)
これらの情報を元に、シェーダーリソースビューを作成します。

ここまで出来ればあとはデバイスに設定するだけです。

セットおよび描画

通常の1枚テクスチャを設定するのと変わらないコードとなります。

まとめ

特に注意が必要だったのはデータを作成する部分でした。

  • サブリソースはテクスチャ配列の数だけ必要
  • シェーダーリソースビューの作成の ViewDimensionには
  • D3D10_SRV_DIMENSION_TEXTURE2DARRAYを設定すること。
    • RTVやDSVのTEXTURE2DARRAYではない点に注意です。

この部分さえクリアすれば何も難しいことはありませんでした。

今回テクスチャ配列を使った例って見かけないので、
とっかかりのコードとして作成してみました。
使い方、やり方わからない!って人達の助けになればいいなと思います。

ダウンロード

今回のソースコード(cppのみ)をおいておきます。

HelloDX10_4.cpp テクスチャ配列を使う例


DirectX10以降のテクスチャ配列について


今回気になることもあって、改めて調べてみました。

はじめに

聞いていた話ではテクスチャ配列の利便性っていうものは、
複数のテクスチャを1つの変数(名)で扱えて便利だよって感じでした。
また大抵の場合、使用されるテクスチャの集合(セット)はユニークであるし、
そういった場合にはそれら集合をまとめて変更できるから良いって話でした。

あるモデルに付いているテクスチャは複数の種類存在します。

  • ディフューズマップ
  • スペキュラマップ
  • ノーマルマップ

だけどもモデルのデータにおいて、その中身はすべて異なるわけです。
よってそのテクスチャ配列を1つ交換するだけで、上記の例だと3つのテクスチャが交換でき、便利。

という話を聞いていたわけです。

疑問点はどこか

テクスチャ配列は1つの変数名となっています。
これのインデックス値を変えることで、参照先テクスチャを変えてサンプリングしてくるわけです。
しかし、サンプリングしてくるのにサンプラーユニットは共通しているわけで、
そうなると、サンプラーのほうに負担がかかってしまうのではないかと思ったのです。

よって、サンプラーがボトルネックになってしまい、
この機能のうまみはないのでは?と疑問に思いました。

DirectX10でのアクセス方法

DirectX10ではシェーダーファイル内で次のようにして、
指定された配列番号のテクスチャを参照することができます。

※ 今までにテクスチャ配列から値を読み出すコードって見たことがないので、書いてみました。
配列内での序数は、UV値設定の最後の要素に入れる、というのさえ分かってしまえば、
他何も難しいことはなさそうです。

まとめ

このコード例を書いていて、気付いてしまいました。
そう、DirectX10以降ではサンプラーはテクスチャと別に設定できるようになったのでした。
だから、テクスチャ配列内序数ごとに使用するサンプラーを切り替えてあげれば、
危惧していた問題点も無くなるというわけです。

このように、サンプラーの設定は N個必要だけど、
テクスチャについては、テクスチャ配列を用いるようにした場合1つの切り替えだけで済むということになりそうです。

補足

とりあえずテクスチャ配列のサンプルを作成中です。
サンプラー使い回しの例で、軽くやってみる予定です。