前回 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)