{"ScriptPreparationCode":"// Shaders from here: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/By_example/Textures_from_code\r\n// A variety of shaders and shader complexity would make this benchmark much more interesting!\r\n\r\nvar vertexShaderSource = \u0060\r\n #version 100\r\n precision highp float;\r\n\r\n attribute vec2 position;\r\n\r\n void main() {\r\n gl_Position = vec4(position, 0.0, 1.0);\r\n gl_PointSize = 128.0;\r\n }\r\n \u0060;\r\n\r\nvar fragmentShaderSource = \u0060\r\n #version 100\r\n precision mediump float;\r\n void main() {\r\n vec2 fragmentPosition = 2.0*gl_PointCoord - 1.0;\r\n float distance = length(fragmentPosition);\r\n float distanceSqrd = distance * distance;\r\n gl_FragColor = vec4(\r\n 0.2/distanceSqrd,\r\n 0.1/distanceSqrd,\r\n 0.0, 1.0 );\r\n }\u0060;\r\n\r\nconst canvas = document.querySelector(\u0022canvas\u0022);\r\nvar gl = canvas.getContext(\u0022webgl\u0022);\r\n\r\n// From https://developer.mozilla.org/en-US/docs/Web/API/KHR_parallel_shader_compile\r\nvar ext = gl.getExtension(\u0027KHR_parallel_shader_compile\u0027);\r\n\r\n// Generator yielding a progress ratio [0.0, 1.0].\r\n// Without the extension, this will jank and only check one program per generation.\r\nfunction* linkingProgress(programs) {\r\n let todo = programs.slice();\r\n while (todo.length) {\r\n if (ext) {\r\n todo = todo.filter((x) =\u003E !gl.getProgramParameter(x, ext.COMPLETION_STATUS_KHR));\r\n } else {\r\n const x = todo.pop();\r\n gl.getProgramParameter(x, gl.LINK_STATUS);\r\n }\r\n if (!todo.length)\r\n return 1.0;\r\n yield 1.0 - (todo.length / programs.length);\r\n }\r\n}\r\n\r\nvar numProgramsToGenerate = 15;","TestCases":[{"Name":"Baseline","Code":"for (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n const program = gl.createProgram();\r\n\r\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\r\n gl.shaderSource(vertexShader, vertexShaderSource);\r\n gl.compileShader(vertexShader);\r\n\r\n const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n gl.shaderSource(fragmentShader, fragmentShaderSource);\r\n gl.compileShader(fragmentShader);\r\n\r\n gl.attachShader(program, vertexShader);\r\n gl.attachShader(program, fragmentShader);\r\n\r\n gl.deleteShader(vertexShader);\r\n gl.deleteShader(fragmentShader);\r\n\r\n gl.linkProgram(program);\r\n\r\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\r\n const linkErrLog = gl.getProgramInfoLog(program);\r\n console.error(linkErrorLog);\r\n }\r\n}","IsDeferred":false},{"Name":"Recommended (without using extension)","Code":"const programs = [];\r\n\r\nfor (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n const program = gl.createProgram();\r\n\r\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\r\n gl.shaderSource(vertexShader, vertexShaderSource);\r\n gl.compileShader(vertexShader);\r\n\r\n const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n gl.shaderSource(fragmentShader, fragmentShaderSource);\r\n gl.compileShader(fragmentShader);\r\n\r\n gl.attachShader(program, vertexShader);\r\n gl.attachShader(program, fragmentShader);\r\n\r\n gl.deleteShader(vertexShader);\r\n gl.deleteShader(fragmentShader);\r\n\r\n \tprograms.push(program);\r\n}\r\n\r\nfor (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n gl.linkProgram(programs[i]);\r\n}\r\n\r\nfor (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n if (!gl.getProgramParameter(programs[i], gl.LINK_STATUS)) {\r\n const linkErrLog = gl.getProgramInfoLog(programs[i]);\r\n console.error(linkErrorLog);\r\n }\r\n}","IsDeferred":false},{"Name":"Recommended (using extension)","Code":"const programs = [];\r\n\r\nfor (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n const program = gl.createProgram();\r\n\r\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\r\n gl.shaderSource(vertexShader, vertexShaderSource);\r\n gl.compileShader(vertexShader);\r\n\r\n const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n gl.shaderSource(fragmentShader, fragmentShaderSource);\r\n gl.compileShader(fragmentShader);\r\n\r\n gl.attachShader(program, vertexShader);\r\n gl.attachShader(program, fragmentShader);\r\n\r\n gl.deleteShader(vertexShader);\r\n gl.deleteShader(fragmentShader);\r\n\r\n \tprograms.push(program);\r\n}\r\n\r\nfor (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n gl.linkProgram(programs[i]);\r\n}\r\n\r\n// You wouldn\u0027t want to loop directly here, rather if progress is not completed,\r\n// continue on with this frame and do something else. Check it again on the next frame.\r\nvar progress = linkingProgress(programs);\r\nwhile (progress \u003C 1.0) {\r\n progress = linkingProgress(programs);\r\n}\r\n\r\nfor (var i = 0; i \u003C numProgramsToGenerate; i\u002B\u002B) {\r\n if (!gl.getProgramParameter(programs[i], gl.LINK_STATUS)) {\r\n const linkErrLog = gl.getProgramInfoLog(programs[i]);\r\n console.error(linkErrorLog);\r\n }\r\n}","IsDeferred":false}]}