diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/uniforms')
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> |