パスワードを忘れた? アカウント作成
175026 journal

L.Entisの日記: GPUとレイトレの話

日記 by L.Entis
この前のエントリでリンクした動画の再生数とコメント数が予想外に一晩で増えたのは何ででしょう…?
「世界の新着動画」で紹介されてとか、何かあったのかな?
個人的には作り捨て程度の感覚だったのですが。

ところで、レイトレの話ですが、普通のリアルタイム系のデータをレイトレする場合、何が一番に問題になるかって、片面ポリゴンなんですよね。
あれ、基本的に全部屈折透過扱いにせざるを得ないので、ポリゴンを裏から見てなにも表示されて無いだけでも、レイトレだと光線追跡回数を1回消費するんですよね。
だから片面ポリゴンはレイトレでは負荷増という、リアルタイム系とは真逆のことに…
まあ、αチャネルの付いているテクスチャも同様なのですが
(あと、片面ポリゴンを張り合わせて両面にしている場合、先に裏側にヒットすると、次の光線追跡では表面はスルーされるので、斑に透過すると言う…)

それはさておき、GPUでのレイトレなのですが、現在のところは、光線追跡だけをGPUに投げて、CPU側はシェーディングをやることになっています。
マルチCPU/マルチコア/マルチスレッドの場合には、他のスレッドはいつも通り、独立して光線追跡とシェーディングの両方をやりますが。
因みにスレッドの同期は、lock プリフィックスや xchg 命令(あるいは xadd 命令)などを利用して、ライン単位で自分の処理する画面領域を取ってきます。
GPU で処理する(CPU の)スレッドは、一度にまとまったライン数を取ってきます。

で、1ray の当たり判定結果を 48 バイトの構造体で、その配列を結果として返してきます。
CPU 側は、GPU に処理を発行したら、1回前の処理結果を元にシェーディングを行って、GPU 処理と平行して処理する形になります。

で、この方式の場合問題になるのが、光線の当たり判定結果のデータサイズなんですよね。
ピクセルあたり48バイトなら全くの余裕なのですが、光源が1つの場合でも追跡数 1 で 4、追跡数 2 で 11 の光線が発生しうるので(初めに当たった位置から、光源方向、屈折透過方向、反射方向に分かれ、光源方向は光源*追跡回数分、屈折と反射はそれぞれ残りの追跡回数だけ更に分離します)、ピクセルあたり 48x4 byte とか 48x11 byte とかのサイズのデータを、処理結果として転送することになります。
それでも、全ポリゴンに対する当たり判定の結果を48バイトで受け取ると言うのは、処理に対するコストとしてはそれほど悪くはないのですが、追跡数が多いとリアルタイム処理としては問題があるところです。
一応、設計上は追跡数の制約は6なのですが(これはGPGPUで関数の再起呼び出しが出来ないため(メモリの制約がある))、実用上は1で考えています。
ただ、追跡回数1では、片面ポリゴンやαチャネルのあるテクスチャを2つはさむと(1つならOK)、そこが透明でもその向こうが見えないと言う困ったことになるので、特殊なアペンド追跡回数ってのが指定できるようになっていて、一番最後の透過光線についてのみ、当たり判定の結果の数を増やすことが出来るようにしてあります。
例えば、追跡回数1、光源数1で、アペンド追跡を2とした場合、ピクセルあたり受け取る処理結果のデータ容量は 48x(4+2) byte となり、追跡回数 3 の場合(48x26)よりかなり節約出来るようになっています。

まあ、そこまでしてレイトレやる意味あんのか?って聞かれたら、私も「いや、まだ現状、遊びみたいなもんだから」としか答えられないのですがw
因みに、動画ではかなり屈折やら反射やらを仕込んだモデルでのデモだったので、追跡回数は2でやっているのですが、これを画面全体GPUで処理して、その結果を受け取る場合、その処理結果の転送だけで100msほど掛かります。
(GPU-CPU転送を除く)処理自体はローポリなこともあって、100ms~300ms程度なので、結構アホですが、CPU側をマルチスレッドで処理する場合には、GPUで処理するピクセル数が1/4位になるので(Cure2Quadなので)そんな事はありません(^^;
因みに、追跡回数1回だと転送は約25msほどになります。
800MHz の ECC 付き DDR2 だったと思うのですが、この転送において、ほぼ理論値どおりの転送速度は出ているようです。(約 3GBytes/sec 程度)
DDR3 世代ならこの半分の転送時間になるものと思います。

で、将来的には GPU でシェーディングまでやらせればいいんじゃないかということにはなるかと思うのですが、スペック的に最低あと10倍は速くなってくれないとその意義が無いわけで(多分10倍速くなった頃には、CPUもより一層高速&マルチコア化が進んで、数10倍は速くならないと意義があるレベルに到達しないと思うのですが)、当面はこれでいいかなと。
と言うか、CPU 側と処理結果を合わせるのが、光線追跡だけでも難儀だったのに(そのためだけに GPU 処理と同じ結果を返す CPU 側の処理コードを書いて、GPU と並列処理する場合には(効率はやや落ちるものの)そちらのコードを走らせている(そうしないと画面上で色々な意味での段差ができるのです))、シェーディングまでとなると、結構ややこしいのです。(ので、そこまでするんなら、GPU 単体動作で、全CPUコアによるレンダリングを圧倒する速度でないとやる意味が無い)
※因みに動画のGPU+CPU処理での陰が縞模様になるバグは、CPU側の互換処理の問題でしたが、すでに修正済み
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

犯人は巨人ファンでA型で眼鏡をかけている -- あるハッカー

読み込み中...