Skip to content

Commit 841dcad

Browse files
committed
Test WEBGL_multi_draw with offsets 2 GB into a 4 GB typed array.
Test case for Chromium bug https://crbug.com/395670641 and Emscripten bug emscripten-core/emscripten#17539 .
1 parent c000377 commit 841dcad

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

sdk/tests/conformance2/wasm/00_test_list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
--min-version 2.0.1 getbuffersubdata-2gb-in-4gb-wasm-memory.html
88
--min-version 2.0.1 getbuffersubdata-4gb-wasm-memory.html
99
--min-version 2.0.1 getbuffersubdata-16gb-wasm-memory.html
10+
--min-version 2.0.1 multi-draw-2gb-in-4gb-wasm-memory.html
1011
--min-version 2.0.1 readpixels-2gb-in-4gb-wasm-memory.html
1112
--min-version 2.0.1 readpixels-4gb-wasm-memory.html
1213
--min-version 2.0.1 readpixels-16gb-wasm-memory.html
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
<!--
2+
Copyright (c) 2025 The Khronos Group Inc.
3+
Use of this source code is governed by an MIT-style license that can be
4+
found in the LICENSE.txt file.
5+
-->
6+
<!DOCTYPE html>
7+
<html>
8+
<head>
9+
<meta charset="utf-8">
10+
<title>Multi-draw test 2GB within Wasm Memory 4GB in size.</title>
11+
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
12+
<script src="../../js/js-test-pre.js"></script>
13+
<script src="../../js/webgl-test-utils.js"> </script>
14+
</head>
15+
<body>
16+
<canvas id="canvas" width="16" height="16" style="width: 64px; height: 64px;"></canvas>
17+
<div id="description"></div>
18+
<div id="console"></div>
19+
<script>
20+
"use strict";
21+
description(document.title);
22+
debug("Tests that WEBGL_multi_draw can be called with ArrayBuffer views ~2GB into ~4GB of WebAssembly Memory.");
23+
debug("");
24+
let wtu = WebGLTestUtils;
25+
let gl = wtu.create3DContext("canvas", undefined, 2);
26+
27+
const canvasSize = 16;
28+
const PAGE = 65536;
29+
const HEAP_SIZE = 4 * 1024 * 1024 * 1024 - PAGE;
30+
const VIEW_SIZE = 2 * 1024 * 1024 * 1024 - PAGE;
31+
32+
(() => {
33+
let md = gl.getExtension("WEBGL_multi_draw");
34+
if (!md) {
35+
testPassed("WEBGL_multi_draw extension is not supported - this is legal");
36+
return;
37+
}
38+
39+
// Red rectangle (two triangles) on the left, green on the right
40+
41+
let vertexData = new Float32Array([
42+
// Left rectangle
43+
-1.0, -1.0,
44+
0.0, -1.0,
45+
0.0, 1.0,
46+
-1.0, 1.0,
47+
-1.0, -1.0,
48+
0.0, 1.0,
49+
50+
// Right rectangle
51+
0.0, -1.0,
52+
1.0, -1.0,
53+
1.0, 1.0,
54+
0.0, 1.0,
55+
0.0, -1.0,
56+
1.0, 1.0
57+
]);
58+
59+
let colorData = new Uint8Array([
60+
255, 0, 0, 255,
61+
255, 0, 0, 255,
62+
255, 0, 0, 255,
63+
255, 0, 0, 255,
64+
255, 0, 0, 255,
65+
255, 0, 0, 255,
66+
67+
0, 255, 0, 255,
68+
0, 255, 0, 255,
69+
0, 255, 0, 255,
70+
0, 255, 0, 255,
71+
0, 255, 0, 255,
72+
0, 255, 0, 255,
73+
]);
74+
75+
let indexData = new Uint16Array([
76+
0, 1, 2,
77+
3, 4, 5,
78+
6, 7, 8,
79+
9, 10, 11
80+
]);
81+
82+
const positionLocation = 0;
83+
const colorLocation = 1;
84+
const tolerance = 1;
85+
86+
let buf = gl.createBuffer();
87+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
88+
gl.bufferData(gl.ARRAY_BUFFER, vertexData, gl.STATIC_DRAW);
89+
gl.enableVertexAttribArray(positionLocation);
90+
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
91+
92+
buf = gl.createBuffer();
93+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
94+
gl.bufferData(gl.ARRAY_BUFFER, colorData, gl.STATIC_DRAW);
95+
gl.enableVertexAttribArray(colorLocation);
96+
gl.vertexAttribPointer(colorLocation, 4, gl.UNSIGNED_BYTE, true, 0, 0);
97+
98+
buf = gl.createBuffer();
99+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
100+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
101+
102+
let program = wtu.setupSimpleVertexColorProgram(gl, positionLocation, colorLocation);
103+
104+
// Set up the "firsts" and "counts" data at the end of the heap
105+
let view;
106+
try {
107+
view = new Int32Array(new WebAssembly.Memory({ initial: HEAP_SIZE / PAGE }).buffer, 0, VIEW_SIZE / Int32Array.BYTES_PER_ELEMENT);
108+
} catch (e) {
109+
testPassed(`Allocating ${HEAP_SIZE} threw: ${e}`);
110+
return;
111+
}
112+
113+
function setupMultiDrawInHeap(typedArray) {
114+
gl.clear(gl.COLOR_BUFFER_BIT);
115+
const length = typedArray.length;
116+
const offset = view.length - length;
117+
view.set(typedArray, offset);
118+
return offset;
119+
}
120+
121+
function checkResult() {
122+
// Check center of all four quadrants of the canvas, because there was a bug in the test where it passed when only
123+
// checking the center of both rectangles.
124+
wtu.checkCanvasRect(gl, canvasSize / 4, canvasSize / 4, 1, 1, wtu.namedColorInColorSpace("Red", "srgb"), "lower left should be red", tolerance);
125+
wtu.checkCanvasRect(gl, canvasSize / 4, 3 * canvasSize / 4, 1, 1, wtu.namedColorInColorSpace("Red", "srgb"), "upper left should be red", tolerance);
126+
wtu.checkCanvasRect(gl, 3 * (canvasSize / 4), canvasSize / 4, 1, 1, wtu.namedColorInColorSpace("Green", "srgb"), "lower right should be green", tolerance);
127+
wtu.checkCanvasRect(gl, 3 * (canvasSize / 4), 3 * canvasSize / 4, 1, 1, wtu.namedColorInColorSpace("Green", "srgb"), "upper right should be green", tolerance);
128+
}
129+
130+
function testDraw(name, args) {
131+
try {
132+
debug('Testing ' + name);
133+
md[name](...args);
134+
checkResult();
135+
} catch (e) {
136+
testFailed(name + ' failed: ' + e);
137+
}
138+
}
139+
140+
const numDraws = 2;
141+
142+
let offset = setupMultiDrawInHeap(new Int32Array([0, 6, 6, 6]));
143+
testDraw('multiDrawArraysWEBGL', [gl.TRIANGLES, view, offset, view, offset + numDraws, numDraws]);
144+
145+
offset = setupMultiDrawInHeap(new Int32Array([6, 6, 0, 6 * Uint16Array.BYTES_PER_ELEMENT]));
146+
testDraw('multiDrawElementsWEBGL', [gl.TRIANGLES, view, offset, gl.UNSIGNED_SHORT, view, offset + numDraws, numDraws]);
147+
148+
offset = setupMultiDrawInHeap(new Int32Array([0, 6, 6, 6, 1, 1]));
149+
testDraw('multiDrawArraysInstancedWEBGL', [gl.TRIANGLES, view, offset, view, offset + numDraws, view, offset + 2 * numDraws, numDraws]);
150+
151+
offset = setupMultiDrawInHeap(new Int32Array([6, 6, 0, 6 * Uint16Array.BYTES_PER_ELEMENT, 1, 1]));
152+
testDraw('multiDrawElementsInstancedWEBGL', [gl.TRIANGLES, view, offset, gl.UNSIGNED_SHORT, view, offset + numDraws, view, offset + 2 * numDraws, numDraws]);
153+
154+
})();
155+
156+
var successfullyParsed = true;
157+
</script>
158+
<script src="../../js/js-test-post.js"></script>
159+
</body>
160+
</html>

0 commit comments

Comments
 (0)