KhronosGroup / WebGL

The Official Khronos WebGL Repository
Other
2.63k stars 668 forks source link

Does spec need to be clear about \0 in strings #3496

Open greggman opened 1 year ago

greggman commented 1 year ago

Example:

const gl = document.querySelector('canvas').getContext('webgl');
const prg = createProgram(
    gl,
    `// \0\nvoid main() { gl_Position = vec4(0, 0, 0, 1); gl_PointSize = 128.0; }`,
    `void main() { gl_FragColor = vec4(0, 1, 1, 1); }`);
gl.useProgram(prg);
gl.drawArrays(gl.POINTS, 0, 1);

function createShader(gl, type, src) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, src);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    throw new Error(gl.getShaderInfoLog(shader));
  }
  return shader;
}

function createProgram(gl, vs, fs, tf) {
  const program = gl.createProgram();
  gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vs));
  gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fs));
  if (tf) {
     gl.transformFeedbackVaryings(program, tf, gl.INTERLEAVED_ATTRIBS); // gl.SEPARATE_ATTRIBS);
  }
  gl.linkProgram(program);
  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    throw new Error(gl.getProgramInfoLog(program));
  }
  return program;
}

Runs in Firefox, fails in Safari and Chrome

https://jsgist.org/?src=c20a4b92a9116ac894553ade4b57c4a8

kdashg commented 1 year ago

Neat!

ESSL 100 says:

There is no end-of-file character. The end of a source string is indicated to the compiler by a length, not a character

But! ESSL 300 says:

A byte with the value zero is always interpreted as the end of the string

kdashg commented 1 year ago

However (ES3?) ShaderSource says:

If length is NULL, all strings in the string argument are considered null- terminated.

greggman commented 1 year ago

So I ended up checking other API points that take strings.

The WebGL 1.0 spec specifically calls out getUniformLocation, getAttribLocation and bindAttribLocation as supposed to be returning INVALID_VALUE if the string has invalid characters, of which \0 is one.

https://registry.khronos.org/webgl/specs/latest/1.0/#CHARACTERS_OUTSIDE_VALID_SET

transformFeedbackVaryings should probably be added to the 2.0 spec in some way

For transformFeedbackVaryings, Chrome and Safari they truncate the strings at \0 and so incorrect match things they shouldn't. Firefox appears take the strings as is and then generetes a link error that the specifed varying was not found.

Following the precedent of the 1.0 spec it would seem that transformFeedbackVaryings should also generate INVALID_VALUE

All 3 browsers correctly generate INVALID_VALUE for getUnifiormLocation and getAttribLocation.

For bindAttirbLocation, Firefox and Safari generate INVALID_VALUE. Chrome cuts the string at \0 and so incorrectly binds locations.