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.
10 <meta charset=
"utf-8">
11 <title>WebGL multisampling fragment shader evaluation
</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>
16 <script id=
"vshader" type=
"x-shader/x-vertex">#version
300 es
17 layout(location=
0) in vec4 aPosition;
21 gl_Position = vec4(aPosition);
22 vPosition = aPosition;
25 <script id=
"fshader" type=
"x-shader/x-fragment">#version
300 es
26 precision highp float;
28 layout(location=
0) out vec4 oColor;
31 if (vPosition.x <
0.0) {
32 oColor = vec4(
1,
0,
0,
1);
33 } else if (vPosition.y <
0.0) {
34 oColor = vec4(
0,
1,
0,
1);
36 oColor = vec4(
0,
0,
1,
1);
43 <div id=
"description"></div>
44 <div id=
"console"></div>
49 var wtu
= WebGLTestUtils
;
50 description("Verify that fragment shader is evaluated only once per framebuffer pixel when multisampling is used.");
52 // GLES 3.0.5 section 3.6.3. Polygon Multisample Rasterization:
53 // "Polygon rasterization produces a fragment for each framebuffer pixel with one or more sample points that satisfy
54 // the point sampling criteria described in section 3.6.1."
56 debug("Regression test for <a href='http://crbug.com/682815'>http://crbug.com/682815</a>");
58 function runTest(testParams
) {
59 let canvas
= document
.createElement('canvas');
62 let gl
= wtu
.create3DContext(canvas
, {antialias
: false}, 2);
64 // Find the supported samples for a multisampled renderbuffer of the appropriate internal format.
65 let samples
= gl
.getInternalformatParameter(gl
.RENDERBUFFER
, gl
[testParams
.internalformat
], gl
.SAMPLES
);
66 if (!samples
|| !samples
.length
) {
67 testFailed("Could not query supported sample counts for required multisampling format " + testParams
.internalformat
);
71 // Note that supported sample counts are required to be reported in descending order.
72 debug('Testing with sample count ' + samples
[0]);
73 // Create a framebuffer with a multisampled renderbuffer with the maximum supported number of samples.
74 let rb
= gl
.createRenderbuffer();
75 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb
);
76 gl
.renderbufferStorageMultisample(gl
.RENDERBUFFER
, samples
[0], gl
[testParams
.internalformat
], 1, 1);
77 let fb
= gl
.createFramebuffer();
78 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
79 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb
);
80 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
81 testFailed("Rendering to a multisampled renderbuffer of format " + testParams
.internalformat
+ " is required.");
85 // Create a program that will choose between one of different possible colors in the fragment shader.
86 // It should be evaluated only once per framebuffer pixel, so only one of the colors will end up in the framebuffer.
87 // However, if the multisampling mode is incorrectly implemented by supersampling, the samples may have different
89 let program
= wtu
.setupProgram(gl
, ["vshader", "fshader"], ["aPosition"]);
91 // Render one triangle using the program. The triangle needs to extend far outside the viewport on all sides, so
92 // that we can safely assume all samples fall inside the triangle. GLES 3.0.5:
93 // "The sample points associated with a pixel may be located inside or outside of the unit square that is considered to bound the pixel."
94 // Here we assume that sample points are less than 9999 pixels away from the pixel they are associated with.
95 let buffer
= gl
.createBuffer();
96 gl
.bindBuffer(gl
.ARRAY_BUFFER
, buffer
);
97 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([ 10000, 30000,
99 10000, -10000]), gl
.STATIC_DRAW
);
100 gl
.enableVertexAttribArray(0);
101 gl
.vertexAttribPointer(0, 2, gl
.FLOAT
, false, 0, 0);
102 gl
.drawArrays(gl
.TRIANGLES
, 0, 3);
104 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
105 gl
.blitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
106 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, null);
108 let readBuffer
= new Uint8Array(4);
109 gl
.readPixels(0, 0, 1, 1, gl
.RGBA
, gl
.UNSIGNED_BYTE
, readBuffer
);
111 // Check that the canvas is one of the colors that the fragment shader may generate, and not a blend of them.
112 let possibleColors
= [
117 let anyColorMatched
= false;
118 for (let i
= 0; i
< possibleColors
.length
; ++i
) {
119 let colorMatched
= true;
120 for (let j
= 0; j
< 4; ++j
) {
121 if (Math
.abs(readBuffer
[j
] - possibleColors
[i
][j
]) > 2) {
122 colorMatched
= false;
126 anyColorMatched
= true;
129 if (!anyColorMatched
) {
130 testFailed("Color in framebuffer was not one of the colors generated by the fragment shader: " + readBuffer
);
132 testPassed("Color in framebuffer was one of the colors generated by the fragment shader: " + readBuffer
);
136 runTest({internalformat
: 'RGBA8'});
138 var successfullyParsed
= true;
140 <script src=
"../../js/js-test-post.js"></script>