2 Copyright (c) 2022 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 framebuffer to texture conformance test.
</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>
17 <canvas id=
"canvas"></canvas>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
22 description("Test resolving multisample depth buffer");
23 debug('Reduced test case for <a href="https://bugs.webkit.org/show_bug.cgi?id=238118">https://bugs.webkit.org/show_bug.cgi?id=238118</a>');
25 // Reproduces an inconistent behavior where if:
26 // 1) You render into a multisampling frame buffer
27 // 2) Geometry is drawn with DEPTH_TEST disabled and then enabled
28 // 3) More than one frame is rendered via requestAnimationFrame
31 const halfSize
= size
/ 2;
33 let wtu
= WebGLTestUtils
;
34 let canvas
= document
.getElementById("canvas");
38 let gl
= wtu
.create3DContext("canvas", {}, 2);
40 function createTexture(res
, format
, bytes
) {
41 let texture
= gl
.createTexture();
42 gl
.bindTexture(gl
.TEXTURE_2D
, texture
);
43 gl
.texStorage2D(gl
.TEXTURE_2D
, 1, format
, res
, res
);
44 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
, gl
.NEAREST
);
45 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAG_FILTER
, gl
.NEAREST
);
46 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_S
, gl
.CLAMP_TO_EDGE
);
47 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_T
, gl
.CLAMP_TO_EDGE
);
48 gl
.bindTexture(gl
.TEXTURE_2D
, null);
52 function createRenderBuffer(res
, format
, samples
) {
53 let rb
= gl
.createRenderbuffer();
54 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb
);
56 gl
.renderbufferStorageMultisample(gl
.RENDERBUFFER
, samples
, format
, res
, res
);
58 gl
.renderbufferStorage(gl
.RENDERBUFFER
, format
, res
, res
);
62 let yellowQuadVAO
= gl
.createVertexArray();
63 gl
.bindVertexArray(yellowQuadVAO
);
64 let yellowQuadProgram
= wtu
.setupColorQuad(gl
, 0, { scale
: 0.75 });
66 let blueQuadVAO
= gl
.createVertexArray();
67 gl
.bindVertexArray(blueQuadVAO
);
68 let blueQuadProgram
= wtu
.setupColorQuad(gl
, 0, { scale
: 0.5 });
70 let fsVAO
= gl
.createVertexArray();
71 gl
.bindVertexArray(fsVAO
);
72 let fsProgram
= wtu
.setupTexturedQuad(gl
, 0, 1);
73 gl
.useProgram(fsProgram
);
74 let fsTexLoc
= gl
.getUniformLocation(fsProgram
, "tex");
75 gl
.uniform1i(fsTexLoc
, 0);
77 // An incorrect render can occur if...
79 // 1) You use renderbufferStorageMultisample.
80 const msaaSamples
= 4;
81 const colorRB
= createRenderBuffer(size
, gl
.RGBA8
, msaaSamples
);
82 const depthRB
= createRenderBuffer(size
, gl
.DEPTH_COMPONENT16
, msaaSamples
);
83 const resolveTex
= createTexture(size
, gl
.RGBA8
);
85 let renderFBO
= gl
.createFramebuffer();
86 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, renderFBO
);
87 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, colorRB
);
88 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.DEPTH_ATTACHMENT
, gl
.RENDERBUFFER
, depthRB
);
90 let resolveFBO
= gl
.createFramebuffer();
91 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, resolveFBO
);
92 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, resolveTex
, 0);
93 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
95 gl
.disable(gl
.CULL_FACE
);
100 // 2) Render from requestAnimationFrame, only starting with the 2nd frame.
101 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, renderFBO
);
103 // Clear background red
104 gl
.clearColor(1, 0, 0, 1);
105 gl
.clear(gl
.COLOR_BUFFER_BIT
|gl
.DEPTH_BUFFER_BIT
);
107 // 3) You disable gl.DEPTH_TEST
108 gl
.disable(gl
.DEPTH_TEST
);
111 gl
.bindVertexArray(yellowQuadVAO
);
112 gl
.useProgram(yellowQuadProgram
);
113 wtu
.drawUByteColorQuad(gl
, [ 255, 255, 0, 255 ]);
115 // 4) And re-enable gl.DEPTH_TEST
116 gl
.enable(gl
.DEPTH_TEST
);
119 gl
.bindVertexArray(blueQuadVAO
);
120 gl
.useProgram(blueQuadProgram
);
121 wtu
.drawUByteColorQuad(gl
, [ 0, 0, 255, 255 ]);
123 // Resolve the multisample framebuffer to a texture
124 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, renderFBO
);
125 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, resolveFBO
);
126 gl
.clearBufferfv(gl
.COLOR
, 0, [0.0, 0.0, 0.0, 0.0]);
127 gl
.blitFramebuffer(0, 0, size
, size
,
129 gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
130 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, null);
131 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
133 // Draw the resolved texture to the backbuffer
134 gl
.bindTexture(gl
.TEXTURE_2D
, resolveTex
);
135 gl
.useProgram(fsProgram
);
136 gl
.bindVertexArray(fsVAO
);
137 wtu
.drawUnitQuad(gl
);
139 // 5) The incorrect render can occur on the second rendered frame, called from
140 // requestAnimationFrame.
142 if (frameCount
== 2) {
143 checkRenderingResults("multisampling-depth-resolve");
144 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "Should be no errors at the end of the test.");
147 requestAnimationFrame(runTest
);
151 requestAnimationFrame(runTest
);
153 function checkRenderingResults(prefix
) {
154 // Outer color should be red
155 wtu
.checkCanvasRect(gl
,
159 prefix
+ ": outer pixels should be red");
161 // Outer quad should be rendered yellow.
162 wtu
.checkCanvasRect(gl
,
166 prefix
+ ": outer quad should be yellow");
168 // Center quad should be rendered blue.
169 wtu
.checkCanvasRect(gl
,
170 halfSize
/ 2 + 1, halfSize
/ 2 + 1,
173 prefix
+ ": center quad should be blue");
176 var successfullyParsed
= true;