diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/buffers')
11 files changed, 1747 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt new file mode 100644 index 000000000..96921fbea --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/00_test_list.txt @@ -0,0 +1,9 @@ +bound-buffer-size-change-test.html +buffer-copying-contents.html +buffer-copying-restrictions.html +buffer-data-and-buffer-sub-data-sub-source.html +buffer-type-restrictions.html +buffer-overflow-test.html +get-buffer-sub-data.html +one-large-uniform-buffer.html +uniform-buffers.html diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html new file mode 100644 index 000000000..a9d13496a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/bound-buffer-size-change-test.html @@ -0,0 +1,140 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL buffer size change test for bindBufferBase/bindBufferRange</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> +<script> +"use strict"; +description("WebGL buffer size change for bindings through bindBufferBase/bindBufferRange"); + +// This test verifies the ES3 behavior, that the bound buffer range (offset, size) is not +// limited by the actual buffer size, and the driver is responsible that no out-of-range +// access may happen. + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); + +debug(""); +debug("bindBufferBase with TRANSFORM_FEEDBACK_BUFFER target"); +var buffer1 = gl.createBuffer(); +gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer1); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Calling bindBufferBase on a buffer where no storage is allocated should succeed."); +shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "buffer1"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer1"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "0"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "0"); + +gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4, gl.STATIC_DRAW); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer1"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "0"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "0"); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("bindBufferBase with UNIFORM_BUFFER target"); +var buffer2 = gl.createBuffer(); +gl.bindBufferBase(gl.UNIFORM_BUFFER, 1, buffer2); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Calling bindBufferBase on a buffer where no storage is allocated should succeed."); +shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "buffer2"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer2"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "0"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "0"); + +gl.bufferData(gl.UNIFORM_BUFFER, 8, gl.STATIC_DRAW); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer2"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "0"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "0"); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("bindBufferRange with TRANSFORM_FEEDBACK_BUFFER target"); +var buffer3 = gl.createBuffer(); +gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer3, 4, 8); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Calling bindBufferRange on a buffer where no storage is allocated should succeed."); +shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)", "buffer3"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4"); + +gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 4, gl.STATIC_DRAW); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4"); + +gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 12, gl.STATIC_DRAW); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "buffer3"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)", "8"); +shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)", "4"); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +debug(""); +debug("bindBufferRange with UNIFORM_BUFFER target"); +var buffer4 = gl.createBuffer(); +var offset = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT); +gl.bindBufferRange(gl.UNIFORM_BUFFER, 1, buffer4, offset, 12); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Calling bindBufferRange on a buffer where no storage is allocated should succeed."); +shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "buffer4"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer4"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "12"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "offset"); + +gl.bufferData(gl.UNIFORM_BUFFER, offset + 8, gl.STATIC_DRAW); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer4"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "12"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "offset"); + +gl.bufferData(gl.UNIFORM_BUFFER, offset + 12, gl.STATIC_DRAW); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)", "buffer4"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)", "12"); +shouldBe("gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)", "offset"); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR); + +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/buffers/buffer-copying-contents.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-contents.html new file mode 100644 index 000000000..8006f2181 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-contents.html @@ -0,0 +1,197 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL buffer copying contents test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("Test copying a buffer's contents to another buffer governed by the WebGL 2 spec."); + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +var vertices = [ + 1.1, 1.0, 1.3, + -1.0, -1.0, -5.0, + 5.3, -1.0, 1.0 +]; + +debug(""); +debug("Test copying between buffers returns correct data"); + +function testCopyBuffers(srcTarget, dstTarget, copyRead, copyWrite) { + var msg = "Copying from " + targetToString(gl, srcTarget) + + " to " + targetToString(gl, dstTarget) + if (copyRead && copyWrite) + msg += " via COPY_READ_BUFFER and COPY_WRITE_BUFFER" + else if (copyRead) + msg += " via COPY_READ_BUFFER" + else if (copyWrite) + msg += " via COPY_WRITE_BUFFER" + else + msg += " directly" + debug("") + debug(msg) + + var srcBuffer = gl.createBuffer(), dstBuffer = gl.createBuffer(); + var originalData = new Float32Array(vertices); + var length = vertices.length * 4; + + gl.bindBuffer(srcTarget, srcBuffer); + gl.bufferData(srcTarget, originalData, gl.STATIC_DRAW); + if (copyRead) + gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer); + + gl.bindBuffer(dstTarget, dstBuffer); + gl.bufferData(dstTarget, new Float32Array(length), gl.STATIC_DRAW); + if (copyWrite) + gl.bindBuffer(gl.COPY_WRITE_BUFFER, dstBuffer); + + var expectedGLError = gl.NO_ERROR; + + if (srcTarget == dstTarget) { + if (!copyRead && copyWrite) { + // srcBuffer isn't bound to any targets because of setting up dstBuffer. + gl.bindBuffer(srcTarget, srcBuffer); + } + if (!copyRead && !copyWrite) { + // Same buffer object, overlapping range. + expectedGLError = gl.INVALID_VALUE; + } + } + if ((srcTarget == gl.ELEMENT_ARRAY_BUFFER && + dstTarget != gl.ELEMENT_ARRAY_BUFFER) || + (srcTarget != gl.ELEMENT_ARRAY_BUFFER && + dstTarget == gl.ELEMENT_ARRAY_BUFFER)) { + expectedGLError = gl.INVALID_OPERATION; + } + + gl.copyBufferSubData(copyRead ? gl.COPY_READ_BUFFER : srcTarget, + copyWrite ? gl.COPY_WRITE_BUFFER : dstTarget, + 0, 0, length); + if (expectedGLError == gl.NO_ERROR) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Copying should work"); + + var retBuffer = new Uint8Array(length); + gl.getBufferSubData(dstTarget, 0, retBuffer); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "gl.getBufferSubData(" + targetToString(gl, dstTarget) + + ", 0, retBuffer) should work"); + + var failed = false; + var retArray = new Float32Array(retBuffer.buffer); + for (var i = 0; i < vertices.length; i++) { + if (originalData[i] != retArray[i]) { + failed = true; + break; + } + } + if (failed) + testFailed("The returned array buffer fails to match original data"); + else + testPassed("The returned array buffer matches original data"); + } else { + wtu.glErrorShouldBe(gl, expectedGLError, "Copying should fail"); + } + + gl.deleteBuffer(srcBuffer); + gl.deleteBuffer(dstBuffer); + shouldBeNull("gl.getParameter(gl.ARRAY_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.COPY_READ_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.COPY_WRITE_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.PIXEL_PACK_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.PIXEL_UNPACK_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING)"); + shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); +} + +function targetToString(gl, target) { + switch (target) { + case gl.ARRAY_BUFFER: + return "ARRAY_BUFFER"; + case gl.COPY_READ_BUFFER: + return "COPY_READ_BUFFER"; + case gl.COPY_WRITE_BUFFER: + return "COPY_WRITE_BUFFER"; + case gl.ELEMENT_ARRAY_BUFFER: + return "ELEMENT_ARRAY_BUFFER"; + case gl.PIXEL_PACK_BUFFER: + return "PIXEL_PACK_BUFFER"; + case gl.PIXEL_UNPACK_BUFFER: + return "PIXEL_UNPACK_BUFFER"; + case gl.TRANSFORM_FEEDBACK_BUFFER: + return "TRANSFORM_FEEDBACK_BUFFER"; + case gl.UNIFORM_BUFFER: + return "UNIFORM_BUFFER"; + default: + return "UNKNOWN BUFFER"; + } +} + +var targets = [ + gl.ARRAY_BUFFER, + gl.ELEMENT_ARRAY_BUFFER, + gl.PIXEL_PACK_BUFFER, + gl.PIXEL_UNPACK_BUFFER, + gl.TRANSFORM_FEEDBACK_BUFFER, + gl.UNIFORM_BUFFER, +] + +for (var srcIndex in targets) { + for (var dstIndex in targets) { + if (targets[srcIndex] != gl.TRANSFORM_FEEDBACK_BUFFER && + targets[dstIndex] != gl.TRANSFORM_FEEDBACK_BUFFER) { + testCopyBuffers(targets[srcIndex], targets[dstIndex], true, true); + } + if (targets[srcIndex] != gl.TRANSFORM_FEEDBACK_BUFFER) { + testCopyBuffers(targets[srcIndex], targets[dstIndex], true, false); + } + if (targets[dstIndex] != gl.TRANSFORM_FEEDBACK_BUFFER) { + testCopyBuffers(targets[srcIndex], targets[dstIndex], false, true); + } + testCopyBuffers(targets[srcIndex], targets[dstIndex], false, false); + } +} + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html new file mode 100644 index 000000000..1833c53fc --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-copying-restrictions.html @@ -0,0 +1,123 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL buffer copying restrictions test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("Test buffer copying restrictions governed by the WebGL 2 spec. The test makes sure that copyBufferSubData acts as expected."); + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); + +var validTargets = [gl.ARRAY_BUFFER, gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, + gl.ELEMENT_ARRAY_BUFFER, gl.PIXEL_PACK_BUFFER, + gl.PIXEL_UNPACK_BUFFER, gl.TRANSFORM_FEEDBACK_BUFFER, + gl.UNIFORM_BUFFER]; + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +var testCopyBuffer = function(srcTarget, dstTarget) { + var srcTargetStr = wtu.glEnumToString(gl, srcTarget), + dstTargetStr = wtu.glEnumToString(gl, dstTarget); + var srcBuffer = gl.createBuffer(), + dstBuffer = gl.createBuffer(); + var testCopyStr = "copying from a gl." + wtu.glEnumToString(gl, srcTarget) + " buffer to a gl." + + wtu.glEnumToString(gl, dstTarget) + " buffer" + + gl.bindBuffer(srcTarget, srcBuffer); + gl.bufferData(srcTarget, new Float32Array(32), gl.STATIC_DRAW); + gl.bindBuffer(dstTarget, dstBuffer); + gl.bufferData(dstTarget, new Float32Array(32), gl.STATIC_DRAW); + gl.copyBufferSubData(srcTarget, dstTarget, 8, 0, 4); + if (srcTarget == dstTarget) + wtu.glErrorShouldBe(gl, gl.NO_ERROR, testCopyStr + " should work."); + else if (srcTarget == gl.ELEMENT_ARRAY_BUFFER || dstTarget == gl.ELEMENT_ARRAY_BUFFER ) + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, testCopyStr + " should fail."); + else + wtu.glErrorShouldBe(gl, gl.NO_ERROR, testCopyStr + " should work."); + + // Special case: COPY_READ_BUFFER and COPY_WRITE_BUFFER are compatible with ELEMENT_ARRAY_BUFFER + // only if the buffer had been initially bound to an ELEMENT_ARRAY_BUFFER + if (srcTarget == gl.ELEMENT_ARRAY_BUFFER && + (dstTarget == gl.COPY_READ_BUFFER || dstTarget == gl.COPY_WRITE_BUFFER)) { + dstBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, dstBuffer); + } else if (dstTarget == gl.ELEMENT_ARRAY_BUFFER && + (srcTarget == gl.COPY_READ_BUFFER || srcTarget == gl.COPY_WRITE_BUFFER)) { + srcBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, srcBuffer); + } else { + return; + } + + gl.bindBuffer(srcTarget, srcBuffer); + gl.bufferData(srcTarget, new Float32Array(32), gl.STATIC_DRAW); + gl.bindBuffer(dstTarget, dstBuffer); + gl.bufferData(dstTarget, new Float32Array(32), gl.STATIC_DRAW); + gl.copyBufferSubData(srcTarget, dstTarget, 8, 0, 4); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, testCopyStr + " should work if all buffers were initially bound to ELEMENT_ARRAY_BUFFER."); +}; + +for (var i = 0; i < validTargets.length; i++) { + debug(""); + debug("Copying data from a " + wtu.glEnumToString(gl, validTargets[i]) + + " buffer to another target"); + for (var j = 0; j < validTargets.length; j++) + testCopyBuffer(validTargets[i], validTargets[j]); +} + +debug(""); +debug("Test copying a buffer of other data (gl.ARRAY_BUFFER) bound to gl.COPY_READ_BUFFER to a " + + "buffer bound to gl.ELEMENT_ARRAY_BUFFER"); +var srcBuffer = gl.createBuffer(), dstBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, srcBuffer); +gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, dstBuffer); +gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Float32Array(32), gl.STATIC_DRAW); +gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(32), gl.STATIC_DRAW); +gl.bindBuffer(gl.COPY_READ_BUFFER, srcBuffer); +gl.copyBufferSubData(gl.COPY_READ_BUFFER, gl.ELEMENT_ARRAY_BUFFER, 0, 0, 4); +wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Copying gl.ARRAY_BUFFER bound to " + + "gl.COPY_READ_BUFFER to a buffer bound to gl.ELEMENT_ARRAY_BUFFER should fail."); + +finishTest(); + +var successfullyParsed = true; +</script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html new file mode 100644 index 000000000..dbf7d45e8 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-data-and-buffer-sub-data-sub-source.html @@ -0,0 +1,204 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<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> + +<script> +"use strict"; +description("Test bufferData/bufferSubData with ArrayBufferView sub source input"); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext(undefined, undefined, 2); + +function verifyBufferData(testCase, sourceByteOffset, size, data) { + var readbackBuffer = new ArrayBuffer(testCase.size * size); + var readbackView = new window[testCase.type](readbackBuffer); + gl.getBufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, readbackView); + var pass = true; + var offset = sourceByteOffset / testCase.size; + for (var ii = 0; ii < size; ++ii) { + if (readbackView[ii] != data[ii]) { + testFailed("expected data at " + ii + ": " + data[iit] + ", got " + readbackView[ii]); + pass = false; + } + } + if (pass) { + testPassed("buffer data uploaded correctly"); + } +} + +function bufferDataTest(testCases) { + for (var idx = 0; idx < testCases.length; ++idx) { + var test = testCases[idx]; + debug(""); + debug("Test bufferData with " + test.type); + + var buf = gl.createBuffer(); + shouldBeNonNull(buf); + + gl.bindBuffer(gl.ARRAY_BUFFER, buf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + var count = 4; + var arrayBuffer = new ArrayBuffer(test.size * count); + var view = new window[test.type](arrayBuffer); + for (var ii = 0; ii < count; ++ii) { + view[ii] = ii; + } + + gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, 0, count + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling bufferData when srcOffset + length is larger than source size"); + + gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, count + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling bufferData when srcOffset + length is larger than source size"); + + gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, count - 1, 2); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling bufferData when srcOffset + length is larger than source size"); + + var offset = 2; + var size = count - offset; + gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, offset); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling bufferData with valid sub source should succeed"); + verifyBufferData(test, 0, size, view.slice(offset, offset + size)); + + offset = 1; + size = 1; + gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, offset, size); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling bufferData with valid sub source should succeed"); + verifyBufferData(test, 0, size, view.slice(offset, offset + size)); + + gl.bufferData(gl.ARRAY_BUFFER, view, gl.STATIC_DRAW, count); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling bufferData with valid sub source of size 0 should succeed"); + + gl.deleteBuffer(buf); + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no GL error"); + } +} + +function bufferSubDataTest(testCases) { + for (var idx = 0; idx < testCases.length; ++idx) { + var test = testCases[idx]; + debug(""); + debug("Test bufferSubData with " + test.type); + + var count = 4; + var totalBufferBytes = test.size * count * 2; + var buf = gl.createBuffer(); + shouldBeNonNull(buf); + gl.bindBuffer(gl.ARRAY_BUFFER, buf); + gl.bufferData(gl.ARRAY_BUFFER, totalBufferBytes, gl.STATIC_DRAW); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + + var arrayBuffer = new ArrayBuffer(test.size * count); + var view = new window[test.type](arrayBuffer); + for (var ii = 0; ii < count; ++ii) { + view[ii] = ii; + } + + var sourceByteOffset = test.size * 2; + + gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, 0, count + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling bufferSubData when srcOffset + length is larger than source size"); + + gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, count + 1); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling bufferSubData when srcOffset + length is larger than source size"); + + gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, count - 1, 2); + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "calling bufferSubData when srcOffset + length is larger than source size"); + + var offset = 2; + var size = count - offset; + gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, offset); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling bufferSubData with valid sub source should succeed"); + verifyBufferData(test, sourceByteOffset, size, view.slice(offset, offset + size)); + + offset = 1; + size = 1; + gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, offset, size); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling bufferSubData with valid sub source should succeed"); + verifyBufferData(test, sourceByteOffset, size, view.slice(offset, offset + size)); + + gl.bufferSubData(gl.ARRAY_BUFFER, sourceByteOffset, view, count); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "calling bufferSubData with valid sub source of size 0 should succeed"); + + gl.deleteBuffer(buf); + gl.bindBuffer(gl.ARRAY_BUFFER, null); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no GL error"); + } +} + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + var testCases = [ + {type: "Uint8Array", size: 1}, + {type: "Int8Array", size: 1}, + {type: "Int16Array", size: 2}, + {type: "Uint16Array", size: 2}, + {type: "Uint32Array", size: 4}, + {type: "Int32Array", size: 4}, + {type: "Float32Array", size: 4}, + {type: "Float64Array", size: 8} + ]; + + bufferDataTest(testCases); + bufferSubDataTest(testCases); +} + +var successfullyParsed = true; +</script> + +<script src="../../js/js-test-post.js"></script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html new file mode 100644 index 000000000..929692df8 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-overflow-test.html @@ -0,0 +1,72 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL buffer overflow test for bindBufferRange</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> +<script> +"use strict"; +description("WebGL buffer overflow test: buffer overflow will not lead to failure in bindBufferRange"); + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); + +debug(""); +var buffer1 = gl.createBuffer(); +gl.bindBufferRange(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer1, 0, 4); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Calling bindBufferRange on a buffer where no storage is allocated should succeed."); +shouldBe("buffer1", "gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)"); +shouldBe("4", "gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_SIZE, 0)"); +shouldBe("0", "gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_START, 0)"); + +var buffer2 = gl.createBuffer(); +gl.bindBuffer(gl.UNIFORM_BUFFER, buffer2); +gl.bufferData(gl.UNIFORM_BUFFER, 4, gl.STATIC_DRAW); +gl.bindBufferRange(gl.UNIFORM_BUFFER, 1, buffer2, 0, 8); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Calling bindBufferRange on a buffer where the storage is not big enough should succeed."); +shouldBe("buffer2", "gl.getIndexedParameter(gl.UNIFORM_BUFFER_BINDING, 1)"); +shouldBe("8", "gl.getIndexedParameter(gl.UNIFORM_BUFFER_SIZE, 1)"); +shouldBe("0", "gl.getIndexedParameter(gl.UNIFORM_BUFFER_START, 1)"); + +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/buffers/buffer-type-restrictions.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html new file mode 100644 index 000000000..57a8a8fbf --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/buffer-type-restrictions.html @@ -0,0 +1,141 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL buffer binding restrictions test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("Test binding restrictions governed by the WebGL 2 spec. The test makes sure that bindBuffer," + + "bindBufferRange, and bindBufferBase acts as expected with every target combination."); + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); + +var validTargets = [gl.ARRAY_BUFFER, gl.ELEMENT_ARRAY_BUFFER, gl.COPY_READ_BUFFER, + gl.COPY_WRITE_BUFFER, gl.PIXEL_PACK_BUFFER, gl.PIXEL_UNPACK_BUFFER, + gl.TRANSFORM_FEEDBACK_BUFFER, gl.UNIFORM_BUFFER]; + +var bindFunctions = ["bindBuffer", "bindBufferRange", "bindBufferBase"]; + +var isCopyTarget = function(target) { + return target == gl.COPY_READ_BUFFER || target == gl.COPY_WRITE_BUFFER; +} + +var noElementArrayVsOtherDataConflicts = function(first, second) { + return isCopyTarget(second) || ((first == gl.ELEMENT_ARRAY_BUFFER) == (second == gl.ELEMENT_ARRAY_BUFFER)); +}; + + +var bind = function(bindFn, target, buffer) { + if (bindFn == "bindBuffer") + gl.bindBuffer(target, buffer); + else if (bindFn == "bindBufferRange") + gl.bindBufferRange(target, 0, buffer, 0, 4); + else if (bindFn == "bindBufferBase") + gl.bindBufferBase(target, 0, buffer); + else + throw new Error("Cannot bind unknown function: " + bindFn); +} + +var testBindingFn = function(firstBindFn, secondBindFn, firstTarget, secondTarget) { + var firstTargetStr = wtu.glEnumToString(gl, firstTarget), + secondTargetStr = wtu.glEnumToString(gl, secondTarget); + var buffer = gl.createBuffer(); + + bind(firstBindFn, firstTarget, buffer); + bind(firstBindFn, firstTarget, null); + bind(secondBindFn, secondTarget, buffer); + bind(secondBindFn, secondTarget, null); + + var messagePrefix = "Binding buffer first with " + firstBindFn + " to gl." + firstTargetStr + + " and then binding buffer with " + secondBindFn + " to gl." + secondTargetStr + " should "; + if (firstTarget == secondTarget || noElementArrayVsOtherDataConflicts(firstTarget, secondTarget)) + wtu.glErrorShouldBe(gl, gl.NO_ERROR, messagePrefix + "WORK"); + else + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, messagePrefix + "FAIL"); + + if ((firstTarget == gl.TRANSFORM_FEEDBACK_BUFFER && secondTarget != gl.TRANSFORM_FEEDBACK_BUFFER) || + (firstTarget != gl.TRANSFORM_FEEDBACK_BUFFER && secondTarget == gl.TRANSFORM_FEEDBACK_BUFFER)) { + bind(firstBindFn, firstTarget, buffer); + bind(secondBindFn, secondTarget, buffer); + + var message = "Binding buffer first with " + firstBindFn + " to gl." + firstTargetStr + + " and simultaneously binding buffer with " + secondBindFn + " to gl." + secondTargetStr + " should FAIL"; + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, message); + } +} + +var testBinding = function(firstTarget, secondTarget) { + for (var i = 0; i < bindFunctions.length; i++) + if (i == 0 || firstTarget == gl.UNIFORM_BUFFER || firstTarget == gl.TRANSFORM_FEEDBACK_BUFFER) + for (var j = 0; j < bindFunctions.length; j++) + if (j == 0 || secondTarget == gl.UNIFORM_BUFFER || secondTarget == gl.TRANSFORM_FEEDBACK_BUFFER) + testBindingFn(bindFunctions[i], bindFunctions[j], firstTarget, secondTarget); +}; + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +debug(""); +debug("Testing each binding function"); + +var buffer1 = gl.createBuffer(); +bind("bindBuffer", gl.ARRAY_BUFFER, buffer1); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBuffer(gl.ARRAY_BUFFER, buffer1) should WORK"); + +var buffer2 = gl.createBuffer(); +bind("bindBufferRange", gl.UNIFORM_BUFFER, buffer2); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBufferRange(gl.UNIFORM_BUFFER, 0, buffer2, 0, 4) should WORK"); + +var buffer3 = gl.createBuffer(); +bind("bindBufferBase", gl.UNIFORM_BUFFER, buffer3); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBufferBase(gl.UNIFORM_BUFFER, 0, buffer3) should WORK"); + +for (var i = 0; i < validTargets.length; i++) { + debug(""); + debug("Testing binding a buffer first to " + wtu.glEnumToString(gl, validTargets[i]) + + " and then to another target"); + for (var j = 0; j < validTargets.length; j++) + testBinding(validTargets[i], validTargets[j]); +} + +finishTest(); + +var successfullyParsed = true; +</script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html new file mode 100644 index 000000000..6026cc5cc --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/get-buffer-sub-data.html @@ -0,0 +1,176 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL getBufferSubData test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("This test makes sure that getBufferSubData acts as expected governed by WebGL 2."); + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); + +var vertices = [ + 1.1, 1.0, 1.3, + -1.0, -1.0, -5.0, + 5.3, -1.0, 1.0 +]; +var floatArray = new Float32Array(vertices); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +var buffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, buffer); +gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW); + +var uninitializedBuffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer); +gl.bufferData(gl.ARRAY_BUFFER, 36, gl.STATIC_DRAW); +gl.bindBuffer(gl.ARRAY_BUFFER, null); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from buffer setup."); + +gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + +debug(""); +debug("Test that getBufferSubData successfully works reading buffer data from gl.ARRAY_BUFFER"); +var retArray = new Float32Array(vertices.length); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)"); + +debug("Argument must be ArrayBufferView, not ArrayBuffer") +shouldThrow("gl.getBufferSubData(gl.ARRAY_BUFFER, 0, new ArrayBuffer(4))"); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should not generate GL error"); +debug("Argument must be ArrayBufferView, not null") +shouldThrow("gl.getBufferSubData(gl.ARRAY_BUFFER, 0, null)"); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should not generate GL error"); + +debug("Check array data to match original data set by the buffer"); +var failed = false; +for (var i = 0; i < vertices.length; i++) { + if (floatArray[i] != retArray[i]) { + failed = true; + break; + } +} +if (failed) + testFailed("The returned array buffer fails to match original data"); +else + testPassed("The returned array buffer matches original data"); + +debug("Test that getBufferSubData successfully works with dstOffset"); +retArray = new Float32Array(vertices.length); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2)"); +shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])"); +shouldBeTrue("areArraysEqual(retArray.slice(2), floatArray.slice(0, floatArray.length - 2))"); + +retArray = new Float32Array(vertices.length); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length)"); +shouldBeTrue("areArraysEqual(retArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])"); + +debug("Test that getBufferSubData fails when given a dstOffset beyond the end of retArray"); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length + 1)"); + +debug("Test that getBufferSubData successfully works with dstOffset and length"); +retArray = new Float32Array(vertices.length); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, 2, 2)"); +shouldBeTrue("areArraysEqual(retArray.slice(0, 2), [0, 0])"); +shouldBeTrue("areArraysEqual(retArray.slice(2, 4), floatArray.slice(0, 2))"); +shouldBeTrue("areArraysEqual(retArray.slice(4), [0, 0, 0, 0, 0])"); + +retArray = new Float32Array(vertices.length); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 1)"); +shouldBeTrue("areArraysEqual(retArray.slice(0, 8), [0, 0, 0, 0, 0, 0, 0, 0])"); +shouldBeTrue("areArraysEqual(retArray.slice(8), floatArray.slice(0, 1))"); + +debug("Test that getBufferSubData fails when given a dstOffset+length beyond the end of retArray"); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray, retArray.length - 1, 2)"); + +debug("Test that getBufferSubData fails when given a buffer with its size larger than the original data"); +var extraLargeBuffer = new Float32Array(vertices.length + 1); +gl.getBufferSubData(gl.ARRAY_BUFFER, 0, extraLargeBuffer); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, + "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, extraLargeBuffer)", + "Extra length should generate INVALID_VALUE."); + +debug("Test that getBufferSubData fails when offset summed with buffer length is larger than the size of the original data size"); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, + "gl.getBufferSubData(gl.ARRAY_BUFFER, retArray.byteLength + 1, retArray)"); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 1, retArray)"); + +debug("Test that getBufferSubData fails when 0 is bound to the target"); +gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); +wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, + "gl.getBufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, retArray)"); + +debug("Test that getBufferSubData fails when offset is less than 0"); +wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, -1, retArray)"); + +debug(""); +debug("Test that getBufferSubData successfully works with uninitialized buffers"); +retArray = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]); +gl.bindBuffer(gl.ARRAY_BUFFER, uninitializedBuffer); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, + "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)"); +shouldBeTrue("areArraysEqual(retArray, [0, 0, 0, 0, 0, 0, 0, 0, 0])"); + +debug(""); +debug("Test that getBufferSubData works when a buffer is immediately resized to be too small"); + +retArray = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]); +gl.bindBuffer(gl.ARRAY_BUFFER, buffer); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, + "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)"); +gl.bufferData(gl.ARRAY_BUFFER, 4, gl.STATIC_DRAW); +shouldBeTrue("areArraysEqual(retArray, floatArray)"); + +debug(""); +debug("Test that getBufferSubData works when a buffer is immediately deleted"); +retArray = new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9]); +gl.bindBuffer(gl.ARRAY_BUFFER, buffer); +gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW); +wtu.shouldGenerateGLError(gl, gl.NO_ERROR, + "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray)"); +gl.deleteBuffer(buffer); +shouldBeTrue("areArraysEqual(retArray, floatArray)"); + +finishTest(); + +var successfullyParsed = true; +</script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/getBufferSubData.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/getBufferSubData.html new file mode 100644 index 000000000..d751e8070 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/getBufferSubData.html @@ -0,0 +1,105 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>WebGL getBufferSubData test.</title> +<link rel="stylesheet" href="../../resources/js-test-style.css"/> +<script src="../../js/js-test-pre.js"></script> +<script src="../../js/webgl-test-utils.js"></script> +</head> +<body> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("This test makes sure that getBufferSubData acts as expected governed by WebGL 2."); + +var wtu = WebGLTestUtils; + +var gl = wtu.create3DContext(undefined, undefined, 2); + +var vertices = [ + 1.1, 1.0, 1.3, + -1.0, -1.0, -5.0, + 5.3, -1.0, 1.0 +]; +var floatArray = new Float32Array(vertices); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup."); + +var buffer = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, buffer); +gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW); + +debug(""); +debug("Test that getBufferSubData successfully works reading buffer data from gl.ARRAY_BUFFER"); +var retArray = new Float32Array(vertices.length); +gl.getBufferSubData(gl.ARRAY_BUFFER, 0, retArray); +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, arrBuffer) should WORK"); + +debug("Check array data to match original data set by the buffer"); +var failed = false; +for (var i = 0; i < vertices.length; i++) { + if (floatArray[i] != retArray[i]) { + failed = true; + break; + } +} +if (failed) + testFailed("The returned array buffer fails to match original data"); +else + testPassed("The returned array buffer matches original data"); + +debug("Test that getBufferSubData fails when given a buffer with its size larger than the original data"); +var extraLargeBuffer = new Uint8Array(vertices.length * Float32Array.BYTES_PER_ELEMENT + 1); +gl.getBufferSubData(gl.ARRAY_BUFFER, 0, extraLargeBuffer); +wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 0, extraLargeBuffer) with extra length should generate INVALID_VALUE"); + +debug("Test that getBufferSubData fails when offset summed with buffer length is larger than the size of the original data size"); +gl.getBufferSubData(gl.ARRAY_BUFFER, vertices.length * Float32Array.BYTES_PER_ELEMENT + 1, retArray); +wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, vertices.length * Float32Array.BYTES_PER_ELEMENT + 1, arrBuffer) with offset larger than original data size should generate INVALID_VALUE"); +gl.getBufferSubData(gl.ARRAY_BUFFER, 1, retArray); +wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, 1, arrBuffer) with offset and length larger than buffer size should generate INVALID_VALUE"); + +debug("Test that getBufferSubData fails when 0 is bound to the target"); +gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); +gl.getBufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, retArray); +wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "gl.getBufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, arrBuffer) should generate INVALID_OPERATION"); + +debug("Test that getBufferSubData fails when offset is less than 0"); +gl.getBufferSubData(gl.ARRAY_BUFFER, -1, retArray); +wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "gl.getBufferSubData(gl.ARRAY_BUFFER, -1, arrBuffer) should generate INVALID_VALUE"); + +finishTest(); + +var successfullyParsed = true; +</script> +</body> +</html> diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html new file mode 100644 index 000000000..5265e1dbf --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/one-large-uniform-buffer.html @@ -0,0 +1,152 @@ +<!-- + +/* +** Copyright (c) 2016 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!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> +</head> +<body> +<div id="description"></div> +<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> +<div id="console"></div> +<script id="vshader" type="x-shader/x-vertex">#version 300 es +in vec4 position; +void main() +{ + gl_Position = position; +} +</script> +<script id="fshader" type="x-shader/x-fragment">#version 300 es +precision mediump float; +uniform uni { + vec4 color; +}; + +out vec4 fragColor; + +void main() +{ + fragColor = color; +} +</script> +<script> +"use strict"; +description("This test covers an ANGLE bug when using a large uniform block data store. ANGLE would confuse an internal clipped uniform buffer size and produce an assert or error."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var quadVB; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + debug(""); + debug("Testing uniform block with large data store"); + runTest(); +} + +function getQuadVerts(depth) { + var quadVerts = new Float32Array(3 * 6); + quadVerts[0] = -1.0; quadVerts[1] = 1.0; quadVerts[2] = depth; + quadVerts[3] = -1.0; quadVerts[4] = -1.0; quadVerts[5] = depth; + quadVerts[6] = 1.0; quadVerts[7] = -1.0; quadVerts[8] = depth; + quadVerts[9] = -1.0; quadVerts[10] = 1.0; quadVerts[11] = depth; + quadVerts[12] = 1.0; quadVerts[13] = -1.0; quadVerts[14] = depth; + quadVerts[15] = 1.0; quadVerts[16] = 1.0; quadVerts[17] = depth; + return quadVerts; +} + +function drawQuad(depth) { + if (!quadVB) { + quadVB = gl.createBuffer() + } + + var quadVerts = getQuadVerts(depth); + + gl.bindBuffer(gl.ARRAY_BUFFER, quadVB); + gl.bufferData(gl.ARRAY_BUFFER, quadVerts, gl.STATIC_DRAW); + gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 0, 0); + gl.enableVertexAttribArray(0); + gl.drawArrays(gl.TRIANGLES, 0, 6); +} + +function runTest() { + + // Create the program + var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["position"]); + if (!program) { + testFailed("Failed to set up the program"); + return; + } + + // Init uniform buffer. To trigger the bug, it's necessary to use the + // DYNAMIC_DRAW usage. This makes ANGLE attempt to map the buffer internally + // with an incorrect copy size. + var ubo = gl.createBuffer(); + var big_size = 4096 * 64; + var data = new Float32Array([0.5, 0.75, 0.25, 1.0]); + gl.bindBuffer(gl.UNIFORM_BUFFER, ubo); + gl.bufferData(gl.UNIFORM_BUFFER, big_size, gl.DYNAMIC_DRAW); + gl.bufferSubData(gl.UNIFORM_BUFFER, 0, data); + + gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo); + var buffer_index = gl.getUniformBlockIndex(program, "uni"); + if (buffer_index == -1) { + testFailed("Failed to get uniform block index"); + return; + } + gl.uniformBlockBinding(program, buffer_index, 0); + + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Setting up uniform block should succeed"); + + // Draw the quad + gl.useProgram(program); + drawQuad(0.5); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Draw with uniform block should succeed"); + + // Verify the output color + var color = [127, 191, 64, 255]; + wtu.checkCanvas(gl, color, "canvas should be same as input uniform", 1); +} + +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/buffers/uniform-buffers.html b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers.html new file mode 100644 index 000000000..8fc8db756 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/buffers/uniform-buffers.html @@ -0,0 +1,428 @@ +<!-- + +/* +** Copyright (c) 2015 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +--> + +<!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 +layout(location=0) in vec3 p; +void main() +{ + gl_Position = vec4(p.xyz, 1.0); +} +</script> +<script id='fbadshader' type='x-shader/x-fragment'>#version 300 es +precision mediump float; +layout(location=0) out vec4 oColor; + +uniform UBOData { + float UBORed; + float UBOGreen; + float UBOBlue; +}; + +uniform Color { + float Red; + float UBOGreen; + float Blue; +}; + +void main() +{ + oColor = vec4(UBORed * Red, UBOGreen * UBOGreen, UBOBlue * Blue, 1.0); +} +</script> +<script id='fshader' type='x-shader/x-fragment'>#version 300 es +precision mediump float; +layout(location=0) out vec4 oColor; + +uniform UBOData { + float UBORed; + float UBOGreen; + float UBOBlue; +}; + +uniform UBOD { + float UBOR; + float UBOG; + float UBOB; +}; + +void main() +{ + oColor = vec4(UBORed * UBOR, UBOGreen * UBOG, UBOBlue * UBOB, 1.0); +} +</script> +<script id='fshadernamed' type='x-shader/x-fragment'>#version 300 es +precision mediump float; +layout(location=0) out vec4 oColor; + +uniform UBOData { + float Red; + float Green; + float Blue; +} UBOA; + +void main() +{ + oColor = vec4(UBOA.Red, UBOA.Green, UBOA.Blue, 1.0); +} +</script> +<script id='fshadernamedarray' type='x-shader/x-fragment'>#version 300 es +precision mediump float; +layout(location=0) out vec4 oColor; + +uniform UBOData { + float Red; + float Green; + float Blue; +} UBOA[2]; + +void main() +{ + oColor = vec4((UBOA[0].Red + UBOA[1].Red) / 2.0, + (UBOA[0].Green + UBOA[1].Green) / 2.0, + (UBOA[0].Blue + UBOA[1].Blue) / 2.0, 1.0); +} +</script> +</head> +<body> +<div id="description"></div> +<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> +<div id="console"></div> +<script> +"use strict"; +description("This test verifies the functionality of the Uniform Buffer objects"); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var b1 = null; +var b2 = null; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + runBindingTest(); + runDrawTest(); + runNamedDrawTest(); + runNamedArrayDrawTest(); +} + +function runBindingTest() { + debug(""); + debug("Testing uniform buffer binding behavior"); + shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "UNIFORM_BUFFER_BINDING query should succeed"); + + debug("Testing basic uniform buffer binding and unbinding"); + b1 = gl.createBuffer(); + b2 = gl.createBuffer(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createBuffer should not set an error"); + shouldBeNonNull("b1"); + shouldBeNonNull("b2"); + gl.bindBuffer(gl.UNIFORM_BUFFER, b1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to bind uniform buffer"); + shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "b1"); + gl.bindBuffer(gl.UNIFORM_BUFFER, b2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to update uniform buffer binding"); + shouldBe("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)", "b2"); + gl.bindBuffer(gl.UNIFORM_BUFFER, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to unbind uniform buffer"); + + debug("Testing deleting uniform buffers"); + gl.deleteBuffer(b1); + gl.deleteBuffer(b2); + shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); + + // Shouldn't be able to bind a deleted buffer. + gl.bindBuffer(gl.UNIFORM_BUFFER, b2); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted buffer should generate INVALID_OPERATION"); + shouldBeNull("gl.getParameter(gl.UNIFORM_BUFFER_BINDING)"); +} + +function runDrawTest() { + debug(""); + debug("Testing drawing with uniform buffers"); + + wtu.setupUnitQuad(gl); + + var testProgram = wtu.setupProgram(gl, ['vshader', 'fbadshader']); + if (testProgram) { + testFailed("To define the same uniform in two uniform blocks should fail"); + } else { + testPassed("To define the same uniform in two uniform blocks should fail"); + } + + var program = wtu.setupProgram(gl, ['vshader', 'fshader']); + if (!program) { + testFailed("Could not compile shader with uniform blocks without error"); + return; + } + + var blockIndex_1 = gl.getUniformBlockIndex(program, "UBOData"); + var blockSize_1 = gl.getActiveUniformBlockParameter(program, blockIndex_1, gl.UNIFORM_BLOCK_DATA_SIZE); + var uniformIndices_1 = gl.getUniformIndices(program, ["UBORed", "UBOGreen", "UBOBlue"]); + var uniformOffsets_1 = gl.getActiveUniforms(program, uniformIndices_1, gl.UNIFORM_OFFSET); + var blockIndex_2 = gl.getUniformBlockIndex(program, "UBOD"); + var blockSize_2 = gl.getActiveUniformBlockParameter(program, blockIndex_2, gl.UNIFORM_BLOCK_DATA_SIZE); + var uniformIndices_2 = gl.getUniformIndices(program, ["UBOR", "UBOG", "UBOB"]); + var uniformOffsets_2 = gl.getActiveUniforms(program, uniformIndices_2, gl.UNIFORM_OFFSET); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error"); + + if (uniformOffsets_1.length < 3 || uniformOffsets_2.length < 3) { + testFailed("Could not query uniform offsets"); + return; + } + + // Verify that the uniform offsets are aligned on 4-byte boundries + // While unaligned values are allowed by the ES3 spec it would be *really* weird for anyone to actually do that. + if (uniformOffsets_1[0] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets_1[0] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets_1[1] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets_1[1] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets_1[2] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets_1[2] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets_2[0] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets_2[0] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets_2[1] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets_2[1] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets_2[2] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets_2[2] / Float32Array.BYTES_PER_ELEMENT)) { + testFailed("Uniform offsets are not well aligned"); + return; + } + + var uboArray_1 = new ArrayBuffer(blockSize_1); + var uboFloatView_1 = new Float32Array(uboArray_1); + uboFloatView_1[uniformOffsets_1[0] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBORed + uboFloatView_1[uniformOffsets_1[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOGreen + uboFloatView_1[uniformOffsets_1[2] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOBlue + var uboArray_2 = new ArrayBuffer(blockSize_2); + var uboFloatView_2 = new Float32Array(uboArray_2); + uboFloatView_2[uniformOffsets_2[0] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBOR + uboFloatView_2[uniformOffsets_2[1] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBOG + uboFloatView_2[uniformOffsets_2[2] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBOB + + var b_1 = gl.createBuffer(); + gl.bindBuffer(gl.UNIFORM_BUFFER, b_1); + gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView_1, gl.DYNAMIC_DRAW); + var b_2 = gl.createBuffer(); + gl.bindBuffer(gl.UNIFORM_BUFFER, b_2); + gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView_2, gl.DYNAMIC_DRAW); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors"); + + var bindings = [1, 2]; + gl.uniformBlockBinding(program, blockIndex_1, bindings[0]); + gl.bindBufferBase(gl.UNIFORM_BUFFER, bindings[0], b_1); + gl.uniformBlockBinding(program, blockIndex_2, bindings[1]); + gl.bindBufferBase(gl.UNIFORM_BUFFER, bindings[1], b_2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferBase without errors"); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2); + + debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call"); + uboFloatView_1[uniformOffsets_1[0] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBORed + uboFloatView_1[uniformOffsets_1[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // UBOGreen + uboFloatView_1[uniformOffsets_1[2] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // UBOBlue + gl.bindBuffer(gl.UNIFORM_BUFFER, b_1); + gl.bufferData(gl.UNIFORM_BUFFER, uboFloatView_1, gl.DYNAMIC_DRAW); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [0, 0, 255, 255], "draw call should set canvas to blue", 2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function runNamedDrawTest() { + debug(""); + debug("Testing drawing with named uniform buffers"); + + wtu.setupUnitQuad(gl); + + var program = wtu.setupProgram(gl, ['vshader', 'fshadernamed']); + if (!program) { + testFailed("Could not compile shader with named uniform blocks without error"); + } + + var blockIndex = gl.getUniformBlockIndex(program, "UBOData"); + var blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE); + var uniformIndices = gl.getUniformIndices(program, ["UBOData.Red", "UBOData.Green", "UBOData.Blue"]); + var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error"); + + if (uniformOffsets.length < 3) { + testFailed("Could not query uniform offsets"); + return; + } + + // Verify that the uniform offsets are aligned on 4-byte boundries + // While unaligned values are allowed by the ES3 spec it would be *really* weird for anyone to actually do that. + if (uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT)) { + testFailed("Uniform offsets are not well aligned"); + return; + } + + var uboArray = new ArrayBuffer(blockSize); + var uboFloatView = new Float32Array(uboArray); + uboFloatView[uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Red + uboFloatView[uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Green + uboFloatView[uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Blue + + b1 = gl.createBuffer(); + gl.bindBuffer(gl.UNIFORM_BUFFER, b1); + gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors"); + + var binding = 3; + gl.uniformBlockBinding(program, blockIndex, binding); + gl.bindBufferBase(gl.UNIFORM_BUFFER, binding, b1); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferBase without errors"); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [255, 0, 0, 255], "draw call should set canvas to red", 2); + + debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call"); + uboFloatView[uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Red + uboFloatView[uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Green + uboFloatView[uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Blue + gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [0, 0, 255, 255], "draw call should set canvas to blue", 2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function runNamedArrayDrawTest() { + debug(""); + debug("Testing drawing with named uniform buffer arrays"); + + wtu.setupUnitQuad(gl); + + var program = wtu.setupProgram(gl, ['vshader', 'fshadernamedarray']); + if (!program) { + testFailed("could not compile shader with named uniform block arrays without error"); + return; + } + + var blockIndex = [gl.getUniformBlockIndex(program, "UBOData[0]"), + gl.getUniformBlockIndex(program, "UBOData[1]")]; + if (blockIndex[0] == gl.INVALID_INDEX || + blockIndex[1] == gl.INVALID_INDEX) { + testFailed("Could not query uniform block index"); + return; + } + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block indices without error"); + var blockSize = [gl.getActiveUniformBlockParameter(program, blockIndex[0], gl.UNIFORM_BLOCK_DATA_SIZE), + gl.getActiveUniformBlockParameter(program, blockIndex[1], gl.UNIFORM_BLOCK_DATA_SIZE)]; + if (blockSize[0] != blockSize[1]) { + testFailed("uniform block instance array with different block sizes"); + } + var uniformIndices = gl.getUniformIndices(program, ["UBOData.Red", "UBOData.Green", "UBOData.Blue"]); + if (uniformIndices < 3 || + uniformIndices[0] == gl.INVALID_INDEX || + uniformIndices[1] == gl.INVALID_INDEX || + uniformIndices[2] == gl.INVALID_INDEX) { + testFailed("Could not query uniform indices"); + return; + } + var uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to query uniform block information without error"); + if (uniformOffsets.length < 3) { + testFailed("Could not query uniform offsets"); + return; + } + + var offsetAlignment = gl.getParameter(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT); + var offset = Math.ceil(blockSize[0] / offsetAlignment) * offsetAlignment; + // Verify that the uniform offsets are aligned on 4-byte boundries + // While unaligned values are allowed by the ES3 spec it would be *really* weird for anyone to actually do that. + if (offset / Float32Array.BYTES_PER_ELEMENT != Math.floor(offset / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT) || + uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT != Math.floor(uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT)) { + testFailed("Uniform offsets are not well aligned"); + return; + } + var bufferSize = offset + blockSize[1]; + var uboArray = new ArrayBuffer(bufferSize); + var uboFloatView = new Float32Array(uboArray); + uboFloatView[uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Red + uboFloatView[uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Green + uboFloatView[uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Blue + uboFloatView[offset / Float32Array.BYTES_PER_ELEMENT + + uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Red + uboFloatView[offset / Float32Array.BYTES_PER_ELEMENT + + uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Green + uboFloatView[offset / Float32Array.BYTES_PER_ELEMENT + + uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Blue + + b1 = gl.createBuffer(); + gl.bindBuffer(gl.UNIFORM_BUFFER, b1); + gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to set UBO data with no errors"); + + var bindings = [4, 5]; + gl.uniformBlockBinding(program, blockIndex[0], bindings[0]); + gl.bindBufferRange(gl.UNIFORM_BUFFER, bindings[0], b1, 0, blockSize[0]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferRange without errors"); + gl.uniformBlockBinding(program, blockIndex[1], bindings[1]); + gl.bindBufferRange(gl.UNIFORM_BUFFER, bindings[1], b1, offset, blockSize[1]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be able to call bindBufferRange without errors"); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [127, 0, 127, 255], "draw call should set canvas to (0.5, 0, 0.5)", 2); + + debug("Changing the data in the uniform buffer should automatically update the uniforms exposed to the draw call"); + uboFloatView[uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Red + uboFloatView[uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Green + uboFloatView[uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Blue + uboFloatView[offset / Float32Array.BYTES_PER_ELEMENT + + uniformOffsets[0] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Red + uboFloatView[offset / Float32Array.BYTES_PER_ELEMENT + + uniformOffsets[1] / Float32Array.BYTES_PER_ELEMENT] = 0.0; // Green + uboFloatView[offset / Float32Array.BYTES_PER_ELEMENT + + uniformOffsets[2] / Float32Array.BYTES_PER_ELEMENT] = 1.0; // Blue + gl.bufferData(gl.UNIFORM_BUFFER, uboArray, gl.DYNAMIC_DRAW); + + wtu.clearAndDrawUnitQuad(gl); + wtu.checkCanvas(gl, [0, 127, 255, 255], "draw call should set canvas to (0, 0.5, 1)", 2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +debug(""); +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> + +</body> +</html> |