summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance/misc/shader-precision-format.html
diff options
context:
space:
mode:
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.html340
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>
+
+