昨日の記事で Quadro FX 1700 と 570 の違いに関して
>おそらく Core/Shader クロックでも違いがあるのでしょう。
こんなことを書きましたが間違いでした。
すみません訂正いたします。
ELSA の製品情報を見たら core クロックは同一でした。
なので、おそらく sp 数による性能の差別化だと思われます。
昨日の記事で Quadro FX 1700 と 570 の違いに関して
>おそらく Core/Shader クロックでも違いがあるのでしょう。
こんなことを書きましたが間違いでした。
すみません訂正いたします。
ELSA の製品情報を見たら core クロックは同一でした。
なので、おそらく sp 数による性能の差別化だと思われます。
ようやく ShaderModel 4.0 対応 Quadro の 1000系がでてきました。
・NVIDIA、ミッドレンジ/エントリー向け「Quadro FX」のラインナップを拡充
1000系はメモリが少なかったので、しっかり 512MB あるのはいい感じです。
ただ 1700/570 も全体的にメモリの転送性能が下がっていますね。
メモリだけ見ると Shader3.0 時代の Quadro の方がバス幅も転送レートも
高かったようです。
そのため記事のスペックだけ見てると、一見 570 との差が少なくなり
FX570 がお得に見えてしまいます。でも公式の比較表をみると
実行性能でもきちんと差別化がはかられているようです。
おそらく Core/Shader クロックでも違いがあるのでしょう。
・NVIDIA Quadro FX Product Comparison
この上の FX 4600/5600 とは性能も(値段も)差がありすぎるので、
3000番台も復活してくれるといいのですが。
HYPERでんちの GPU 表も更新しました。
・DirectX10 GPU
表を見て気がついた疑問。Desktop の Quadro FX1700 や FX570
よりも Mobile の Quadro FX1600M や FX570M の方が転送レートが
高いのはなぜだろう。
ブエルタ、やっとペタッキが勝った!
・復活の勝利、ペタッキがブエルタ通算18勝目を飾る
Autodesk Maya 2008 来ました。
保守に入っていればすぐにダウンロードすることができます。
これまでは 7.0、8.0、8.5 のようにナンバリングされていましたが
今回から 2008 です。略して Maya08。Maya8.0 に似てますが違います。
インストールフォルダも 2008 になりました。
起動時の Output Window にはまだ Maya9.0 と表示されています。
内部的には本当は Version 9.0 ?・・いえいえ
API の Version 番号は一気に増えて 200800 になっていました。
以前は ~ 700、800、850 だったので、内部的にも本当に 2008 に
なっているみたいです。
API 850 → 200800
いろんな機能追加があると思いますが、D3D 関連だと
・mentalray の dds 入力サポート
・hlslShader の追加
あたりが主なトピックでしょうか。
Maya 自体は dds に対応していたものの mentalray では使えなかった
ので、うっかり dds を貼ったシーンをそのままレンダリングして
落ちたり・・。それを回避するために事前に texture path を置き
換える mel を作ったり、なんてことが過去にはありました。
ビューポートで描画できるハードウエアシェーダーは 4.5 あたりから
ついており、今までも CgFx 等を使って表示させることができました。
今度は HLSL の対応です。Direct3D の Effect (fx) フォーマットの
ファイルを読み込み、マテリアルとして適用することができます。
実際に使ってみました。
・Plug-in マネージャーで hlslShader.mll を有効にする
・Panel の Renderer を Default (High Quality でない) にする
・Panel の Shading から Hardware Textureing を ON にする
これで hlslShader のノードを作って描画確認できます。
とりあえず
C:\Program Files\Autodesk\Maya2008\devkit\plug-ins\
に入っている、Maya_fixedFunction.fx を読み込ませると簡単な
描画テストができるようです。
CgFx と違い、OpenGL ではなく本当に Direct3D を使っています。
ついに Maya 上で Direct3D を扱えるようになったわけですね。
API 的には class MD3D9Render が追加されており、ここから
IDirect3DDevice9 のインターフェースを取得することができるようです。
基本的には
World
WorldInverse
View
ViewInverse
Projection
WorldView
WorldViewProjection
などの古くから使われている一般的な Semantic に対応しています。
また Annotation を使った DXSAS にも対応しているようです。
(DXSAS = DirectX Standard Annotations and Semantics)
ただし Maya 内のライトとのリンクはまだ行われておらず、
シェーダーに入力されるパラメータの一種として設定しなければ
ならないようです。
実際に hlslShader を使いながらの開発はまだしないかもしれま
せんが、D3D のインターフェースを直接扱えるようになった点は
かなり大きな変化だと思います。
残念ながら D3D10 ではありません。Direct3D 10 だと Vista に
限定されてしまうし、まだ仕方ないのかもしれません。
Buffer への書き込みに DISCARD + Map() を使うことで、ドライバが
バッファの Rename を行うことができます。つまりアプリケーション
側では同一のバッファのつもりでも、実際はぜんぜん違うメモリに
書き込んでいたりするわけです。
これは最適化のためで、フレームバッファと同じようにドライバ側で
勝手に SwapChain 化してくれるようなもの。
その代わり Rename 数の上限によってバッファが枯渇する可能性が
あるそうです。(関連は下記エントリ)
・Gamefest Japan 2007 (2) Direct3D 10
この Rename の状況を軽く調べてみました。
●同じバッファが割り当てられているかどうか確認する方法
(1) Map() した時のアドレス値 (*ppData の値) を比較する。
(2) D3D10_MAP_WRITE_DISCARD かつ D3D10_CPU_ACCESS_WRITEのみ
であるにもかかわらず、敢えて前回書き込んだ値を読み出してみる。
(1) だけでも十分かもしれませんが念のため (2) も調べました。
●条件
ConstantBuffer を作成してみます。Map() でアクセスするには
下記の指定が必要です。
・D3D10_USAGE_DYNAMIC
・D3D10_CPU_ACCESS_WRITE
・D3D10_BIND_CONSTANT_BUFFER
使用した GPU は GeForce8800GTS です。
●未使用バッファ 16byte
16byte のバッファを作って、毎フレーム Map() で書き込んでみました。
このバッファは特に ~SetConstantBuffer() していないので、Busy に
なることはないはずです。
左から
・アドレス
・Bufferサイズ
・これから書き込む値
・書き込み前に読み出したメモリの値
と並んでいます。
addr size write read 073eb400 16byte (00000000) 00000000 073eb800 16byte (00000001) 00000000 073eba00 16byte (00000002) 00000000 073ebc00 16byte (00000003) 00000000 073ebe00 16byte (00000004) 00000000 073ec000 16byte (00000005) 00000000 073ec200 16byte (00000006) 00000000 073ec400 16byte (00000007) 00000000 (A) 073ec600 16byte (00000008) 00000000 ~ 073f4600 16byte (00000042) 00000000 073f4800 16byte (00000043) 00000000 073ec400 16byte (00000044) 00000007 (B) 一周 (A)で書き込んだ 7 073ec600 16byte (00000045) 00000008 ~ 073f4600 16byte (0000007f) 00000042 073f4800 16byte (00000080) 00000043 073ec400 16byte (00000081) 00000044 (C) 一周 (B)で書き込んだ 44 073ec600 16byte (00000082) 00000045 073ec800 16byte (00000083) 00000046 ~
アドレスは 512byte 単位で割り振られています。60個程度のバッファが
順次割り当てられ、繰り返し利用されているように見えます。
未使用バッファでも毎回違うアドレスになるのは予想外でした。
●未使用バッファ 512byte
512byte のバッファではずれが小さくなっています。どちらにしろ
未使用バッファなのでたまたまかもしれません。
addr size write read 0727b600 512byte (00000000) 00000000 0727b800 512byte (00000001) 00000000 0727b600 512byte (00000002) 00000000 0727b800 512byte (00000003) 00000001 0727b600 512byte (00000004) 00000002 ~
●実バッファ 1088byte
実際に ~SetConstantBuffer() してシェーダー参照されている
描画に使っているバッファを見てみます。
addr size write read
*L1 0754b000 1088byte (0) 0
*L1 0754b000 1088byte (1) 1
*L1 0754b000 1088byte (2) 2
*L1 0754b000 1088byte (3) 3
*L1 0754b000 1088byte (4) 4
~
ここでの write は、1つ前のフレームで書き込んだ値です。
アドレスも、前回書き込んだ値も一致しています。
同じバッファが割り当てられています。
このプログラムは厳密に CPU と GPU の同期を管理しているため、
次の Map() までに描画が完了してしまっている可能性があります。
●実バッファ 1088byte ×2
1フレーム中、同じバッファに2度転送を行ってみました。
L0/L1 のペアで1フレームです。
addr size write read
*L0 0735b000 1088byte (0) 0
*L1 0735b500 1088byte (1) 0
*L0 0735b000 1088byte (2) 1
*L1 0735b500 1088byte (3) 2
*L0 0735b000 1088byte (4) 3
*L1 0735b500 1088byte (5) 4
~
今度はそれぞれ異なるバッファが割り当てられています。
参照されている Buffer は実際の描画が完了するまで Busy に
なり、アクセスから保護されている様子がわかります。
やっと予想した動作が見えてきました。
●実バッファ 1088byte ×20
今度は1フレーム中、同じバッファに20回書き込みます。
addr size write read
*L0 0719b000 1088byte (0) 0
*L1 0719b500 1088byte (1) 0
*L2 0719ba00 1088byte (2) 0
~
*L17 071a0500 1088byte (17) 0
*L18 071a0a00 1088byte (18) 0
*L19 071a0f00 1088byte (19) 0
*L0 0719b000 1088byte (20) 1
*L1 0719b500 1088byte (21) 2
*L2 0719ba00 1088byte (22) 3
~
Rename の様子が良くわかります。
ちなみに各 Map() と Map() の間に Draw を挟んでいないので、
本来は最後の Map() 以外は破棄してかまわない状況です。
今のところ Map( DISCARD ) を実行した数分だけバッファが
割り当てられているようです。
Busy の情報はリネーム元のバッファ1つ分しか持っていない
のでしょうか。
●実バッファ 1088byte ×20000
2000回では変化無かったので、一気に 20000回行きます。
*L0 071fb000 1088byte (0) 0 *L1 071fb500 1088byte (1) 0 ~ *L3916 0aee5c00 1088byte (3916) 0 *L3917 0aee6100 1088byte (3917) 0 *L3918 071fb000 1088byte (3918) 1 *L3919 071fb500 1088byte (3919) 2 *L3920 071fba00 1088byte (3920) 3 ~
20000回を待たずに再利用されています。
やっぱり本当は使っていないことがばれているのかもしれません。
ここまでで考えられるバッファサイズはおよそ 8Mbyte でしょうか。
動きは見えましたが、完全に捕まえるためにはきちんとテスト
プログラムを作った方がよさそうです。ちょっと試したくらいでは
まだわからないですね。
引き続き Microsoft Gamefest Japan 2007 の話題です。
関連エントリ
・Gamefest Japan 2007 (1) Direct3D 10 と Meltdown
・Microsoft Gamefest Japan 2007
Direct3D 10 に直接関連するのは下記の 2コマです。
1. Windows Vista グラフィックス 開発の手ほどき: Direct3D 10 and 10.1
2. Windows to Reality : D3D10 グラフィックスのゲームへの投入
メインはたぶん 2. の方でしょう。内容は、D3D9 から D3D10 へ
の移行を促すためのアドバイスです。
・9 から 10 に移行しても API を変えただけでは必ずしも速くならないこと
・どうして API や仕組みを変えたのか
・理由を踏まえてどう使えばいいのか
・Direct3D9 から移行しつつ 10 で想定した使い方を引き出す手法
とはいえ Direct3D10 の SDK に触れたことが無いと、少々
ぴんとこない内容だったかもしれません。
そのため前提となる知識として、Direct3D10 を解説した 1. の
「Windows Vista グラフィックス 開発の手ほどき: Direct3D 10 and 10.1」
が入ります。
逆にすでに D3D10 上で設計し、実際に開発をしている人に
とっては、移行時のテクニックも不要なので参考になる点は
少なかったかもしれません。
現在 D3D9 を使っている人、または移行中の人がターゲットです。
D3D9 から D3D10 への設計の変更や API の大きな変更は、
技術者が新たに使い方を覚え直す必要があり、また移植性や
ソースの互換性を失うリスクがあります。
それでもやる価値があると判断したわけで、その一番の目的は
パフォーマンスの向上でした。
ところが D3D10 の機能変更の意義と、新しい設計の意味を
きちんと理解して使わなければパフォーマンスがさっぱり
あがらなかったものと考えられます。
つまり単なる移植で D3D9 から機械的に API を置き換えた
だけではだめだということです。
そのポイントをいくつか絞って紹介しており、比較的大きな
変更をしなくても D3D10 の設計思想に合わせられる折衷案も
合わせて提示されています。
最終的な結論は、やっぱり D3D10 の機能を活用し、
そのために新たに設計しなおすことが一番とのこと。
以下いくつか気になった点など
バッファを Map(Lock) して CPU がアクセスする場合、
DISCARD や NO_OVERWRITE 指定は高速だということが良く知ら
れています。その理由は GPU/CPU が同期待ちをする必要が
無いからで、特に DISCARD はドライバが必要に応じて
Buffer Rename を行います。
この Rename 数には上限があって、バッファが枯渇する
可能性があることが述べられていました。
なるほど、そこまで考えたことはありませんでした。
ConstantBuffer は DISCARD アクセスしかできないので、
更新手段を選択する判断材料になりそうです。
UpdateSubresourece() に関する説明は、メモリコピーの負荷が
アプリケーション側しか考慮していないように見えたので
少々わかりにくかったかもしれません。
Clear~() 系はフレームバッファ全体なので、ステートに
基づいたクリアが必要ならシェーダーを作ってポリゴンを
書けとのこと。
cbuffer より tbuffer の方がランダムアクセスに適している
場合があるそうです。index によるアクセスなど。
これは意外でした。
そもそも cbuffer が速くないのか、
インデックスのアドレッシングが苦手なのか、
texture cache のおかげなのか、
いつか検証してみたいポイントです。
[unroll(n)] は n 回までのアンロールを強制して、最適化
のヒントに使える、と書かれています。
でも以前試した限りでは、回数指定をつけると n 回で
ループ自体を打ち切ってしまうのでプログラムの動作その
ものが変化してしまいます。もしかしたらこれは意図した
動作では無いのかもしれません。
ConstantBuffer は自前で管理せよとのこと。
この辺は構造からしてやっぱり、といった感じ。
Direct3D 10.1 に関しては特に目新しい情報はありませんでした。
ShaderModel4.1 の変更は思ったより小さいかもしれません。
単に 10.1 用の新しいリソース命令が追加されただけ、とか
十分ありえます。ps1.0→1.3 と同じような感じで。