<!DOCTYPE html>
<html crossorigin>
<head>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script type="x-shader/x-vertex" id="vertex">
#version 100
uniform mat4 overflow;
void main() {
gl_Position = overflow * vec4(0.11, 0.22, 0.33, 1.0);
}
</script>
<script type="x-shader/x-fragment" id="fragment">
#version 100
void main() {
gl_FragColor = vec4(0.11, 0.22, 0.33, 1.0);
}
</script>
</head>
<body>
<canvas id="canvas1" width="64px" height="64px">
</canvas>
<script>
test(() => {
const kWasmPage = 1 << 16;
const kNumPages = 33000;
const kMemSizeInBytes = kNumPages * kWasmPage;
const kMemSizeInWords = kMemSizeInBytes / 4;
// Maximum allowed size of an ArrayBuffer as defined by PartitionAlloc.
const kArrayBufferSizeLimitInBytes = 2145386496;
let mem;
try {
mem = new WebAssembly.Memory({initial: kNumPages, maximum: kNumPages});
} catch (e) {
// We failed to allocate the WebAssembly memory. We can just return.
assert_equals(e.constructor, RangeError);
assert_equals(e.message,
"WebAssembly.Memory(): could not allocate memory");
return;
}
let canvas = document.getElementById("canvas1");
let gl = canvas.getContext("webgl2");
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.querySelector("#vertex").innerHTML);
gl.compileShader(vertexShader);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.querySelector("#fragment").innerHTML);
gl.compileShader(fragmentShader);
let program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
overflow = gl.getUniformLocation(program, "overflow");
gl.useProgram(program);
let fData = new Float32Array(mem.buffer, 8);
let iData = new Int32Array(mem.buffer, 8);
let uData = new Uint32Array(mem.buffer, 8);
let u8Data = new Uint8Array(mem.buffer, 8);
const kTooBigBufferData = (kArrayBufferSizeLimitInBytes / 4) + 32;
let tooBigView = new Uint32Array(mem.buffer, 8, kTooBigBufferData);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, tooBigView, gl.STATIC_READ);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.bufferData(gl.ARRAY_BUFFER, mem.buffer, gl.STATIC_READ);
assert_not_equals(gl.getError(), gl.NO_ERROR);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, tooBigView);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, mem.buffer);
assert_not_equals(gl.getError(), gl.NO_ERROR);
gl.bufferData(gl.ARRAY_BUFFER, iData, gl.STATIC_READ, 16, 1296);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.bufferData(gl.ARRAY_BUFFER, iData, gl.STATIC_READ, 16, kTooBigBufferData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, iData, 16, 1296);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, iData, 16, kTooBigBufferData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.getBufferSubData(gl.ARRAY_BUFFER, 0, iData, 16, 1296);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.getBufferSubData(gl.ARRAY_BUFFER, 0, iData, 16, kTooBigBufferData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
// TODO(crbug.com/1353652): Make the following `uniform*` operations pass.
gl.uniform1fv(overflow, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform2fv(overflow, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform3fv(overflow, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform4fv(overflow, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform1iv(overflow, iData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform2iv(overflow, iData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform3iv(overflow, iData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform4iv(overflow, iData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform1uiv(overflow, uData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform2uiv(overflow, uData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform3uiv(overflow, uData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniform4uiv(overflow, uData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix2fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix3fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix4fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix2x3fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix3x2fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix2x4fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix4x2fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix3x4fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.uniformMatrix4x3fv(overflow, false, fData, 16, 1296);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
const kTooBigInWords = kMemSizeInWords - 32;
gl.uniform1fv(overflow, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform2fv(overflow, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform3fv(overflow, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform4fv(overflow, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform1iv(overflow, iData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform2iv(overflow, iData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform3iv(overflow, iData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform4iv(overflow, iData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix2fv(overflow, false, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix3fv(overflow, false, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix4fv(overflow, false, fData);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform1fv(overflow, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform2fv(overflow, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform3fv(overflow, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform4fv(overflow, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform1iv(overflow, iData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform2iv(overflow, iData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform3iv(overflow, iData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform4iv(overflow, iData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform1uiv(overflow, uData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform2uiv(overflow, uData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform3uiv(overflow, uData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniform4uiv(overflow, uData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix2fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix3fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix4fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix2x3fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix3x2fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix2x4fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix4x2fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix3x4fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.uniformMatrix4x3fv(overflow, false, fData, 16, kTooBigInWords);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.vertexAttrib1fv(0, fData);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.vertexAttrib2fv(0, fData);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.vertexAttrib3fv(0, fData);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.vertexAttrib4fv(0, fData);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.vertexAttribI4iv(0, iData);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.vertexAttribI4uiv(0, uData);
assert_equals(gl.getError(), gl.NO_ERROR);
const clear_offset = kMemSizeInWords - 100;
gl.clearBufferfv(gl.COLOR, 0, fData);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.clearBufferfv(gl.COLOR, 0, fData, clear_offset);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Make the following `clearBuffer*` operations pass.
gl.clearBufferiv(gl.COLOR, 0, iData);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.clearBufferiv(gl.COLOR, 0, iData, clear_offset);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.clearBufferuiv(gl.COLOR, 0, uData);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
gl.clearBufferuiv(gl.COLOR, 0, uData, clear_offset);
assert_equals(gl.getError(), gl.INVALID_OPERATION);
// The read data (8x12=96) should still fit in.
const read_offset = kMemSizeInWords - 100;
const too_big_width = 16895999;
const too_big_height_in_words = 32;
const too_big_height_in_bytes = 128;
assert_greater_than(too_big_width * too_big_height_in_words,
kArrayBufferSizeLimitInBytes / 4);
gl.readPixels(0, 0, 8, 12, gl.RGBA, gl.UNSIGNED_BYTE, u8Data);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.readPixels(0, 0, too_big_width, too_big_height_in_words, gl.RGBA, gl.UNSIGNED_BYTE, u8Data);
assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.readPixels(0, 0, 8, 12, gl.RGBA, gl.UNSIGNED_BYTE, u8Data, 16);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.readPixels(0, 0, 8, 12, gl.RGBA, gl.UNSIGNED_BYTE, u8Data, read_offset);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.readPixels(0, 0, too_big_width, too_big_height_in_words, gl.RGBA, gl.UNSIGNED_BYTE, u8Data, 4);
assert_equals(gl.getError(), gl.INVALID_VALUE);
let texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 8, 12, 0, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texImage2D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, too_big_width,
// too_big_height_in_bytes, 0, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 8, 12, 0, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, 16);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 8, 12, 0, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, read_offset);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test to texImage2D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, too_big_width,
// too_big_height_in_bytes, 0, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data, 16);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 8, 12, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texSubImage2D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, too_big_width,
// too_big_height_in_bytes, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 8, 12, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, 16);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 8, 12, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, read_offset);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texSubImage2D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, too_big_width,
// too_big_height_in_bytes, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data, 16);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_3D, texture);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 8, 12, 6, 0, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texImage3D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, too_big_width,
// too_big_height_in_bytes, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 8, 12, 6, 0, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, 16);
assert_equals(gl.getError(), gl.NO_ERROR);
gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, 8, 12, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, read_offset);
assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texImage3D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA, too_big_width,
// too_big_height_in_bytes, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data, 16);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 8, 12, 6, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, 16);
// assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texSubImage3D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, too_big_width,
// too_big_height_in_bytes, 1, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
// TODO(crbug.com/1353652): Fix the following tests of texSubImage3D so that
// they pass without error. At the moment they pass the ArrayBuffer size check
// but fail in the webgl backend.
gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 8, 12, 6, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, 16);
// assert_equals(gl.getError(), gl.NO_ERROR);
gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, 8, 12, 1, gl.RGBA, gl.UNSIGNED_BYTE,
u8Data, read_offset);
// assert_equals(gl.getError(), gl.NO_ERROR);
// TODO(crbug.com/1353652): Fix this test of texSubImage3D so that more data than
// kArrayBufferSizeLimitInBytes is required. This should result in
// INVALID_VALUE.
// gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, 0, too_big_width,
// too_big_height_in_bytes, gl.RGBA, gl.UNSIGNED_BYTE,
// u8Data, 16);
// assert_equals(gl.getError(), gl.INVALID_VALUE);
// TODO(crbug.com/1353652): Add tests for the following functions:
// * webgl's compressedTexImage2D
// * webgl2's compressedTexImage2D
// * webgl's compressedTexSubImage2D
// * webgl2's compressedTexSubImage2D
// * compressedTexImage3D
// * compressedTexSubImage3D
}, "Test that webgl accepts a small view of ArrayBuffer bigger than 2GB.");
</script>
</body>
</html>