Yakiimo3D

Mostly DirectX 11 Programming

smallpt CPU Optimizations

http://www.butamanrenderer.com/
Butaman Rendererのblog。最近趣味で実装を始めようとしているglobal illumination rendererのblogです。

http://www.butamanrenderer.com/2010/09/19/smallpt-cpu-optimizations/
Butaman Renderer blogのsmallpt cpu optimization記事。

先月から少しずつ行ってきた、smallptのSIMD & マルチスレッドCPU高速化版のblog記事を書きました。DirectX11でprogressive renderingとtonemapを行い、デモとそのソースコードを公開したので、Yakiimo3Dでも紹介しておきます。最適化無しのシングルスレッドのsmallptの実装と比較したら4CPUのCore2Quadで5.71-6.73倍高速化できました。マルチスレッドの実績として3.18-3.75倍、高速化されますが、rayとsphereのデータをSOAに再構成して、SIMDでray-sphere交差の計算を行う処理もある程度の高速化につながりました。もうすでにナイスなOpenCL smallpt GPGPU実装(http://davibu.interfree.it/opencl/smallptgpu/smallptGPU.html)が存在しますが、比較対象となる高速化したCPU版ができたので、将来的に自分もDirectCompute smallpt GPGPU実装をやりたいなと思います。

Hieroglyph 3 DX11 Rendering Engine

http://hieroglyph3.codeplex.com/
Hieroglyph 3のCodePlexページ。

http://www.gamedev.net/community/forums/mod/journal/journal.asp?user=JasonZ
Jason Zinkのgamedev.net日記。最近はHieroglyph 3に関する記述が多いです。

数ヶ月前に単純なDX11 tessellationのサンプルを検索している時に知りました。Hieroglyph 3はオープンソースのDirectX11 rendering engineですが、単純なDX11 tessellationサンプルだけでなく、DirectCompute SSAOやDirectCompute water simulationのサンプルも提供しています。最近はdeferred context multithreaded renderingにも対応したみたいです。他にMITライセンスのDX11 rendering engineは知らないので、DX11を勉強している人にとっては面白いエンジンのような気がします。

Siggraph 2010: 3 New Intel DirectX11 Demos

http://visual-computing.intel-research.net/art/publications/sdsm/
Sample Distribution Shadow Maps

http://visual-computing.intel-research.net/art/publications/avsm/
Adaptive Volumetric Shadow Maps

http://visual-computing.intel-research.net/art/publications/deferred_rendering/
Deferred Rendering for Current and Future Rendering Pipelines

Beyond3Dのスレを読んで知りました (http://forum.beyond3d.com/showthread.php?t=58180)。デモはソース付きで、3つとも自分のHD5750で動作しました。

DX11 Order Independent Transparency with MSAA

はじめに

前回のDX11 OIT デモ(http://www.yakiimo3d.com/2010/07/19/dx11-order-independent-transparency/)を拡張して、MSAAに対応させました。

プログラムのソースとバイナリがDLできるCodePlexリンクは記事の最後の方に貼っています。

関連リンク集

1) http://www.yakiimo3d.com/2010/07/19/dx11-order-independent-transparency/
自分の元DX11 OITデモの記事です。 元デモはMSAA無しなので(オンにしたら本当なら表示がバグるだけのはずだけど、必要がないのにswapchainのbufferをDXGI_USAGE_UNORDERED_ACCESSフラグを立てて生成しているので、swapchain生成で落ちてしまいます)、色付Quadのedgeのジャギーが結構目立っています。

2) http://developer.amd.com/documentation/presentations/Pages/default.aspx
ATIのプレゼンリンク集ページから”GDC 2010: OIT and GI using DX11 linked lists”のプレゼン・パワポがDLできます。プレゼンでは、アルゴリズムのMSAAへの対応方法も記述されていたので、前回と同じく今回のデモもこのプレゼンを参考に実装しています。

デモ・スクリーンショット






上から順番にMSAA none、 MSAA 2x、 MSAA 4x、 MSAA 8xです。none、2x、4x、間では大きな改善が確認できますが、4xと8xの違いはあんまり分からないです 個人的には4x辺りからedgeのジャギーが気にならなくなります。サンプリング数を増やすと処理負荷が増え、fpsがどんどん落ちます。

実装の詳細

元デモからそんなに沢山の変更無しでMSAA対応を実装できました。主な変更点はSV_COVERAGEとSV_SAMPLEINDEX semantic parameterをpixel shaderの入力構造体へ追加して利用した事です。

StoreFragments.hlslへの変更点

struct ScenePS_Input
{
    float4 pos               : SV_POSITION;
    float4 color             : COLOR0;
    uint nCoverage        : SV_COVERAGE;                // Bit set according to which samples are covered.
};

SV_COVERAGE セマンティックのnCoverage parameterをpixel shaderの入力構造体に追加して、pixelのどのsampleがfragmentにcoverされているかの情報を取得しています。例えばnCoverageの1、4ビット目が立っていたら、samples 1 、4がcoverされていたことを意味します。MSAA対応の為に、fragmentの色と深度以外にもsample coverage情報をStructuredBufferの構造体に書き出すように変更しました。

SortFragmentsAndRender.hlslへの変更点

struct QuadPS_Input
{
    float4 pos          : SV_POSITION;
    uint nSampleIndex       : SV_SAMPLEINDEX;        // specify to run pixel shader per sample instead of per pixel  
};
...
// Read and store linked list data to the temporary buffer.
while( nNext != 0xFFFFFFFF )
{
    FragmentLink element = FragmentLinkSRV[nNext];
    aData[ nNumFragment ] = element.fragmentData;

    // Use sample only if the fragment covered it.
    if( aData[ nNumFragment ].nDepthAndCoverage & (1<<input.nSampleIndex) )
    {
        anIndex[ nNumFragment ] = nNumFragment;
        ++nNumFragment;
    }          
    nNext = element.nNext;
}

SV_SAMPLEINDEXはDX10.1で追加されたセマンティックで、DX11でも利用できます。 SV_SAMPLEINDEXセマンティックを持つparameterをpixel shaderの入力構造体に追加することで、pixel shaderをpixel毎ではなくsample毎に走らせる事が可能です。ソートとブレンドのSortFragmentsAndRender.hlslをsample毎に実行し、fragmentによってカバーされていないsampleを破棄する事で、StructuredBufferが入力データにもかかわらず、framebufferへの書き出し時のMSAA anti-aliasingが正しく処理されています。

OIT with MSAA Demo

Source Code & Binary
http://yakiimo3d.codeplex.com/releases/view/49570
デモは4x MSAAの設定から開始します。Change DeviceメニュのMultisample Count項目からMSAAの設定を変更できます。

雑多なコメント

SV_SAMPLEINDEX pixel shader semanticを利用して、pixel単位ではなくsample単位で初めてpixel shaderをまわしました。10.1からできる処理ですが、DX9では出来なかった事ができた、新しいAPIを触っている感を少し感じれました。SV_SAMPLEINDEXはDeferred RenderingのMSAA対応などでも利用するらしいです。今回のblog記事を執筆の休憩中にXBOX Live ArcadeのLimboを少し遊んでみたけど、中々良いゲームみたいです。寓話的でダークな雰囲気や、光、暗闇、霧を使ったグラフィックスの演出が綺麗で、作品として個人的に魅力を感じます。買ってよかったぞ感を感じています。

DX11 Order Independent Transparency

はじめに

ATI DX11 linked list OITアルゴリズムを自分も実装してみました。DirectX11 SDKのOITサンプルはCompute Shaderのサンプル的なもので実行速度が遅いですが、ATIのOITアルゴリズムは速いよと聞いていたので(実際結構速いです)、実装してみました。もうすでに何人もの方々がDX11 linked list OITの実装を公開していますが、参考にしながら自分の実装を行ないました。

プログラムのソースとバイナリがDLできるCodeplexリンクは記事の最後の方に貼っています。

関連リンク集

1) http://developer.amd.com/documentation/presentations/Pages/default.aspx
ATIのプレゼンリンク集ページから”GDC 2010: OIT and GI using DX11 linked lists”のプレゼン・パワポがDLできます。今回のデモはこのプレゼンのアルゴリズムを実装しています。

2) http://www4.atword.jp/cathy39/category/direct3d11/oit-direct3d11/
日本人GPU Pro投稿者のKaori Kubotaさんのlinked list OIT実装です。ソースコードを文中に用いた、丁寧で分かりやすい説明です。D3D11_BUFFER_UAV_FLAG_COUNTERとかサンプルで利用されていないDX11の機能の参考になりました。自分の今回の実装はATIのプレゼン資料とKubotaさんのblog記事を元に実装しています。

3) http://orenk2k.blogspot.com/2010/03/oit-order-independent-transparency.html
Linked list OIT実装についてのblog記事です。分かりやすい説明です。

4) http://sites.google.com/site/monshonosuana/directxno-hanashi-1/directx-110
Monshoさんのlinked list OIT実装です。分かりやすい説明で、ソースコード、バイナリがDLできます。

5) http://www.uraldev.ru/articles/id/36
Linked list OIT実装についてのblog記事です。記事がロシア語なので、google translateを利用して読みました。個人ブログではなく、開発者サイトへの投稿記事みたいなので、気合が入って書かれています。ソースコードとバイナリがDLできます。 http://www.wolfgang-engel.info/blogs/?p=116のコメント欄に作者がリンクが張っているので知りました。

6) http://joescg.blogspot.com/2010/01/oita-buffer-demo.html
もう一個ロシア語blog記事のOIT実装です。google translateをまた利用しました。http://www.geeks3d.com/forums/index.php/topic,861.0.htmlを読んで知りました。

7) http://www.yakiimo3d.com/2010/06/19/dx11-high-quality-global-illumination-rendering-using-rasterization/
今回のDX11 linked list手法はOIT以外にも利用方法があるみたいです。Toshiya Hachisukaさんの “High-Quality Global Illumination Rendering Using Rasterization”アルゴリズムとかも今回のATI StructuredBuffer linked list手法で高速化できるみたいです。

デモ・スクリーンショット



ID3D11BlendStateを利用した普通のalpha blendingの描画結果です。青色のポリゴンが間違って赤色のポリゴンの手前に描画されています。各色付ポリゴンはひとつのドロー・コールで描画されているので、ポリゴンをソートして正しいalpha blending結果にすることも無理です。



DX11 OITを利用した描画結果です。pixel単位にfragmentがソートされるので、正しく描画されています。

実装の詳細

参考にできる文章が他にも沢山あるので、linked list OITアルゴリズムの説明は書かないです。自分のATI HD5750だと、DirectX SDK OITサンプルが320×240の画面サイズで10 fpsぐらいでしたが、今回のATI OITの実装は640×480の画面サイズで700 fpsぐらいでました。普通のID3D11BlendStateを利用したalpha blendingだと画面サイズ640×480で3000 fpsぐらいでます。

OITデモ

Source Code & Binary
http://yakiimo3d.codeplex.com/releases/view/49213

コメント

最後にデモを公開して3ヶ月以上間隔があいてしまった。先月は少し落ち込んでいたけど、大分回復したので、もう少し実装頑張りたいです。次は今回のOITデモをベースとした半透明マテリアルの実装とか、DX11 tesselation機能を利用したDX11 Phong Tesselationデモとかを考えています。