OptiX memo
OptixX APIにおけるintersection アルゴリズム
https://scrapbox.io/files/64a04e2ce03192001b10e3b1.png
RayGeneration
最初のRayの生成を行う部分 optixLaunch()の呼び出しで実行される。内部でTraceRayを呼び出すことでASのTraversalが行われる。
Any Hit
Intersectionがされるとまず呼び出されるもの。ここで衝突か否かを分岐することが可能であり、Alpha抜きなどをすることが出来る。
Closest Hit
衝突が行われたときに実行される(Any Hitを通った場合)。
Miss
レイが衝突しなかった時に呼び出されるやつ。
CPU側の処理
- Device Context
Device contextはOptixAPIの呼び出し用の本体みたいなやつ。まずはここでContextの初期化を行う。
code:c
// CUDAの初期化
cudaFree( 0 );
// OptixAPIの初期化
optixInit();
// DeviceContextのオプション 何も指定しなければdefaultになる
OptixDeviceContextOptions options = {};
// Associate a CUDA context (and therefore a specific GPU) with this
// Device Context
CUcontext cuCtx = 0; // NULLは現在アクティブなcontextを使用する事を意味する
OptixDeviceContext context = nullptr;
optixDeviceContextCreate( cuCtx, &options, &context ); //Contextの初期化
- Accelaration Structures
OptixにおけるASはInstance Accelaration Structure(IAS)とGeometry Accelaration Structure (GAS)の2種類存在する。GASはジオメトリ情報をそのまま持っているやつでIASはそれを基にInstanceを作ったやつ。この辺見ると分かりやすいとおもう
-- OptixAccelBuildOptions
https://scrapbox.io/files/64a4129b92bbb1001ca53efc.png
buildFrags : ASビルド時の設定
https://scrapbox.io/files/64a412f4b78953001c616ef7.png
OPTIX_BUILD_FLAG_NONE : 特になし
OPTIX_BUILD_FLAG_ALLOW_UPDATE : optixAccelBuildを呼び出した後に新しい頂点データでビルドの更新を許す
OPTIX_BUILD_FLAG_ALLOW_COMPACTION : ASの圧縮を許可する(多分)
OPTIX_BUILD_FLAG_PREFER_FAST_TRACE : トレースを速くする?下のBuildと排他的
OPTIX_BUILD_FLAG_PREFER_FAST_BUILD : ビルドを速くする?上のTraceと排他的
OPTIX_BUILD_FLAG_ALLOW_RANDOM_VERTEX_ACCESS : vertexに対するrandomアクセスを許可する
optixGetTriangleVertexData等を使うときはこれを指定する必要があるみたい
OPTIX_BUILD_FLAG_ALLOW_RANDOM_INSTANCE_ACCESS : Instanceに対するランダムアクセスを許可する
optixGetInstanceTraversableFromIASが使えるようになるらしい
OPTIX_BUILD_FLAG_ALLOW_OPACITY_MICROMAP_UPDATE : OpacityMicroMapのアップデートを許可する
OPTIX_BUILD_FLAG_ALLOW_DISABLE_OPACITY_MICROMAPS : instanceのDISABLE_OPACITY_MICROMAPSを許可してくれる?
operation : 今このビルドが最初の生成なのか更新なのかを示すもの。IASの更新と可であればBUILD_~UPDATEを指定する必要が多分ある
https://scrapbox.io/files/64a415192588c9001c029eca.png
UPDATEは境界の更新だけを行う(なのでIASの移動などであればこれを使うべき)ただし大幅に変化する場合はパフォーマンスが落ちる可能性があるらしい
MotionOption
モーションありだとこの辺見ておく必要がある?
まだ開発中の雰囲気があるのでほっといても良さそう
https://scrapbox.io/files/64a4158da77bd1001b313170.png
numKeys : >1の時、モーションが有効化される。Motionが非有効化だとtimeBeginやtimeEnd、fragが全て無視される
timeBegin : モーションがスタートする時間。timeEndより小さく
timeEnd : モーションが終わる時間
flags : アニメーションのフラグ
https://scrapbox.io/files/64a41656917c9c001c44f80c.png
特にフラグの説明がないのでまだちゃんと使えるものではないと思われる?
GASはTriangleだけではなく様々なジオメトリも扱える。Triangleの場合
code:GAS例
OptixBuildInputTriangleArray& buildInput =
buildInputs0.triangleArray; buildInput.type = OPTIX_BUILD_INPUT_TYPE_TRIANGLES;
buildInput.vertexBuffers = &d_vertexBuffer;
buildInput.numVertices = numVertices;
buildInput.vertexFormat = OPTIX_VERTEX_FORMAT_FLOAT3;
buildInput.vertexStrideInBytes = sizeof(float3);
buildInput.indexBuffer = d_indexBuffer;
buildInput.numIndexTriplets = numTriangles;
buildInput.indexFormat = OPTIX_INDICES_FORMAT_UNSIGNED_INT3;
buildInput.indexStrideInBytes = sizeof(int3);
buildInput.preTransform = 0;
https://scrapbox.io/files/64a069ffedfdbb001becc0ab.png
type GASデータの種類の設定 OPTIX_BUILD_INPUT_TYPE_TRIANGLEなら所謂ポリゴン
vertexBuffers メッシュの頂点データ指定するとこ(指定するのはCUDApointerであることに注意)
numVertex 頂点数
vertexFormat 頂点データのフォーマット 通常ならFloat3でいいと思う
vertexStrideInvBites 1つの頂点のbit数の指定
indexBuffer インデックスデータをしてするとこ
numIndexTriplets ポリゴン数を指定する
indexFormat インデックスデータのフォーマット
frag : Anihit等の適応を行うかの設定部分
https://scrapbox.io/files/64a3ed5b8a7b1a001c86f61f.png
OPTIX_GEOMETRY_FLAG_NONE : 特になし
OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT : ANYHITの呼び出しをしないようにする(IASで上書きできるっぽい)
OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL : 一度につきAnyHitが呼び出されるようになる。(明示的に書かないと何度もAnyHitが呼ばれる可能性があるらしい)
OPTIX_GEOMETRY_FLAG_DISABLE_TRIANGLE_FACE_CULLING : カリングを無視する
sbtIndexOffsetBuffer: 各ポリゴンのSBTのindexを指定するところ。注意としてGASやIASで設定されるOffsetからの相対indexである。下の図で言うSBT_GAS_Indexに相当する
https://scrapbox.io/files/64a3f92875b367001c294a2c.png
primitiveIndexOffset : optixGetPrimitiveIndex()の呼び出し時におけるprimitive indexのバイアス?
preTransform なにこれ?
以上のOptionを設定したら次はGAS生成時に使用する一時的なメモリの確保を行う
https://scrapbox.io/files/64a411e23ace99001c21bc33.png
ここでのtempbuffer~は生成時にのみ使うバッファ、outputは多分GASのデータ入れる奴なので事前に用意して最後まで使う。
GASようのhandleを用意し、先ほど制作したAS,GASのオプションと一時バッファ、outputバッファを指定して生成を行う。
https://scrapbox.io/files/64a4121d51fa7b001ca660b1.png
-- ASの圧縮について
ASは生成時にメモリ上で飛び飛びのデータになることがあるため、これを圧縮して効率化できる。compress
この辺は以下の記事を見た方がいいと思う
IASについても同様
-- IAS
GASのデータをInstanceという形で用いる。
OptixInstance
https://scrapbox.io/files/64a41c1392bbb1001ca5b7b9.png
transform : IASに対してかけるAffine行列の要素(12要素なのは一番下の行が0,0,0,1で固定だから)
https://scrapbox.io/files/64a41f959cce74001c55fc63.png
この図で言うa~bの部分(列優先)
instanceId : アプリケーション側で設定するインスタンスのID、適当に決めてヨシ(リミットはOPTIX_DEVICE_PROPERTY_LIMIT_MAX_INSTANCE_ID)
sbtOffset : SBTのインスタンス用のオフセット
visiblityMask : トラバーサルする時のマスク。mask & visiblityMask = 0の時にレイは衝突しなくなる。特に消したいとかないのであれば255を設定していいと思う
flags
https://scrapbox.io/files/64a41d900f67ef001bf14c59.png
OPTIX_INSTANCE_FLAG_DISABLE_TRIANGLE_FACE_CULLING : カリングをオフにする。レイのフラグを無視して行われる
OPTIX_INSTANCE_FLAG_FLIP_TRIANGLE_FACING : ポリゴンの向きを反転させる
OPTIX_INSTANCE_FLAG_DISABLE_ANYHIT : ANIHITを呼び出さなくする。Rayのフラグより強い
OPTIX_INSTANCE_FLAG_ENFORCE_ANYHIT : ANIHITを強制的に呼び出す。
OPTIX_INSTANCE_FLAG_FORCE_OPACITY_MICROMAP_2_STATE
OPTIX_INSTANCE_FLAG_DISABLE_OPACITY_MICROMAPS
traversableHandle : GASのハンドルを指定する場所(多分IASも入れられる)
pad アライメント? 16バイトのアライメントを確保するため、80バイトまで丸める。
- Program
いわゆるシェーダーはOptix上ではProgramと呼称する。ProgramにはOptixModule OptixProgramGroup, Optix Pipelineの設定が必要である。
- Module
CUDAコードをコンパイルするとPTXというファイルが出てくるが、これをOptixModuleという形で紐づける。Moduleの生成にはModuleCompileOptionとPipelineCompileOptionの設定が必要(Pipelineの方は後々使うので保存しておくこと)
ModuleCompileOptionの設定項目
https://scrapbox.io/files/64a192f2128d84001bd06306.png
maxResterCount : SASS?のコンパイル時に許容されるレズスタ数の最大数(明示的にしないなら0)
SASSについてはこの辺みるといいかも
optLevel : 最適化のレベル設定
OPTIX_COMPILE_OPTIMIZATION_DEFAULT : 全ての最適化 とりあえずこれでいい気がする
OPTIX_COMPILE_OPTIMIZATION_LEVEL_0 : 最適化なし
OPTIX_COMPILE_OPTIMIZATION_LEVEL_1 : いくつか最適化あり
OPTIX_COMPILE_OPTIMIZATION_LEVEL_2 : 大体の最適化あり
OPTIX_COMPILE_OPTIMIZATION_LEVEL_3 : 全ての最適化あり
debugLevel : デバッグレベルの設定
OPTIX_COMPILE_DEBUG_LEVEL_DEFAULT : 最低限
OPTIX_COMPILE_DEBUG_LEVEL_NONE : Debug情報を出さない
OPTIX_COMPILE_DEBUG_LEVEL_MINIMAL : パフォーマンスに影響しないデバッグ情報を作る
OPTIX_COMPILE_DEBUG_LEVEL_MODERATE : ある程度のコストがかかるけどもう少し詳しいデバッグをする
OPTIX_COMPILE_DEBUG_LEVEL_FULL : フルデバッグ情報を出す
boundValues : なに?
numPayloadTypes : PipelineCompileOptionsでのnumPalyloadValueが0ならここでも0でなくてはいけない
https://scrapbox.io/files/64a1afedb2b39b001b522b67.png
PipelineCompileOptionの設定項目
usesMotionBlur : モーションブラーのON OFFをするとこ Bool値を入れる
traversableGraphFlags
OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_ANY : トラバース可能なグラフが有効であることを示す
OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_GAS : 変換を伴わない単一のGASだけ有効になる
OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING : GASに直接接続された単一IASだけ有効
numPayloadValues : numPayloadTypes
numAttributeValues :
exceptionFlags :
https://scrapbox.io/files/64a2d4f757a0b0001cb2228a.png
OPTIX_EXCEPTION_FLAG_NONE : 例外出力をオフにする
OPTIX_EXCEPTION_FLAG_STACK_OVERFLOW : 継続スタックに関わる例外チェックを有効にする
OPTIX_EXCEPTION_FLAG_TRACE_DEPTH : トレースデプスに関わる例外チェックを有効にする
OPTIX_EXCEPTION_FLAG_USER : optixThrowException()を通したユーザー例外チェックを有効にする。このフラグはmoduleで呼び出す場合は必ずONにすることが必要である。
OPTIX_EXCEPTION_FLAG_DEBUG : トラバーサルに関わる様々な例外チェックを有効にする
pipelineLaunchParamsVariableName : Launch時に渡すパラメーター名 exampleだと"params"って名前のやつ
usesPrimitiveTypeFlags : トラバーサルするプリミティブのフラグ。0とするとCUSTOMとTRIANGLEが可能になる。カーブとか使いたいんならこの辺いじる必要がありそう
https://scrapbox.io/files/64a2903b76997f001d89ade7.png
allowOpacity Micromaps : Micromapとはアルファ抜きした物体に対して近似的にポリゴンを作って衝突判定を減らす機能以下参照。これのON OFF
optixModuleCreateFromPTX
https://scrapbox.io/files/64a2d96ab1e91f001cec2869.png
Sampleで使ってるModuleを作るやつ
ここではPTXのファイルの文字列を読み込みこれoptixModuleCeateFormPTX()にOption等を渡して生成している。多分この前の原因はここの辺で絶対パスが指定されているせいで出なかったのだと考えられる。
- Program Group
OptixProgramGroupはシェーダーを生成する
https://scrapbox.io/files/64a2f21cdde250001c8a4dc1.png
OptixProgramGroupDescでオプションを作る
kind : 種類を設定する
OPTIX_PROGRAM_GROUP_KIND_RAYGEN : RayGen
OPTIX_PROGRAM_GROUP_KIND_MISS : Miss
OPTIX_PROGRAM_GROUP_KIND_EXCEPTION : Program group containing an exception (EX) program.
OPTIX_PROGRAM_GROUP_KIND_HITGROUP :
OPTIX_PROGRAM_GROUP_KIND_CALLABLES :
raygen
module : モジュールの指定場所
entryFunctionName : functionの名前指定部分
miss
module
entryFunctionName
hitgroup
https://scrapbox.io/files/64a3126b4cf45f001c67f599.png
moduleCH : ClosestHitのModule
entryFunctionNameCH : ClosestHitの名前
moduleAH : AnyHitに適用するModule
entryFunctionNameAH :
moduleIS : intesection programに適用するModule
Intersection Programは自分で交差判定を書くことが出来る奴
- PipeLine生成
パイプラインの生成はcompile optionとlink optionが必要である。
OptixPipelineLinkOptions
maxTraceDepth : レイの最大反射数
debugLevel : デバッグの情報を出すのかの設定、内容自体はModule compileと同様。何故かリファレンスには載ってない。
https://scrapbox.io/files/64a328e3e7a947001c038f9e.png
その後、Pipelineを生成する
https://scrapbox.io/files/64a3292cefe03b001b35eb3f.png
sampleだとなんか後に続いているけど謎
なんだろうね
https://scrapbox.io/files/64a3294343539a001c3f2b24.png
- SBT shader binding tanble
SBTってなあに?→マテリアルの値のように各シェーダーのパラメーターを保存しているテーブル
SBTはOptixShaderBindingTableで作られ、最終的にはoptixLaunchで起動する際に渡すことでdeviceに渡される。
https://scrapbox.io/files/64a31a497c7184001b5646f4.png
https://scrapbox.io/files/64a31a524cf45f001c680ae2.png
OptixShaderBindingTableは以下のような構造体
https://scrapbox.io/files/64a31a89efe03b001b35b6f7.png
基本的にはマテリアルのデータをDeviceにコピーし、そのポインタ―をそれぞれのシェーダーで持って置くみたいな感じ
マテリアルのデータに使う構造体は他の方で定義していて、例えばこんな感じ
https://scrapbox.io/files/64a31b337a6608001cb96163.png
Sampleとかだと更に構造体を用意しており、以下のような感じになっている。多分これ使った方がいい
https://scrapbox.io/files/64a31b51c978d1001c65d47e.png
流れとしては
上記の構造体とDevice上のポインタを用意
値を設定
optixSbtrecordPackHeaderを実行
https://scrapbox.io/files/64a31bc71fc330001b098356.png
Device上のメモリ確保後、メモリコピー
例
https://scrapbox.io/files/64a31ce5174119001b928877.png
ClosestHitとかだと複数マテリアルあるけどこれは各マテリアルでRecord作ってその配列をコピーすればOK
https://scrapbox.io/files/64a31d9be826ce001c770b30.png
最終的にはSBTの各項目にrecordのdevice pointerとstrideと要素数を与えて記録は終わり
・出会ったバグ
- 何故かGASのSBTのOffsetが反映されない
解決
GASのSBTのoffsetはsbtIndexOffsetBufferで指定できる。ここに各primitiveにおけるSBToffsetを渡してあげればよい
https://scrapbox.io/files/64df6061806f4c001c791d16.png
今回はなぜかそうしてもoffsetが反映されなかった(IAS等のoffsetは機能しており、ちゃんと対応したShaderもコンパイルされて反映されていることは確認している。なのでGASのOffsetだけ反応しないみたいな感じだった)
原因
上記のoffsetはnumSbtRecordsの値によって(0~numSbtRecords-1)の範囲に収めるべきと書いてあった。
numSbtRecordsを見てみると1と入力されていたのでこれが多分原因だった。また、これを変更する際にはfragもその分用意しな
くてはいけない(ちゃんとエラーが出る)
Materialが2個だけの場合だったらこんな感じに書き換えれば上手くいった
https://scrapbox.io/files/64df613bc4ad99001b41cac4.png
https://scrapbox.io/files/64df61325da834001b6ab0fd.png