cbufferの定義だと全部グローバルになってちゃんと管理しないと名前の被りとか出てきそう。
参考にしていたシェーダプログラムがやっているように、ConstantBuffer<AAA>で定義するように書き換えてみた。
5.1まではD3DCompile関数でコンパイル出来た。
IDxcLibraryとIDxcCompiler2を予め用意しておいて、コンパイル時にIDxcLibrary::CreateBlobWithEncodingFromPinnedを呼び出す。
するとコンパイルが通らない。
うすうす知ってたけど、シェーダモデルを5.1に上げる必要がある。
vs_5_0とps_5_0をvs_5_1とps_5_1に変えればいいだけなんだけど、なんにも表示されなくなった。いろいろ試してみたけどわからず。
5.1には下位互換がないのか?なにかが抜けているのか?
シェーダモデルについて調べてみると、今の最新が6.6らしい。
どうせハマるなら5.1とかやってる場合じゃないと思い、6にあげようとするも6からはコンパイラが変わって、d3dcompiler_47.dllからdxcompiler.dllになる。
#include <D3Dcompiler.h> #pragma comment( lib, "d3dcompiler.lib")
旧インクルードとライブラリ
#include <dxcapi.h> #pragma comment (lib, "dxcompiler.lib")
新インクルードとライブラリ
ただ、この関数受け付ける文字列がsjisで、若干使いづらい。
6.0からはグローバル関数ではなく、COMオブジェクトに変わる。
tCom<IDxcLibrary> oLibrary ;
::DxcCreateInstance( CLSID_DxcLibrary, IID_PPV_ARGS( &oLibrary )) ;
tCom<IDxcCompiler2> oCompiler ;
::DxcCreateInstance( CLSID_DxcCompiler, IID_PPV_ARGS( &oCompiler )) ;
tCom<IDxcBlobEncoding> oSource ;
oLibrary->CreateBlobWithEncodingFromPinned( sSrc.Ptr(), sSrc.Len(), CP_UTF8, &oSource ) ;
#if defined(_DEBUG)
cWS pArgs[] = { L"-Ges", L"-Zi", L"-Od" } ;
#else
cWS pArgs[] = { L"-Ges", L"-O3" } ;
#endif
tCom<IDxcOperationResult> oResult ;
oCompiler->Compile( oSource.Get(), sName, sFunc, sModel, pArgs, fArray( pArgs ), nullptr, 0, nullptr, &oResult ) ;
HRESULT nRet ;
oResult->GetStatus( &nRet ) ;
if( FAILED( nRet )) {
tCom<IDxcBlobEncoding> oErr, oErr16 ;
oResult->GetErrorBuffer( &oErr ) ;
oLibrary->GetBlobAsUtf16( oErr.Get(), &oErr16 ) ;
mLogE( sModel, cWS( oErr16->GetBufferPointer())) ;
return false ;
}
tCom<IDxcBlob> oVS ;
oResult->GetResult( oVS.ReleaseAndGetAddressOf()) ;
ここに渡せる文字列がコードページ指定できるけど、UTF16の渡し方がわからず。
見つけたサンプルがCP_UTF8を渡していたのでUTF-8で渡すことにした。
コンパイルはIDxcCompiler::Compile関数を呼び出す。
ここで渡す文字列は全部UTF16でそのまま渡せるようになった。
最初の引数はCreateBlobWithEncodingFromPinnedの結果をそのまま渡す。
次がソース名。エラー表示とかで役立どのソースかの識別に役立つ。
次がエントリポイントでシェーダの関数名を渡す。
その次がシェーダモデル。vs_6_6とps_6_6を渡す。
その次がコンパイルスイッチ。今までフラグで渡していたけど文字列で渡す形式にかわった。いままで渡していたものと同じようにしてみた。
あとはマクロと、インクルードなのでnullにしておいた。
実行後、IDxcOperationResultが返って、IDxcOperationResult::GetStatusを呼び出して結果を確認する。
エラーの場合はIDxcOperationResult::GetErrorBufferでエラー情報を取り出し、GetBlobAsUtf16でUTF16に変換してIDxcBlobEncoding::GetBufferPointerでエラーの文字列が取り出せる。
今までのエラー情報は、行番号とカラム位置だけだったけど、今度のはソースと一緒にエラー箇所が表示されるのですごく直しやすい。
うまく行った場合はIDxcOperationResult::GetResultでIDxcBlobを取得する。
D3D12_GRAPHICS_PIPELINE_STATE_DESC oGPSD = {} ;
D3D12_SHADER_BYTECODE & oSB = oGPSD.VS ;
oSB.pShaderBytecode = oVS->GetBufferPointer() ;
oSB.BytecodeLength = oVS->GetBufferSize() ;
これが今までのBlobと同じで、バイトコードに設定する関数も同じ。
コンパイル部分の修正が終わって、いざ実行してみると起動しない。
dxcompiler.dllがないからだ。
正規の方法はどうなるかわからないが嫌な予感がしたのはgithubでこのコンパイラのソースが公開されているので、ここのバイナリかソースを自分でコンパイルするのか?
とりあえず動かしたいので自分のPCを探すとたくさん見つかった。
PIXのが新しそうだったのでそれをコピーした。
改めて実行してみるとシェーダのコンパイルエラーが発生した。
ネットで検索してみると、開発者モードでないとだめと書いてあったけどすでに他の件で開発者モードには設定済み。オプションに-Vdを指定すればいいとか、デバイスを作る前にD3D12ExperimentalShaderModels機能を有効にするとかあったけどこれもだめだった。
コンパイル時に署名をつけるらしく、dxil.dllというのも必要みたい。
これもPIXの同じフォルダにあったのでコピーした。
これでやっと動くようになったと思いきや、冒頭の状態に戻った。
何も表示されない状態。
PIXでデバッグしてみると、メッシュのボーン情報がシェーダに渡ってない。
定数バッファの書き換えの時に管理名を変えたんだけど、描画時に指定している名称を変え忘れていた。
5.1に変えたからとか全く関係なかったけど、5から6へ移行するための契機としていい不具合だった。
0 件のコメント:
コメントを投稿