I'm seeing a very strange issue on certain OSX machines where my WebGL program seems to be using the wrong texture contents for drawing.
I have a sprite batch set up, where I buffer together a bunch of sprite quads into a single draw call. I also use multi texturing to reduce the number of draw calls further, drawing sprites for several textures in the same draw call.
Each vertex has the following data:
// 16 bytes float x; float y; float u; float v; // 16 bytes float texture_offset_x; float texture_offset_y; float texture_scale_width; float texture_scale_height; // 24 bytes float t0; float t1; float t2; float t3; float t4; float t5; // 8 bytes float width_scale; float height_scale; // 4 bytes unsigned byte r; unsigned byte g; unsigned byte b; unsigned byte a; // Texture sampler index float texture_index;
And the fragment shader combines the draw calls like this:
"#version 100", "", "uniform lowp sampler2D sampler0;", "uniform lowp sampler2D sampler1;", "uniform lowp sampler2D sampler2;", "uniform lowp sampler2D sampler3;", "uniform lowp sampler2D sampler4;", "uniform lowp sampler2D sampler5;", "uniform lowp sampler2D sampler6;", "uniform lowp sampler2D sampler7;", "", "varying mediump vec2 vTextureCoord;", "varying lowp vec4 vTintColor;", "varying lowp float vTextureIndex;", "", "void main(void) {", " lowp vec4 fragColors[8];", " fragColors[0] = texture2D(sampler0, vTextureCoord);", " fragColors[1] = texture2D(sampler1, vTextureCoord);", " fragColors[2] = texture2D(sampler2, vTextureCoord);", " fragColors[3] = texture2D(sampler3, vTextureCoord);", " fragColors[4] = texture2D(sampler4, vTextureCoord);", " fragColors[5] = texture2D(sampler5, vTextureCoord);", " fragColors[6] = texture2D(sampler6, vTextureCoord);", " fragColors[7] = texture2D(sampler7, vTextureCoord);", "", " lowp float fragIncluded[8];", "", " fragIncluded[0] = float(vTextureIndex <= 0.5);", " fragIncluded[1] = float(vTextureIndex >= 0.5 && vTextureIndex < 1.5);", " fragIncluded[2] = float(vTextureIndex >= 1.5 && vTextureIndex < 2.5);", " fragIncluded[3] = float(vTextureIndex >= 2.5 && vTextureIndex < 3.5);", " fragIncluded[4] = float(vTextureIndex >= 3.5 && vTextureIndex < 4.5);", " fragIncluded[5] = float(vTextureIndex >= 4.5 && vTextureIndex < 5.5);", " fragIncluded[6] = float(vTextureIndex >= 5.5 && vTextureIndex < 6.5);", " fragIncluded[7] = float(vTextureIndex >= 6.5 && vTextureIndex < 7.5);", "", " lowp vec4 fragColor = fragColors[0] * fragIncluded[0] + ", " fragColors[1] * fragIncluded[1] + ", " fragColors[2] * fragIncluded[2] + ", " fragColors[3] * fragIncluded[3] + ", " fragColors[4] * fragIncluded[4] + ", " fragColors[5] * fragIncluded[5] + ", " fragColors[6] * fragIncluded[6] + ", " fragColors[7] * fragIncluded[7];", "", " gl_FragColor = fragColor * vTintColor;", "}"
Everything works fine in most cases. However on some OSX machines, the texture being sampled appears incorrect sometimes. Specifically this seems to happen most often on NVidia based MacBooks, but I've also been able to reproduce it on an Intel HD 5000. This happens all of Chrome, Safari and Firefox, so I'm pretty sure it's not related to the WebGL implementation itself. Could this be a driver bug in OSX?
My scene is composed of a bunch of UI. Most of the UI elements are drawn from one UI sprite sheet, and the text is drawn from a bitmap font sprite sheet. The bug usually exhibits itself in having the text drawn using the UI sprite sheet texture instead. I have verified with both a shader modification, and by using the WebGL Inspector that I have the correct textures bound to the correct samplers at the time of the draw call.
I did notice that this seems to be triggered by having texture A bound to sampler1, and texture B bound to sampler2 in one draw call, and the next draw call having them reversed, with texture A bound to sampler2 and texture B bound to sampler1.
This issue can currently be reproduced live at this URL: https://tinytappers.bigvikinggames.com/
It is most easily visible by opening one of two bottom menus, and while it's open, tapping on the enemy in the top section of the screen. Usually either the tapping itself, or the enemy death animation is enough to cause the text in the lower menu to quickly switch between textures. Again, this is only on a few specific OSX machines.
Can anyone else reproduce this? Does anyone have any idea what's happening? I'm pretty sure the data I'm passing to WebGL is correct. Can anyone find any problem with the data?