diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html | 645 |
1 files changed, 645 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html new file mode 100644 index 0000000000..20256c6ace --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/transform_feedback/transform_feedback.html @@ -0,0 +1,645 @@ +<!-- +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 Transform Feedback 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> +</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">#version 300 es + +in vec4 in_data; +out vec4 out_add; +out vec4 out_mul; +void main(void) { + out_add = in_data + vec4(2.0, 3.0, 4.0, 5.0); + out_mul = in_data * vec4(2.0, 3.0, 4.0, 5.0); +} +</script> +<script id="fshader" type="x-shader/x-fragment">#version 300 es +precision mediump float; +out vec4 out_color; +void main(void) { + out_color = vec4(1.0, 1.0, 1.0, 1.0); +} +</script> +<script> +"use strict"; +description("This test verifies the functionality of the Transform Feedback objects."); + +debug(""); + +var wtu = WebGLTestUtils; +var canvas = document.getElementById("canvas"); +var gl = wtu.create3DContext(canvas, null, 2); +var tf = null; +var tf1 = null; +var buf = null; +let out_add_buffer = null; +var program = null; +var activeInfo = null; +var query = null; +var numberOfQueryCompletionAttempts = 0; + +if (!gl) { + testFailed("WebGL context does not exist"); +} else { + testPassed("WebGL context exists"); + + runBindingTest(); + runTFBufferBindingTest(); + runObjectTest(); + runGetBufferSubDataTest(); + runUnboundDeleteTest(); + runBoundDeleteTest(); + runOneOutputFeedbackTest(); + // Must be the last test, since it's asynchronous and calls finishTest(). + runTwoOutputFeedbackTest(); +} + +function runBindingTest() { + debug(""); + debug("Testing binding enum"); + + shouldBe("gl.TRANSFORM_FEEDBACK_BINDING", "0x8E25"); + + gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TRANSFORM_FEEDBACK_BINDING query should succeed"); + + // Default value is null + shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "null"); + + debug("Testing binding a Transform Feedback object"); + tf = gl.createTransformFeedback(); + tf1 = gl.createTransformFeedback(); + shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)"); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "tf"); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1); + shouldBe("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)", "tf1"); + gl.deleteTransformFeedback(tf); + gl.deleteTransformFeedback(tf1); + shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)"); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted Transform Feedback object"); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); + shouldBeNull("gl.getParameter(gl.TRANSFORM_FEEDBACK_BINDING)"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); +} + +function runTFBufferBindingTest() { + debug(""); + debug("Testing binding and unbinding transform feedback objects and buffers"); + + buf = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, buf); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 16, gl.STATIC_DRAW); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null); + + tf = gl.createTransformFeedback(); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); + + // gl.TRANSFORM_FEEDBACK_BUFFER is part of Transform Feedback objects' + // state. See OpenGL ES 3.0.5 Section 6.24. + // + // Since the TRANSFORM_FEEDBACK was just unbound, there should be nothing + // bound. + shouldBeNull('gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)'); + + // Binding the buffer to the ARRAY_BUFFER binding point should succeed. + gl.bindBuffer(gl.ARRAY_BUFFER, buf); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "binding buffer to ARRAY_BUFFER"); + + gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.deleteBuffer(buf); + buf = null; + gl.deleteTransformFeedback(tf); + tf = null; +} + +function runObjectTest() { + debug(""); + debug("Testing object creation"); + + tf = gl.createTransformFeedback(); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createTransformFeedback should not set an error"); + shouldBeNonNull("tf"); + + // Expect false if never bound + shouldBeFalse("gl.isTransformFeedback(tf)"); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + shouldBeTrue("gl.isTransformFeedback(tf)"); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); + shouldBeTrue("gl.isTransformFeedback(tf)"); + gl.deleteTransformFeedback(tf); + shouldBeFalse("gl.isTransformFeedback(tf)"); + + shouldBeFalse("gl.isTransformFeedback(null)"); + + tf = null; +} + +function runOneOutputFeedbackTest() { + debug(""); + debug("Testing one-output transform feedback"); + + // Build the input and output buffers + var in_data = [ + 1.0, 2.0, 3.0, 4.0, + 2.0, 4.0, 8.0, 16.0, + 0.75, 0.5, 0.25, 0.0 + ]; + + var in_buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW); + + out_add_buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW); + + // Create the transform feedback shader + program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], + ["out_add"], gl.SEPARATE_ATTRIBS, + ["in_data"]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeNonNull("program"); + + // Draw the the transform feedback buffers + tf = gl.createTransformFeedback(); + + gl.enableVertexAttribArray(0); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer); + + gl.enable(gl.RASTERIZER_DISCARD); + gl.beginTransformFeedback(gl.POINTS); + + debug("Testing switching program while transform feedback is active"); + gl.pauseTransformFeedback(); + var program2 = wtu.setupSimpleColorProgram(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Switching program while transform feedback is active and paused should succeed"); + gl.useProgram(program); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Switching program while transform feedback is active and paused should succeed"); + gl.resumeTransformFeedback(); + gl.useProgram(program2); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Switching program while transform feedback is active should fail"); + shouldBe("gl.getParameter(gl.CURRENT_PROGRAM)", "program"); + + debug("Testing deleting an active transform feedback object"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors before testing deletion"); + gl.deleteTransformFeedback(tf); + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Deleting the transform feedback while active should fail, and have no effect"); + shouldBe("gl.isTransformFeedback(tf)", "true"); + debug("Resuming testing of single-output transform feedback"); + + gl.drawArrays(gl.POINTS, 0, 3); + + gl.endTransformFeedback(); + gl.disable(gl.RASTERIZER_DISCARD); + + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null); + + // Verify the output buffer contents + var add_expected = [ + 3.0, 5.0, 7.0, 9.0, + 4.0, 7.0, 12.0, 21.0, + 2.75, 3.5, 4.25, 5.0 + ]; + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, add_expected); + + gl.deleteBuffer(in_buffer); + gl.deleteBuffer(out_add_buffer); + gl.deleteProgram(program); + gl.deleteTransformFeedback(tf); + + tf = null; + program = null; +} + +function runTwoOutputFeedbackTest() { + debug(""); + debug("Testing two-output transform feedback"); + + // Build the input and output buffers + var in_data = [ + 1.0, 2.0, 3.0, 4.0, + 2.0, 4.0, 8.0, 16.0, + 0.75, 0.5, 0.25, 0.0 + ]; + + var in_buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW); + + out_add_buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW); + + var out_mul_buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_mul_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW); + + // Create the transform feedback shader + program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], + ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS, + ["in_data"]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeNonNull("program"); + + // Create a query object to check the number of primitives written + query = gl.createQuery(); + + // Draw the the transform feedback buffers + tf = gl.createTransformFeedback(); + + gl.enableVertexAttribArray(0); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, out_mul_buffer); + + gl.enable(gl.RASTERIZER_DISCARD); + gl.beginTransformFeedback(gl.POINTS); + gl.beginQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query); + + gl.drawArrays(gl.POINTS, 0, 3); + + gl.endQuery(gl.TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); + gl.endTransformFeedback(); + gl.disable(gl.RASTERIZER_DISCARD); + + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 1, null); + + // Verify the output buffer contents + var add_expected = [ + 3.0, 5.0, 7.0, 9.0, + 4.0, 7.0, 12.0, 21.0, + 2.75, 3.5, 4.25, 5.0 + ]; + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, add_expected); + + var mul_expected = [ + 2.0, 6.0, 12.0, 20.0, + 4.0, 12.0, 32.0, 80.0, + 1.5, 1.5, 1.0, 0.0 + ]; + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_mul_buffer); + wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, mul_expected); + + gl.deleteBuffer(in_buffer); + gl.deleteBuffer(out_add_buffer); + gl.deleteBuffer(out_mul_buffer); + gl.deleteProgram(program); + gl.deleteTransformFeedback(tf); + + tf = null; + program = null; + + // Check the result of the query. It should not be available yet. + // This constant was chosen arbitrarily to take around 1 second on + // one WebGL implementation on one desktop operating system. (Busy- + // loops based on calling Date.now() have been found unreliable.) + var numEarlyTests = 50000; + while (--numEarlyTests > 0) { + gl.finish(); + if (gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) { + testFailed("Query's result became available too early"); + finishTest(); + return; + } + } + testPassed("TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query's result didn't become available too early"); + + // Complete the rest of the test asynchronously. + requestAnimationFrame(completeTransformFeedbackQueryTest); +} + +function runUnboundDeleteTest() { + debug(""); + debug("Testing deleting buffers attached to an unbound transform feedback object"); + + // Theoretically it would be possible to verify the result of performing + // transform feedback into a deleted buffer object. The buffer would have to + // be latched into a VAO as well as into the transform feedback object. In + // order to get the results out of the output buffer, it would be necessary + // to run transform feedback again, reading from the buffer bound to the + // VAO, and writing into a (non-deleted) buffer object latched into the + // transform feedback object. It's not possible to arrange things to be able + // to copyBufferSubData from the deleted buffer object into a temporary one + // for readback. + + // This would be a lot of code to test an unlikely corner case, so instead, + // this test verifies simpler behaviors. + + out_add_buffer = gl.createBuffer(); + const output_buffer_length = Float32Array.BYTES_PER_ELEMENT * 16; + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, output_buffer_length, gl.STATIC_DRAW); + + // Set up the transform feedback object + tf = gl.createTransformFeedback(); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer); + + // Unbind transform feedback and delete out_add_buffer. + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); + gl.deleteBuffer(out_add_buffer); + debug("isBuffer should report false after deletion"); + shouldBe("gl.isBuffer(out_add_buffer)", "false"); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + debug("Transform feedback object should keep output buffer alive"); + shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "out_add_buffer"); + // Deleting the buffer again while the transform feedback is bound shouldn't unbind it. + gl.deleteBuffer(out_add_buffer); + debug("Deleting output buffer again should be a no-op"); + shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "out_add_buffer"); + + // Try unbinding and rebinding the transform feedback object just + // to make sure that has no effect on the attached output buffer. + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + debug("Transform feedback object should still keep output buffer alive"); + shouldBe("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)", "out_add_buffer"); + + gl.deleteTransformFeedback(tf); + + tf = null; + out_add_buffer = null; +} + +function runBoundDeleteTest() { + debug(""); + debug("Testing deleting buffers attached to a bound transform feedback object"); + + out_add_buffer = gl.createBuffer(); + const output_buffer_length = Float32Array.BYTES_PER_ELEMENT * 16; + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, output_buffer_length, gl.STATIC_DRAW); + + // Set up the transform feedback object + tf = gl.createTransformFeedback(); + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer); + + // Delete the output buffer + gl.deleteBuffer(out_add_buffer); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + debug("Buffer should have been unbound from active transform feedback"); + shouldBeNull("gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0)"); + + gl.deleteTransformFeedback(tf); + + tf = null; + out_add_buffer = null; +} + +var retArray; + +function verifyGetBufferSubData(expected) { + wtu.shouldGenerateGLError(gl, expected, "gl.getBufferSubData(gl.TRANSFORM_FEEDBACK_BUFFER, 0, retArray, 0, retArray.length)"); +} + +function runGetBufferSubDataTest() { + debug(""); + debug("Test that getBufferSubData..."); + + // Build the input and output buffers + var in_data = [ + 1.0, 2.0, 3.0, 4.0, + 2.0, 4.0, 8.0, 16.0, + 0.75, 0.5, 0.25, 0.0 + ]; + + retArray = new Float32Array(in_data.length); + + var in_buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(in_data), gl.STATIC_DRAW); + + out_add_buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * in_data.length, gl.STATIC_DRAW); + + // Create the transform feedback shader + program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], + ["out_add"], gl.SEPARATE_ATTRIBS, + ["in_data"]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeNonNull("program"); + + // Draw the the transform feedback buffers + tf = gl.createTransformFeedback(); + + gl.enableVertexAttribArray(0); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); + + debug("... passes when a transform feedback object is not bound"); + verifyGetBufferSubData(gl.NO_ERROR); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer); + + debug("... passes when a transform feedback object is bound but not active"); + verifyGetBufferSubData(gl.NO_ERROR); + + gl.enable(gl.RASTERIZER_DISCARD); + gl.beginTransformFeedback(gl.POINTS); + + debug("... fails when a transform feedback object is active"); + verifyGetBufferSubData(gl.INVALID_OPERATION); + + gl.drawArrays(gl.POINTS, 0, 3); + + gl.endTransformFeedback(); + gl.disable(gl.RASTERIZER_DISCARD); + + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null); + + // Verify the output buffer contents + var add_expected = [ + 3.0, 5.0, 7.0, 9.0, + 4.0, 7.0, 12.0, 21.0, + 2.75, 3.5, 4.25, 5.0 + ]; + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, add_expected); + + tf = null; + program = null; +} + +function completeTransformFeedbackQueryTest() { + debug(""); + debug("Testing TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query"); + + ++numberOfQueryCompletionAttempts; + if (numberOfQueryCompletionAttempts > 500) { + testFailed("Query didn't become available in a reasonable time"); + finishTest(); + return; + } + + if (!gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE)) { + requestAnimationFrame(completeTransformFeedbackQueryTest); + return; + } + + var result = gl.getQueryParameter(query, gl.QUERY_RESULT); + if (result == 3) { + testPassed("TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query returned a correct result (3)"); + } else { + testFailed("TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query returned an incorrect result " + result + " (expected 3)"); + } + + runVaryingsTest(); +} + +function verifyTransformFeedbackVarying(prog, index, valid, name) { + activeInfo = gl.getTransformFeedbackVarying(prog, index); + if (valid) { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, + "Should be no errors from valid getTransformFeedbackVarying."); + shouldBeNonNull("activeInfo"); + shouldBe("activeInfo.name", "'" + name + "'"); + shouldBe("activeInfo.type", "gl.FLOAT_VEC4"); + shouldBe("activeInfo.size", "1"); + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, + "Should be INVALID_VALUE when calling getTransformFeedbackVarying with an invalid index."); + shouldBeNull("activeInfo"); + } +} + +function runVaryingsTest() { + debug(""); + debug("Testing transform feedback varyings"); + + // Create the transform feedback shader. This is explicitly run after runTwoOutputFeedbackTest, + // as re-linking the shader here will test browser caching. + program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], + ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS, + ["in_data"]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeNonNull("program"); + + // Check the varyings + shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "2"); + verifyTransformFeedbackVarying(program, 0, true, "out_add"); + verifyTransformFeedbackVarying(program, 1, true, "out_mul"); + verifyTransformFeedbackVarying(program, 2, false); + + // transformFeedbackVaryings() doesn't take effect until a successful link. + gl.transformFeedbackVaryings(program, ["out_mul"], gl.SEPARATE_ATTRIBS); + shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "2"); + verifyTransformFeedbackVarying(program, 0, true, "out_add"); + verifyTransformFeedbackVarying(program, 1, true, "out_mul"); + verifyTransformFeedbackVarying(program, 2, false); + + // Now relink. + gl.linkProgram(program); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)"); + shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "1"); + verifyTransformFeedbackVarying(program, 0, true, "out_mul"); + verifyTransformFeedbackVarying(program, 1, false); + verifyTransformFeedbackVarying(program, 2, false); + + // Test recompiling/relinking the program + // Regression test for http://crbug.com/716018 + var skipCompileStatus = true; + program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], + ["out_add", "out_mul"], gl.SEPARATE_ATTRIBS, + ["in_data"], undefined, undefined, skipCompileStatus); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeTrue("gl.getProgramParameter(program, gl.LINK_STATUS)"); + shouldBe("gl.getProgramParameter(program, gl.TRANSFORM_FEEDBACK_VARYINGS)", "2"); + verifyTransformFeedbackVarying(program, 0, true, "out_add"); + verifyTransformFeedbackVarying(program, 1, true, "out_mul"); + verifyTransformFeedbackVarying(program, 2, false); + + runContextLostOneOutputFeedbackTest(); +} + +function runContextLostOneOutputFeedbackTest() { + var ext = gl.getExtension("WEBGL_lose_context"); + if (!ext) { + debug("No WEBGL_lose_context support"); + finishTest(); + return; + } + debug(""); + debug("Testing switching program after context lost while transform feedback is active"); + + var in_buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(12), gl.STATIC_DRAW); + + out_add_buffer = gl.createBuffer(); + gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, out_add_buffer); + gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, Float32Array.BYTES_PER_ELEMENT * 12, gl.STATIC_DRAW); + + // Create an extra program to try switching to + var program2 = wtu.setupSimpleColorProgram(gl); + + // Create the transform feedback shader + program = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"], + ["out_add"], gl.SEPARATE_ATTRIBS, + ["in_data"]); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "linking transform feedback shader should not set an error"); + shouldBeNonNull("program"); + + // Draw the the transform feedback buffers + tf = gl.createTransformFeedback(); + + gl.enableVertexAttribArray(0); + gl.bindBuffer(gl.ARRAY_BUFFER, in_buffer); + gl.vertexAttribPointer(0, 4, gl.FLOAT, false, 16, 0); + + gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); + gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, out_add_buffer); + + gl.beginTransformFeedback(gl.POINTS); + + debug("Calling loseContext()"); + ext.loseContext(); + shouldBeTrue("gl.isContextLost()"); + shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL"); + shouldBe("gl.getError()", "gl.NO_ERROR"); + debug("Trying to switch program"); + gl.useProgram(program2); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No transform feedback error generated on lost context"); + finishTest(); +} + +debug(""); +</script> + +</body> +</html> |