2 Copyright (c) 2019 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.
10 <link rel=
"stylesheet" href=
"../../resources/js-test-style.css"/>
11 <script src=
"../../js/js-test-pre.js"></script>
12 <script src=
"../../js/webgl-test-utils.js"></script>
13 <title>WebGL Out-of-Bounds Index Buffer Conformance Test
</title>
16 <canvas id=
"canvas" width=
"8" height=
"8" style=
"width: 100px; height: 100px;"></canvas>
17 <div id=
"description"></div>
18 <div id=
"console"></div>
19 <script id=
"vsCheckOutOfBounds" type=
"x-shader/x-vertex">
20 precision mediump float;
21 attribute vec2 position;
22 attribute vec4 vecRandom;
25 // Per the spec, each component can either contain existing contents
26 // of the buffer or
0.
27 bool testFloatComponent(float component) {
28 return (component ==
0.2 || component ==
0.0);
30 // The last component is additionally allowed to be
1.0.
31 bool testLastFloatComponent(float component) {
32 return testFloatComponent(component) || component ==
1.0;
36 if (testFloatComponent(vecRandom.x) &&
37 testFloatComponent(vecRandom.y) &&
38 testFloatComponent(vecRandom.z) &&
39 testLastFloatComponent(vecRandom.w)) {
40 v_color = vec4(
0.0,
1.0,
0.0,
1.0); // green -- We're good
42 v_color = vec4(
1.0,
0.0,
0.0,
1.0); // red -- Unexpected value
44 gl_Position = vec4(position,
0.0,
1.0);
49 description("This test verifies that out-of-bounds index buffers behave according to spec.");
51 // Prepare an element array buffer that indexes out-of-bounds beginning with the start index passed in.
52 // Ensure that drawElements flags either no error or INVALID_OPERATION. In the case of INVALID_OPERATION,
53 // no canvas pixels can be touched. In the case of NO_ERROR, all written values must either be the
54 // zero vertex or a value in the vertex buffer. See vsCheckOutOfBounds shader.
55 function drawAndVerifyOutOfBoundsIndex(gl
, startIndex
) {
56 gl
.clearColor(0.0, 0.0, 1.0, 1.0); // Start with blue to indicate no pixels touched.
57 gl
.clear(gl
.COLOR_BUFFER_BIT
| gl
.DEPTH_BUFFER_BIT
);
59 prepareElementArrayBuffer(gl
, /*StartIndex*/startIndex
);
61 gl
.drawElements(gl
.TRIANGLE_STRIP
, 4, gl
.UNSIGNED_SHORT
, /*offset*/0);
62 var error
= gl
.getError();
63 if (error
=== gl
.INVALID_OPERATION
) {
64 testPassed("drawElements flagged INVALID_OPERATION, which is valid so long as all canvas pixels were not touched.");
65 wtu
.checkCanvas(gl
, [0, 0, 255, 255]);
66 } else if (error
=== gl
.NO_ERROR
) {
67 testPassed("drawElements flagged NO_ERROR, which is valid so long as all canvas pixels are green.");
68 wtu
.checkCanvas(gl
, [0, 255, 0, 255]);
70 testFailed("Invalid error flagged by drawElements. Should be INVALID_OPERATION or NO_ERROR");
74 // Create an element array buffer with a tri-strip that starts at startIndex and make
75 // it the active element array buffer.
76 function prepareElementArrayBuffer(gl
, startIndex
) {
77 var glElementArrayBuffer
= gl
.createBuffer();
78 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, glElementArrayBuffer
);
79 var quadIndices
= new Uint16Array(4);
80 for (var i
= 0; i
< quadIndices
.length
; i
++) {
81 quadIndices
[i
] = startIndex
+ i
;
83 gl
.bufferData(gl
.ELEMENT_ARRAY_BUFFER
, quadIndices
, gl
.STATIC_DRAW
);
87 var wtu
= WebGLTestUtils
;
88 var canvas
= document
.getElementById("canvas");
89 var gl
= wtu
.create3DContext(canvas
, {antialias
: false});
91 var numberOfQuads
= 200;
93 // Create a vertex buffer with 200 properly formed tri-strip quads. These quads will cover the canvas texture
94 // such that every single pixel is touched by the fragment shader.
95 var glQuadBuffer
= gl
.createBuffer();
96 gl
.bindBuffer(gl
.ARRAY_BUFFER
, glQuadBuffer
);
97 var quadPositions
= new Float32Array(numberOfQuads
* /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4);
98 for (var i
= 0; i
< quadPositions
.length
; i
+= /*ComponentsPerQuad*/2 * /*VerticesPerQuad*/4) {
99 quadPositions
[i
+0] = -1.0; // upper left
100 quadPositions
[i
+1] = 1.0;
101 quadPositions
[i
+2] = 1.0; // upper right
102 quadPositions
[i
+3] = 1.0;
103 quadPositions
[i
+4] = -1.0; // lower left
104 quadPositions
[i
+5] = -1.0;
105 quadPositions
[i
+6] = 1.0; // lower right
106 quadPositions
[i
+7] = -1.0;
108 gl
.bufferData(gl
.ARRAY_BUFFER
, quadPositions
, gl
.STATIC_DRAW
);
109 gl
.enableVertexAttribArray(0);
110 gl
.vertexAttribPointer(0, 2, gl
.FLOAT
, false, 0, 0);
112 // Create a small vertex buffer with determined-ahead-of-time "random" values (0.2). This buffer will be
113 // the one indexed off the end.
114 var glVertexBuffer
= gl
.createBuffer();
115 gl
.bindBuffer(gl
.ARRAY_BUFFER
, glVertexBuffer
);
116 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([0.2, 0.2, 0.2, 0.2]), gl
.STATIC_DRAW
);
117 gl
.enableVertexAttribArray(1);
118 gl
.vertexAttribPointer(1, 4, gl
.FLOAT
, false, 0, 0);
120 // Setup the verification program.
121 var glProgram
= wtu
.setupProgram(gl
, ["vsCheckOutOfBounds", wtu
.simpleVertexColorFragmentShader
], ["position", "vecRandom"]);
122 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "Shader and buffer setup should not generate errors");
124 debug("Test -- Index off the end of the vertex buffer near the beginning of the out of bounds area.");
125 drawAndVerifyOutOfBoundsIndex(gl
, /*StartIndex*/4);
129 debug("Test -- Index off the end of the vertex buffer near the end of the out of bounds area.")
130 drawAndVerifyOutOfBoundsIndex(gl
, /*StartIndex*/numberOfQuads
- 4);
132 var successfullyParsed
= true;
134 <script src=
"../../js/js-test-post.js"></script>