Source code
Revision control
Copy as Markdown
Other Tools
<!--
Copyright (c) 2019 The Khronos Group Inc.
Use of this source code is governed by an MIT-style license that can be
found in the LICENSE.txt file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL OES_vertex_array_object_bufferData Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
<!-- comment in the script tag below to test through JS emualation of the extension. -->
<!--
<script src="../../../demos/google/resources/OESVertexArrayObject.js"></script>
-->
</head>
<body>
<div id="description"></div>
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
<div id="console"></div>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_color;
void main(void) {
gl_Position = a_position;
v_color = a_color;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 v_color;
void main(void) {
gl_FragColor = v_color;
}
</script>
<script>
"use strict";
description("This test verifies drawing results when using gl.bufferData with the OES_vertex_array_object extension.");
debug("");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas);
var ext = null;
var vao = null;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Setup emulated OESVertexArrayObject if it has been included.
if (window.setupVertexArrayObject) {
debug("using emuated OES_vertex_array_object");
setupVertexArrayObject(gl);
}
// Query the extension and store globally so shouldBe can access it
ext = gl.getExtension("OES_vertex_array_object");
if (!ext) {
testPassed("No OES_vertex_array_object support -- this is legal");
} else {
testPassed("Successfully enabled OES_vertex_array_object extension");
runBufferDataTest();
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors");
}
}
/**
* The OES_vertex_array_object extension seems to work incorrectly on some handheld devices,
* namely the Nexus 5, and Nexus 7 (in 2014/01) when using bufferData before binding the VAO.
* The tested OS was Android KitKat 4.4.2, the effects were the same in all tested browsers
* (Chrome, Chrome Beta, Firefox, Firefox Beta), so it is likely a driver bug.
* These devices have the similar Adreno 320 and Adreno 330 GPUs respectively.
*
* The issuse resulted from this sequence of actions in a requestAnimationFrame loop:
* 1. upload some vertex buffers with gl.bufferData (eg. colors)
* 2. bind the VAO
* 3. clear the canvas
* 4. draw (some triangles) to the canvas
* 5. unbind the VAO
*
* This caused the drawn triangles to be drawn with black (0) for most of the frames, with some
* rare frames presenting the correct render results. Interestingly on both devices exactly every
* 64th frame passed (starting with the very first one), the others failed.
* (Because of this, we test multiple frames.)
* When positions were uploaded, seemingly nothing was drawn, that's likely because the
* position buffer was also all 0s.
*
* The issue did not occur:
* - if step 1. and 2. were swapped
* - or if step5 was ommited (probably because that makes step 2 a no-op since the VAO is bound)
*/
function runBufferDataTest() {
debug("Testing draws with bufferData");
canvas.width = 50; canvas.height = 50;
gl.viewport(0, 0, canvas.width, canvas.height);
var testColor = [0, 255, 0, 255];
var clearColor = [255, 0, 0, 255];
// Where the issue occures, this is the sequence of success/failure every time:
// result: success fail fail fail fail ... success fail fail ...
// currentTestCount: 0 1 2 3 4 ... 64 65 66 ...
// So with just 1 test it passes, but 2 tests are enough. Here we use 3.
var numberOfTests = 3;
var currentTestCount = 0;
var positionLoc = 0;
var colorLoc = 1;
var gridRes = 1;
var program = wtu.setupSimpleVertexColorProgram(gl, positionLoc, colorLoc);
var vao0 = ext.createVertexArrayOES();
ext.bindVertexArrayOES(vao0);
var buffers = wtu.setupIndexedQuadWithOptions(gl,
{ gridRes: gridRes,
positionLocation: positionLoc
});
var colorTypedArray = createColorTypedArray();
var colorBuffer = gl.createBuffer(gl.ARRAY_BUFFER);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.enableVertexAttribArray(colorLoc);
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
ext.bindVertexArrayOES(null);
testDrawing();
function testDrawing() {
// this order works fine:
// ext.bindVertexArrayOES(vao0);
// uploadColor();
// this order doesn't:
uploadColor();
ext.bindVertexArrayOES(vao0);
wtu.clearAndDrawIndexedQuad(gl, 1, clearColor);
ext.bindVertexArrayOES(null);
//debug("<span>"+currentTestCount+"</span");
wtu.checkCanvas(gl, testColor, "should be green")
if (++currentTestCount < numberOfTests) {
testDrawing();
// wtu.requestAnimFrame(testDrawing);
} else {
// clean up
ext.deleteVertexArrayOES(vao0);
}
}
function uploadColor() {
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colorTypedArray, gl.STREAM_DRAW);
}
function createColorTypedArray() {
var colors = [];
var pOffset = 0;
for (var yy = 0; yy <= gridRes; ++yy) {
for (var xx = 0; xx <= gridRes; ++xx) {
colors[pOffset + 0] = testColor[0];
colors[pOffset + 1] = testColor[1];
colors[pOffset + 2] = testColor[2];
colors[pOffset + 3] = testColor[3];
pOffset += 4;
}
}
return new Float32Array(colors);
}
}
debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>
</body>
</html>