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 <meta charset=
"utf-8">
11 <title>WebGL Instanced Arrays Conformance Tests
</title>
12 <link rel=
"stylesheet" href=
"../../resources/js-test-style.css"/>
13 <script src=
"../../js/desktop-gl-constants.js"></script>
14 <script src=
"../../js/js-test-pre.js"></script>
15 <script src=
"../../js/webgl-test-utils.js"></script>
18 <div id=
"description"></div>
19 <canvas id=
"canvas" style=
"width: 128px; height: 128px;"> </canvas>
20 <div id=
"console"></div>
21 <script id=
"outputVertexShader" type=
"x-shader/x-vertex">#version
300 es
22 in highp vec2 aPosition;
23 in highp float aOffset;
24 in highp float aColor;
25 out mediump float vColor;
27 gl_Position = vec4(aPosition,
0.0,
1.0) + vec4(aOffset,
0.0,
0.0,
0.0);
32 <script id=
"outputFragmentShader" type=
"x-shader/x-fragment">#version
300 es
33 layout(location =
0) out mediump vec4 oColor;
34 in mediump float vColor;
36 oColor = vec4(vColor,
0.0,
0.0,
1.0);
42 description("This test verifies a bug related with instanced rendering on Mac AMD.");
43 debug("http://crbug.com/645298");
47 var wtu
= WebGLTestUtils
;
48 var canvas
= document
.getElementById("canvas");
49 var gl
= wtu
.create3DContext(canvas
, null, 2);
51 // The second and fourth test cases fail - it seems if the divisor doesn't change,
52 // the next instanced draw call behaves incorrectly.
53 // Also note that if we don't perform a readPixels (in wtu.checkCanvasRect), the bug
56 { instanceCount
: 8, divisor
: 4 },
57 { instanceCount
: 6, divisor
: 4 },
58 { instanceCount
: 6, divisor
: 3 },
59 { instanceCount
: 8, divisor
: 3 },
63 testFailed("WebGL context does not exist");
65 testPassed("WebGL context exists");
67 for (var ii
= 0; ii
< testCases
.length
; ++ii
) {
68 runDrawArraysTest(testCases
[ii
].instanceCount
, testCases
[ii
].divisor
);
71 for (var ii
= 0; ii
< testCases
.length
; ++ii
) {
72 runDrawElementsTest(testCases
[ii
].instanceCount
, testCases
[ii
].divisor
);
76 function runDrawArraysTest(instanceCount
, divisor
) {
78 debug("Testing drawArraysInstanced: instanceCount = " + instanceCount
+ ", divisor = " + divisor
);
80 gl
.viewport(0, 0, canvas
.width
, canvas
.height
);
82 var vao
= gl
.createVertexArray();
83 gl
.bindVertexArray(vao
);
85 var program
= wtu
.setupProgram(gl
, ["outputVertexShader", "outputFragmentShader"]);
86 var positionLoc
= gl
.getAttribLocation(program
, "aPosition");
87 var offsetLoc
= gl
.getAttribLocation(program
, "aOffset");
88 var colorLoc
= gl
.getAttribLocation(program
, "aColor");
89 if (!program
|| positionLoc
< 0 || offsetLoc
< 0 || colorLoc
< 0) {
90 testFailed("Set up program failed");
93 testPassed("Set up program succeeded");
95 var scale
= 1.0 / instanceCount
;
97 gl
.enableVertexAttribArray(positionLoc
);
98 gl
.vertexAttribDivisor(positionLoc
, 0);
99 var positions
= new Float32Array([
107 var positionBuffer
= gl
.createBuffer();
108 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
109 gl
.bufferData(gl
.ARRAY_BUFFER
, positions
, gl
.STATIC_DRAW
);
110 gl
.vertexAttribPointer(positionLoc
, 2, gl
.FLOAT
, false, 0, 0);
112 gl
.enableVertexAttribArray(offsetLoc
);
113 gl
.vertexAttribDivisor(offsetLoc
, 1);
114 var offsets
= new Float32Array(instanceCount
);
115 for (var ii
= 0; ii
< instanceCount
; ++ii
) {
116 offsets
[ii
] = scale
* (1 - instanceCount
+ ii
* 2);
118 var offsetBuffer
= gl
.createBuffer();
119 gl
.bindBuffer(gl
.ARRAY_BUFFER
, offsetBuffer
);
120 gl
.bufferData(gl
.ARRAY_BUFFER
, offsets
, gl
.STATIC_DRAW
);
121 gl
.vertexAttribPointer(offsetLoc
, 1, gl
.FLOAT
, false, 0, 0);
123 gl
.enableVertexAttribArray(colorLoc
);
124 gl
.vertexAttribDivisor(colorLoc
, divisor
);
125 var colorCount
= instanceCount
/ divisor
;
126 if ((instanceCount
% divisor
) != 0)
128 var colors
= new Float32Array(colorCount
);
129 for (var ii
= 0; ii
< colorCount
; ++ii
) {
130 colors
[ii
] = 1.0 / colorCount
* (ii
+ 1);
132 var colorBuffer
= gl
.createBuffer();
133 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
134 gl
.bufferData(gl
.ARRAY_BUFFER
, colors
, gl
.STATIC_DRAW
);
135 gl
.vertexAttribPointer(colorLoc
, 1, gl
.FLOAT
, false, 0, 0);
137 gl
.drawArraysInstanced(gl
.TRIANGLES
, 0, 6, instanceCount
);
138 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "drawArraysInstanced should succeed");
141 for (var ii
= 0; ii
< instanceCount
; ++ii
) {
142 if ((ii
% divisor
) == 0)
144 var refColor
= [ Math
.floor(colors
[colorIndex
] * 255), 0, 0, 255 ];
145 wtu
.checkCanvasRect(gl
, Math
.floor(canvas
.width
/ instanceCount
* ii
) + 1, 0, 1, canvas
.height
, refColor
,
146 "instance " + ii
+ " should be " + refColor
, 2);
149 gl
.deleteBuffer(positionBuffer
);
150 gl
.deleteBuffer(offsetBuffer
);
151 gl
.deleteBuffer(colorBuffer
);
152 gl
.deleteProgram(program
);
153 gl
.deleteVertexArray(vao
);
154 gl
.bindBuffer(gl
.ARRAY_BUFFER
, null);
156 gl
.bindVertexArray(null);
157 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "clean up should succeed");
160 function runDrawElementsTest(instanceCount
, divisor
) {
162 debug("Testing drawElementsInstanced: instanceCount = " + instanceCount
+ ", divisor = " + divisor
);
164 gl
.viewport(0, 0, canvas
.width
, canvas
.height
);
166 var vao
= gl
.createVertexArray();
167 gl
.bindVertexArray(vao
);
169 var program
= wtu
.setupProgram(gl
, ["outputVertexShader", "outputFragmentShader"]);
170 var positionLoc
= gl
.getAttribLocation(program
, "aPosition");
171 var offsetLoc
= gl
.getAttribLocation(program
, "aOffset");
172 var colorLoc
= gl
.getAttribLocation(program
, "aColor");
173 if (!program
|| positionLoc
< 0 || offsetLoc
< 0 || colorLoc
< 0) {
174 testFailed("Set up program failed");
177 testPassed("Set up program succeeded");
179 var scale
= 1.0 / instanceCount
;
181 gl
.enableVertexAttribArray(positionLoc
);
182 gl
.vertexAttribDivisor(positionLoc
, 0);
183 var positions
= new Float32Array([
189 var positionBuffer
= gl
.createBuffer();
190 gl
.bindBuffer(gl
.ARRAY_BUFFER
, positionBuffer
);
191 gl
.bufferData(gl
.ARRAY_BUFFER
, positions
, gl
.STATIC_DRAW
);
192 gl
.vertexAttribPointer(positionLoc
, 2, gl
.FLOAT
, false, 0, 0);
194 gl
.enableVertexAttribArray(offsetLoc
);
195 gl
.vertexAttribDivisor(offsetLoc
, 1);
196 var offsets
= new Float32Array(instanceCount
);
197 for (var ii
= 0; ii
< instanceCount
; ++ii
) {
198 offsets
[ii
] = scale
* (1 - instanceCount
+ ii
* 2);
200 var offsetBuffer
= gl
.createBuffer();
201 gl
.bindBuffer(gl
.ARRAY_BUFFER
, offsetBuffer
);
202 gl
.bufferData(gl
.ARRAY_BUFFER
, offsets
, gl
.STATIC_DRAW
);
203 gl
.vertexAttribPointer(offsetLoc
, 1, gl
.FLOAT
, false, 0, 0);
205 gl
.enableVertexAttribArray(colorLoc
);
206 gl
.vertexAttribDivisor(colorLoc
, divisor
);
207 var colorCount
= instanceCount
/ divisor
;
208 if ((instanceCount
% divisor
) != 0)
210 var colors
= new Float32Array(colorCount
);
211 for (var ii
= 0; ii
< colorCount
; ++ii
) {
212 colors
[ii
] = 1.0 / colorCount
* (ii
+ 1);
214 var colorBuffer
= gl
.createBuffer();
215 gl
.bindBuffer(gl
.ARRAY_BUFFER
, colorBuffer
);
216 gl
.bufferData(gl
.ARRAY_BUFFER
, colors
, gl
.STATIC_DRAW
);
217 gl
.vertexAttribPointer(colorLoc
, 1, gl
.FLOAT
, false, 0, 0);
219 var indexBuffer
= gl
.createBuffer();
220 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, indexBuffer
);
221 var indices
= new Uint16Array([0, 1, 2, 0, 2, 3]);
222 gl
.bufferData(gl
.ELEMENT_ARRAY_BUFFER
, indices
, gl
.STATIC_DRAW
);
224 gl
.drawElementsInstanced(gl
.TRIANGLES
, 6, gl
.UNSIGNED_SHORT
, 0, instanceCount
);
225 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "drawElementsInstanced should succeed");
228 for (var ii
= 0; ii
< instanceCount
; ++ii
) {
229 if ((ii
% divisor
) == 0)
231 var refColor
= [ Math
.floor(colors
[colorIndex
] * 255), 0, 0, 255 ];
232 wtu
.checkCanvasRect(gl
, Math
.floor(canvas
.width
/ instanceCount
* ii
) + 1, 0, 1, canvas
.height
, refColor
,
233 "instance " + ii
+ " should be " + refColor
, 2);
236 gl
.deleteBuffer(positionBuffer
);
237 gl
.deleteBuffer(offsetBuffer
);
238 gl
.deleteBuffer(colorBuffer
);
239 gl
.deleteBuffer(indexBuffer
);
240 gl
.deleteProgram(program
);
241 gl
.deleteVertexArray(vao
);
242 gl
.bindBuffer(gl
.ARRAY_BUFFER
, null);
243 gl
.bindBuffer(gl
.ELEMENT_ARRAY_BUFFER
, null);
245 gl
.bindVertexArray(null);
246 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "clean up should succeed");
250 var successfullyParsed
= true;
252 <script src=
"../../js/js-test-post.js"></script>