WebGL: シェーダのコンパイルが描画開始時に発生してストールする
問題
シェーダーのコンパイルが遅い……のはまだ許せるのだが、 gl.compileShader や gl.linkProgram を使ってシェーダをコンパイルしたタイミングでなく、実際に使い始めるタイミングでストールが発生する ANGLEのバックエンドを変えてみた
DX11バックエンドがやばそう
Nsightで計測してみた
C:/Users/<username>/AppData/Local/Google/Chrome SxS/Application/chrome.exe
ふつうのChromeでもちろん構わないが、普段Chromeは使っているので別のexecutableがよかった
--no-sandbox --disable-gpu-watchdog --disable-gpu-program-cache
--gpu-startup-dialog はLive Analysis時にNsightとのコネクションを失うので最悪
https://gyazo.com/c770773a4615b3a90b8c230b3db08e61
1260ms......
https://gyazo.com/fd01486b01550a39a6f327e8b9dbc550
D3DCompile が Draw 直前に来ている様子が見える
D3D全然知らんがどうせシェーダプログラムのコンパイルとドローコールやろ
ANGLEのソース読む
ANGLEのスタックトレースを追ってみる:
HLSLCompiler::compileToBinary 🔗 D3DCompile っぽい形跡
Renderer11::compileToExecutable 🔗 ProgramD3D::getPixelExecutableForCachedOutputLayout 🔗 Context11::triggerDrawCallProgramRecompilation 🔗 StateManager11::syncProgram 🔗 StateManager11::updateState 🔗 StateManager11::drawArrays 🔗 はい
やること
StateManager11::syncProgram のコメント 🔗 曰く、 code:cc
// Things that affect a program's dirtyness:
// 1. Directly changing the program executable -> triggered in StateManager11::syncState.
// 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal.
// 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal.
// 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState.
// 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState.
// 6. An internal shader was used. -> triggered in StateManager11::set*Shader.
// 7. Drawing with/without point sprites. -> checked in StateManager11::updateState.
// TODO(jmadill): Use dirty bits for transform feedback.
つまり、実際に用いるVBOとフレームバッファを使って一度レンダリングをしてやれば、そのタイミングでD3D上でシェーダのコンパイルが走る
結果
stallしなくなった
VBOとフレームバッファ引っ張ってきて一回レンダリングしてあげようね