Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
Shader compilation strategies
(version: 0)
Validating guidance from https://developer.mozilla.org/en-US/docs/Web/API/KHR_parallel_shader_compile
Comparing performance of:
Baseline vs Recommended (without using extension) vs Recommended (using extension)
Created:
3 years ago
by:
Guest
Jump to the latest result
HTML Preparation code:
<canvas id='test' width='100' height='100'></canvas>
Script Preparation code:
// Shaders from here: https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/By_example/Textures_from_code // A variety of shaders and shader complexity would make this benchmark much more interesting! var vertexShaderSource = ` #version 100 precision highp float; attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); gl_PointSize = 128.0; } `; var fragmentShaderSource = ` #version 100 precision mediump float; void main() { vec2 fragmentPosition = 2.0*gl_PointCoord - 1.0; float distance = length(fragmentPosition); float distanceSqrd = distance * distance; gl_FragColor = vec4( 0.2/distanceSqrd, 0.1/distanceSqrd, 0.0, 1.0 ); }`; const canvas = document.querySelector("canvas"); var gl = canvas.getContext("webgl"); // From https://developer.mozilla.org/en-US/docs/Web/API/KHR_parallel_shader_compile var ext = gl.getExtension('KHR_parallel_shader_compile'); // 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) { 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 1.0; yield 1.0 - (todo.length / programs.length); } } var numProgramsToGenerate = 15;
Tests:
Baseline
for (var i = 0; i < numProgramsToGenerate; i++) { const program = gl.createProgram(); const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { const linkErrLog = gl.getProgramInfoLog(program); console.error(linkErrorLog); } }
Recommended (without using extension)
const programs = []; for (var i = 0; i < numProgramsToGenerate; i++) { const program = gl.createProgram(); const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); programs.push(program); } for (var i = 0; i < numProgramsToGenerate; i++) { gl.linkProgram(programs[i]); } for (var i = 0; i < numProgramsToGenerate; i++) { if (!gl.getProgramParameter(programs[i], gl.LINK_STATUS)) { const linkErrLog = gl.getProgramInfoLog(programs[i]); console.error(linkErrorLog); } }
Recommended (using extension)
const programs = []; for (var i = 0; i < numProgramsToGenerate; i++) { const program = gl.createProgram(); const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); programs.push(program); } for (var i = 0; i < numProgramsToGenerate; i++) { gl.linkProgram(programs[i]); } // You wouldn't want to loop directly here, rather if progress is not completed, // continue on with this frame and do something else. Check it again on the next frame. var progress = linkingProgress(programs); while (progress < 1.0) { progress = linkingProgress(programs); } for (var i = 0; i < numProgramsToGenerate; i++) { if (!gl.getProgramParameter(programs[i], gl.LINK_STATUS)) { const linkErrLog = gl.getProgramInfoLog(programs[i]); console.error(linkErrorLog); } }
Rendered benchmark preparation results:
Suite status:
<idle, ready to run>
Run tests (3)
Previous results
Fork
Test case name
Result
Baseline
Recommended (without using extension)
Recommended (using extension)
Fastest:
N/A
Slowest:
N/A
Latest run results:
No previous run results
This benchmark does not have any results yet. Be the first one
to run it!
Autogenerated LLM Summary
(model
llama3.2:3b
, generated one year ago):
Let's break down the benchmark results and analyze the three test cases: **Test Cases:** 1. **Baseline**: This test case links each program individually using `gl.linkProgram(programs[i])` without utilizing the shader link group extension. 2. **Recommended (without using extension)**: Similar to the baseline, but the same logic is used, just with a different name for clarity. 3. **Recommended (using extension)**: This test case uses the shader link group extension (`linkingProgress(programs)`) to manage program linking. **Benchmark Results:** The results show the following: * The Baseline test has the lowest executions per second (40.98360824584961). * The Recommended (without using extension) test has a higher executions per second (66.4168472290039), which is closer to the Recommended (using extension) test. * The Recommended (using extension) test has the highest executions per second (72.04963684082031). **Analysis:** The results suggest that using the shader link group extension (`linkingProgress(programs)`) provides a significant performance improvement over linking programs individually (Baseline and Recommended without extension). This is likely because the extension allows for more efficient management of program dependencies and reduces the overhead associated with individual linking operations. In contrast, the Baseline test has the lowest executions per second, indicating that linking each program individually incurs additional overhead compared to using the shader link group extension. The Recommended (without using extension) test falls somewhere in between, suggesting that this approach still offers some performance benefits but not as much as utilizing the shader link group extension. **Key Takeaways:** * Using the shader link group extension can provide significant performance improvements over linking programs individually. * Linking each program individually incurs additional overhead compared to using the shader link group extension. * The Recommended (without using extension) test falls in between the Baseline and Recommended (using extension) tests, suggesting that this approach still offers some benefits but not as much as utilizing the shader link group extension.
Related benchmarks:
WebGL math library comparison
Array Indice vs Slice
shaders strings comparisons
shaders strings comparisons with Set has()
Comments
Confirm delete:
Do you really want to delete benchmark?