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