xref: /aosp_15_r20/external/angle/src/tests/gl_tests/RobustFragmentShaderOutputTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // RobustFragmentShaderOutputTest: Tests for the custom ANGLE extension.
7 
8 #include "test_utils/ANGLETest.h"
9 #include "test_utils/gl_raii.h"
10 
11 #include "util/random_utils.h"
12 
13 #include <stdint.h>
14 
15 using namespace angle;
16 
17 namespace
18 {
ExtEnabled()19 bool ExtEnabled()
20 {
21     return IsGLExtensionEnabled("GL_ANGLE_robust_fragment_shader_output");
22 }
23 }  // namespace
24 
25 class RobustFragmentShaderOutputTest : public ANGLETest<>
26 {
27   public:
RobustFragmentShaderOutputTest()28     RobustFragmentShaderOutputTest() {}
29 };
30 
31 // Basic behaviour from the extension.
TEST_P(RobustFragmentShaderOutputTest,Basic)32 TEST_P(RobustFragmentShaderOutputTest, Basic)
33 {
34     ANGLE_SKIP_TEST_IF(!ExtEnabled());
35 
36     const char kFS[] = R"(#version 300 es
37 precision mediump float;
38 out vec4 outvar;
39 void main() {
40     outvar = vec4(0.0, 1.0, 0.0, 1.0);
41 })";
42     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
43 
44     GLFramebuffer framebuffer;
45     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
46 
47     constexpr GLsizei kSize = 2;
48     std::vector<GLColor> bluePixels(kSize * kSize, GLColor::blue);
49 
50     GLTexture texA;
51     glBindTexture(GL_TEXTURE_2D, texA);
52     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
53                  bluePixels.data());
54     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texA, 0);
55 
56     GLTexture texB;
57     glBindTexture(GL_TEXTURE_2D, texB);
58     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
59                  bluePixels.data());
60     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texB, 0);
61 
62     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
63 
64     // Verify initial attachment colors (blue).
65     glReadBuffer(GL_COLOR_ATTACHMENT0);
66     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
67 
68     glReadBuffer(GL_COLOR_ATTACHMENT1);
69     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
70 
71     constexpr std::array<GLenum, 2> kDrawBuffers = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
72     glDrawBuffers(2, kDrawBuffers.data());
73     glViewport(0, 0, kSize, kSize);
74     glUseProgram(program);
75     ASSERT_GL_NO_ERROR();
76 
77     // Draw, verify first attachment is updated (green) and second is unchanged (blue).
78     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f, 1.0f, true);
79     ASSERT_GL_NO_ERROR();
80 
81     glReadBuffer(GL_COLOR_ATTACHMENT0);
82     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
83 
84     glReadBuffer(GL_COLOR_ATTACHMENT1);
85     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
86 }
87 
88 // Test that changing framebuffer attachments work
TEST_P(RobustFragmentShaderOutputTest,ChangingFramebufferAttachments)89 TEST_P(RobustFragmentShaderOutputTest, ChangingFramebufferAttachments)
90 {
91     ANGLE_SKIP_TEST_IF(!ExtEnabled());
92 
93     const char kFS[] = R"(#version 300 es
94 precision mediump float;
95 layout(location = 1) out vec4 color1;
96 layout(location = 3) out vec4 color2;
97 
98 uniform vec4 color1In;
99 uniform vec4 color2In;
100 
101 void main() {
102     color1 = color1In;
103     color2 = color2In;
104 })";
105     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
106     glUseProgram(program);
107 
108     GLint color1Loc = glGetUniformLocation(program, "color1In");
109     ASSERT_NE(color1Loc, -1);
110     GLint color2Loc = glGetUniformLocation(program, "color2In");
111     ASSERT_NE(color2Loc, -1);
112 
113     constexpr GLsizei kSize = 2;
114     const std::vector<GLColor> initColor(kSize * kSize, GLColor::transparentBlack);
115 
116     GLTexture color1;
117     glBindTexture(GL_TEXTURE_2D, color1);
118     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
119                  initColor.data());
120 
121     GLTexture color2;
122     glBindTexture(GL_TEXTURE_2D, color2);
123     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
124                  initColor.data());
125 
126     GLTexture color3;
127     glBindTexture(GL_TEXTURE_2D, color3);
128     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
129                  initColor.data());
130 
131     // Draw with matching framebuffer attachments
132     GLFramebuffer framebuffer;
133     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
134     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color1, 0);
135     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color2, 0);
136     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
137 
138     std::array<GLenum, 4> drawBuffers = {GL_NONE, GL_COLOR_ATTACHMENT1, GL_NONE,
139                                          GL_COLOR_ATTACHMENT3};
140     glDrawBuffers(4, drawBuffers.data());
141     glViewport(0, 0, kSize, kSize);
142     ASSERT_GL_NO_ERROR();
143 
144     glEnable(GL_BLEND);
145     glBlendFunc(GL_ONE, GL_ONE);
146 
147     // Draw once, should update color1 and color2
148     glUniform4f(color1Loc, 1, 0, 0, 0);
149     glUniform4f(color2Loc, 0, 1, 0, 0);
150     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
151 
152     // Change the framebuffer attachments, this time adding an attachment that's not written to.
153     // This attachment should be unmodified.
154     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color3, 0);
155     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
156     drawBuffers[0] = GL_COLOR_ATTACHMENT0;
157     glDrawBuffers(4, drawBuffers.data());
158 
159     glUniform4f(color1Loc, 0, 0, 1, 1);
160     glUniform4f(color2Loc, 0, 0, 0, 1);
161     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
162 
163     // Shuffle attachments.
164     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
165     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color2, 0);
166     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color3, 0);
167     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
168 
169     glUniform4f(color1Loc, 0, 0, 1, 0);
170     glUniform4f(color2Loc, 1, 0, 0, 1);
171     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
172 
173     // Switch back to matching attachment count
174     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
175     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
176     drawBuffers[0] = GL_NONE;
177     glDrawBuffers(4, drawBuffers.data());
178 
179     glUniform4f(color1Loc, 1, 0, 0, 0);
180     glUniform4f(color2Loc, 0, 1, 0, 0);
181     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
182 
183     // Verify results
184     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
185     glReadBuffer(GL_COLOR_ATTACHMENT0);
186     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::magenta);
187 
188     glReadBuffer(GL_COLOR_ATTACHMENT1);
189     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::white);
190 
191     glReadBuffer(GL_COLOR_ATTACHMENT3);
192     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::yellow);
193 
194     ASSERT_GL_NO_ERROR();
195 }
196 
197 // Test that changing framebuffers work
TEST_P(RobustFragmentShaderOutputTest,ChangingFramebuffers)198 TEST_P(RobustFragmentShaderOutputTest, ChangingFramebuffers)
199 {
200     ANGLE_SKIP_TEST_IF(!ExtEnabled());
201 
202     const char kFS[] = R"(#version 300 es
203 precision mediump float;
204 layout(location = 1) out vec4 color1;
205 layout(location = 3) out vec4 color2;
206 
207 uniform vec4 color1In;
208 uniform vec4 color2In;
209 
210 void main() {
211     color1 = color1In;
212     color2 = color2In;
213 })";
214     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
215     glUseProgram(program);
216 
217     GLint color1Loc = glGetUniformLocation(program, "color1In");
218     ASSERT_NE(color1Loc, -1);
219     GLint color2Loc = glGetUniformLocation(program, "color2In");
220     ASSERT_NE(color2Loc, -1);
221 
222     constexpr GLsizei kSize = 2;
223     const std::vector<GLColor> initColor(kSize * kSize, GLColor::transparentBlack);
224 
225     GLTexture color1;
226     glBindTexture(GL_TEXTURE_2D, color1);
227     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
228                  initColor.data());
229 
230     GLTexture color2;
231     glBindTexture(GL_TEXTURE_2D, color2);
232     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
233                  initColor.data());
234 
235     GLTexture color3;
236     glBindTexture(GL_TEXTURE_2D, color3);
237     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
238                  initColor.data());
239 
240     GLFramebuffer framebuffer1;
241     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
242     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color1, 0);
243     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color2, 0);
244     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
245 
246     GLFramebuffer framebuffer2;
247     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
248     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color1, 0);
249     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color2, 0);
250     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color3, 0);
251     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
252 
253     GLFramebuffer framebuffer3;
254     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer3);
255     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
256     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color2, 0);
257     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color3, 0);
258     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
259 
260     GLFramebuffer framebuffer4;
261     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer4);
262     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color2, 0);
263     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color3, 0);
264     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
265 
266     // Draw with matching framebuffer attachments
267     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
268 
269     std::array<GLenum, 4> drawBuffers = {GL_NONE, GL_COLOR_ATTACHMENT1, GL_NONE,
270                                          GL_COLOR_ATTACHMENT3};
271     glDrawBuffers(4, drawBuffers.data());
272     glViewport(0, 0, kSize, kSize);
273     ASSERT_GL_NO_ERROR();
274 
275     glEnable(GL_BLEND);
276     glBlendFunc(GL_ONE, GL_ONE);
277 
278     // Draw once, should update color1 and color2
279     glUniform4f(color1Loc, 1, 0, 0, 0);
280     glUniform4f(color2Loc, 0, 1, 0, 0);
281     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
282 
283     // Change the framebuffer attachments, this time adding an attachment that's not written to.
284     // This attachment should be unmodified.
285     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
286 
287     drawBuffers[0] = GL_COLOR_ATTACHMENT0;
288     glDrawBuffers(4, drawBuffers.data());
289 
290     glUniform4f(color1Loc, 0, 0, 1, 1);
291     glUniform4f(color2Loc, 0, 0, 0, 1);
292     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
293 
294     // Shuffle attachments.
295     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer3);
296     glDrawBuffers(4, drawBuffers.data());
297 
298     glUniform4f(color1Loc, 0, 0, 1, 0);
299     glUniform4f(color2Loc, 1, 0, 0, 1);
300     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
301 
302     // Switch back to matching attachment count
303     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer4);
304 
305     drawBuffers[0] = GL_NONE;
306     glDrawBuffers(4, drawBuffers.data());
307 
308     glUniform4f(color1Loc, 1, 0, 0, 0);
309     glUniform4f(color2Loc, 0, 1, 0, 0);
310     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
311 
312     // Verify results
313     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer3);
314     glReadBuffer(GL_COLOR_ATTACHMENT0);
315     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::magenta);
316 
317     glReadBuffer(GL_COLOR_ATTACHMENT1);
318     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::white);
319 
320     glReadBuffer(GL_COLOR_ATTACHMENT3);
321     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::yellow);
322 
323     ASSERT_GL_NO_ERROR();
324 }
325 
326 // Test that changing program outputs work
TEST_P(RobustFragmentShaderOutputTest,ChangingProgramOutputs)327 TEST_P(RobustFragmentShaderOutputTest, ChangingProgramOutputs)
328 {
329     ANGLE_SKIP_TEST_IF(!ExtEnabled());
330 
331     const char kFS1[] = R"(#version 300 es
332 precision mediump float;
333 layout(location = 1) out vec4 color1;
334 
335 uniform vec4 color1In;
336 
337 void main() {
338     color1 = color1In;
339 })";
340 
341     const char kFS2[] = R"(#version 300 es
342 precision mediump float;
343 layout(location = 1) out vec4 color1;
344 layout(location = 3) out vec4 color2;
345 
346 uniform vec4 color1In;
347 uniform vec4 color2In;
348 
349 void main() {
350     color1 = color1In;
351     color2 = color2In;
352 })";
353 
354     const char kFS3[] = R"(#version 300 es
355 precision mediump float;
356 layout(location = 0) out vec4 color1;
357 layout(location = 1) out vec4 color2;
358 layout(location = 3) out vec4 color3;
359 
360 uniform vec4 color1In;
361 uniform vec4 color2In;
362 uniform vec4 color3In;
363 
364 void main() {
365     color1 = color1In;
366     color2 = color2In;
367     color3 = color3In;
368 })";
369 
370     ANGLE_GL_PROGRAM(program1, essl3_shaders::vs::Simple(), kFS1);
371     glUseProgram(program1);
372     GLint program1Color1Loc = glGetUniformLocation(program1, "color1In");
373     ASSERT_NE(program1Color1Loc, -1);
374 
375     ANGLE_GL_PROGRAM(program2, essl3_shaders::vs::Simple(), kFS2);
376     glUseProgram(program2);
377     GLint program2Color1Loc = glGetUniformLocation(program2, "color1In");
378     ASSERT_NE(program2Color1Loc, -1);
379     GLint program2Color2Loc = glGetUniformLocation(program2, "color2In");
380     ASSERT_NE(program2Color2Loc, -1);
381 
382     ANGLE_GL_PROGRAM(program3, essl3_shaders::vs::Simple(), kFS3);
383     glUseProgram(program3);
384     GLint program3Color1Loc = glGetUniformLocation(program3, "color1In");
385     ASSERT_NE(program2Color1Loc, -1);
386     GLint program3Color2Loc = glGetUniformLocation(program3, "color2In");
387     ASSERT_NE(program2Color2Loc, -1);
388     GLint program3Color3Loc = glGetUniformLocation(program3, "color3In");
389     ASSERT_NE(program3Color3Loc, -1);
390 
391     constexpr GLsizei kSize = 2;
392     const std::vector<GLColor> initColor(kSize * kSize, GLColor::transparentBlack);
393 
394     GLTexture color1;
395     glBindTexture(GL_TEXTURE_2D, color1);
396     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
397                  initColor.data());
398 
399     GLTexture color2;
400     glBindTexture(GL_TEXTURE_2D, color2);
401     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
402                  initColor.data());
403 
404     GLTexture color3;
405     glBindTexture(GL_TEXTURE_2D, color3);
406     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSize, kSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
407                  initColor.data());
408 
409     // Draw with matching framebuffer attachments
410     GLFramebuffer framebuffer;
411     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
412     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
413     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, color2, 0);
414     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, color3, 0);
415     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
416 
417     std::array<GLenum, 4> drawBuffers = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_NONE,
418                                          GL_COLOR_ATTACHMENT3};
419     glDrawBuffers(4, drawBuffers.data());
420     glViewport(0, 0, kSize, kSize);
421     ASSERT_GL_NO_ERROR();
422 
423     glEnable(GL_BLEND);
424     glBlendFunc(GL_ONE, GL_ONE);
425 
426     // Draw with 2 outputs, should update color2 and color3
427     glUseProgram(program2);
428     glUniform4f(program2Color1Loc, 0.6, 0, 0, 0);
429     glUniform4f(program2Color2Loc, 0, 0.7, 0, 0);
430     drawQuad(program2, essl3_shaders::PositionAttrib(), 0.5f);
431 
432     // Draw with 1 output, should update color2
433     glUseProgram(program1);
434     glUniform4f(program1Color1Loc, 0.5, 0, 0, 0);
435     drawQuad(program1, essl3_shaders::PositionAttrib(), 0.5f);
436 
437     // Draw with 3 outputs, should update all
438     glUseProgram(program3);
439     glUniform4f(program3Color1Loc, 0, 0, 1, 1);
440     glUniform4f(program3Color2Loc, 0, 1, 0, 0);
441     glUniform4f(program3Color3Loc, 0, 0.4, 0, 0);
442     drawQuad(program3, essl3_shaders::PositionAttrib(), 0.5f);
443 
444     // Draw with 2 outputs again, should update color2 and color3
445     glUseProgram(program2);
446     glUniform4f(program2Color1Loc, 0, 0, 0, 1);
447     glUniform4f(program2Color2Loc, 0, 0, 0, 1);
448     drawQuad(program2, essl3_shaders::PositionAttrib(), 0.5f);
449 
450     // Verify results
451     glReadBuffer(GL_COLOR_ATTACHMENT0);
452     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::blue);
453 
454     glReadBuffer(GL_COLOR_ATTACHMENT1);
455     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::yellow);
456 
457     glReadBuffer(GL_COLOR_ATTACHMENT3);
458     EXPECT_PIXEL_RECT_EQ(0, 0, kSize, kSize, GLColor::green);
459 
460     ASSERT_GL_NO_ERROR();
461 }
462 
463 ANGLE_INSTANTIATE_TEST_ES3(RobustFragmentShaderOutputTest);
464