tor-browser

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

oes-shader-multisample-interpolation.html (11431B)


      1 <!--
      2 Copyright (c) 2023 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_shader_multisample_interpolation 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 </head>
     16 <body>
     17 <canvas width="32" height="32" id="c"></canvas>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <script>
     21 "use strict";
     22 description("This test verifies the functionality of the OES_shader_multisample_interpolation extension, if it is available.");
     23 
     24 debug("");
     25 
     26 var wtu = WebGLTestUtils;
     27 var gl = wtu.create3DContext("c", { antialias: false }, 2);
     28 var ext;
     29 
     30 function runShaderTests(extensionEnabled) {
     31    debug("");
     32    debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
     33 
     34    const macroVertex = `#version 300 es
     35        in vec4 vPosition;
     36        void main() {
     37        #ifdef GL_OES_shader_multisample_interpolation
     38            gl_Position = vPosition;
     39        #else
     40            #error no GL_OES_shader_multisample_interpolation;
     41        #endif
     42        }`;
     43 
     44    const macroFragment = `#version 300 es
     45        precision highp float;
     46        out vec4 my_FragColor;
     47        void main() {
     48        #ifdef GL_OES_shader_multisample_interpolation
     49            my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
     50        #else
     51            #error no GL_OES_shader_multisample_interpolation;
     52        #endif
     53        }`;
     54 
     55    for (const shaders of [[wtu.simpleVertexShaderESSL300, macroFragment],
     56                           [macroVertex, wtu.simpleColorFragmentShaderESSL300]]) {
     57        // Expect the macro shader to succeed ONLY if enabled
     58        if (wtu.setupProgram(gl, shaders)) {
     59            if (extensionEnabled) {
     60                testPassed("Macro defined in shaders when extension is enabled");
     61            } else {
     62                testFailed("Macro defined in shaders when extension is disabled");
     63            }
     64        } else {
     65            if (extensionEnabled) {
     66                testFailed("Macro not defined in shaders when extension is enabled");
     67            } else {
     68                testPassed("Macro not defined in shaders when extension is disabled");
     69            }
     70        }
     71    }
     72 
     73    const missingVertex = `#version 300 es
     74        sample out float interpolant;
     75        in vec4 vPosition;
     76        void main() {
     77            gl_Position = vPosition;
     78        }`;
     79 
     80    const missingFragment = `#version 300 es
     81        precision highp float;
     82        sample in float interpolant;
     83        out vec4 my_FragColor;
     84        void main() {
     85            my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
     86        }`;
     87 
     88    // Always expect the shader missing the #extension pragma to fail (whether enabled or not)
     89    for (const shaders of [[missingVertex, wtu.simpleColorFragmentShaderESSL300],
     90                           [wtu.simpleVertexShaderESSL300, missingFragment],
     91                           [missingVertex, missingFragment]]) {
     92        if (wtu.setupProgram(gl, shaders)) {
     93            testFailed("Sample interpolation qualifier allowed without #extension pragma");
     94        } else {
     95            testPassed("Sample interpolation qualifier disallowed without #extension pragma");
     96        }
     97    }
     98 
     99    const validVertex = `#version 300 es
    100        #extension GL_OES_shader_multisample_interpolation : enable
    101        sample out float interpolant;
    102        in vec4 vPosition;
    103        void main() {
    104            gl_Position = vPosition;
    105        }`;
    106 
    107    const validFragment = `#version 300 es
    108        #extension GL_OES_shader_multisample_interpolation : enable
    109        precision highp float;
    110        sample in float interpolant;
    111        out vec4 my_FragColor;
    112        void main() {
    113            my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    114        }`;
    115 
    116    // Try to compile a shader using a sample qualifier that should only succeed if enabled
    117    if (wtu.setupProgram(gl, [validVertex, validFragment])) {
    118        if (extensionEnabled) {
    119            testPassed("Sample interpolation qualifier compiled successfully when extension enabled");
    120        } else {
    121            testFailed("Sample interpolation qualifier compiled successfully when extension disabled");
    122        }
    123    } else {
    124        if (extensionEnabled) {
    125            testFailed("Sample interpolation qualifier failed to compile when extension enabled");
    126        } else {
    127            testPassed("Sample interpolation qualifier failed to compile when extension disabled");
    128        }
    129    }
    130 }
    131 
    132 function runQueryTests(extensionEnabled) {
    133    debug("");
    134    debug("Testing parameters with extension " + (extensionEnabled ? "enabled" : "disabled"));
    135    if (extensionEnabled) {
    136        shouldBeGreaterThanOrEqual("gl.getParameter(ext.FRAGMENT_INTERPOLATION_OFFSET_BITS_OES)", "4");
    137        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    138 
    139        const limit = 0.5 - Math.pow(2, -gl.getParameter(ext.FRAGMENT_INTERPOLATION_OFFSET_BITS_OES));
    140        shouldBeLessThanOrEqual("gl.getParameter(ext.MIN_FRAGMENT_INTERPOLATION_OFFSET_OES)", `-${limit}`);
    141        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    142        shouldBeGreaterThanOrEqual("gl.getParameter(ext.MAX_FRAGMENT_INTERPOLATION_OFFSET_OES)", `${limit}`);
    143        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    144    } else {
    145        shouldBeNull("gl.getParameter(0x8E5B /* MIN_FRAGMENT_INTERPOLATION_OFFSET_OES */)");
    146        wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
    147        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    148        shouldBeNull("gl.getParameter(0x8E5C /* MAX_FRAGMENT_INTERPOLATION_OFFSET_OES */)");
    149        wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
    150        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    151        shouldBeNull("gl.getParameter(0x8E5D /* FRAGMENT_INTERPOLATION_OFFSET_BITS_OES */)");
    152        wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
    153        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    154    }
    155 }
    156 
    157 function checkEnums() {
    158    debug("");
    159    debug("Check enums");
    160    shouldBe("ext.MIN_FRAGMENT_INTERPOLATION_OFFSET_OES", "0x8E5B");
    161    shouldBe("ext.MAX_FRAGMENT_INTERPOLATION_OFFSET_OES", "0x8E5C");
    162    shouldBe("ext.FRAGMENT_INTERPOLATION_OFFSET_BITS_OES", "0x8E5D");
    163 }
    164 
    165 /*
    166 * This test renders a triangle using MSAAx4 and 1x1 viewport
    167 * with the following vertex colors.
    168 *
    169 * | Position |   Color   |
    170 * |==========|===========|
    171 * | (-1, -1) | (0, 0, 0) |
    172 * | (-1, +1) | (0, 1, 0) |
    173 * | (+1, -1) | (1, 0, 0) |
    174 *
    175 * This triangle cannot cover all four samples.
    176 *
    177 * When default interpolation is used, the vertex color is interpolated
    178 * once, most likely in the pixel center.
    179 *
    180 * When per-sample interpolation is used, the vertex color is interpolated
    181 * several times, producing a distinct value for each covered sample.
    182 * Due to the asymmetry of sample positions, the resolved pixel color must
    183 * not match the color produced by default interpolation.
    184 *
    185 * OpenGL specs do not guarantee specific sample positions, so the test
    186 * checks only that the resolved colors are different.
    187 */
    188 function runInterpolationTest() {
    189    debug("");
    190    debug("Testing multisample interpolation");
    191 
    192    function draw(program) {
    193        gl.viewport(0, 0, 1, 1);
    194        gl.useProgram(program);
    195 
    196        const posLoc = gl.getAttribLocation(program, "position");
    197        const buf = gl.createBuffer();
    198        gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    199        gl.bufferData(
    200            gl.ARRAY_BUFFER,
    201            new Float32Array([
    202                -1.0, -1.0,
    203                -1.0, +1.0,
    204                +1.0, -1.0]),
    205            gl.STATIC_DRAW);
    206 
    207        gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
    208        gl.enableVertexAttribArray(posLoc);
    209 
    210        const rbo = gl.createRenderbuffer();
    211        gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
    212        gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 1, 1);
    213 
    214        const fbo = gl.createFramebuffer();
    215        gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    216        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
    217 
    218        wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE);
    219 
    220        gl.clear(gl.COLOR_BUFFER_BIT);
    221        gl.drawArrays(gl.TRIANGLES, 0, 3);
    222 
    223        gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo);
    224        gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
    225        gl.blitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, gl.COLOR_BUFFER_BIT, gl.NEAREST);
    226        wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
    227 
    228        gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
    229    }
    230 
    231    const vertexCenter = `#version 300 es
    232        in vec4 position;
    233        out vec4 interp_color;
    234        void main() {
    235            gl_Position = position;
    236            interp_color = vec4(position.xy * 0.5 + 0.5, 0.0, 1.0);
    237        }`;
    238 
    239    const fragmentCenter = `#version 300 es
    240        precision highp float;
    241        in vec4 interp_color;
    242        out vec4 fragColor;
    243        void main() {
    244            fragColor = interp_color;
    245        }`;
    246    const programCenter = wtu.setupProgram(gl, [vertexCenter, fragmentCenter]);
    247 
    248    draw(programCenter);
    249    const centerColor = new Uint8Array(4);
    250    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, centerColor);
    251 
    252    const vertexSample = `#version 300 es
    253        #extension GL_OES_shader_multisample_interpolation : require
    254        in vec4 position;
    255        sample out vec4 interp_color;
    256        void main() {
    257            gl_Position = position;
    258            interp_color = vec4(position.xy * 0.5 + 0.5, 0.0, 1.0);
    259        }`;
    260 
    261    const fragmentSample = `#version 300 es
    262        #extension GL_OES_shader_multisample_interpolation : require
    263        precision highp float;
    264        sample in vec4 interp_color;
    265        out vec4 fragColor;
    266        void main() {
    267            fragColor = interp_color;
    268        }`;
    269    const programSample = wtu.setupProgram(gl, [vertexSample, fragmentSample]);
    270 
    271    draw(programSample);
    272    const sampleColor = new Uint8Array(4);
    273    gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, sampleColor);
    274 
    275    const message = `Pixel-center value: ${centerColor}, sample-average value: ${sampleColor}`;
    276    if (centerColor[0] == sampleColor[0] && centerColor[1] == sampleColor[1]) {
    277        testFailed(message);
    278    } else {
    279        testPassed(message);
    280    }
    281 }
    282 
    283 function runTest() {
    284    if (!gl) {
    285        testFailed("WebGL context does not exist");
    286        return;
    287    }
    288    testPassed("WebGL context exists");
    289 
    290    runQueryTests(false);
    291    runShaderTests(false);
    292 
    293    debug("");
    294    ext = gl.getExtension("OES_shader_multisample_interpolation");
    295    wtu.runExtensionSupportedTest(gl, "OES_shader_multisample_interpolation", ext !== null);
    296 
    297    if (!ext) {
    298        testPassed("No OES_shader_multisample_interpolation support -- this is legal");
    299    } else {
    300        testPassed("Successfully enabled OES_shader_multisample_interpolation extension");
    301        runQueryTests(true);
    302        runShaderTests(true);
    303        runInterpolationTest();
    304    }
    305 }
    306 
    307 runTest();
    308 
    309 var successfullyParsed = true;
    310 </script>
    311 <script src="../../js/js-test-post.js"></script>
    312 </body>
    313 </html>