out-of-bounds-test.js (17904B)
1 /* 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. 5 */ 6 7 'use strict'; 8 9 var OutOfBoundsTest = (function() { 10 11 var runCommonInvalidValueTests = function(callTemplate, gl, wtu, ext) { 12 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: -1, type: 'gl.UNSIGNED_BYTE', offset: 0})); 13 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: -1})); 14 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: -1, type: 'gl.UNSIGNED_BYTE', offset: 1})); 15 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_BYTE', offset: -1})); 16 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: '0xffffffff', type: 'gl.UNSIGNED_BYTE', offset: 0})); 17 }; 18 19 var setupProgramAndBindVertexArray = function(gl, wtu) { 20 var program = wtu.loadStandardProgram(gl); 21 22 gl.useProgram(program); 23 var vertexObject = gl.createBuffer(); 24 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 25 gl.enableVertexAttribArray(0); 26 27 return program; 28 }; 29 30 var setupProgram2 = function(gl, wtu) { 31 var vshader = [ 32 'attribute vec3 aOne;', 33 'attribute vec2 aTwo;', 34 'void main() {', 35 ' gl_Position = vec4(aOne, 1.0) + vec4(aTwo, 0.0, 1.0);', 36 '}' 37 ].join('\n'); 38 39 var fshader = [ 40 'void main() {', 41 ' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);', 42 '}' 43 ].join('\n'); 44 45 var program = wtu.setupProgram(gl, [vshader, fshader], [ "aOne", "aTwo" ]); 46 if (!program) { 47 testFailed("failed to create test program"); 48 } 49 return program; 50 }; 51 52 var runDrawArraysTest = function(callTemplate, gl, wtu, ext) { 53 var program = setupProgramAndBindVertexArray(gl, wtu); 54 55 debug("Test empty buffer") 56 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ ]), gl.STATIC_DRAW); 57 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 58 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 1})); 59 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 10000})); 60 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 1, count: 0})); 61 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 0})); 62 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 100, count: 0})); 63 runCommonInvalidValueTests(callTemplate, gl, wtu, ext); 64 65 debug("") 66 debug("Test buffer with 3 float vectors") 67 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW); 68 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 69 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 3})); 70 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 3, count: 2})); 71 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 10000})); 72 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 0})); 73 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 100, count: 0})); 74 runCommonInvalidValueTests(callTemplate, gl, wtu, ext); 75 76 debug("") 77 debug("Test buffer with interleaved (3+2) float vectors") 78 79 setupProgram2(gl, wtu); 80 81 var vbo = gl.createBuffer(); 82 gl.bindBuffer(gl.ARRAY_BUFFER, vbo); 83 // enough for 9 vertices, so 3 triangles 84 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*5), gl.STATIC_DRAW); 85 86 // bind first 3 elements, with a stride of 5 float elements 87 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, 0); 88 // bind 2 elements, starting after the first 3; same stride of 5 float elements 89 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, 3*4); 90 91 gl.enableVertexAttribArray(0); 92 gl.enableVertexAttribArray(1); 93 94 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9})); 95 96 // negative values must generate INVALID_VALUE; they can never be valid 97 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: 0, count: -500})); 98 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: -200, count: 1})); 99 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: -200, count: -500})); 100 101 // 0xffffffff needs to convert to a 'long' IDL argument as -1, as per 102 // WebIDL 4.1.7. JS ToInt32(0xffffffff) == -1. Thus INVALID_VALUE. 103 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: 0, count: '0xffffffff'})); 104 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: '0xffffffff', count: '0xffffffff'})); 105 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {offset: '0xffffffff', count: 1})); 106 107 // values that could otherwise be valid but aren't due to bindings generate 108 // INVALID_OPERATION 109 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: 0, count: 10000})); 110 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {offset: '0x7fffffff', count: 1})); 111 }; 112 113 var runDrawElementsTest = function(callTemplate, gl, wtu, ext) { 114 var program = setupProgramAndBindVertexArray(gl, wtu); 115 var contextVersion = wtu.getDefault3DContextVersion(); 116 117 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW); 118 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 119 120 121 debug(''); 122 debug('Test null index buffer'); 123 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 124 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0})); 125 126 debug(''); 127 debug('Test empty index buffer'); 128 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer()); 129 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0})); 130 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); 131 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0})); 132 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_BYTE', offset: 0})); 133 runCommonInvalidValueTests(callTemplate, gl, wtu, ext); 134 135 debug(''); 136 debug('Test buffer with 3 byte indexes'); 137 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array([ 0, 1, 2 ]), gl.STATIC_DRAW); 138 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); 139 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 2})); 140 wtu.shouldGenerateGLError(gl, [gl.NO_ERROR, gl.INVALID_OPERATION], wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 0})); 141 runCommonInvalidValueTests(callTemplate, gl, wtu, ext); 142 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 4})); 143 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 10000, type: 'gl.UNSIGNED_BYTE', offset: 10000})); 144 145 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, (new Uint8Array([ 3, 0, 1, 2 ])).subarray(1), gl.STATIC_DRAW)'); 146 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); 147 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, new Uint8Array([ 3, 0, 1]))'); 148 var indexValidationError = wtu.shouldGenerateGLError(gl, [gl.INVALID_OPERATION, gl.NO_ERROR], wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); 149 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, (new Uint8Array([ 3, 0, 1, 2 ])).subarray(1))'); 150 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_BYTE', offset: 0})); 151 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_BYTE', offset: 0})); 152 153 debug(''); 154 debug('Test buffer with interleaved (3+2) float vectors'); 155 156 setupProgram2(gl, wtu); 157 158 var vbo = gl.createBuffer(); 159 gl.bindBuffer(gl.ARRAY_BUFFER, vbo); 160 // enough for 9 vertices, so 3 triangles 161 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*5), gl.STATIC_DRAW); 162 163 // bind first 3 elements, with a stride of 5 float elements 164 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 5*4, 0); 165 // bind 2 elements, starting after the first 3; same stride of 5 float elements 166 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 5*4, 3*4); 167 168 gl.enableVertexAttribArray(0); 169 gl.enableVertexAttribArray(1); 170 171 var ebo = gl.createBuffer(); 172 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); 173 // For WebGL 2, PRIMITIVE_RESTART_FIXED_INDEX is always enabled. 174 // 0xffff will be handled as a primitive restart. 175 if (contextVersion <= 1) { 176 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( 177 [ 0, 1, 2, 178 1, 2, 0, 179 2, 0, 1, 180 201, 202, 203, 181 0x7fff, 0x7fff, 0x7fff, 182 0xffff, 0xffff, 0xffff ]), 183 gl.STATIC_DRAW); 184 } else { 185 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( 186 [ 0, 1, 2, 187 1, 2, 0, 188 2, 0, 1, 189 201, 202, 203, 190 0x7fff, 0x7fff, 0x7fff, 191 0xffff - 1, 0xffff - 1, 0xffff - 1 ]), 192 gl.STATIC_DRAW); 193 } 194 195 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 9, type: 'gl.UNSIGNED_SHORT', offset: 0})); 196 197 198 // invalid operation with indices that would be valid with correct bindings 199 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 9, type: 'gl.UNSIGNED_SHORT', offset: 1000})); 200 wtu.shouldGenerateGLError(gl, indexValidationError, wtu.replaceParams(callTemplate, {count: 12, type: 'gl.UNSIGNED_SHORT', offset: 0})); 201 wtu.shouldGenerateGLError(gl, indexValidationError, wtu.replaceParams(callTemplate, {count: 15, type: 'gl.UNSIGNED_SHORT', offset: 0})); 202 wtu.shouldGenerateGLError(gl, indexValidationError, wtu.replaceParams(callTemplate, {count: 18, type: 'gl.UNSIGNED_SHORT', offset: 0})); 203 wtu.shouldGenerateGLError(gl, indexValidationError, wtu.replaceParams(callTemplate, {count: 3, type: 'gl.UNSIGNED_SHORT', offset: 2*15})); 204 205 // 0xffffffff needs to convert to a 'long' IDL argument as -1, as per 206 // WebIDL 4.1.7. JS ToInt32(0xffffffff) == -1. Thus INVALID_VALUE. 207 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, wtu.replaceParams(callTemplate, {count: '0xffffffff', type: 'gl.UNSIGNED_SHORT', offset: 0})); 208 // offset is defined as GLintptr, which is long long in IDL (64-bit). 209 // 2^32 - 1 should not overflow, and only result in INVALID_OPERATION. 210 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 1, type: 'gl.UNSIGNED_SHORT', offset: '0xffffffff'})); 211 212 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: '0x7fffffff', type: 'gl.UNSIGNED_SHORT', offset: 0})); 213 214 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 0, type: 'gl.UNSIGNED_SHORT', offset: 0})); 215 216 // invalid operation with offset that's not a multiple of the type size 217 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 0})); 218 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 1})); 219 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2})); 220 221 // invalid operation if no buffer is bound to ELEMENT_ARRAY_BUFFER 222 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 223 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 0})); 224 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); 225 226 debug(''); 227 debug('Test buffer setting attrib 0 to a buffer too small and disable it.'); 228 var smallVBO = gl.createBuffer(); 229 gl.bindBuffer(gl.ARRAY_BUFFER, smallVBO); 230 gl.bufferData(gl.ARRAY_BUFFER, 1, gl.STATIC_DRAW); 231 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0x10); 232 gl.disableVertexAttribArray(0); 233 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2})); 234 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 235 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {count: 6, type: 'gl.UNSIGNED_SHORT', offset: 2})); 236 }; 237 238 var runInstancedTest = function(callTemplate, gl, wtu, ext) { 239 setupProgram2(gl, wtu); 240 241 // Initialize non-instanced attribute data. 242 // Enough for 9 vertices, so 3 triangles. 243 var vbo = gl.createBuffer(); 244 gl.bindBuffer(gl.ARRAY_BUFFER, vbo); 245 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(9*3), gl.STATIC_DRAW); 246 247 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 248 249 // Setup buffer for instanced attribute data. 250 var vbo2 = gl.createBuffer(); 251 gl.bindBuffer(gl.ARRAY_BUFFER, vbo2); 252 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 253 254 gl.enableVertexAttribArray(0); 255 gl.enableVertexAttribArray(1); 256 257 debug('Test out-of-range instanced attributes'); 258 debug(''); 259 260 debug('Test with an empty buffer for the instanced attribute'); 261 ext.vertexAttribDivisorANGLE(1, 1); 262 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 0})); 263 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 10000, primcount: 0})); 264 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1})); 265 266 debug('Test with a buffer with 1 float for the instanced attribute'); 267 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(1), gl.STATIC_DRAW); 268 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 0})); 269 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 10000, primcount: 0})); 270 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1})); 271 272 debug(''); 273 debug('Test with a buffer with 2 floats for the instanced attribute'); 274 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(2), gl.STATIC_DRAW); 275 debug('Divisor 1'); 276 ext.vertexAttribDivisorANGLE(1, 1); 277 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 1})); 278 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 2})); 279 debug('Divisor 3'); 280 ext.vertexAttribDivisorANGLE(1, 3); 281 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 3})); 282 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 4})); 283 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 10000})); 284 285 debug(''); 286 debug('Test with a buffer with 4 floats for the instanced attribute'); 287 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(4), gl.STATIC_DRAW); 288 debug('Divisor 1'); 289 ext.vertexAttribDivisorANGLE(1, 1); 290 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 2})); 291 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 3})); 292 debug('Divisor 2'); 293 ext.vertexAttribDivisorANGLE(1, 2); 294 wtu.shouldGenerateGLError(gl, gl.NO_ERROR, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 4})); 295 wtu.shouldGenerateGLError(gl, gl.INVALID_OPERATION, wtu.replaceParams(callTemplate, {offset: 0, count: 9, primcount: 5})); 296 }; 297 298 var runDrawArraysInstancedTest = function(callTemplate, gl, wtu, ext) { 299 runInstancedTest(callTemplate, gl, wtu, ext); 300 }; 301 302 var runDrawElementsInstancedTest = function(callTemplate, gl, wtu, ext) { 303 var ebo = gl.createBuffer(); 304 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ebo); 305 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint8Array( 306 [ 0, 1, 2, 307 5, 4, 3, 308 6, 7, 8 ]), 309 gl.STATIC_DRAW); 310 callTemplate = wtu.replaceParams(callTemplate, {type: 'gl.UNSIGNED_BYTE', offset: '$(offset)', count: '$(count)', primcount: '$(primcount)'}); 311 runInstancedTest(callTemplate, gl, wtu, ext); 312 }; 313 314 return { 315 runDrawArraysTest: runDrawArraysTest, 316 runDrawArraysInstancedTest: runDrawArraysInstancedTest, 317 runDrawElementsTest: runDrawElementsTest, 318 runDrawElementsInstancedTest: runDrawElementsInstancedTest 319 }; 320 321 })();