C-WebGL: ESSLシェーダをVulkanのGLSLに変換したい
やってみた方が早いんじゃないかということで。。
実際に手で書き換えてみた
実際の変更は:
-
#version 450 core
を設定する (ANGLEの該当箇所) -
gl_FragColor
は専用のout
を定義し 、gl_
で始まる名前はユーザが使えないのでwebgl_
にしておく (ANGLEの該当箇所) -
attribute
はin
、varying
はin
(フラグメントシェーダ) かout
(バーテックスシェーダ)にする -
texture2D
はtexture
にする - 基本型の
uniform
は1つのUBOにまとめる - 入出力に
layout
を指定する
3 と 4 は WebGL2 fundamentalsにシェーダの移行方法として説明がある 。 5 と 6 はVulkanの要請。
というわけで、
- 入出力の列挙
-
texture2d
、textureCube
あたりの変換 - レイアウトの生成
あたりさえ処理してしまえば簡単に変換できてしまうように見える。 ...本当か。。?
AST を鑑賞する
とりあえず、glslangのASTを変換してやればよさそうなので、元々のASTを観察してみることにする。
$ ./glslangValidator.exe -i orig.frag
orig.frag
ERROR: 0:1: 'float' : type requires declaration of default precision qualifier
ERROR: 0:1: 'TEXEL_COUNT_V' : variables with qualifier 'const' must be initialized
ERROR: 0:1: '' : compilation terminated
ERROR: 3 compilation errors. No code generated.
Shader version: 100
ERROR: node is still EOpNull!
0:? Linker Objects
0:? 'TEXEL_COUNT_V' ( temp mediump float)
... 元のもバリデータ通らないじゃないか。。 -r
オプションでこの辺のチェックは省略できる
-r | --relaxed-errors relaxed GLSL semantic error-checking mode
出力結果: https://gist.github.com/okuoku/bad334177f4966463a21b60cd7356b07#file-out_orig-ast-txt
例えば、
// Set initial color
gl_FragColor = BLUE;
の行は、
0:27 move second child to first child ( temp mediump 4-component vector of float)
0:27 'gl_FragColor' ( fragColor mediump 4-component vector of float FragColor)
0:27 Constant:
0:27 0.000000
0:27 0.000000
0:27 1.000000
0:27 1.000000
のようにダンプされる。
複雑なシェーダを手で変換してみる
今回はthreejsのglTF extensions sampleで使われている、glTF標準PBRシェーダを変換してみることにした。
Gistって過去の変更にリンク貼れないのか。。
解決方法がわからないのが2点。
-
diffuse
のようにリネームすべき識別子が関数パラメタ等としても使われている場合にどうするのか 。glslang側に識別子のリネーム機能とかないかな。。Schemeで言うところのマクロの健全性問題だ。 -
gl_FrontFacing
のような、頂点シェーダじゃない出力変数をどうやってバインドするのか 。これはVulkanをちゃんと見ないとダメだな。。
あと、
Push constants
- replace non-opaque uniforms
-Think of them as small, fast-access uniform buffer memory
と有るし本来GLで言うところの uniform
はVulkan的な意味のpush constantsにしたい(実際、push constantsはシェーダ側のレジスタにマップされるので実装的にも近いはず)が、Vulkanの最低保証サイズが128bytesでGL側の最低保証サイズ(128 floats)より小さいので使えない可能性がある。
builtinは宣言不要で利用できた
GL_KHR_vulkan_glsl の仕様書を読み返してみたところ、普通にbuiltinは従来のGLSLの名称のままで使えるって事になっていた。というわけで、ココに書いてあるbuiltin変数はVulkan上でも同様に宣言されていると考えてOKということになる。