You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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循环的正常结果


异常的代码示例(带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>

异常结果截图

带for循环的异常结果


问题解答

是否是系统导致该问题?

不是Ubuntu系统本身直接引发的问题,核心原因是Intel 11代酷睿核显的Linux驱动存在GLSL处理bug。你的代码完全符合WebGL2规范——固定次数的for循环访问本地常量大小数组是合法的,但驱动在编译着色器时,可能没有正确展开循环或处理数组索引逻辑,导致颜色采样异常。

其他用户是否会遇到相同bug?

会的。Intel核显的Linux驱动在WebGL/OpenGL的GLSL细节兼容性上偶发这类问题,尤其是11代酷睿的Iris Xe核显,在部分驱动版本下,已有用户反馈过类似循环中数组访问、纹理采样失效的案例。

该如何上报此bug?

  1. 先收集关键信息:
    • 显卡驱动版本、内核版本:执行lshw -c video获取
    • 浏览器具体版本(比如Chrome 118、Firefox 119)
    • 你提供的这两个可复现问题的最小代码
    • 异常和正常的结果截图
  2. 选择上报渠道:
    • 优先上报给Intel开源驱动项目:可以在Intel Graphics Drivers官网的bug追踪系统提交,或者直接到GitHub的intel-gpu相关仓库反馈
    • 如果是在浏览器中出现的问题,也可以同步提交给对应浏览器的bug系统(比如Chrome的crbug.com,Firefox的bugzilla.mozilla.org),但核心修复还是需要驱动层面解决
    • 也可以在Ubuntu的launchpad bug追踪系统提交,最终会流转到Intel驱动团队

内容的提问来源于stack exchange,提问作者oceanGermanique

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:12:00