summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/test/webgl-conf/checkout/conformance2/uniforms
parentInitial commit. (diff)
downloadfirefox-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/conformance2/uniforms')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt9
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html121
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html120
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html404
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html335
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html138
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html93
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html122
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html115
9 files changed, 1457 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt
new file mode 100644
index 0000000000..05e01f554c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/00_test_list.txt
@@ -0,0 +1,9 @@
+--min-version 2.0.1 draw-with-uniform-blocks.html
+--min-version 2.0.1 gl-uniform-arrays-sub-source.html
+--min-version 2.0.1 query-uniform-blocks-after-shader-detach.html
+--min-version 2.0.1 uniform-blocks-with-arrays.html
+--min-version 2.0.1 simple-buffer-change.html
+--min-version 2.0.1 dependent-buffer-change.html
+--min-version 2.0.1 incompatible-texture-type-for-sampler.html
+--min-version 2.0.1 large-uniform-buffers.html
+
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html
new file mode 100644
index 0000000000..888305e6d6
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/dependent-buffer-change.html
@@ -0,0 +1,121 @@
+<!--
+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 draw with uniform blocks conformance tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+// Ported from: https://github.com/google/angle/blob/master/src/tests/gl_tests/UniformBufferTest.cpp#L1507
+description("Regression test for https://bugs.chromium.org/p/chromium/issues/detail?id=792966");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ var uboBuf1 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 1, 0, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ // Resize the buffer - triggers a re-allocation in the D3D11 back-end.
+ debug("draw upper triangle - should be green");
+ var bigData = new Float32Array(128 * 4);
+ bigData.set([ 0, 1, 0, 1 ]);
+ gl.bufferData(gl.UNIFORM_BUFFER, bigData, gl.STATIC_DRAW);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html
new file mode 100644
index 0000000000..3fa7949eac
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/draw-with-uniform-blocks.html
@@ -0,0 +1,120 @@
+<!--
+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 draw with uniform blocks conformance tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+description("Regression test for crbug.com/793307 and https://bugzilla.mozilla.org/show_bug.cgi?id=1424258");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ var uboBuf1 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 1, 0, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ debug("draw upper triangle - should be green");
+ var uboBuf2 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 1, uboBuf2);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 0, 1, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 1);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html
new file mode 100644
index 0000000000..7780a7ba01
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/gl-uniform-arrays-sub-source.html
@@ -0,0 +1,404 @@
+<!--
+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 uniform array Conformance Tests</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>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="example" width="2" height="2"> </canvas>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_position;
+void main() {
+ gl_Position = a_position;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+uniform $(type) color[3];
+out vec4 myFragColor;
+void main() {
+ myFragColor = vec4(color[0]$(elem), color[1]$(elem), color[2]$(elem), 1);
+}
+</script>
+<script>
+"use strict";
+description();
+debug("");
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+var vSrc = wtu.getScript("vshader");
+var fTemplate = wtu.getScript("fshader");
+
+// |color| is defined in fragment shader as an array of 3 elements.
+var uniformArraySize = 3;
+var initialUniformValue = 99;
+
+var typeInfos = [
+ { type: 'float',
+ setter: 'uniform1fv',
+ elem: '',
+ numElementsPerType: 1,
+ srcValues: [16, 15],
+ srcValuesWithOffset: [0, 0, 16, 15],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
+ srcOffset: 2,
+ },
+ { type: 'int',
+ setter: 'uniform1iv',
+ elem: '',
+ numElementsPerType: 1,
+ srcValues: [16, 15],
+ srcValuesWithOffset: [0, 0, 16, 15],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
+ srcOffset: 2,
+ },
+ { type: 'uint',
+ setter: 'uniform1uiv',
+ elem: '',
+ numElementsPerType: 1,
+ srcValues: [16, 15],
+ srcValuesWithOffset: [0, 0, 16, 15],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 0],
+ srcOffset: 2,
+ },
+ { type: 'vec2',
+ setter: 'uniform2fv',
+ elem: '[1]',
+ numElementsPerType: 2,
+ srcValues: [16, 15, 14, 13],
+ srcValuesWithOffset: [0, 16, 15, 14, 13],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
+ srcOffset: 1,
+ },
+ { type: 'ivec2',
+ setter: 'uniform2iv',
+ elem: '[1]',
+ numElementsPerType: 2,
+ srcValues: [16, 15, 14, 13],
+ srcValuesWithOffset: [0, 16, 15, 14, 13],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
+ srcOffset: 1,
+ },
+ { type: 'uvec2',
+ setter: 'uniform2uiv',
+ elem: '[1]',
+ numElementsPerType: 2,
+ srcValues: [16, 15, 14, 13],
+ srcValuesWithOffset: [0, 16, 15, 14, 13],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 0],
+ srcOffset: 1,
+ },
+ { type: 'vec3',
+ setter: 'uniform3fv',
+ elem: '[2]',
+ numElementsPerType: 3,
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
+ srcOffset: 1,
+ },
+ { type: 'ivec3',
+ setter: 'uniform3iv',
+ elem: '[2]',
+ numElementsPerType: 3,
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
+ srcOffset: 1,
+ },
+ { type: 'uvec3',
+ setter: 'uniform3uiv',
+ elem: '[2]',
+ numElementsPerType: 3,
+ srcValues: [16, 15, 14, 13, 12, 11],
+ srcValuesWithOffset: [0, 16, 15, 14, 13, 12, 11],
+ srcValuesWithOffsetAndLength: [0, 16, 15, 14, 13, 12, 11, 0, 0],
+ srcOffset: 1,
+ },
+ { type: 'vec4',
+ setter: 'uniform4fv',
+ elem: '[3]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+ { type: 'ivec4',
+ setter: 'uniform4iv',
+ elem: '[3]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+ { type: 'uvec4',
+ setter: 'uniform4uiv',
+ elem: '[3]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+
+ // Matrix
+ { type: 'mat2',
+ setter: 'uniformMatrix2fv',
+ elem: '[1][1]',
+ numElementsPerType: 4,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 0],
+ srcOffset: 3,
+ },
+ { type: 'mat3',
+ setter: 'uniformMatrix3fv',
+ elem: '[2][2]',
+ numElementsPerType: 9,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0],
+ srcOffset: 3,
+ },
+ { type: 'mat4',
+ setter: 'uniformMatrix4fv',
+ elem: '[3][3]',
+ numElementsPerType: 16,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+ { type: 'mat2x3',
+ setter: 'uniformMatrix2x3fv',
+ elem: '[1][2]',
+ numElementsPerType: 6,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0],
+ srcOffset: 4,
+ },
+ { type: 'mat3x2',
+ setter: 'uniformMatrix3x2fv',
+ elem: '[2][1]',
+ numElementsPerType: 6,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0],
+ srcOffset: 3,
+ },
+ { type: 'mat2x4',
+ setter: 'uniformMatrix2x4fv',
+ elem: '[1][3]',
+ numElementsPerType: 8,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+ { type: 'mat4x2',
+ setter: 'uniformMatrix4x2fv',
+ elem: '[3][1]',
+ numElementsPerType: 8,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffset: [0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
+ srcValuesWithOffsetAndLength: [0, 0, 0, 0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0],
+ srcOffset: 5,
+ },
+ { type: 'mat3x4',
+ setter: 'uniformMatrix3x4fv',
+ elem: '[2][3]',
+ numElementsPerType: 12,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+ { type: 'mat4x3',
+ setter: 'uniformMatrix4x3fv',
+ elem: '[3][2]',
+ numElementsPerType: 12,
+ srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffset: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
+ srcValuesWithOffsetAndLength: [0, 0, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 0, 0, 0, 0],
+ srcOffset: 2,
+ },
+
+];
+
+function checkUniformValues(program, typeInfo, useInitialValues) {
+ var numSrcValues = typeInfo.srcValues.length / typeInfo.numElementsPerType;
+ for (var ii = 0; ii < uniformArraySize; ++ii) {
+ var expectedValues;
+ if (useInitialValues || ii >= numSrcValues) {
+ expectedValues = new Array(typeInfo.numElementsPerType);
+ for (var jj = 0; jj < typeInfo.numElementsPerType; ++jj) {
+ expectedValues[jj] = initialUniformValue;
+ }
+ } else {
+ expectedValues = typeInfo.srcValues.slice(
+ typeInfo.numElementsPerType * ii, typeInfo.numElementsPerType * (ii + 1));
+ }
+ var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can get location of element " + ii + " of array from gl.getUniformLocation");
+ var value = gl.getUniform(program, elemLoc);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can get value of element " + ii + " of array from gl.getUniform");
+ var equal = true;
+ if (value === null) {
+ equal = false;
+ } else if (typeInfo.numElementsPerType == 1) {
+ if (value != expectedValues[0]) {
+ equal = false;
+ }
+ } else {
+ for (var jj = 0; jj < typeInfo.numElementsPerType; ++jj) {
+ if (value[jj] != expectedValues[jj]) {
+ equal = false;
+ break;
+ }
+ }
+ }
+ assertMsg(equal,
+ "value put in (" + expectedValues + ") matches value pulled out (" +
+ (value === null ? "null" : value) + ")");
+ }
+}
+
+for (var tt = 0; tt < typeInfos.length; ++tt) {
+ var typeInfo = typeInfos[tt];
+ debug("");
+ debug("check " + typeInfo.type);
+ var srcLength = typeInfo.srcValues.length;
+ var fSrc = wtu.replaceParams(fTemplate, typeInfo);
+ var program = wtu.loadProgram(gl, vSrc, fSrc);
+ if (!program) {
+ testFailed("Failed to create the program");
+ continue;
+ }
+ gl.useProgram(program);
+
+ var loc = gl.getUniformLocation(program, "color[0]");
+ if (!loc) {
+ testFailed("Failed to obtain the location of the uniform");
+ continue;
+ }
+
+ function setter(loc, array, srcOffset, srcLength) {
+ var isMatrix = (typeInfo.setter.indexOf("Matrix") == 7);
+ if (typeof(srcOffset) != 'undefined') {
+ if (isMatrix) {
+ gl[typeInfo.setter](loc, gl.FALSE, array, srcOffset, srcLength);
+ } else {
+ gl[typeInfo.setter](loc, array, srcOffset, srcLength);
+ }
+ } else if (typeof(srcLength) != 'undefined') {
+ if (isMatrix) {
+ gl[typeInfo.setter](loc, gl.FALSE, array, srcOffset);
+ } else {
+ gl[typeInfo.setter](loc, array, srcOffset);
+ }
+ } else {
+ if (isMatrix) {
+ gl[typeInfo.setter](loc, gl.FALSE, array);
+ } else {
+ gl[typeInfo.setter](loc, array);
+ }
+ }
+ }
+
+ // Initialize uniforms to value 99 and verify it.
+ var initValues = new Array(typeInfo.numElementsPerType * uniformArraySize);
+ for (var ii = 0; ii < typeInfo.numElementsPerType * uniformArraySize; ++ii) {
+ initValues[ii] = initialUniformValue;
+ }
+ setter(loc, initValues);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "no error from initializing uniforms to 99");
+ checkUniformValues(program, typeInfo, true);
+
+ setter(loc, typeInfo.srcValues);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " without srcOffset / srcLength");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValues, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = 0");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValues, 0, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = 0 / srcLength = 0");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValuesWithOffset, typeInfo.srcOffset);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = " + typeInfo.srcOffset);
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValuesWithOffset, typeInfo.srcOffset, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = " + typeInfo.srcOffset + " / srcLength = 0");
+ checkUniformValues(program, typeInfo);
+
+ setter(loc, typeInfo.srcValuesWithOffsetAndLength, typeInfo.srcOffset, srcLength);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR,
+ "can set an array of uniforms with gl." + typeInfo.setter +
+ " with srcOffset = " + typeInfo.srcOffset + " / srcLength = " + srcLength);
+ checkUniformValues(program, typeInfo);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors");
+
+ // Negative tests
+ setter(loc, typeInfo.srcValues, typeInfo.srcValues.length + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with srcOffset out-of-bounds");
+
+ setter(loc, typeInfo.srcValues, 0, typeInfo.srcValues.length + 1);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with srcLength out-of-bounds");
+
+ setter(loc, typeInfo.srcValues, typeInfo.srcOffset, srcLength);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with srcOffset + srcLength out-of-bounds");
+
+ setter(loc, typeInfo.srcValues, typeInfo.srcValues.length);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with 0 data");
+
+ if (typeInfo.numElementsPerType > 1) {
+ setter(loc, typeInfo.srcValuesWithOffsetAndLength, typeInfo.srcOffset);
+ wtu.glErrorShouldBe(gl, gl.INVALID_VALUE,
+ "gl." + typeInfo.setter + " with array length minus srcOffset not multiple of " + typeInfo.type);
+ }
+}
+
+debug("");
+var successfullyParsed = true;
+
+</script>
+<script src="../../js/js-test-post.js"></script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html
new file mode 100644
index 0000000000..90cb54317a
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/incompatible-texture-type-for-sampler.html
@@ -0,0 +1,335 @@
+<!--
+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 uniform samplers with incompatible texture formats tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+ gl_PointSize = 1.0;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+description("Test that using an incompatible texture type generates INVALID_OPERATION at draw time");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function makeFragmentShader(samplerType, uvType) {
+ return `#version 300 es
+ precision mediump float;
+ uniform mediump ${samplerType} u_tex;
+ out vec4 color;
+ void main() {
+ color = vec4(texture(u_tex, ${uvType}));
+ }
+ `;
+}
+
+// Sampler types.
+const FLOAT = 1;
+const SIGNED = 2;
+const UNSIGNED = 3;
+const SHADOW = 4;
+
+const textureInternalFormatInfo = {};
+{
+ const t = textureInternalFormatInfo;
+ // unsized formats
+ t[gl.ALPHA] = { textureFormat: gl.ALPHA, samplerType: FLOAT, depth: false, bytesPerElement: [1, 2, 2, 4], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.LUMINANCE] = { textureFormat: gl.LUMINANCE, samplerType: FLOAT, depth: false, bytesPerElement: [1, 2, 2, 4], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.LUMINANCE_ALPHA] = { textureFormat: gl.LUMINANCE_ALPHA, samplerType: FLOAT, depth: false, bytesPerElement: [2, 4, 4, 8], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
+ t[gl.RGB] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3, 6, 6, 12, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_5_6_5], };
+ t[gl.RGBA] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4, 8, 8, 16, 2, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_4_4_4_4, gl.UNSIGNED_SHORT_5_5_5_1], };
+
+ // sized formats
+ t[gl.R8] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [1], type: [gl.UNSIGNED_BYTE], };
+ t[gl.R8_SNORM] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [1], type: [gl.BYTE], };
+ t[gl.R16F] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [4, 2], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.R32F] = { textureFormat: gl.RED, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.FLOAT], };
+ t[gl.R8UI] = { textureFormat: gl.RED_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [1], type: [gl.UNSIGNED_BYTE], };
+ t[gl.R8I] = { textureFormat: gl.RED_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [1], type: [gl.BYTE], };
+ t[gl.R16UI] = { textureFormat: gl.RED_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [2], type: [gl.UNSIGNED_SHORT], };
+ t[gl.R16I] = { textureFormat: gl.RED_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [2], type: [gl.SHORT], };
+ t[gl.R32UI] = { textureFormat: gl.RED_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT], };
+ t[gl.R32I] = { textureFormat: gl.RED_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [4], type: [gl.INT], };
+ t[gl.RG8] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [2], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RG8_SNORM] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [2], type: [gl.BYTE], };
+ t[gl.RG16F] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [8, 4], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RG32F] = { textureFormat: gl.RG, samplerType: FLOAT, depth: false, bytesPerElement: [8], type: [gl.FLOAT], };
+ t[gl.RG8UI] = { textureFormat: gl.RG_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [2], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RG8I] = { textureFormat: gl.RG_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [2], type: [gl.BYTE], };
+ t[gl.RG16UI] = { textureFormat: gl.RG_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RG16I] = { textureFormat: gl.RG_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [4], type: [gl.SHORT], };
+ t[gl.RG32UI] = { textureFormat: gl.RG_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [8], type: [gl.UNSIGNED_INT], };
+ t[gl.RG32I] = { textureFormat: gl.RG_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [8], type: [gl.INT], };
+ t[gl.RGB8] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.SRGB8] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGB565] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3, 2], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_6_5], };
+ t[gl.RGB8_SNORM] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [3], type: [gl.BYTE], };
+ t[gl.R11F_G11F_B10F] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_10F_11F_11F_REV], };
+ t[gl.RGB9_E5] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_5_9_9_9_REV], };
+ t[gl.RGB16F] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12, 6], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RGB32F] = { textureFormat: gl.RGB, samplerType: FLOAT, depth: false, bytesPerElement: [12], type: [gl.FLOAT], };
+ t[gl.RGB8UI] = { textureFormat: gl.RGB_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [3], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGB8I] = { textureFormat: gl.RGB_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [3], type: [gl.BYTE], };
+ t[gl.RGB16UI] = { textureFormat: gl.RGB_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [6], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RGB16I] = { textureFormat: gl.RGB_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [6], type: [gl.SHORT], };
+ t[gl.RGB32UI] = { textureFormat: gl.RGB_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [12], type: [gl.UNSIGNED_INT], };
+ t[gl.RGB32I] = { textureFormat: gl.RGB_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [12], type: [gl.INT], };
+ t[gl.RGBA8] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.SRGB8_ALPHA8] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGBA8_SNORM] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.BYTE], };
+ t[gl.RGB5_A1] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4, 2, 4], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_5_5_1, gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA4] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4, 2], type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_4_4_4_4], };
+ t[gl.RGB10_A2] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA16F] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [16, 8], type: [gl.FLOAT, gl.HALF_FLOAT], };
+ t[gl.RGBA32F] = { textureFormat: gl.RGBA, samplerType: FLOAT, depth: false, bytesPerElement: [16], type: [gl.FLOAT], };
+ t[gl.RGBA8UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_BYTE], };
+ t[gl.RGBA8I] = { textureFormat: gl.RGBA_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [4], type: [gl.BYTE], };
+ t[gl.RGB10_A2UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [4], type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
+ t[gl.RGBA16UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [8], type: [gl.UNSIGNED_SHORT], };
+ t[gl.RGBA16I] = { textureFormat: gl.RGBA_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [8], type: [gl.SHORT], };
+ t[gl.RGBA32I] = { textureFormat: gl.RGBA_INTEGER, samplerType: SIGNED, depth: false, bytesPerElement: [16], type: [gl.INT], };
+ t[gl.RGBA32UI] = { textureFormat: gl.RGBA_INTEGER, samplerType: UNSIGNED, depth: false, bytesPerElement: [16], type: [gl.UNSIGNED_INT], };
+
+ // Sized Internal
+ // Note that samplerType is FLOAT for depth formats, not SHADOW. Shadow
+ // samplers are handled as a special case in the test code because they have
+ // special rules about TEXTURE_COMPARE_MODE.
+ t[gl.DEPTH_COMPONENT16] = { textureFormat: gl.DEPTH_COMPONENT, samplerType: FLOAT, depth: true, bytesPerElement: [2, 4], type: [gl.UNSIGNED_SHORT, gl.UNSIGNED_INT], };
+ t[gl.DEPTH_COMPONENT24] = { textureFormat: gl.DEPTH_COMPONENT, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.UNSIGNED_INT], };
+ t[gl.DEPTH_COMPONENT32F] = { textureFormat: gl.DEPTH_COMPONENT, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.FLOAT], };
+ t[gl.DEPTH24_STENCIL8] = { textureFormat: gl.DEPTH_STENCIL, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.UNSIGNED_INT_24_8], };
+ t[gl.DEPTH32F_STENCIL8] = { textureFormat: gl.DEPTH_STENCIL, samplerType: FLOAT, depth: true, bytesPerElement: [4], type: [gl.FLOAT_32_UNSIGNED_INT_24_8_REV], };
+
+ // TODO: Compressed formats.
+
+ Object.keys(t).forEach(function(internalFormat) {
+ const info = t[internalFormat];
+ info.bytesPerElementMap = {};
+ info.bytesPerElement.forEach(function(bytesPerElement, ndx) {
+ const type = info.type[ndx];
+ info.bytesPerElementMap[type] = bytesPerElement;
+ });
+ });
+}
+
+const floatSamplerTypes = [
+ { type: 'sampler2D', uvType: 'vec2(0)', target: gl.TEXTURE_2D, },
+ { type: 'sampler3D', uvType: 'vec3(0)', target: gl.TEXTURE_3D, },
+ { type: 'samplerCube', uvType: 'vec3(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'sampler2DArray', uvType: 'vec3(0)', target: gl.TEXTURE_2D_ARRAY, },
+];
+
+const signedIntSamplerTypes = [
+ { type: 'isampler2D', uvType: 'vec2(0)', target: gl.TEXTURE_2D, },
+ { type: 'isampler3D', uvType: 'vec3(0)', target: gl.TEXTURE_3D, },
+ { type: 'isamplerCube', uvType: 'vec3(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'isampler2DArray', uvType: 'vec3(0)', target: gl.TEXTURE_2D_ARRAY, },
+];
+
+const unsignedIntSamplerTypes = [
+ { type: 'usampler2D', uvType: 'vec2(0)', target: gl.TEXTURE_2D, },
+ { type: 'usampler3D', uvType: 'vec3(0)', target: gl.TEXTURE_3D, },
+ { type: 'usamplerCube', uvType: 'vec3(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'usampler2DArray', uvType: 'vec3(0)', target: gl.TEXTURE_2D_ARRAY, },
+];
+
+const shadowSamplerTypes = [
+ { type: 'sampler2DShadow', uvType: 'vec3(0)', target: gl.TEXTURE_2D, },
+ { type: 'samplerCubeShadow', uvType: 'vec4(0)', target: gl.TEXTURE_CUBE_MAP, },
+ { type: 'sampler2DArrayShadow', uvType: 'vec4(0)', target: gl.TEXTURE_2D_ARRAY, },
+]
+
+/**
+ * Gets the number of bytes per element for a given internalFormat / type
+ * @param {number} internalFormat The internalFormat parameter from texImage2D etc..
+ * @param {number} type The type parameter for texImage2D etc..
+ * @return {number} the number of bytes per element for the given internalFormat, type combo
+ * @memberOf module:twgl/textures
+ */
+function getBytesPerElementForInternalFormat(internalFormat, type) {
+ const info = textureInternalFormatInfo[internalFormat];
+ if (!info) {
+ throw "unknown internal format";
+ }
+ const bytesPerElement = info.bytesPerElementMap[type];
+ if (bytesPerElement === undefined) {
+ throw "unknown internal format";
+ }
+ return bytesPerElement;
+}
+
+function make2DTexture(target, internalFormat, format, type) {
+ gl.texImage2D(target, 0, internalFormat, 1, 1, 0, format, type, null);
+}
+
+function make3DTexture(target, internalFormat, format, type) {
+ gl.texImage3D(target, 0, internalFormat, 1, 1, 1, 0, format, type, null);
+}
+
+function makeCubeMapTexture(target, internalFormat, format, type) {
+ [
+ gl.TEXTURE_CUBE_MAP_POSITIVE_X,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_X,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Y,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ gl.TEXTURE_CUBE_MAP_POSITIVE_Z,
+ gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,
+ ].forEach(function(target) {
+ gl.texImage2D(target, 0, internalFormat, 1, 1, 0, format, type, null);
+ });
+}
+
+function runTest() {
+ const targets = {};
+ targets[gl.TEXTURE_2D] = { fn: make2DTexture, },
+ targets[gl.TEXTURE_3D] = { fn: make3DTexture, },
+ targets[gl.TEXTURE_CUBE_MAP] = { fn: makeCubeMapTexture, },
+ targets[gl.TEXTURE_2D_ARRAY] = { fn: make3DTexture, },
+
+ Object.keys(targets).forEach(function(target) {
+ target = parseInt(target);
+ const targetInfo = targets[target];
+ targetInfo.textures = [];
+ Object.keys(textureInternalFormatInfo).forEach(function(internalFormat) {
+ internalFormat = parseInt(internalFormat);
+ const isDepthFormat = textureInternalFormatInfo[internalFormat].depth;
+ if (target === gl.TEXTURE_3D && isDepthFormat) {
+ return;
+ }
+ const info = textureInternalFormatInfo[internalFormat];
+ const texture = gl.createTexture();
+ gl.bindTexture(target, texture);
+ targetInfo.fn(target, internalFormat, info.textureFormat, info.type[0]);
+ targetInfo.textures.push({
+ internalFormat: internalFormat,
+ texture: texture,
+ });
+ gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(target, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from setup for ${wtu.glEnumToString(gl, target)} ${wtu.glEnumToString(gl, internalFormat)}`);
+ });
+ });
+
+ const samplerObject = gl.createSampler();
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
+
+ // The rules implemented here are:
+
+ // Float samplers accept only float textures and normalized integer textures
+ // (signed or unsigned) and depth textures with TEXTURE_COMPARE_MODE set to
+ // NONE.
+
+ // Signed samplers accept only signed unnormalized integer textures.
+
+ // Unsigned samplers accept only unsigned unnormalized integer textures.
+
+ // Shadow samplers accept only depth textures with
+ // TEXTURE_COMPARE_MODE set to COMPARE_REF_TO_TEXTURE.
+
+ testSamplerType(FLOAT, floatSamplerTypes);
+ testSamplerType(SIGNED, signedIntSamplerTypes);
+ testSamplerType(UNSIGNED, unsignedIntSamplerTypes);
+ testSamplerType(SHADOW, shadowSamplerTypes);
+
+ function testSamplerType(samplerType, samplerInfos) {
+ samplerInfos.forEach(function(samplerInfo) {
+ debug(`\nchecking ${samplerInfo.type}`);
+ const program = wtu.setupProgram(gl, ['vshader', makeFragmentShader(samplerInfo.type, samplerInfo.uvType)], [], console.log.bind(console));
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ const target = samplerInfo.target;
+ const targetInfo = targets[target];
+ targetInfo.textures.forEach(function(textureInfo) {
+ const internalFormat = textureInfo.internalFormat;
+ const desc = wtu.glEnumToString(gl, internalFormat);
+ const info = textureInternalFormatInfo[internalFormat];
+
+ // The texture object can have two values of TEXTURE_COMPARE_MODE: NONE or
+ // COMPARE_REF_TO_TEXTURE. However, the sampler can have three states:
+ // No sampler object bound, sampler object with NONE, and sampler object with
+ // COMPARE_REF_TO_TEXTURE. When a sampler object is bound, it overrides the
+ // texture object's state. We test 2*3=6 possible combinations of state.
+
+ // First test the three states that result in TEXTURE_COMPARE_MODE being NONE.
+ let expected = samplerType == info.samplerType ? gl.NONE : gl.INVALID_OPERATION;
+ gl.bindTexture(target, textureInfo.texture);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state NONE, no sampler object`);
+
+ gl.bindSampler(0, samplerObject);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state NONE, sampler state NONE`);
+
+ gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state COMPARE_REF_TO_TEXTURE, sampler state NONE`);
+
+ // Now test test the three states that result in TEXTURE_COMPARE_MODE being COMPARE_REF_TO_TEXTURE.
+ if (info.depth) {
+ expected = samplerType == SHADOW ? gl.NONE : gl.INVALID_OPERATION;
+ }
+ gl.bindSampler(0, null);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state COMPARE_REF_TO_TEXTURE, no sampler object`);
+
+ gl.bindSampler(0, samplerObject);
+ gl.samplerParameteri(samplerObject, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state COMPARE_REF_TO_TEXTURE, sampler state COMPARE_REF_TO_TEXTURE`);
+
+ gl.texParameteri(target, gl.TEXTURE_COMPARE_MODE, gl.NONE);
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expected, `${desc} texture state NONE, sampler state COMPARE_REF_TO_TEXTURE`);
+ gl.bindSampler(0, null);
+ });
+ });
+ };
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html
new file mode 100644
index 0000000000..5e67195ea8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/large-uniform-buffers.html
@@ -0,0 +1,138 @@
+<!--
+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 large uniform buffers conformance tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+description("Test for UBOs sized over 65536 - https://bugs.chromium.org/p/angleproject/issues/detail?id=3388");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ var uboBuf = gl.createBuffer();
+ var uboData = new Float32Array(0x20000);
+
+ var offs0 = 0x00000;
+ // Red
+ uboData[offs0 + 0] = 1;
+ uboData[offs0 + 1] = 0;
+ uboData[offs0 + 2] = 0;
+ uboData[offs0 + 3] = 1;
+
+ var offs1 = 0x10000;
+ const alignment = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT);
+ if (offs1 % alignment != 0)
+ testFailed("Platform has a strange uniform buffer offset alignment requirement: " + alignment);
+
+ // Green
+ uboData[offs1 + 0] = 0;
+ uboData[offs1 + 1] = 1;
+ uboData[offs1 + 2] = 0;
+ uboData[offs1 + 3] = 1;
+
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboData, gl.STATIC_DRAW);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, uboBuf, offs0 * 4, 0x10);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ debug("draw upper triangle - should be green");
+ var uboBuf2 = gl.createBuffer();
+ gl.bindBufferRange(gl.UNIFORM_BUFFER, 0, uboBuf, offs1 * 4, 0x10);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html
new file mode 100644
index 0000000000..24c7060e5c
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/query-uniform-blocks-after-shader-detach.html
@@ -0,0 +1,93 @@
+<!--
+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 Uniform Buffers Conformance Tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+
+in vec4 position;
+
+uniform localInputs
+{
+ mat4 projectionModelViewMatrix;
+};
+
+void main ()
+{
+ gl_Position = projectionModelViewMatrix * position;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+
+out lowp vec4 resultColor;
+
+void main()
+{
+ resultColor = vec4(0,1,0,1);
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+<script>
+// Adopted from the test case provided in crbug.com/735784
+"use strict";
+description("This tests UBO block lookups still work after detaching shaders");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, null, 2);
+
+function runTest(gl) {
+ var program = wtu.loadProgramFromScript(gl, "vshader", "fshader");
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+
+ var shaders = gl.getAttachedShaders(program);
+ if (!shaders || shaders.length != 2) {
+ testFailed("getAttachedShaders failed");
+ return;
+ }
+ gl.detachShader (program, shaders[0]);
+ gl.detachShader (program, shaders[1]);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");
+
+ var index = gl.getUniformBlockIndex(program, "localInputs");
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from getUniformBlockIndex");
+ if (index == gl.INVALID_INDEX) {
+ testFailed("getUniformBlockIndex returns INVALID_INDEX");
+ } else {
+ testPassed("getUniformBlockIndex returns valid index");
+ }
+}
+
+if (!gl) {
+ testFailed("WebGL context does not exist");
+} else {
+ testPassed("WebGL context exists");
+ runTest(gl);
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html
new file mode 100644
index 0000000000..c5646faae8
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/simple-buffer-change.html
@@ -0,0 +1,122 @@
+<!--
+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 draw with uniform blocks conformance tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 a_vertex;
+void main(void) {
+ gl_Position = a_vertex;
+}
+</script>
+<script id="fshader" type="x-shader/x-fragment">#version 300 es
+precision mediump float;
+layout (std140) uniform color_ubo {
+ vec4 color;
+};
+out vec4 fragColor;
+void main(void) {
+ fragColor = color;
+}
+</script>
+</head>
+<body>
+<canvas id="example" width="100", height="100"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+debug("");
+
+// Ported from: https://github.com/google/angle/blob/master/src/tests/gl_tests/UniformBufferTest.cpp#L1463
+description("Regression test for https://bugs.chromium.org/p/chromium/issues/detail?id=792966");
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext("example", undefined, 2);
+
+function runTest() {
+ var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_vertex']);
+ var uboIndex = gl.INVALID_INDEX;
+ if (program)
+ uboIndex = gl.getUniformBlockIndex(program, "color_ubo");
+ if (!program || uboIndex == gl.INVALID_INDEX) {
+ testFailed("Loading program failed");
+ return;
+ }
+ testPassed("Loading program succeeded");
+
+ var vertices = new Float32Array([
+ -1, -1, 0,
+ 1, -1, 0,
+ -1, 1, 0,
+ 1, 1, 0
+ ]);
+ var vertexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuf);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+ var indexBuf = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuf);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Int16Array([ 0, 1, 2, 2, 1, 3 ]), gl.STATIC_DRAW);
+
+ var uboDataSize = gl.getActiveUniformBlockParameter(
+ program, uboIndex, gl.UNIFORM_BLOCK_DATA_SIZE);
+ if (uboDataSize == 0) {
+ testFailed("uniform block data size invalid");
+ return;
+ }
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from setup");
+
+ debug("draw lower triangle - should be red");
+ var uboBuf1 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf1);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 1, 0, 0, 1 ]));
+ gl.uniformBlockBinding(program, uboIndex, 0);
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ // Bind a second buffer to the same binding point (0). This should set to draw green.
+ debug("draw upper triangle - should be green");
+ var uboBuf2 = gl.createBuffer();
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uboBuf2);
+ gl.bufferData(gl.UNIFORM_BUFFER, uboDataSize, gl.STATIC_DRAW);
+ gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array([ 0, 1, 0, 1 ]));
+ gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 6);
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ var width = 100, height = 100;
+ wtu.checkCanvasRectColor(gl, 0, 0, width/2-5, height/2-5, [255, 0, 0, 255], 2,
+ function() { testPassed("lower left should be red"); },
+ function() { testFailed("lower left should be red"); });
+ wtu.checkCanvasRectColor(gl, width/2+5, height/2+5, width/2-5, height/2-5, [0, 255, 0, 255], 2,
+ function() { testPassed("top right should be green"); },
+ function() { testFailed("top right should be green"); });
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ testPassed("WebGL context creation succeeded");
+ runTest();
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html
new file mode 100644
index 0000000000..2d40a62c00
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/uniforms/uniform-blocks-with-arrays.html
@@ -0,0 +1,115 @@
+<!--
+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 uniform blocks containing arrays conformance tests</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>
+<script id="vshader" type="x-shader/x-vertex">#version 300 es
+in vec4 vPosition;
+void main() {
+ gl_Position = vPosition;
+}
+</script>
+<script id="fshaderArraysOfStructs" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+struct light_t {
+ vec4 intensity;
+};
+const int maxLights = 2;
+layout(std140) uniform lightData { light_t lights[maxLights]; };
+vec4 processLight(vec4 lighting, light_t light)
+{
+ return lighting + light.intensity;
+}
+void main()
+{
+ vec4 lighting = vec4(0, 1, 0, 1);
+ for (int n = 0; n < maxLights; n++)
+ lighting = processLight(lighting, lights[n]);
+ my_FragColor = lighting;
+}
+</script>
+<script id="fshaderArraysOfStructsContainingArrays" type="x-shader/x-fragment">#version 300 es
+precision highp float;
+out vec4 my_FragColor;
+struct light_t {
+ vec4 intensity[3];
+};
+const int maxLights = 2;
+layout(std140) uniform lightData { light_t lights[maxLights]; };
+vec4 processLight(vec4 lighting, light_t light)
+{
+ return lighting + light.intensity[1];
+}
+void main()
+{
+ vec4 lighting = vec4(0, 1, 0, 1);
+ for (int n = 0; n < maxLights; n++)
+ lighting = processLight(lighting, lights[n]);
+ my_FragColor = lighting;
+}
+</script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description();
+
+// GLSL ES 3.00.6 section 4.3.7:
+// "Otherwise, built-in types, previously declared structures, and arrays of these are allowed as the type of a declarator in the same manner they are allowed outside a block."
+
+var wtu = WebGLTestUtils;
+var gl = wtu.create3DContext(undefined, undefined, 2);
+
+function runTest(fragShader, bufferFloatCount, shaderBlockDescription) {
+ debug('');
+ debug('Testing fragment shader with an uniform block containing ' + shaderBlockDescription);
+ var program = wtu.setupProgram(gl, ['vshader', fragShader], ['vPosition'], undefined, true);
+ if (!program) {
+ testFailed("Loading program failed");
+ return;
+ }
+ var blockIndex = gl.getUniformBlockIndex(program, "lightData");
+
+ var uniformBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.UNIFORM_BUFFER, uniformBuffer);
+ gl.bufferData(gl.UNIFORM_BUFFER, new Float32Array(bufferFloatCount), gl.DYNAMIC_READ);
+
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, uniformBuffer);
+ gl.uniformBlockBinding(program, blockIndex, 0);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from uniform buffer setup");
+
+ wtu.clearAndDrawUnitQuad(gl);
+
+ wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No errors from draw");
+
+ wtu.checkCanvas(gl, [0, 255, 0, 255], 'should be green', 1);
+}
+
+if (!gl) {
+ testFailed("WebGL context creation failed");
+} else {
+ wtu.setupUnitQuad(gl);
+ runTest("fshaderArraysOfStructs", 2 * 4, 'arrays of structs');
+ runTest("fshaderArraysOfStructsContainingArrays", 2 * 3 * 4, 'arrays of structs containing arrays');
+}
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../../js/js-test-post.js"></script>
+
+</body>
+</html>