KHR_parallel_shader_compile
WebGL working group (public_webgl 'at' khronos.org)
Jie Chen, (jie.a.chen 'at' intel.com)
Geoff Lang, (geofflang 'at' google.com)
Members of the WebGL working group
Last modified date: November 24, 2020
Revision: 6
WebGL extension #37
Written against the WebGL API 1.0 specification.
This extension exposes the KHR_parallel_shader_compile functionality to WebGL.
The following WebGL-specific behavioral changes apply:
MAX_SHADER_COMPILER_THREADS_KHR is not supported.maxShaderCompilerThreadsKHR is not supported.Consult the above extension for documentation, issues and new functions and enumerants.
When this extension is enabled:
COMPLETION_STATUS_KHR) can be queried without potentially incurring
stalls.
Notes:
[Exposed=(Window,Worker), LegacyNoInterfaceObject]
interface KHR_parallel_shader_compile {
const GLenum COMPLETION_STATUS_KHR = 0x91B1;
};
var canvas = document.createElement("canvas");
var gl = canvas.getContext("webgl");
var ext = gl.getExtension('KHR_parallel_shader_compile');
var vSource = "attribute vec2 position; void main() { gl_Position = vec4(position, 0, 1); }";
var fSource = "precision mediump float; void main() { gl_FragColor = vec4(1,0,0,1); }";
var vShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vShader, vSource);
gl.compileShader(vShader);
var fShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fShader, fSource);
gl.compileShader(fShader);
var program = gl.createProgram();
gl.attachShader(program, vShader);
gl.attachShader(program, fShader);
gl.linkProgram(program);
function checkToUseProgram() {
if (gl.getProgramParameter(program, gl.LINK_STATUS) == true) {
gl.useProgram(program);
} else {
// error check.
}
}
if (ext) {
function checkCompletion() {
if (gl.getProgramParameter(program, ext.COMPLETION_STATUS_KHR) == true) {
checkToUseProgram();
} else {
requestAnimationFrame(checkCompletion);
}
}
requestAnimationFrame(checkCompletion);
} else {
checkToUseProgram();
}
In general, best practice with or without the extension is:
// Assuming lists of `shaders` and `programs`:
for (const x of shaders)
gl.compileShader(x); // Never check compile status unless subsequent linking fails.
for (const x of programs)
gl.linkProgram(x);
With the extension, apps would be able to poll whether programs have
linked without janking, but these are likely to take the same total
wall time to link:
// Generator yielding a progress ratio [0.0, 1.0].
// Without the extension, this will jank and only check one program per generation.
function* linkingProgress(programs) {
const ext = gl.getExtension('KHR_parallel_shader_compile');
let todo = programs.slice();
while (todo.length) {
if (ext) {
todo = todo.filter(x => !gl.getProgramParameter(x, ext.COMPLETION_STATUS_KHR));
} else {
const x = todo.pop();
gl.getProgramParameter(x, gl.LINK_STATUS);
}
if (!todo.length)
return;
yield 1.0 - (todo.length / programs.length);
}
}
Revision 1, 2018/08/07
Revision 2, 2018/09/14
Revision 3, 2019/01/30
Revision 4, 2019/04/23
Revision 5, 2019/05/10
Revision 6, 2020/11/24