oes-vertex-array-object-bufferData.html (6190B)
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 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL OES_vertex_array_object_bufferData Conformance Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 <!-- comment in the script tag below to test through JS emualation of the extension. --> 16 <!-- 17 <script src="../../../demos/google/resources/OESVertexArrayObject.js"></script> 18 --> 19 </head> 20 <body> 21 <div id="description"></div> 22 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> 23 <div id="console"></div> 24 <script id="vshader" type="x-shader/x-vertex"> 25 attribute vec4 a_position; 26 attribute vec4 a_color; 27 varying vec4 v_color; 28 void main(void) { 29 gl_Position = a_position; 30 v_color = a_color; 31 } 32 </script> 33 <script id="fshader" type="x-shader/x-fragment"> 34 precision mediump float; 35 varying vec4 v_color; 36 void main(void) { 37 gl_FragColor = v_color; 38 } 39 </script> 40 <script> 41 "use strict"; 42 description("This test verifies drawing results when using gl.bufferData with the OES_vertex_array_object extension."); 43 44 debug(""); 45 46 var wtu = WebGLTestUtils; 47 var canvas = document.getElementById("canvas"); 48 var gl = wtu.create3DContext(canvas); 49 var ext = null; 50 var vao = null; 51 52 if (!gl) { 53 testFailed("WebGL context does not exist"); 54 } else { 55 testPassed("WebGL context exists"); 56 57 // Setup emulated OESVertexArrayObject if it has been included. 58 if (window.setupVertexArrayObject) { 59 debug("using emuated OES_vertex_array_object"); 60 setupVertexArrayObject(gl); 61 } 62 63 // Query the extension and store globally so shouldBe can access it 64 ext = gl.getExtension("OES_vertex_array_object"); 65 if (!ext) { 66 testPassed("No OES_vertex_array_object support -- this is legal"); 67 68 } else { 69 testPassed("Successfully enabled OES_vertex_array_object extension"); 70 71 runBufferDataTest(); 72 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); 73 } 74 } 75 76 /** 77 * The OES_vertex_array_object extension seems to work incorrectly on some handheld devices, 78 * namely the Nexus 5, and Nexus 7 (in 2014/01) when using bufferData before binding the VAO. 79 * The tested OS was Android KitKat 4.4.2, the effects were the same in all tested browsers 80 * (Chrome, Chrome Beta, Firefox, Firefox Beta), so it is likely a driver bug. 81 * These devices have the similar Adreno 320 and Adreno 330 GPUs respectively. 82 * 83 * The issuse resulted from this sequence of actions in a requestAnimationFrame loop: 84 * 1. upload some vertex buffers with gl.bufferData (eg. colors) 85 * 2. bind the VAO 86 * 3. clear the canvas 87 * 4. draw (some triangles) to the canvas 88 * 5. unbind the VAO 89 * 90 * This caused the drawn triangles to be drawn with black (0) for most of the frames, with some 91 * rare frames presenting the correct render results. Interestingly on both devices exactly every 92 * 64th frame passed (starting with the very first one), the others failed. 93 * (Because of this, we test multiple frames.) 94 * When positions were uploaded, seemingly nothing was drawn, that's likely because the 95 * position buffer was also all 0s. 96 * 97 * The issue did not occur: 98 * - if step 1. and 2. were swapped 99 * - or if step5 was ommited (probably because that makes step 2 a no-op since the VAO is bound) 100 */ 101 function runBufferDataTest() { 102 debug("Testing draws with bufferData"); 103 104 canvas.width = 50; canvas.height = 50; 105 gl.viewport(0, 0, canvas.width, canvas.height); 106 107 var testColor = [0, 255, 0, 255]; 108 var clearColor = [255, 0, 0, 255]; 109 110 // Where the issue occures, this is the sequence of success/failure every time: 111 // result: success fail fail fail fail ... success fail fail ... 112 // currentTestCount: 0 1 2 3 4 ... 64 65 66 ... 113 // So with just 1 test it passes, but 2 tests are enough. Here we use 3. 114 var numberOfTests = 3; 115 var currentTestCount = 0; 116 117 var positionLoc = 0; 118 var colorLoc = 1; 119 var gridRes = 1; 120 121 var program = wtu.setupSimpleVertexColorProgram(gl, positionLoc, colorLoc); 122 123 var vao0 = ext.createVertexArrayOES(); 124 ext.bindVertexArrayOES(vao0); 125 126 var buffers = wtu.setupIndexedQuadWithOptions(gl, 127 { gridRes: gridRes, 128 positionLocation: positionLoc 129 }); 130 131 var colorTypedArray = createColorTypedArray(); 132 133 var colorBuffer = gl.createBuffer(gl.ARRAY_BUFFER); 134 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 135 gl.enableVertexAttribArray(colorLoc); 136 gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0); 137 138 ext.bindVertexArrayOES(null); 139 140 testDrawing(); 141 142 function testDrawing() { 143 // this order works fine: 144 // ext.bindVertexArrayOES(vao0); 145 // uploadColor(); 146 147 // this order doesn't: 148 uploadColor(); 149 ext.bindVertexArrayOES(vao0); 150 151 wtu.clearAndDrawIndexedQuad(gl, 1, clearColor); 152 153 ext.bindVertexArrayOES(null); 154 155 //debug("<span>"+currentTestCount+"</span"); 156 wtu.checkCanvas(gl, testColor, "should be green") 157 158 if (++currentTestCount < numberOfTests) { 159 testDrawing(); 160 // wtu.requestAnimFrame(testDrawing); 161 } else { 162 // clean up 163 ext.deleteVertexArrayOES(vao0); 164 } 165 } 166 167 function uploadColor() { 168 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 169 gl.bufferData(gl.ARRAY_BUFFER, colorTypedArray, gl.STREAM_DRAW); 170 } 171 172 function createColorTypedArray() { 173 var colors = []; 174 var pOffset = 0; 175 for (var yy = 0; yy <= gridRes; ++yy) { 176 for (var xx = 0; xx <= gridRes; ++xx) { 177 colors[pOffset + 0] = testColor[0]; 178 colors[pOffset + 1] = testColor[1]; 179 colors[pOffset + 2] = testColor[2]; 180 colors[pOffset + 3] = testColor[3]; 181 pOffset += 4; 182 } 183 } 184 return new Float32Array(colors); 185 } 186 } 187 188 debug(""); 189 var successfullyParsed = true; 190 </script> 191 <script src="../../js/js-test-post.js"></script> 192 193 </body> 194 </html>