diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html b/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html new file mode 100644 index 0000000000..46be2a8145 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html @@ -0,0 +1,340 @@ +<!-- +Copyright (c) 2019 The Khronos Group Inc. +Use of this source code is governed by an MIT-style license that can be +found in the LICENSE.txt file. +--> +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL shader precision format test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"> </script> +</head> +<body> +<canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +var wtu = WebGLTestUtils; +description(document.title); +debug("Tests that WebGLShaderPrecisionFormat class and getShaderPrecisionFormat work."); +debug(""); +var gl = wtu.create3DContext("canvas"); + +function verifyShaderPrecisionFormat(shadertype, precisiontype) { + shouldBeTrue('gl.getShaderPrecisionFormat(' + shadertype + ', ' + + precisiontype + ') instanceof WebGLShaderPrecisionFormat'); +} + +debug(""); +debug("Test that getShaderPrecisionFormat returns a WebGLShaderPrecisionFormat object."); +debug(""); + +verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.LOW_FLOAT'); +verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.MEDIUM_FLOAT'); +verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.HIGH_FLOAT'); +verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.LOW_INT'); +verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.MEDIUM_INT'); +verifyShaderPrecisionFormat('gl.VERTEX_SHADER', 'gl.HIGH_INT'); +verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.LOW_FLOAT'); +verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.MEDIUM_FLOAT'); +verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.HIGH_FLOAT'); +verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.LOW_INT'); +verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.MEDIUM_INT'); +verifyShaderPrecisionFormat('gl.FRAGMENT_SHADER', 'gl.HIGH_INT'); + +debug(""); +debug("Test that getShaderPrecisionFormat throws an error with invalid parameters."); +debug(""); + +wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.getShaderPrecisionFormat(gl.HIGH_INT, gl.VERTEX_SHADER)'); + +debug(""); +debug("Test that WebGLShaderPrecisionFormat values are sensible."); +debug(""); + +// The minimum values are from OpenGL ES Shading Language spec, section 4.5. + +var shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 1'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 1'); +shouldBeTrue('shaderPrecisionFormat.precision >= 8'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 14'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 14'); +shouldBeTrue('shaderPrecisionFormat.precision >= 10'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 62'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 62'); +shouldBeTrue('shaderPrecisionFormat.precision >= 16'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_INT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 8'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 8'); +shouldBeTrue('shaderPrecisionFormat.precision == 0'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_INT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 10'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 10'); +shouldBeTrue('shaderPrecisionFormat.precision == 0'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_INT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 16'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 16'); +shouldBeTrue('shaderPrecisionFormat.precision == 0'); + +var shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_FLOAT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 1'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 1'); +shouldBeTrue('shaderPrecisionFormat.precision >= 8'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 14'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 14'); +shouldBeTrue('shaderPrecisionFormat.precision >= 10'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.LOW_INT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 8'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 8'); +shouldBeTrue('shaderPrecisionFormat.precision == 0'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_INT); +shouldBeTrue('shaderPrecisionFormat.rangeMin >= 10'); +shouldBeTrue('shaderPrecisionFormat.rangeMax >= 10'); +shouldBeTrue('shaderPrecisionFormat.precision == 0'); + +debug(""); +debug("Test optional highp support in fragment shaders."); +debug(""); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT); +shouldBeTrue('(shaderPrecisionFormat.rangeMin == 0 && shaderPrecisionFormat.rangeMax == 0 && shaderPrecisionFormat.precision == 0) || (shaderPrecisionFormat.rangeMin >= 62 && shaderPrecisionFormat.rangeMax >= 62 && shaderPrecisionFormat.precision >= 16)'); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT); +shouldBeTrue('(shaderPrecisionFormat.rangeMin == 0 && shaderPrecisionFormat.rangeMax == 0 && shaderPrecisionFormat.precision == 0) || (shaderPrecisionFormat.rangeMin >= 16 && shaderPrecisionFormat.rangeMax >= 16 && shaderPrecisionFormat.precision == 0)'); + +debug(""); +debug("Test that getShaderPrecisionFormat returns the same thing every call."); +debug(""); + +shaderPrecisionFormat = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT); +var shaderPrecisionFormat2 = gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.LOW_FLOAT); +shouldBeTrue('shaderPrecisionFormat.rangeMin == shaderPrecisionFormat2.rangeMin'); +shouldBeTrue('shaderPrecisionFormat.rangeMax == shaderPrecisionFormat2.rangeMax'); +shouldBeTrue('shaderPrecisionFormat.precision == shaderPrecisionFormat2.precision'); + +debug(""); +debug("Test that specified precision matches rendering results"); +debug(""); + +function testRenderPrecisionSetup(gl, shaderPair) { + const program = wtu.setupProgram(gl, shaderPair); + + // Create a buffer and setup an attribute. + // We wouldn't need this except for a bug in Safari and arguably + // this should be removed from the test but we can't test the test itself + // without until the bug is fixed. + // see https://bugs.webkit.org/show_bug.cgi?id=197592 + { + gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); + gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW); + const loc = gl.getAttribLocation(program, 'position'); + gl.enableVertexAttribArray(loc); + gl.vertexAttribPointer(loc, 1, gl.UNSIGNED_BYTE, false, 0, 0); + } + + gl.useProgram(program); + + return program; +} + +function testRenderPrecision(gl, shaderType, type, precision, expected, msg) { + gl.clear(gl.COLOR_BUFFER_BIT); + gl.drawArrays(gl.POINTS, 0, 1); + + const pixel = new Uint8Array(4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); + + wtu.checkCanvasRect(gl, 0, 0, 1, 1, expected, msg, 5); +} + +function testRenderPrecisionFloat(gl, precisionEnum, precision) { + function test(gl, shaderPair, shaderType) { + const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum); + const value = 2 ** format.precision - 1; + + const length = v => Math.sqrt(v.reduce((sum, v) => sum + v * v, 0)); + const normalize = (v) => { + const l = length(v); + return v.map(v => v / l); + }; + + const input = [Math.sqrt(value), Math.sqrt(value), Math.sqrt(value)]; + const expected = [...normalize(input).map(v => (v * 0.5 + 0.5) * 255 | 0), 255]; + + const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} float precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`; + const program = testRenderPrecisionSetup(gl, shaderPair); + const vLocation = gl.getUniformLocation(program, 'v'); + gl.uniform3fv(vLocation, input); + testRenderPrecision(gl, shaderType, 'float', precision, expected, msg); + } + + { + const vs = ` + attribute vec4 position; + uniform ${precision} vec3 v; + varying ${precision} vec4 v_result; + void main() { + gl_Position = position; + gl_PointSize = 1.0; + v_result = vec4(normalize(v) * 0.5 + 0.5, 1); + } + `; + + const fs = ` + precision ${precision} float; + varying ${precision} vec4 v_result; + void main() { + gl_FragColor = v_result; + } + `; + + test(gl, [vs, fs], gl.VERTEX_SHADER); + } + + { + const vs = ` + attribute vec4 position; + void main() { + gl_Position = position; + gl_PointSize = 1.0; + } + `; + + const fs = ` + precision ${precision} float; + uniform ${precision} vec3 v; + void main() { + gl_FragColor = vec4(normalize(v) * 0.5 + 0.5, 1); + } + `; + + test(gl, [vs, fs], gl.FRAGMENT_SHADER); + } +} + +function testRenderPrecisionInt(gl, precisionEnum, precision) { + function test(gl, shaderPair, shaderType) { + const format = gl.getShaderPrecisionFormat(shaderType, precisionEnum); + const value = 1 << (format.rangeMax - 1); + + const input = [value, value, value, value]; + const expected = [255, 255, 255, 255]; + + const msg = `${wtu.glEnumToString(gl, shaderType)}: ${precision} int precision: ${format.precision}, rangeMin: ${format.rangeMin}, rangeMax: ${format.rangeMax}`; + const program = testRenderPrecisionSetup(gl, shaderPair); + gl.uniform1i(gl.getUniformLocation(program, 'v'), value); + gl.uniform1f(gl.getUniformLocation(program, 'f'), value); + testRenderPrecision(gl, shaderType, 'int', precision, expected, msg); + } + + { + const vs = ` + attribute vec4 position; + uniform ${precision} int v; + uniform highp float f; + varying vec4 v_result; + + void main() { + gl_Position = position; + gl_PointSize = 1.0; + float diff = abs(float(v) - f); + bool pass = diff < 1.0; + v_result = vec4(pass); + } + `; + + const fs = ` + precision mediump float; + varying vec4 v_result; + void main() { + gl_FragColor = v_result; + } + `; + test(gl, [vs, fs], gl.VERTEX_SHADER); + } + + { + const vs = ` + attribute vec4 position; + void main() { + gl_Position = position; + gl_PointSize = 1.0; + } + `; + + const fs = ` + precision ${precision} float; + uniform ${precision} int v; + uniform mediump float f; + + void main() { + mediump float diff = abs(float(v) - f); + bool pass = diff < 1.0; + gl_FragColor = vec4(pass); + } + `; + + test(gl, [vs, fs], gl.FRAGMENT_SHADER); + } +} + +// because the canvas can be 16 bit IIRC +const fb = gl.createFramebuffer(gl.FRAMEBUFFER); +gl.bindFramebuffer(gl.FRAMEBUFFER, fb); + +const tex = gl.createTexture(); +gl.bindTexture(gl.TEXTURE_2D, tex); +gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + +gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, + tex, + 0); + +gl.viewport(0, 0, 1, 1); + +{ + testRenderPrecisionFloat(gl, gl.LOW_FLOAT, 'lowp'); + testRenderPrecisionFloat(gl, gl.MEDIUM_FLOAT, 'mediump'); + + const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT); + if (format.precision !== 0) { + testRenderPrecisionFloat(gl, gl.HIGH_FLOAT, 'highp'); + } +} + +{ + testRenderPrecisionInt(gl, gl.LOW_INT, 'lowp'); + testRenderPrecisionInt(gl, gl.MEDIUM_INT, 'mediump'); + + const format = gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_INT); + if (format.rangeMax !== 0) { + testRenderPrecisionInt(gl, gl.HIGH_INT, 'highp'); + } +} + +finishTest(); +</script> + +</body> +</html> + + |