前回 Nexus 7 の Adreno 320 で OpenGL ES 3.0 のシェーダーが正しく動作しないと
書いたのですが、条件が絞れてきました。
UniformBlock の変数を直接演算に用いると Shader Compiler の
glLinkProgram() で Internal Error が発生するか直後にクラッシュします。
#version 300 es // GLSL: VertexShader precision highp float; uniform SceneBlock { mat4 PView; mat4 ViewMatrix; }; in vec3 POSITION; in vec3 NORMAL; in vec2 TEXCOORD; out vec3 onormal; out vec2 otexcoord; void main() { vec4 opos= vec4( POSITION.xyz, 1.0 ) * PView; // ← ここ opos.z= 2.0 * opos.z - opos.w; gl_Position= opos; onormal= vec3( 0.0, 0.0, -1.0 ); otexcoord= TEXCOORD.xy; }
下記のように、Uniform Block 内の変数を一旦ローカル変数にコピーすると
問題なく動くようになります。
void main() { mat4 pv= PView; // Uniform Block の変数をローカルにコピー vec4 opos= vec4( POSITION.xyz,1.0 ) * pv; opos.z= 2.0 * opos.z - opos.w; gl_Position= opos; onormal= vec3( 0.0, 0.0, -1.0 ); otexcoord= TEXCOORD.xy; }
Fragment Shader も同じです。
OpenGL ES 2.0 では Uniform Block が無いので問題ありません。
OpenGL ES 3.0 でも Uniform Block を使わない ( default Uniform Block だけ使う)
場合も問題ありませんでした。
Adreno 320 以外ではどちらのコードも動きます。
Mali-T604 実機, Adreno SDK の OpenGL ES 3.0 Emulator,
Mali Developer Tools の OpenGL ES 3.0 Emulator いずれも問題ありませんでした。
症状を確認した本体
・Nexus 7 (2013)
・Android 4.3 JSS15Q
GL_VERSION: OpenGL ES 3.0 V@14.0 AU@ (CL@) GL_RENDERER: Adreno (TM) 320 GL_VENDOR: Qualcomm GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 3.00
購入直後一度システムソフトウエアの更新があり、GL_VERSION の内容が
置き換わっています。上記は更新後です。
更新後も同じ症状が出ています。
回避方法がわかったので、とりあえず Adreno 320 でも OpenGL ES 3.0 用
シェーダーの動作確認ができました。
他に Intel HD 4000 (9.18.10.3165) でも Uniform Block で問題が出ています。
Uniform Block 内で mat3x4 の配列を宣言すると、index の計算を間違えるようです。
(layout std140 指定済み)
すべて vec4 宣言し、自分で matrix に組み立てることで回避できます。
関連エントリ
・Nexus 7 (2013) の Adreno 320 と OpenGL ES 3.0 (Android 4.3)