tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

switching-objects.html (9317B)


      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>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;
     24 
     25 void main() {
     26   out_value1 = in_value * 2.;
     27   out_value2 = in_value * 4.;
     28 }
     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.);
     35 }
     36 </script>
     37 <script>
     38 "use strict";
     39 description("Tests switching transform feedback objects.");
     40 
     41 debug("<h3>Setup</h3>")
     42 
     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");
     48 }
     49 
     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");
     64 
     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");
     75 
     76 debug("<h3>Baseline transform feedback success case</h3>");
     77 
     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");
     85 
     86 gl.bindBuffer(gl.TRANSFORM_FEEDBACK_BUFFER, tfBuffer1);
     87 wtu.checkFloatBuffer(gl, gl.TRANSFORM_FEEDBACK_BUFFER, expected_tf_output);
     88 
     89 debug("<h3>Generic binding is not changed when switching TF object</h3>");
     90 
     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.
     97 
     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");
    106 
    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");
    112 
    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);
    117 
    118 debug("<h3>Error switching TF object while TF is enabled</h3>");
    119 
    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);
    126 
    127 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
    128 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "bind while unpaused");
    129 
    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);
    136 
    137 
    138 debug("<h3>Successfully switching TF object while TF is paused</h3>");
    139 
    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);
    144 
    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);
    149 
    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);
    162 
    163 gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf2);
    164 gl.endTransformFeedback();
    165 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "end on tf2");
    166 
    167 debug("<h3>Misc. invalid operations</h3>")
    168 
    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");
    175 
    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");
    190 
    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");
    197 
    198 finishTest();
    199 
    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;
    207 }
    208 
    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);
    215  }
    216 }
    217 
    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);
    224  }
    225 }
    226 
    227 
    228 </script>
    229 
    230 </body>
    231 </html>