11代Intel酷睿Ubuntu设备WebGL2着色器for循环异常求助
问题:WebGL2片段着色器for循环在Ubuntu Intel设备上失效
我有两个功能完全一致的WebGL2片段着色器,唯一区别是第二个使用了for循环。但在搭载11th Gen Intel® Core™ i7-11370H×8处理器的Ubuntu笔记本上,带for循环的着色器无法正常工作。
正常工作的代码示例(无for循环)
JavaScript 代码
const gl = document.querySelector('canvas').getContext('webgl2'); const vs = `#version 300 es void main() { gl_PointSize = 300.0; gl_Position = vec4(0, 0, 0, 1); }`; const fs = `#version 300 es precision mediump float; uniform sampler2D tex[3]; out vec4 outColor; void main() { vec4 colors[3]; // you can't index textures with non-constant integer expressions // in WebGL2 (you can in WebGL1 lol) colors[0] = texture(tex[0], vec2(0)); colors[1] = texture(tex[1], vec2(0)); colors[2] = texture(tex[2], vec2(0)); vec4 color = vec4(0); float x = gl_PointCoord.x * 3.0; int i=0; float amount = step(float(i), x) * step(x, float(i + 1)); color = mix(color, colors[i], amount); i=1; amount = step(float(i), x) * step(x, float(i + 1)); color = mix(color, colors[i], amount); i=2; amount = step(float(i), x) * step(x, float(i + 1)); color = mix(color, colors[i], amount); outColor = vec4(color.rgb, 1); }`; let vertex = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertex, vs); gl.compileShader(vertex); let fragment = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragment, fs); gl.compileShader(fragment); const program = gl.createProgram(); gl.attachShader(program,vertex); gl.attachShader(program,fragment); gl.linkProgram(program); gl.useProgram(program); const tex1 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex1); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([255, 0, 0, 255])); const tex2 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex2); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 255, 0, 255])); const tex3 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex3); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 0, 255, 255])); const textureLoc = gl.getUniformLocation(program, "tex[0]"); gl.uniform1iv(textureLoc, [0, 1, 2]); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, tex1); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, tex2); gl.activeTexture(gl.TEXTURE2); gl.bindTexture(gl.TEXTURE_2D, tex3); gl.drawArrays(gl.POINTS, 0, 1);
HTML 代码
<canvas id="canvas"></canvas>
正常结果截图

异常的代码示例(带for循环)
JavaScript 代码
const gl = document.querySelector('canvas').getContext('webgl2'); const vs = `#version 300 es void main() { gl_PointSize = 300.0; gl_Position = vec4(0, 0, 0, 1); } `; const fs = `#version 300 es precision mediump float; uniform sampler2D tex[3]; out vec4 outColor; void main() { vec4 colors[3]; // you can't index textures with non-constant integer expressions // in WebGL2 (you can in WebGL1 lol) colors[0] = texture(tex[0], vec2(0)); colors[1] = texture(tex[1], vec2(0)); colors[2] = texture(tex[2], vec2(0)); // //THIS "FOR" LOOP DOES NOT WORK ON ONE OF MY COMPUTERS // vec4 color = vec4(0); for (int i = 0; i < 3; ++i) { float x = gl_PointCoord.x * 3.0; float amount = step(float(i), x) * step(x, float(i + 1)); color = mix(color, colors[i], amount); } outColor = vec4(color.rgb, 1); } `; let vertex = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertex, vs); gl.compileShader(vertex); let fragment = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragment, fs); gl.compileShader(fragment); const program = gl.createProgram(); gl.attachShader(program,vertex); gl.attachShader(program,fragment); gl.linkProgram(program); gl.useProgram(program); const tex1 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex1); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([255, 0, 0, 255])); const tex2 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex2); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 255, 0, 255])); const tex3 = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex3); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,new Uint8Array([0, 0, 255, 255])); const textureLoc = gl.getUniformLocation(program, "tex[0]"); gl.uniform1iv(textureLoc, [0, 1, 2]); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, tex1); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, tex2); gl.activeTexture(gl.TEXTURE2); gl.bindTexture(gl.TEXTURE_2D, tex3); gl.drawArrays(gl.POINTS, 0, 1);
HTML 代码
<canvas id="canvas"></canvas>
异常结果截图

问题解答
是否是系统导致该问题?
不是Ubuntu系统本身直接引发的问题,核心原因是Intel 11代酷睿核显的Linux驱动存在GLSL处理bug。你的代码完全符合WebGL2规范——固定次数的for循环访问本地常量大小数组是合法的,但驱动在编译着色器时,可能没有正确展开循环或处理数组索引逻辑,导致颜色采样异常。
其他用户是否会遇到相同bug?
会的。Intel核显的Linux驱动在WebGL/OpenGL的GLSL细节兼容性上偶发这类问题,尤其是11代酷睿的Iris Xe核显,在部分驱动版本下,已有用户反馈过类似循环中数组访问、纹理采样失效的案例。
该如何上报此bug?
- 先收集关键信息:
- 显卡驱动版本、内核版本:执行
lshw -c video获取 - 浏览器具体版本(比如Chrome 118、Firefox 119)
- 你提供的这两个可复现问题的最小代码
- 异常和正常的结果截图
- 显卡驱动版本、内核版本:执行
- 选择上报渠道:
- 优先上报给Intel开源驱动项目:可以在Intel Graphics Drivers官网的bug追踪系统提交,或者直接到GitHub的intel-gpu相关仓库反馈
- 如果是在浏览器中出现的问题,也可以同步提交给对应浏览器的bug系统(比如Chrome的crbug.com,Firefox的bugzilla.mozilla.org),但核心修复还是需要驱动层面解决
- 也可以在Ubuntu的launchpad bug追踪系统提交,最终会流转到Intel驱动团队
内容的提问来源于stack exchange,提问作者oceanGermanique
相关产品推荐
相关产品推荐

