Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / extensions / oes-shader-multisample-interpolation.html
blobdcb272c2f0843966905e7c49cf3ab2a5833464be
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 -->
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.");
24 debug("");
26 var wtu = WebGLTestUtils;
27 var gl = wtu.create3DContext("c", { antialias: false }, 2);
28 var ext;
30 function runShaderTests(extensionEnabled) {
31 debug("");
32 debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled"));
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 }`;
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 }`;
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");
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");
73 const missingVertex = `#version 300 es
74 sample out float interpolant;
75 in vec4 vPosition;
76 void main() {
77 gl_Position = vPosition;
78 }`;
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 }`;
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");
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;
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);
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");
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");
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");
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");
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");
166 * This test renders a triangle using MSAAx4 and 1x1 viewport
167 * with the following vertex colors.
169 * | Position | Color |
170 * |==========|===========|
171 * | (-1, -1) | (0, 0, 0) |
172 * | (-1, +1) | (0, 1, 0) |
173 * | (+1, -1) | (1, 0, 0) |
175 * This triangle cannot cover all four samples.
177 * When default interpolation is used, the vertex color is interpolated
178 * once, most likely in the pixel center.
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.
185 * OpenGL specs do not guarantee specific sample positions, so the test
186 * checks only that the resolved colors are different.
188 function runInterpolationTest() {
189 debug("");
190 debug("Testing multisample interpolation");
192 function draw(program) {
193 gl.viewport(0, 0, 1, 1);
194 gl.useProgram(program);
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);
207 gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
208 gl.enableVertexAttribArray(posLoc);
210 const rbo = gl.createRenderbuffer();
211 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
212 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, 1, 1);
214 const fbo = gl.createFramebuffer();
215 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
216 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
218 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE);
220 gl.clear(gl.COLOR_BUFFER_BIT);
221 gl.drawArrays(gl.TRIANGLES, 0, 3);
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");
228 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
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);
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;
246 const programCenter = wtu.setupProgram(gl, [vertexCenter, fragmentCenter]);
248 draw(programCenter);
249 const centerColor = new Uint8Array(4);
250 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, centerColor);
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);
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;
269 const programSample = wtu.setupProgram(gl, [vertexSample, fragmentSample]);
271 draw(programSample);
272 const sampleColor = new Uint8Array(4);
273 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, sampleColor);
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);
283 function runTest() {
284 if (!gl) {
285 testFailed("WebGL context does not exist");
286 return;
288 testPassed("WebGL context exists");
290 runQueryTests(false);
291 runShaderTests(false);
293 debug("");
294 ext = gl.getExtension("OES_shader_multisample_interpolation");
295 wtu.runExtensionSupportedTest(gl, "OES_shader_multisample_interpolation", ext !== null);
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();
307 runTest();
309 var successfullyParsed = true;
310 </script>
311 <script src="../../js/js-test-post.js"></script>
312 </body>
313 </html>