2009年03月22日

テクスチャプラグインのマルチスレッドレンダリング

Blenderの公式マニュアルでこちらのページを見ると、テクスチャプラグインはBlender2.46からマルチスレッドレンダリングに対応していることがわかります。そして、以前のバージョンのプラグインをマルチスレッドでレンダリングすると、レンダリング結果にノイズのようなものが発生するので、その場合はシングルスレッドでレンダリングするようにと書かれています。

プラグインリポジトリで公開されているテクスチャプラグインを調べてみると、プラグインの種類によっては目立たないものもありますが、ほとんどのものでノイズのようなものが確認できます。
pic090321_01.jpg pic090321_02.jpg

前回の記事で作成したテスト用のプラグインは、実はマルチスレッドに対応したものになっています。スレッド数を「4」とかにしてもノイズがでたりすることはありません。Blender2.46以降の「plugins」フォルダのサンプルをコンパイルすると、その結果できあがるプラグインはマルチスレッドレンダリングに対応したものになります。
プラグインリポジトリで公開されているファイルの中には、Blenderの「plugins」フォルダに付属しているサンプルと同じ「clouds2」「tiles」もあります。そちらは古いバージョンとしてコンパイルされているので、マルチスレッドでレンダリングするとノイズが出ます。この違いはどこにあるのでしょうか。
pic090321_03.jpg pic090321_05.jpg

プラグインリポジトリにあるソースコード「clouds2.c」「tiles.c」と最新版の「plugins」フォルダの中のソースコードとを比べることで、古いバージョンのテクスチャプラグインをマルチスレッドレンダリングに対応させるための方法がわかりそうです。
このくらいの行数のファイルであれば、両方をテキストエディタで見比べることで違いを確認することもできますが、Linuxのツール「Diff」というものを使うとより確実に調べることができます。「Diff」自体はコマンドラインから使用するものですが、Gnome、KDEなどのデスクトップ上で使えるような派生ツールがいくつも作られていて、Windowsでも同じようなものはたくさんみつかります。Ubuntuの「アプリケーションの追加と削除」を見てみると、以前Vectexのソースを調べるのに使ったMeldの他にTkDiff、Kompareなどがありました。今回は「Meld差分ビュワー」を使って「clouds2.c」の新旧のバージョンの違いを調べてみたいと思います。
pic090321_06.jpg

どちらを比較元にするかで若干表示が変わってくると思いますが、とりあえず普通に古い方をオリジナル(画面左)として、新しいバージョン(画面右)との違いを表示させてみます。
pic090321_07.jpg

まず、冒頭のコメント部分が違っています。とりあえず動作には関係ないので無視していいでしょう。
pic090321_08.jpg

この「Meld」というツールではツールバーの「下へ」「上へ」というボタンを押すと、ファイルの中の内容が違っている部分に画面を移動させることができます。次に見つかったのはPlugin_tex_doit()、plugin_instance_init()の2つの関数のプロトタイプ宣言の部分です。
pic090321_09.jpg

plugin_tex_doit()関数には、新しいバージョンでは引数が一つ追加されています。結果から言いますと、テクスチャプラグインをマルチスレッドに対応させるために変更されたのは、まさにこの部分となります。
前回の記事を見ていただくとわかりますが、この引数はresult[]配列へのポインタになります。複数のスレッドがplugin_tex_doit()関数を呼び出している場合、古いバージョンではresult配列に書き込まれた計算結果を別のスレッドが上書きしてしまうことがあります。本来渡されるべき値が変更されてしまったピクセルは、周辺のピクセルとは全然別の色として表示され、点状、線状のノイズのようになります。
新しいバージョンでは各スレッドにそれぞれ自分用のresult[]配列を引数として与えることで、この問題が解決されています。
プロトタイプ宣言が変更されているので、当然それと対応する関数本体のコードも同じように変更されています。この関数の本体はソースコードの最後の方にあります。
もう一方のplugin_instance_init()関数は古いバージョンにはなかったものが、新しいバージョンで追加されたようです。

次の変更箇所です。
pic090321_10.jpg

まず、plugin_instance_init()関数の本体が追加されています。
そして、plugin_getinfo()関数の中身で最後の方が2ヶ所ほど変更されています。一つ目は、"info->tex_doit="と"(TexDoit) plugin_tex_doit;"の間のスペースが一つ余分だったのが修正されています。これは無視していいような内容ですね。
二つ目はplugin_instande_init()関数が追加されたことに関連して、Blender本体からこの関数にアクセスするための情報がここに追加されているようです。

次に、plugin_tex_doit()関数の本体の部分です。
pic090321_11.jpg pic090321_12.jpg

関数の前の部分のコメントが削除されていますが、これは無視していいでしょう。
そして、先ほどのプロトタイプ宣言の変更に対応して、関数名に続く引数の記述部分に「float *result」が追加されています。
元々、result[]配列はグローバルなデータとして同じ名前でplugin_tex_doit()関数の中で使われていたものです。そのため、result[]配列に関しては、この関数内部のコードはまったく変更されていません。

最後の変更部分です。
pic090321_13.jpg

これは関数の戻り値を「0」「1」「2」というような数値ではなく、「TEX_INT」「TES_RGB」「TES_NOR」というマクロを使った定数の表記に変えているようです。「plugins」フォルダの「include」にあるplugin.hの86行目あたりを見てみると、以下のように記述があります。

/* return values (bitfield like) for textures (DNA_texture_types.h) */
#define TEX_INT         0
#define TEX_RGB         1
#define TEX_NOR         2

前回のサンプルプラグインでは直接「0」を返してしまいましたが、本来はこのように「TEX_INT」という定数を使うべきだったようです。(とりあえず、そのままでも動作には問題なさそうなので放置しておきます。まずいかな...。)

ということで、ざっと新旧のバージョンの変更内容を見てきました。
plugin_tex_doit()関数の引数にresult[]配列を渡すようにすること、plugin_instance_init()関数が新しく追加されたこと、基本的にはこの2点が変わっただけで、プラグインの動作に直接関わる部分には変更はないようです。これらの部分を修正してコンパイルし直せば、プラグインリポジトリにあるたくさんのプラグインもマルチスレッドでレンダリングできるようになりそうな感じがします。
次回は、プラグインリポジトリのテクスチャプラグインのソースコードを修正して、実際に動作するか試してみるつもりです。
posted by mato at 00:14| Comment(0) | Blender | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。