Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / transform_feedback / switching-objects.html
blobfce82dd21f6594873c88198f0978223aac45f619
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 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <title>Switching transform feedback objects</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 </head>
16 <body>
17 <div id="description"></div>
18 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
19 <div id="console"></div>
20 <script id="vshader" type="x-shader/x-vertex">#version 300 es
21 in float in_value;
22 out float out_value1;
23 out float out_value2;
25 void main() {
26 out_value1 = in_value * 2.;
27 out_value2 = in_value * 4.;
29 </script>
30 <script id="fshader" type="x-shader/x-fragment">#version 300 es
31 precision mediump float;
32 out vec4 dummy;
33 void main() {
34 dummy = vec4(0.);
36 </script>
37 <script>
38 "use strict";
39 description("Tests switching transform feedback objects.");
41 debug("<h3>Setup</h3>")
43 var wtu = WebGLTestUtils;
44 var canvas = document.getElementById("canvas");
45 var gl = wtu.create3DContext(canvas, null, 2);
46 if (!gl) {
47 testFailed("WebGL context does not exist");
50 // Setup
51 const prog_interleaved = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
52 ["out_value1", "out_value2"], gl.INTERLEAVED_ATTRIBS,
53 ["in_value"]);
54 const prog_no_varyings = wtu.setupTransformFeedbackProgram(gl, ["vshader", "fshader"],
55 [], gl.INTERLEAVED_ATTRIBS,
56 ["in_value"]);
57 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "shader compilation");
58 const vertexBuffer = createBuffer(gl, new Float32Array([1, 2, 3, 4]));
59 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
60 gl.enableVertexAttribArray(0);
61 gl.vertexAttribPointer(0, 1, gl.FLOAT, false, 0, 0);
62 gl.useProgram(prog_interleaved);
63 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "vertex buffer and program setup");
65 const tf1 = gl.createTransformFeedback();
66 const tf2 = gl.createTransformFeedback();
67 const tfBuffer1 = createBuffer(gl, new Float32Array([0, 0]));
68 const tfBuffer2 = createBuffer(gl, new Float32Array([0, 0]));
69 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
70 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer1);
71 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
72 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer2);
73 const expected_tf_output = [2, 4];
74 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "TF object setup");
76 debug("<h3>Baseline transform feedback success case</h3>");
78 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
79 gl.beginTransformFeedback(gl.POINTS);
80 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin TF");
81 gl.drawArrays(gl.POINTS, 0, 1);
82 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "draw");
83 gl.endTransformFeedback();
84 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end TF");
86 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
87 wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
89 debug("<h3>Generic binding is not changed when switching TF object</h3>");
91 // According to the GL ES spec historically, TRANSFORM_FEEDBACK_BUFFER_BINDING is listed as part
92 // of the transform feedback object state. However, many drivers treat it as global context state
93 // and not part of the tranform feedback object, which means that it does not change when
94 // bindTransformFeedback is called. Khronos has resolved to change the spec to specify the latter
95 // behavior: https://gitlab.khronos.org/opengl/API/issues/66 (Khronos private link). This tests
96 // for the new behavior.
98 // Set each buffer to contain its buffer number. We use this to check which
99 // buffer is *really* bound at the driver level by reading the buffer contents.
100 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null);
101 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
102 gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([1]), gl.STREAM_READ);
103 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer2);
104 gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([2]), gl.STREAM_READ);
105 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bufferData");
107 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
108 checkParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, tfBuffer2);
109 checkIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, tfBuffer1);
110 wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, [2]);
111 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readback");
113 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, null);
114 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
115 checkParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, null);
116 checkIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0, tfBuffer2);
118 debug("<h3>Error switching TF object while TF is enabled</h3>");
120 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
121 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
122 gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([0, 0]), gl.STREAM_READ);
123 gl.beginTransformFeedback(gl.POINTS);
124 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin");
125 checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf1);
127 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
128 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bind while unpaused");
130 // Check that nothing actually changed and rendering still works
131 checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf1);
132 gl.drawArrays(gl.POINTS, 0, 1);
133 gl.endTransformFeedback();
134 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should complete successfully");
135 wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
138 debug("<h3>Successfully switching TF object while TF is paused</h3>");
140 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
141 gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([0, 0]), gl.STREAM_READ);
142 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer2);
143 gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, new Float32Array([0, 0]), gl.STREAM_READ);
145 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
146 gl.beginTransformFeedback(gl.POINTS);
147 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin on tf2");
148 checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf2);
150 gl.pauseTransformFeedback();
151 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf1);
152 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bind while paused");
153 gl.beginTransformFeedback(gl.POINTS);
154 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "begin on tf1");
155 checkParameter(gl.TRANSFORM_FEEDBACK_BINDING, tf1);
156 gl.drawArrays(gl.POINTS, 0, 1);
157 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "draw should succeed");
158 gl.endTransformFeedback();
159 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end on tf1");
160 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
161 wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
163 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
164 gl.endTransformFeedback();
165 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end on tf2");
167 debug("<h3>Misc. invalid operations</h3>")
169 gl.endTransformFeedback();
170 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "endTransformFeedback before begin");
171 gl.pauseTransformFeedback();
172 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "pauseTransformFeedback when not active");
173 gl.resumeTransformFeedback();
174 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "pauseTransformFeedback when not active");
176 gl.beginTransformFeedback(gl.POINTS);
177 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "transform feedback should begin successfully");
178 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 1);
179 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "wrong primitive mode");
180 gl.useProgram(prog_no_varyings);
181 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "switch program while active");
182 gl.resumeTransformFeedback();
183 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "resumeTransformFeedback when not paused");
184 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
185 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bindTransformFeedback when active");
186 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer2);
187 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "bindBuffer(TRANSFORM_FEEDBACK_BUFFER) when active");
188 gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer2);
189 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bindBufferBase(TRANSFORM_FEEDBACK_BUFFER) when active");
191 gl.pauseTransformFeedback();
192 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "pause");
193 gl.pauseTransformFeedback();
194 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "already paused");
195 gl.endTransformFeedback();
196 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end while paused");
198 finishTest();
200 // Helper functions
201 function createBuffer(gl, dataOrSize) {
202 const buf = gl.createBuffer();
203 gl.bindBuffer(gl.ARRAY_BUFFER, buf);
204 gl.bufferData(gl.ARRAY_BUFFER, dataOrSize, gl.STATIC_DRAW);
205 gl.bindBuffer(gl.ARRAY_BUFFER, null);
206 return buf;
209 function checkParameter(param, expected) {
210 const value = gl.getParameter(param);
211 if (value != expected) {
212 testFailed(wtu.glEnumToString(gl, param) + " was " + value + ", but expected " + expected);
213 } else {
214 testPassed(wtu.glEnumToString(gl, param) + " was " + value + ", matching expected " + expected);
218 function checkIndexedParameter(param, index, expected) {
219 const value = gl.getIndexedParameter(param, index);
220 if (value != expected) {
221 testFailed(wtu.glEnumToString(gl, param) + "[" + index + "] was " + value + ", but expected " + expected);
222 } else {
223 testPassed(wtu.glEnumToString(gl, param) + "[" + index + "] was " + value + ", matching expected " + expected);
228 </script>
230 </body>
231 </html>