2006/11/26
GeForce8800 注文と PS3 のモニタで悩む
やっと GeForce8800 を注文しました。(GTSだけど)
未だに旧世代の AGP で粘っていたので、Video カードだけでなく PC丸ごとの
発注となりました。最初は Vista 発売まで待つつもりだったんだけど、
品薄らしくてすぐに入手できるとは限らないので、思い切って買いました。
ちなみに今のPCについてるカードは GeForce6800GT (256MB,AGP) です。
たしか GeForce6800Ultra と GT がほぼ同時期の発売で、ShaderModel3.0 の
デビューと同時入手です。
Playstation3 も欲しかったのですが、よくよく考えたら家には PS3 がつながる
モニタが全くありません。普通の TV すらなくて、つながりそうなのは PC 用の
液晶モニタ VGA(DVI-A), DVI-D だけです。
(TV は携帯の V905SH だけで何とかなってます、、)
Xbox360 のように VGA ケーブルがあればいいんだけど PS3 には無さそうです。
Playstation3 がつながるモニタをまとめると次のようになります
○SDアナログ接続
・ビデオ端子(黄色いコネクタ) のTV
・S端子 のTV
・D2端子 のTV
○HDアナログ接続
・D3~D5 対応 TV
・コンポーネントケーブル 対応TV
○デジタル接続
・HDMI 端子付きの TV で表示
・HDMI 端子付きの液晶モニタで表示
・HDMI から DVI-D 変換して HDCP 対応の DVI 端子付きモニタで表示
参考ページ
・はじめてのPS3 Q&A
D端子/コンポーネント を VGA (DVI-A) に繋ぐには「トランスコーダ」という
色差→RGB 変換機が必要だそうです。
この場合入力信号の色フォーマットだけ置き換えるので、同期信号の周波数や解像度
などは変わりません。そのため RGB に変換しても入力信号にモニタが対応して
いなければ表示できないようです。
解像度まで自由に変換できるものはスキャンコンバータに分類されます。スキャン
コンバータはバッファリングが必要なので、ものによっては遅延が発生する可能性
があります。
もし PS3 が入手できたら、SD (ビデオ/S) 接続の場合はとりあえず安価な
スキャンコンバータか PC用キャプチャカードを使い、HD ならトランスコーダを
試してみようと思っています。
このあたりの情報は下記のページを参考にさせていただきました。
・Transcoders Info in 2ch
http://trasco.s53.xrea.com/
・液晶モニタ de 次世代ゲーム機
http://wiki.livedoor.jp/lcd_de_game/d/FrontPage
未だに旧世代の AGP で粘っていたので、Video カードだけでなく PC丸ごとの
発注となりました。最初は Vista 発売まで待つつもりだったんだけど、
品薄らしくてすぐに入手できるとは限らないので、思い切って買いました。
ちなみに今のPCについてるカードは GeForce6800GT (256MB,AGP) です。
たしか GeForce6800Ultra と GT がほぼ同時期の発売で、ShaderModel3.0 の
デビューと同時入手です。
Playstation3 も欲しかったのですが、よくよく考えたら家には PS3 がつながる
モニタが全くありません。普通の TV すらなくて、つながりそうなのは PC 用の
液晶モニタ VGA(DVI-A), DVI-D だけです。
(TV は携帯の V905SH だけで何とかなってます、、)
Xbox360 のように VGA ケーブルがあればいいんだけど PS3 には無さそうです。
Playstation3 がつながるモニタをまとめると次のようになります
○SDアナログ接続
・ビデオ端子(黄色いコネクタ) のTV
・S端子 のTV
・D2端子 のTV
○HDアナログ接続
・D3~D5 対応 TV
・コンポーネントケーブル 対応TV
○デジタル接続
・HDMI 端子付きの TV で表示
・HDMI 端子付きの液晶モニタで表示
・HDMI から DVI-D 変換して HDCP 対応の DVI 端子付きモニタで表示
参考ページ
・はじめてのPS3 Q&A
D端子/コンポーネント を VGA (DVI-A) に繋ぐには「トランスコーダ」という
色差→RGB 変換機が必要だそうです。
この場合入力信号の色フォーマットだけ置き換えるので、同期信号の周波数や解像度
などは変わりません。そのため RGB に変換しても入力信号にモニタが対応して
いなければ表示できないようです。
解像度まで自由に変換できるものはスキャンコンバータに分類されます。スキャン
コンバータはバッファリングが必要なので、ものによっては遅延が発生する可能性
があります。
もし PS3 が入手できたら、SD (ビデオ/S) 接続の場合はとりあえず安価な
スキャンコンバータか PC用キャプチャカードを使い、HD ならトランスコーダを
試してみようと思っています。
このあたりの情報は下記のページを参考にさせていただきました。
・Transcoders Info in 2ch
http://trasco.s53.xrea.com/
・液晶モニタ de 次世代ゲーム機
http://wiki.livedoor.jp/lcd_de_game/d/FrontPage
2006/11/25
シェーダーとスレッド化
GeForce8800 になって Shader Unit のマルチスレッドがどうこうといわれるように
なったわけですが、スレッド化そのものは ATI(AMD)系だろうとかなり前から
使われているテクニックです。
この辺の話は後藤さんの記事でかなり突っ込んで紹介されています。
http://pc.watch.impress.co.jp/docs/2006/1121/kaigai320.htm
この記事で書かれている3つのスレッディングのうち「カスケード」と呼ばれている
ものは割と初期の段階から用いられています。後藤さんの説明では「メモリアクセス」
のレイテンシを隠蔽するためとなっていますが、これはもともとシェーダーの
パイプラインを埋めるのが目的です。
例えばシェーダー命令で直前の命令と依存関係が発生する場合、アウトオブオーダー
実行でない限りパイプラインの終了を待つためにストールが発生します。
dp3 r0.x, r2, c5
rsq r1.x, r0.x
この例では dp3 の d0.x の演算が完了するまで rsq は実行できません。命令上は
順番並んでいても、パイプライン化が行われているためすべての命令実行は半分以上
がオーバーラップしているからです。
仮にパイプラインステージ数が5段と仮定するとイメージ的には次のようになります。
・依存関係がない場合
dp3 F D E E W _
rsq _ F D E E W
・依存関係がある場合
dp3 F D E E W _
rsq _ F D _ _ E E W
前の命令完了を待つため数サイクル分のストール(パイプラインの空き)が生じます。
そのため動作速度を上げるには、命令を並べ替えて依存関係が発生しないように
プログラムを改良する必要があります。
(なお、この例ではレジスタの読み書きに関するストールなので、実際はバイパス化
でもうちょっと効率が上がるかもしれません)
シェーダーでは依存関係がない複数の演算が同時に大量発生するので、複数のコン
テキストを用いたスレッド化(カスケード化)でパイプラインを埋めることができます。
例えば 3スレッド(カスケード)で頂点演算する場合 V0~V2 の3頂点を同時に処理
します。
V0:dp3 F D E E W _ ... (1)
V1:dp3 _ F D E E W _
V2:dp3 _ _ F D E E W _
V0:rsq _ _ _ F D E E W _ ... (2)
V1:rsq _ _ _ _ F D E E W _
V2:rsq _ _ _ _ _ F D E E W _
V0,V1,V2 は依存関係が無いことがわかっているためストールは発生しません。
また V0 同士の場合でも、(1) の V0:dp3 演算のあと、(2) の V0:rsq 実行時には
すでに dp3 の演算が完了しているので、命令の並び上直接依存関係があっても見か
け上レイテンシ無しに実行することができます。
この場合特に最適化コンパイラや人間が並び替えで最適化する必要も無く効率が良い
ことがわかります。
レイテンシを考えながら書かなければならない他のハードと比べて、シェーダーの
プログラミングが便利で簡単なのはこのおかげだと思っています。
その代わり1つの実行パイプでもスレッド数分のコンテキストを保持しなければな
らず、またパイプラインが深くなればなるほどレイテンシを隠すためのスレッドが
余計に必要になることがわかります。
ShaderModel2.0 世代の GPU では、このリソース量の上限が実際の演算速度上の制限
になっていたようです。リソースが枯渇すると各スレッドの実行に必要なコンテキス
トの割り当てができず、実行できるスレッド数が減ってしまいます。
演算ユニットやパイプラインに余裕があっても、スレッドを発行できずに動作速度が
頭打ちになってしまうわけです。
昔の GPU で性能を謳う部分に「ハードウエアスレッド○○個」と書かれていたこ
とがありますが、このようにスレッド化はインオーダー実行時のレイテンシを隠す
ための機能なので、その分並列演算能力が増加するわけではありません。
スレッドが無くてもぎりぎりまで最適化したストールが発生しないコードは、
理論上は動作効率が変わらないことになります。
その分人間やコンパイラが苦労わけですが。
なったわけですが、スレッド化そのものは ATI(AMD)系だろうとかなり前から
使われているテクニックです。
この辺の話は後藤さんの記事でかなり突っ込んで紹介されています。
http://pc.watch.impress.co.jp/docs/2006/1121/kaigai320.htm
この記事で書かれている3つのスレッディングのうち「カスケード」と呼ばれている
ものは割と初期の段階から用いられています。後藤さんの説明では「メモリアクセス」
のレイテンシを隠蔽するためとなっていますが、これはもともとシェーダーの
パイプラインを埋めるのが目的です。
例えばシェーダー命令で直前の命令と依存関係が発生する場合、アウトオブオーダー
実行でない限りパイプラインの終了を待つためにストールが発生します。
dp3 r0.x, r2, c5
rsq r1.x, r0.x
この例では dp3 の d0.x の演算が完了するまで rsq は実行できません。命令上は
順番並んでいても、パイプライン化が行われているためすべての命令実行は半分以上
がオーバーラップしているからです。
仮にパイプラインステージ数が5段と仮定するとイメージ的には次のようになります。
・依存関係がない場合
dp3 F D E E W _
rsq _ F D E E W
・依存関係がある場合
dp3 F D E E W _
rsq _ F D _ _ E E W
前の命令完了を待つため数サイクル分のストール(パイプラインの空き)が生じます。
そのため動作速度を上げるには、命令を並べ替えて依存関係が発生しないように
プログラムを改良する必要があります。
(なお、この例ではレジスタの読み書きに関するストールなので、実際はバイパス化
でもうちょっと効率が上がるかもしれません)
シェーダーでは依存関係がない複数の演算が同時に大量発生するので、複数のコン
テキストを用いたスレッド化(カスケード化)でパイプラインを埋めることができます。
例えば 3スレッド(カスケード)で頂点演算する場合 V0~V2 の3頂点を同時に処理
します。
V0:dp3 F D E E W _ ... (1)
V1:dp3 _ F D E E W _
V2:dp3 _ _ F D E E W _
V0:rsq _ _ _ F D E E W _ ... (2)
V1:rsq _ _ _ _ F D E E W _
V2:rsq _ _ _ _ _ F D E E W _
V0,V1,V2 は依存関係が無いことがわかっているためストールは発生しません。
また V0 同士の場合でも、(1) の V0:dp3 演算のあと、(2) の V0:rsq 実行時には
すでに dp3 の演算が完了しているので、命令の並び上直接依存関係があっても見か
け上レイテンシ無しに実行することができます。
この場合特に最適化コンパイラや人間が並び替えで最適化する必要も無く効率が良い
ことがわかります。
レイテンシを考えながら書かなければならない他のハードと比べて、シェーダーの
プログラミングが便利で簡単なのはこのおかげだと思っています。
その代わり1つの実行パイプでもスレッド数分のコンテキストを保持しなければな
らず、またパイプラインが深くなればなるほどレイテンシを隠すためのスレッドが
余計に必要になることがわかります。
ShaderModel2.0 世代の GPU では、このリソース量の上限が実際の演算速度上の制限
になっていたようです。リソースが枯渇すると各スレッドの実行に必要なコンテキス
トの割り当てができず、実行できるスレッド数が減ってしまいます。
演算ユニットやパイプラインに余裕があっても、スレッドを発行できずに動作速度が
頭打ちになってしまうわけです。
昔の GPU で性能を謳う部分に「ハードウエアスレッド○○個」と書かれていたこ
とがありますが、このようにスレッド化はインオーダー実行時のレイテンシを隠す
ための機能なので、その分並列演算能力が増加するわけではありません。
スレッドが無くてもぎりぎりまで最適化したストールが発生しないコードは、
理論上は動作効率が変わらないことになります。
その分人間やコンパイラが苦労わけですが。
2006/11/23
Cell の SPU(SPE) 命令を見て
暇なときに SPU(SPE) の命令を眺めたりしてましたが、普通の CPU ぽい命令が
かなりあって意外でした。というかレジスタが128bitでどの命令もSIMDになってる
だけでそれ以外は普通な感じです。
http://cell.scei.co.jp/
○演算は基本的に4種類
・8要素 16bit short int
・4要素 32bit int
・4要素 32bit float
・2要素 64bit double float
Intel でいえば全部 SSE で書いてるようなもの。x64 以降は fpu ではなく浮動
少数演算には常に SSE を使うらしいので割と近いのかもしれません。そういえば
VisualC++ も 2005 版になってデフォルトで SSE を使うようになってますね。
もちろん SPE は 3オペランドなので、その点は SSE 系より使いやすそうです。
レジスタも多いし。
もうひとつ意外だったのが、浮動少数演算系の命令が少なくて本当に必要最小限
であること。GPU の Shader のような至れり尽くせりのベクトル演算を期待すると
少々肩透かしを食らいます。(Shader の高度な演算も内部では複数の演算に分解
されている可能性はあります)
初期の SSE のように水平加算系の命令はなく、内積演算等でも同じようにベクトルの
並べ替えが発生するようです。4ベクトル同時演算の SIMD を活かすにはやっぱり
AoS SoA 変換も必要らしい。
GeForce8800(G80) がスカラー単位の演算ユニットに分離したのとは方向性が異なり
ます。そういえば G80 では内積などの水平系命令は演算ユニットをまたぐわけですが
どのような実装になってるんでしょう。
かなりあって意外でした。というかレジスタが128bitでどの命令もSIMDになってる
だけでそれ以外は普通な感じです。
http://cell.scei.co.jp/
○演算は基本的に4種類
・8要素 16bit short int
・4要素 32bit int
・4要素 32bit float
・2要素 64bit double float
Intel でいえば全部 SSE で書いてるようなもの。x64 以降は fpu ではなく浮動
少数演算には常に SSE を使うらしいので割と近いのかもしれません。そういえば
VisualC++ も 2005 版になってデフォルトで SSE を使うようになってますね。
もちろん SPE は 3オペランドなので、その点は SSE 系より使いやすそうです。
レジスタも多いし。
もうひとつ意外だったのが、浮動少数演算系の命令が少なくて本当に必要最小限
であること。GPU の Shader のような至れり尽くせりのベクトル演算を期待すると
少々肩透かしを食らいます。(Shader の高度な演算も内部では複数の演算に分解
されている可能性はあります)
初期の SSE のように水平加算系の命令はなく、内積演算等でも同じようにベクトルの
並べ替えが発生するようです。4ベクトル同時演算の SIMD を活かすにはやっぱり
AoS SoA 変換も必要らしい。
GeForce8800(G80) がスカラー単位の演算ユニットに分離したのとは方向性が異なり
ます。そういえば G80 では内積などの水平系命令は演算ユニットをまたぐわけですが
どのような実装になってるんでしょう。
2006/11/20
ハードの進化を否定するのはいいことなのか
ゲームの開発が大変になったと良く聞きます。ハードの性能が上がってより高い
クオリティのものが作れるようになったし、同時にユーザーが求める内容も
あがります。
その分だけ物量も必要で開発人数も増えて規模が大きくなりました。
ますます分業化が進んで個々の作業はさらに専門化し、作る人と考える人の距離が
遠ざかります。作り方を理解し作業工程まで工夫した設計がなかなかできず、
物量に頼る機会がますます増えてしまいます。
ハードの進化についていけずに、力技の対応で食いつないできたつけが回ってきたの
かもしれません。
開発がついていけないからといってハードの進化を否定するのは少々強引な気が
します。既存の環境やハードウエアなら使いこなしているから開発の負担が減る
だろうという考えも少々短絡的ではないでしょうか。
使っていればやっぱり不満点や足りない点が出てくるものです。あと少し、もう少し
だけここが改良されていればここまでできたのに、あともうちょっとメモリがあれば、
もうちょっと CPU が速ければ、クオリティがあがるのに、などなど。
進化しなければその同じ制限に再び悩まされることになります。世の中では、
例えば PC では当たり前に解決されていることであっても、進化を止めてしまったら
古い手法を使い続けなければなりません。
PC のスペックはものすごい速さで進化しています。10年前と比較すると 40倍の
CPU 速度に 20~30倍のメモリ量に、10倍の HDD 容量などなど。だからとって
プログラマの作業が極端に大変になったかといえばそうでもありません。
ハードが進化した分制限が無くなり、メモリや CPU速度に余裕が生まれて新しい開発
手法も使えるようになっています。class ライブラリが整備され、デバッガも高機能
になって、スクリプト言語による開発も幅広く用いられるようになりました。
メモリやディスクを大量に消費する重いアルゴリズムでも以前と比べると気楽に
使えます。
もちろん新しいことを覚え続けなければならないのは当然だけど、むしろ制限は
減ってきています。
前の世代でぎりぎりまで使い切って、限界が見えていればいるほどハードの進化は
歓迎すべきものでしょう。もしかしたら使いこなせていないときは、ハードの進化
が重くのしかかってくるのかもしれません。
同じように、データの作成手法でもさまざまな変化が必要でしょう。性能があがった
ことでいくらでもデータの作りこみができるようになりました。
2D 時代に例えれば色数に制限が無くなったようなもので、描こうと思えばどんな
絵でも出ます。パレットやチップが足りないといった言い訳はできなくなったし、
本当に力を入れるべき表現のポイントを絞らなければならないでしょう。
また不要な手間はできるだけ省き、人間が手でやる必要が無い部分は徹底的に
ツール化していく必要があるでしょう。
リアルタイム 3D CG の進化はまだまだこれからです。始まったばかりです。
クオリティのものが作れるようになったし、同時にユーザーが求める内容も
あがります。
その分だけ物量も必要で開発人数も増えて規模が大きくなりました。
ますます分業化が進んで個々の作業はさらに専門化し、作る人と考える人の距離が
遠ざかります。作り方を理解し作業工程まで工夫した設計がなかなかできず、
物量に頼る機会がますます増えてしまいます。
ハードの進化についていけずに、力技の対応で食いつないできたつけが回ってきたの
かもしれません。
開発がついていけないからといってハードの進化を否定するのは少々強引な気が
します。既存の環境やハードウエアなら使いこなしているから開発の負担が減る
だろうという考えも少々短絡的ではないでしょうか。
使っていればやっぱり不満点や足りない点が出てくるものです。あと少し、もう少し
だけここが改良されていればここまでできたのに、あともうちょっとメモリがあれば、
もうちょっと CPU が速ければ、クオリティがあがるのに、などなど。
進化しなければその同じ制限に再び悩まされることになります。世の中では、
例えば PC では当たり前に解決されていることであっても、進化を止めてしまったら
古い手法を使い続けなければなりません。
PC のスペックはものすごい速さで進化しています。10年前と比較すると 40倍の
CPU 速度に 20~30倍のメモリ量に、10倍の HDD 容量などなど。だからとって
プログラマの作業が極端に大変になったかといえばそうでもありません。
ハードが進化した分制限が無くなり、メモリや CPU速度に余裕が生まれて新しい開発
手法も使えるようになっています。class ライブラリが整備され、デバッガも高機能
になって、スクリプト言語による開発も幅広く用いられるようになりました。
メモリやディスクを大量に消費する重いアルゴリズムでも以前と比べると気楽に
使えます。
もちろん新しいことを覚え続けなければならないのは当然だけど、むしろ制限は
減ってきています。
前の世代でぎりぎりまで使い切って、限界が見えていればいるほどハードの進化は
歓迎すべきものでしょう。もしかしたら使いこなせていないときは、ハードの進化
が重くのしかかってくるのかもしれません。
同じように、データの作成手法でもさまざまな変化が必要でしょう。性能があがった
ことでいくらでもデータの作りこみができるようになりました。
2D 時代に例えれば色数に制限が無くなったようなもので、描こうと思えばどんな
絵でも出ます。パレットやチップが足りないといった言い訳はできなくなったし、
本当に力を入れるべき表現のポイントを絞らなければならないでしょう。
また不要な手間はできるだけ省き、人間が手でやる必要が無い部分は徹底的に
ツール化していく必要があるでしょう。
リアルタイム 3D CG の進化はまだまだこれからです。始まったばかりです。
2006/11/15
Gears of War がすごすぎる
Xbox360 のゲームソフト Gears of War のグラフィックがすごすぎます。
http://www.xbox.com/en-US/games/g/gearsofwar/
Unreal Engine 3 の本家 Epic Games 開発なので、もちろんエンジンそのものが
最初からすごいんだけど…。
とにかくその Engine 性能を限界まで引き出すすばらしいデータの数々。
キャラもマップも今まで見たことが無いくらい、緻密で作りこんであって、
それでいてプログラムの性能を活かしきる。
エフェクトやシェーダーの効果もさりげなくて実に効果的です。
見たのは 2006/11/7 発売の海外版だけど、
日本語版も 2007/01/18 に発売されるようです。
http://www.xbox.com/ja-JP/games/g/gearsofwar/
今まで見たゲームの中では最高の緻密さ。圧倒的なクオリティです。
これをもっと大々的に宣伝したらもうちょっとは Xbox360 もいけるんじゃないかと
思ってしまいました。
○今日のシェーダーメモ
mul( float4x4, float4 ) と mul( float4, float4x4 ) の違い
// mul( float4x4, float4 )
mul r0, c1, v0.y
mad r0, c0, v0.x, r0
mad r0, c2, v0.z, r0
mad o0, c3, v0.w, r0
// mul( float4, float4x4 )
dp4 o0.x, v0, c0
dp4 o0.y, v0, c1
dp4 o0.z, v0, c2
dp4 o0.w, v0, c3
http://www.xbox.com/en-US/games/g/gearsofwar/
Unreal Engine 3 の本家 Epic Games 開発なので、もちろんエンジンそのものが
最初からすごいんだけど…。
とにかくその Engine 性能を限界まで引き出すすばらしいデータの数々。
キャラもマップも今まで見たことが無いくらい、緻密で作りこんであって、
それでいてプログラムの性能を活かしきる。
エフェクトやシェーダーの効果もさりげなくて実に効果的です。
見たのは 2006/11/7 発売の海外版だけど、
日本語版も 2007/01/18 に発売されるようです。
http://www.xbox.com/ja-JP/games/g/gearsofwar/
今まで見たゲームの中では最高の緻密さ。圧倒的なクオリティです。
これをもっと大々的に宣伝したらもうちょっとは Xbox360 もいけるんじゃないかと
思ってしまいました。
○今日のシェーダーメモ
mul( float4x4, float4 ) と mul( float4, float4x4 ) の違い
// mul( float4x4, float4 )
mul r0, c1, v0.y
mad r0, c0, v0.x, r0
mad r0, c2, v0.z, r0
mad o0, c3, v0.w, r0
// mul( float4, float4x4 )
dp4 o0.x, v0, c0
dp4 o0.y, v0, c1
dp4 o0.z, v0, c2
dp4 o0.w, v0, c3
2006/11/11
続 GeForce8800GTX と SM4.0 の整数演算
D3D10 でなくても OpenGL の NVIDIA 拡張ならできるということをすっかり忘れて
いました。
http://developer.nvidia.com/object/nvidia_opengl_specs.html
しかも CUDA という新しい GPU 向けプログラミングキットまで出ています。
一般的な C言語を使って GPU 向けプログラムが書けて、演算用のストリーム
プロセッサとして活用できるようです。マルチコア CPU でもせいぜい数個のスレッド
が走る程度ですが、CUDA では数千というスレッドが可能とのこと。
http://developer.nvidia.com/object/cuda.html
描画向けパイプラインを流用して演算させる手間が要らず、ハードにあわせた専用の
シェーディング言語を用いなくても良いわけです。ShaderModel4.0 の仕様になって
非常に汎用性が高く、一般の計算用途に活用できる構造になりました。
CUDA はさらにその先を行ってるわけです。
あらためて仕様を見てみると、D3D10 の ShaderModel4.0 HLSL でも演算可能な
32bit int の整数型が追加されています。整数型が追加されたことで、bit 演算や
シフト演算子も使えるようになっています。
D3D10 ではアセンブラによるシェーダープログラミングはなくなっており HLSL のみ
のサポートです。マニュアルにもアセンブラについては書かれていません。
その代わり上記リンクにある資料から OpenGL の NVIDIA 拡張命令で 4.0 相当の
アセンブラ命令を見ることができます。これまで存在しなかった AND, OR, XOR,
NOT, SHL, SHR, I2F, PK/UP~ の整数系命令が並んでいることがわかります。
int 型整数の乗算は 32bit 分の演算が必要なので、浮動小数点演算よりも負担が
高くなります。整数乗算の制度を 24bit に制限するオプションがあり、これで
浮動少数点相当の演算コストで高速に乗算できるようになっています。
また整数乗算では 64bit 相当の演算を行った後、上位 32bit のみ受け取ることも
できます。上位と下位を同時に受け取れないので結果を 64bit で受け取りたい場合
は乗算が 2命令必要になります。
比較は結果をレジスタに bool 値で代入できる専用の命令もありますが、演算や
代入と同時に結果をフラグに反映させることができます。これも汎用 CPU と同じ
ように、zero, carry, overflow, sign の4つの flag が揃っています。
フラグの更新と参照は依存関係を持つためパイプラインストールに原因になりがち
です。これを CC0 と CC1 の2セットのフラグレジスタを使い分けることで回避
しているようです。
VertexShader → GeometryShader はそのまま直接値を渡すことができますが、
VertexShader/GeometryShader → PixelShader の場合は間にラスタライザが介入
します。この場合の補間は float で行われます。補間を行わない場合は任意の型で
渡すことができるようです。
いました。
http://developer.nvidia.com/object/nvidia_opengl_specs.html
しかも CUDA という新しい GPU 向けプログラミングキットまで出ています。
一般的な C言語を使って GPU 向けプログラムが書けて、演算用のストリーム
プロセッサとして活用できるようです。マルチコア CPU でもせいぜい数個のスレッド
が走る程度ですが、CUDA では数千というスレッドが可能とのこと。
http://developer.nvidia.com/object/cuda.html
描画向けパイプラインを流用して演算させる手間が要らず、ハードにあわせた専用の
シェーディング言語を用いなくても良いわけです。ShaderModel4.0 の仕様になって
非常に汎用性が高く、一般の計算用途に活用できる構造になりました。
CUDA はさらにその先を行ってるわけです。
あらためて仕様を見てみると、D3D10 の ShaderModel4.0 HLSL でも演算可能な
32bit int の整数型が追加されています。整数型が追加されたことで、bit 演算や
シフト演算子も使えるようになっています。
D3D10 ではアセンブラによるシェーダープログラミングはなくなっており HLSL のみ
のサポートです。マニュアルにもアセンブラについては書かれていません。
その代わり上記リンクにある資料から OpenGL の NVIDIA 拡張命令で 4.0 相当の
アセンブラ命令を見ることができます。これまで存在しなかった AND, OR, XOR,
NOT, SHL, SHR, I2F, PK/UP~ の整数系命令が並んでいることがわかります。
int 型整数の乗算は 32bit 分の演算が必要なので、浮動小数点演算よりも負担が
高くなります。整数乗算の制度を 24bit に制限するオプションがあり、これで
浮動少数点相当の演算コストで高速に乗算できるようになっています。
また整数乗算では 64bit 相当の演算を行った後、上位 32bit のみ受け取ることも
できます。上位と下位を同時に受け取れないので結果を 64bit で受け取りたい場合
は乗算が 2命令必要になります。
比較は結果をレジスタに bool 値で代入できる専用の命令もありますが、演算や
代入と同時に結果をフラグに反映させることができます。これも汎用 CPU と同じ
ように、zero, carry, overflow, sign の4つの flag が揃っています。
フラグの更新と参照は依存関係を持つためパイプラインストールに原因になりがち
です。これを CC0 と CC1 の2セットのフラグレジスタを使い分けることで回避
しているようです。
VertexShader → GeometryShader はそのまま直接値を渡すことができますが、
VertexShader/GeometryShader → PixelShader の場合は間にラスタライザが介入
します。この場合の補間は float で行われます。補間を行わない場合は任意の型で
渡すことができるようです。
2006/11/10
nVIDIA GeForce8800GTX 出ました!!
一日中、暇があれば GeForce8800 の記事ばかり眺めていました。
D3D10 世代、ShaderModel4.0 世代の GPU の発表です。
http://www.nvidia.com/page/geforce8.html
GeForce8800 はアーキテクチャ自体が完全に異なるフルモデルチェンジです。
nVIDIA の GPU はだいたい2世代ごとに完全に生まれ変わります。
NV3 RIVA128, RIVA128ZX
NV4 RIVA-TNT, RIVA-TNT2
NV10 GeForce256, GeForce2 hwT&L
NV20 GeForce3, GeForce4 SM1
NV30 GeForceFX5800 SM2
NV40(G70) GeForce6800, GeForce7800 SM3
G80 GeForce8800 SM4
失敗作(?)だった FX を除いて大幅なアーキテクチャの刷新と、マイナーバージョン
アップによる高速化を繰り返しています。なので 7800 を買っても機能的には 6800
とほとんど同じだけど、8800 は完全に違います。速度ではなく機能を求めるプログ
ラマ的には今が買いです。
アーキテクチャの改変時は、機能が大幅に増える代わりにあんまり速くなっていない
ことが多々ありました。新しい機能を使えばもちろんパフォーマンスというかできる
ことは比較にならないのですが、例えば DX7 未対応のアプリケーションでは
GeForce256 より TNT2 の方が高速でした。
しかし 8800 は、新しい Shader4.0 を使わなくても従来の 3.0 アプリケーション
でも 2倍の速度で動くらしい!! これで D3D10 のアプリケーションが走ったら、
一体どこまでできるのやら。本当はすぐにでもほしいんだけど、
もしかして Vista が出るまで D3D10 は待ち?
もしかして DirectX10 SDK のリリースまでおあずけ?
もしかして Vista 用の 88 対応ドライバがまだ?
全部揃うまでもうちょっと我慢がいるみたいです
D3D10 世代、ShaderModel4.0 世代の GPU の発表です。
http://www.nvidia.com/page/geforce8.html
GeForce8800 はアーキテクチャ自体が完全に異なるフルモデルチェンジです。
nVIDIA の GPU はだいたい2世代ごとに完全に生まれ変わります。
NV3 RIVA128, RIVA128ZX
NV4 RIVA-TNT, RIVA-TNT2
NV10 GeForce256, GeForce2 hwT&L
NV20 GeForce3, GeForce4 SM1
NV30 GeForceFX5800 SM2
NV40(G70) GeForce6800, GeForce7800 SM3
G80 GeForce8800 SM4
失敗作(?)だった FX を除いて大幅なアーキテクチャの刷新と、マイナーバージョン
アップによる高速化を繰り返しています。なので 7800 を買っても機能的には 6800
とほとんど同じだけど、8800 は完全に違います。速度ではなく機能を求めるプログ
ラマ的には今が買いです。
アーキテクチャの改変時は、機能が大幅に増える代わりにあんまり速くなっていない
ことが多々ありました。新しい機能を使えばもちろんパフォーマンスというかできる
ことは比較にならないのですが、例えば DX7 未対応のアプリケーションでは
GeForce256 より TNT2 の方が高速でした。
しかし 8800 は、新しい Shader4.0 を使わなくても従来の 3.0 アプリケーション
でも 2倍の速度で動くらしい!! これで D3D10 のアプリケーションが走ったら、
一体どこまでできるのやら。本当はすぐにでもほしいんだけど、
もしかして Vista が出るまで D3D10 は待ち?
もしかして DirectX10 SDK のリリースまでおあずけ?
もしかして Vista 用の 88 対応ドライバがまだ?
全部揃うまでもうちょっと我慢がいるみたいです
2006/11/03
mipmap とフィルタリング(続き)
mipmap は pixel 毎に異なるテクスチャを参照するため、その境界がはっきりと見
えてしまうことがあります。
この境界をぼかすために 2つの level の mip テクスチャ間で線形補間を行うこと
ができます。u-v 方向にかかるバイリニアフィルタに対して mip level 方向が
加わるためトライリニアフィルタと呼ばれます。
u方向とv方向の解像度が異なる場合など、向きによって適切な mip level に大きな
差が生じる場合は少々厄介です。
例えばカメラに対して大きく傾いている地面や天井は、元のテクスチャ画像よりも
細長い形状となります。縦方向(画面の奥に向かって)は小さいテクスチャを参照
したいのですが、横方向にはもっと大きな解像度の画像が必要です。
そのため高い解像度のテクスチャを参照しつつ、縦方向(画面の奥)に向かって
縮小をかけます。これが異方性フィルタリング(Anisotropic filtering)です。
ぼけぼけだった mipmap の効果も引き締まって見えるので見栄えのいい画面に
なります。が、きれいに縮小するためには部分的に mipmap のデータを作ってるよう
なもの。重い処理となってしまいます。
傾きの大きいポリゴン以外は効果が小さいので、場所によってどの程度まで
フィルタリングするのか使い分けがいります。極端な例だとビルボードには全く
必要ないわけです。
(前の記事)
http://ch09144.kitaguni.tv/e309230.html
えてしまうことがあります。
この境界をぼかすために 2つの level の mip テクスチャ間で線形補間を行うこと
ができます。u-v 方向にかかるバイリニアフィルタに対して mip level 方向が
加わるためトライリニアフィルタと呼ばれます。
u方向とv方向の解像度が異なる場合など、向きによって適切な mip level に大きな
差が生じる場合は少々厄介です。
例えばカメラに対して大きく傾いている地面や天井は、元のテクスチャ画像よりも
細長い形状となります。縦方向(画面の奥に向かって)は小さいテクスチャを参照
したいのですが、横方向にはもっと大きな解像度の画像が必要です。
そのため高い解像度のテクスチャを参照しつつ、縦方向(画面の奥)に向かって
縮小をかけます。これが異方性フィルタリング(Anisotropic filtering)です。
ぼけぼけだった mipmap の効果も引き締まって見えるので見栄えのいい画面に
なります。が、きれいに縮小するためには部分的に mipmap のデータを作ってるよう
なもの。重い処理となってしまいます。
傾きの大きいポリゴン以外は効果が小さいので、場所によってどの程度まで
フィルタリングするのか使い分けがいります。極端な例だとビルボードには全く
必要ないわけです。
(前の記事)
http://ch09144.kitaguni.tv/e309230.html
2006/11/02
mipmap が嫌われる
ゲーム開発ではなぜか mipmap が嫌われることがあります。
GPU のレンダリングではカメラからの距離に応じて、参照するテクスチャの解像度
を切り替えることができます。例えば 512x512 pixel のテクスチャ画像がある場合
あらかじめ縮小した画像を次のように何パターンも用意しておきます。
256x256
128x128
64x64
32x32
:
カメラから近い場合は高い解像度のテクスチャを参照しますが、遠くの場合は
高い解像度を使う必要がありません。mipmap を用意しておけばそのため遠くに行く
ほど小さいテクスチャの参照で済みます。いわゆるテクスチャ解像度の LOD の
ことです。この mip レベルの選択は pixel のレンダリング時に行われます。
正確にはカメラからの距離というよりも、レンダリングするポリゴンの面積から
計算すると効率が良いことがわかります。画面のピクセルに対してできる限り1対1で
対応する解像度のテクスチャを参照したいたいためです。
実際の実装ではピクセル間の uv の密集度から mipmap のレベルを判断します。
ピクセル間の差分は、PixelShader でも 2.x 以降なら dsx, dsy 命令で求める
ことができます。
テクスチャの拡大と異なり、縮小時のフィルタリングにはより多くの pixel 情報を
畳み込む必要があります。例えば最大まで縮小した 1x1 pixel の点には元の
テクスチャのすべての平均値が含まれます。
この計算はリアルタイムに向かないので、前処理でフィルタリングしておける
mipmap は低負荷ながら遠くのポリゴンのちらつきをおさえて画質の向上に
つながります。
もちろんテクスチャアクセス時の負担も減るので mipmap を使った方がテクスチャ
フェッチは高速です。
mipmap はできるだけ使ったほうが良いのです。
デメリットは、あらかじめ縮小した画像を含んでいる分だけテクスチャ容量が
1.34倍程度に増えることです。
コンシューマ系のゲーム開発で mipmap があまり使われないのは、ひとつは容量の
問題でしょう。Xbox1 以降なら容量に対してアクセス負荷が高いので、使用した
場合のメリットの方が大きいと考えられます。
極端にバスアクセスが速かったり、シェーダーでピクセル演算の方が重くて
テクスチャ読み込みが負担にならない場合はこの限りではありません。
もうひとつは mipmap を使ったほうが負荷が高いという思い込みがまだ残って
いることかもしれません。
そして画像が過度にぼけすぎることです。
画質がぼけすぎるのは、最適な解像度よりも下のレベルのテクスチャが参照される
ことがあるためです。
例えばテクスチャ画像とレンダリングされるポリゴンの縦横比が極端に異なると、
短い辺では最適な解像度でも、長い辺では解像度が足りなくなってしまいます。
見た目よりも低いレベルのテクスチャが参照され、引き伸ばされるが故に余計に
ぼけているように見えます。
3D 視点で描画される地面のように、カメラに対して角度のついたポリゴンはこの
傾向が強いので非常にボケボケの画質になりがちです。せっかく書き込んだ
テクスチャの詳細も失われてしまうので、これを嫌がるデザイナーも多いのです。
こんなときは mipmap を切るのではなく異方性フィルタ(Anisotropic filtering)
を活用します。
(続く)
GPU のレンダリングではカメラからの距離に応じて、参照するテクスチャの解像度
を切り替えることができます。例えば 512x512 pixel のテクスチャ画像がある場合
あらかじめ縮小した画像を次のように何パターンも用意しておきます。
256x256
128x128
64x64
32x32
:
カメラから近い場合は高い解像度のテクスチャを参照しますが、遠くの場合は
高い解像度を使う必要がありません。mipmap を用意しておけばそのため遠くに行く
ほど小さいテクスチャの参照で済みます。いわゆるテクスチャ解像度の LOD の
ことです。この mip レベルの選択は pixel のレンダリング時に行われます。
正確にはカメラからの距離というよりも、レンダリングするポリゴンの面積から
計算すると効率が良いことがわかります。画面のピクセルに対してできる限り1対1で
対応する解像度のテクスチャを参照したいたいためです。
実際の実装ではピクセル間の uv の密集度から mipmap のレベルを判断します。
ピクセル間の差分は、PixelShader でも 2.x 以降なら dsx, dsy 命令で求める
ことができます。
テクスチャの拡大と異なり、縮小時のフィルタリングにはより多くの pixel 情報を
畳み込む必要があります。例えば最大まで縮小した 1x1 pixel の点には元の
テクスチャのすべての平均値が含まれます。
この計算はリアルタイムに向かないので、前処理でフィルタリングしておける
mipmap は低負荷ながら遠くのポリゴンのちらつきをおさえて画質の向上に
つながります。
もちろんテクスチャアクセス時の負担も減るので mipmap を使った方がテクスチャ
フェッチは高速です。
mipmap はできるだけ使ったほうが良いのです。
デメリットは、あらかじめ縮小した画像を含んでいる分だけテクスチャ容量が
1.34倍程度に増えることです。
コンシューマ系のゲーム開発で mipmap があまり使われないのは、ひとつは容量の
問題でしょう。Xbox1 以降なら容量に対してアクセス負荷が高いので、使用した
場合のメリットの方が大きいと考えられます。
極端にバスアクセスが速かったり、シェーダーでピクセル演算の方が重くて
テクスチャ読み込みが負担にならない場合はこの限りではありません。
もうひとつは mipmap を使ったほうが負荷が高いという思い込みがまだ残って
いることかもしれません。
そして画像が過度にぼけすぎることです。
画質がぼけすぎるのは、最適な解像度よりも下のレベルのテクスチャが参照される
ことがあるためです。
例えばテクスチャ画像とレンダリングされるポリゴンの縦横比が極端に異なると、
短い辺では最適な解像度でも、長い辺では解像度が足りなくなってしまいます。
見た目よりも低いレベルのテクスチャが参照され、引き伸ばされるが故に余計に
ぼけているように見えます。
3D 視点で描画される地面のように、カメラに対して角度のついたポリゴンはこの
傾向が強いので非常にボケボケの画質になりがちです。せっかく書き込んだ
テクスチャの詳細も失われてしまうので、これを嫌がるデザイナーも多いのです。
こんなときは mipmap を切るのではなく異方性フィルタ(Anisotropic filtering)
を活用します。
(続く)