xref: /aosp_15_r20/external/angle/src/tests/gl_tests/LinkAndRelinkTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2017 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 // LinkAndRelinkFailureTest:
7 //   Link and relink failure tests for rendering pipeline and compute pipeline.
8 
9 #include <vector>
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
18 class LinkAndRelinkTest : public ANGLETest<>
19 {
20   protected:
LinkAndRelinkTest()21     LinkAndRelinkTest() {}
22 };
23 
24 class LinkAndRelinkTestES3 : public ANGLETest<>
25 {
26   protected:
LinkAndRelinkTestES3()27     LinkAndRelinkTestES3() {}
28 };
29 
30 class LinkAndRelinkTestES31 : public ANGLETest<>
31 {
32   protected:
LinkAndRelinkTestES31()33     LinkAndRelinkTestES31() {}
34 };
35 
36 // Test destruction of a context with a pending relink of the current in-use
37 // program.
TEST_P(LinkAndRelinkTest,DestructionWithPendingRelink)38 TEST_P(LinkAndRelinkTest, DestructionWithPendingRelink)
39 {
40     constexpr char kVS[] = "void main() {}";
41     constexpr char kFS[] = "void main() {}";
42 
43     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
44     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
45 
46     GLuint program = glCreateProgram();
47     glAttachShader(program, vs);
48     glAttachShader(program, fs);
49 
50     glLinkProgram(program);
51     glUseProgram(program);
52     glLinkProgram(program);
53     EXPECT_GL_NO_ERROR();
54 }
55 
56 // When a program link or relink fails, if you try to install the unsuccessfully
57 // linked program (via UseProgram) and start rendering or dispatch compute,
58 // We can not always report INVALID_OPERATION for rendering/compute pipeline.
59 // The result depends on the previous state: Whether a valid program is
60 // installed in current GL state before the link.
61 // If a program successfully relinks when it is in use, the program might
62 // change from a rendering program to a compute program in theory,
63 // or vice versa.
64 
65 // When program link fails and no valid rendering program is installed in the GL
66 // state before the link, it should report an error for UseProgram
TEST_P(LinkAndRelinkTest,RenderingProgramFailsWithoutProgramInstalled)67 TEST_P(LinkAndRelinkTest, RenderingProgramFailsWithoutProgramInstalled)
68 {
69     glUseProgram(0);
70     GLuint program = glCreateProgram();
71 
72     glLinkProgram(program);
73     GLint linkStatus;
74     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
75     EXPECT_GL_FALSE(linkStatus);
76 
77     glUseProgram(program);
78     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
79 
80     glDrawArrays(GL_POINTS, 0, 1);
81     EXPECT_GL_NO_ERROR();
82 }
83 
84 // When program link or relink fails and a valid rendering program is installed
85 // in the GL state before the link, using the failed program via UseProgram
86 // should report an error, but starting rendering should succeed.
87 // However, dispatching compute always fails.
TEST_P(LinkAndRelinkTest,RenderingProgramFailsWithProgramInstalled)88 TEST_P(LinkAndRelinkTest, RenderingProgramFailsWithProgramInstalled)
89 {
90     // Install a render program in current GL state via UseProgram, then render.
91     // It should succeed.
92     constexpr char kVS[] = "void main() {}";
93     constexpr char kFS[] = "void main() {}";
94 
95     GLuint program = glCreateProgram();
96 
97     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
98     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
99 
100     EXPECT_NE(0u, vs);
101     EXPECT_NE(0u, fs);
102 
103     glAttachShader(program, vs);
104     glDeleteShader(vs);
105 
106     glAttachShader(program, fs);
107     glDeleteShader(fs);
108 
109     glLinkProgram(program);
110 
111     GLint linkStatus;
112     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
113     EXPECT_GL_TRUE(linkStatus);
114 
115     EXPECT_GL_NO_ERROR();
116 
117     glUseProgram(program);
118     EXPECT_GL_NO_ERROR();
119     glDrawArrays(GL_POINTS, 0, 1);
120     EXPECT_GL_NO_ERROR();
121 
122     glDispatchCompute(8, 4, 2);
123     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
124 
125     // Link failure, and a valid program has been installed in the GL state.
126     GLuint programNull = glCreateProgram();
127 
128     glLinkProgram(programNull);
129     glGetProgramiv(programNull, GL_LINK_STATUS, &linkStatus);
130     EXPECT_GL_FALSE(linkStatus);
131 
132     // Starting rendering should succeed.
133     glDrawArrays(GL_POINTS, 0, 1);
134     EXPECT_GL_NO_ERROR();
135 
136     glDispatchCompute(8, 4, 2);
137     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
138 
139     // Using the unsuccessfully linked program should report an error.
140     glUseProgram(programNull);
141     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
142 
143     // Using the unsuccessfully linked program, that program should not
144     // replace the program binary residing in the GL state. It will not make
145     // the installed program invalid either, like what UseProgram(0) can do.
146     // So, starting rendering should succeed.
147     glDrawArrays(GL_POINTS, 0, 1);
148     EXPECT_GL_NO_ERROR();
149 
150     glDispatchCompute(8, 4, 2);
151     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
152 
153     // We try to relink the installed program, but make it fail.
154 
155     // No vertex shader, relink fails.
156     glDetachShader(program, vs);
157     glLinkProgram(program);
158     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
159     EXPECT_GL_FALSE(linkStatus);
160     EXPECT_GL_NO_ERROR();
161 
162     // Starting rendering should succeed.
163     glDrawArrays(GL_POINTS, 0, 1);
164     EXPECT_GL_NO_ERROR();
165 
166     glDispatchCompute(8, 4, 2);
167     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
168 
169     // Using the unsuccessfully relinked program should report an error.
170     glUseProgram(program);
171     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
172 
173     // Using the unsuccessfully relinked program, that program should not
174     // replace the program binary residing in the GL state. It will not make
175     // the installed program invalid either, like what UseProgram(0) can do.
176     // So, starting rendering should succeed.
177     glDrawArrays(GL_POINTS, 0, 1);
178     EXPECT_GL_NO_ERROR();
179 
180     glDispatchCompute(8, 4, 2);
181     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
182 }
183 
184 // Tests uniform default values.
TEST_P(LinkAndRelinkTest,UniformDefaultValues)185 TEST_P(LinkAndRelinkTest, UniformDefaultValues)
186 {
187     // TODO(anglebug.com/42262609): Understand why rectangle texture CLs made this fail.
188     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
189     constexpr char kFS[] = R"(precision mediump float;
190 uniform vec4 u_uniform;
191 
192 bool isZero(vec4 value) {
193     return value == vec4(0,0,0,0);
194 }
195 
196 void main()
197 {
198     gl_FragColor = isZero(u_uniform) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
199 })";
200 
201     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
202     glUseProgram(program);
203 
204     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
205     ASSERT_GL_NO_ERROR();
206     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
207 
208     GLint loc = glGetUniformLocation(program, "u_uniform");
209     ASSERT_NE(-1, loc);
210     glUniform4f(loc, 0.1f, 0.2f, 0.3f, 0.4f);
211 
212     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
213     ASSERT_GL_NO_ERROR();
214     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
215 
216     glLinkProgram(program);
217     ASSERT_GL_NO_ERROR();
218 
219     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
220     ASSERT_GL_NO_ERROR();
221     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
222 }
223 
224 // When program link fails and no valid compute program is installed in the GL
225 // state before the link, it should report an error for UseProgram and
226 // DispatchCompute.
TEST_P(LinkAndRelinkTestES31,ComputeProgramFailsWithoutProgramInstalled)227 TEST_P(LinkAndRelinkTestES31, ComputeProgramFailsWithoutProgramInstalled)
228 {
229     glUseProgram(0);
230     GLuint program = glCreateProgram();
231 
232     glLinkProgram(program);
233     GLint linkStatus;
234     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
235     EXPECT_GL_FALSE(linkStatus);
236 
237     glUseProgram(program);
238     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
239 
240     glDispatchCompute(8, 4, 2);
241     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
242 }
243 
244 // When program link or relink fails and a valid compute program is installed in
245 // the GL state before the link, using the failed program via UseProgram should
246 // report an error, but dispatching compute should succeed.
TEST_P(LinkAndRelinkTestES31,ComputeProgramFailsWithProgramInstalled)247 TEST_P(LinkAndRelinkTestES31, ComputeProgramFailsWithProgramInstalled)
248 {
249     // Install a compute program in the GL state via UseProgram, then dispatch
250     // compute. It should succeed.
251     constexpr char kCS[] =
252         R"(#version 310 es
253         layout(local_size_x=1) in;
254         void main()
255         {
256         })";
257 
258     GLuint program = glCreateProgram();
259 
260     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
261     EXPECT_NE(0u, cs);
262 
263     glAttachShader(program, cs);
264     glDeleteShader(cs);
265 
266     glLinkProgram(program);
267     GLint linkStatus;
268     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
269     EXPECT_GL_TRUE(linkStatus);
270 
271     EXPECT_GL_NO_ERROR();
272 
273     glUseProgram(program);
274     EXPECT_GL_NO_ERROR();
275     glDispatchCompute(8, 4, 2);
276     EXPECT_GL_NO_ERROR();
277 
278     glDrawArrays(GL_POINTS, 0, 1);
279     EXPECT_GL_NO_ERROR();
280 
281     // Link failure, and a valid program has been installed in the GL state.
282     GLuint programNull = glCreateProgram();
283 
284     glLinkProgram(programNull);
285     glGetProgramiv(programNull, GL_LINK_STATUS, &linkStatus);
286     EXPECT_GL_FALSE(linkStatus);
287 
288     // Dispatching compute should succeed.
289     glDispatchCompute(8, 4, 2);
290     EXPECT_GL_NO_ERROR();
291 
292     glDrawArrays(GL_POINTS, 0, 1);
293     EXPECT_GL_NO_ERROR();
294 
295     // Using the unsuccessfully linked program should report an error.
296     glUseProgram(programNull);
297     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
298 
299     // Using the unsuccessfully linked program, that program should not
300     // replace the program binary residing in the GL state. It will not make
301     // the installed program invalid either, like what UseProgram(0) can do.
302     // So, dispatching compute should succeed.
303     glDispatchCompute(8, 4, 2);
304     EXPECT_GL_NO_ERROR();
305 
306     glDrawArrays(GL_POINTS, 0, 1);
307     EXPECT_GL_NO_ERROR();
308 
309     // We try to relink the installed program, but make it fail.
310 
311     // No compute shader, relink fails.
312     glDetachShader(program, cs);
313     glLinkProgram(program);
314     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
315     EXPECT_GL_FALSE(linkStatus);
316     EXPECT_GL_NO_ERROR();
317 
318     // Dispatching compute should succeed.
319     glDispatchCompute(8, 4, 2);
320     EXPECT_GL_NO_ERROR();
321 
322     glDrawArrays(GL_POINTS, 0, 1);
323     EXPECT_GL_NO_ERROR();
324 
325     // Using the unsuccessfully relinked program should report an error.
326     glUseProgram(program);
327     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
328 
329     // Using the unsuccessfully relinked program, that program should not
330     // replace the program binary residing in the GL state. It will not make
331     // the installed program invalid either, like what UseProgram(0) can do.
332     // So, dispatching compute should succeed.
333     glDispatchCompute(8, 4, 2);
334     EXPECT_GL_NO_ERROR();
335 
336     glDrawArrays(GL_POINTS, 0, 1);
337     EXPECT_GL_NO_ERROR();
338 }
339 
340 // If you compile and link a compute program successfully and use the program,
341 // then dispatching compute and rendering can succeed (with undefined behavior).
342 // If you relink the compute program to a rendering program when it is in use,
343 // then dispatching compute will fail, but starting rendering can succeed.
TEST_P(LinkAndRelinkTestES31,RelinkProgramSucceedsFromComputeToRendering)344 TEST_P(LinkAndRelinkTestES31, RelinkProgramSucceedsFromComputeToRendering)
345 {
346     constexpr char kCS[] = R"(#version 310 es
347 layout(local_size_x=1) in;
348 void main()
349 {
350 })";
351 
352     GLuint program = glCreateProgram();
353 
354     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
355     EXPECT_NE(0u, cs);
356 
357     glAttachShader(program, cs);
358     glDeleteShader(cs);
359 
360     glLinkProgram(program);
361     glDetachShader(program, cs);
362     GLint linkStatus;
363     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
364     EXPECT_GL_TRUE(linkStatus);
365 
366     EXPECT_GL_NO_ERROR();
367 
368     glUseProgram(program);
369     EXPECT_GL_NO_ERROR();
370     glDispatchCompute(8, 4, 2);
371     EXPECT_GL_NO_ERROR();
372 
373     glDrawArrays(GL_POINTS, 0, 1);
374     EXPECT_GL_NO_ERROR();
375 
376     constexpr char kVS[] = "void main() {}";
377     constexpr char kFS[] = "void main() {}";
378 
379     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
380     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
381     EXPECT_NE(0u, vs);
382     EXPECT_NE(0u, fs);
383 
384     glAttachShader(program, vs);
385     glDeleteShader(vs);
386 
387     glAttachShader(program, fs);
388     glDeleteShader(fs);
389 
390     glLinkProgram(program);
391     glDetachShader(program, vs);
392     glDetachShader(program, fs);
393     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
394     EXPECT_GL_TRUE(linkStatus);
395 
396     EXPECT_GL_NO_ERROR();
397 
398     glDrawArrays(GL_POINTS, 0, 1);
399     EXPECT_GL_NO_ERROR();
400 
401     glDispatchCompute(8, 4, 2);
402     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
403 }
404 
405 // If you compile and link a rendering program successfully and use the program,
406 // then starting rendering can succeed, while dispatching compute will fail.
407 // If you relink the rendering program to a compute program when it is in use,
408 // then starting rendering will fail, but dispatching compute can succeed.
TEST_P(LinkAndRelinkTestES31,RelinkProgramSucceedsFromRenderingToCompute)409 TEST_P(LinkAndRelinkTestES31, RelinkProgramSucceedsFromRenderingToCompute)
410 {
411     // http://anglebug.com/42263641
412     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
413 
414     constexpr char kVS[] = "void main() {}";
415     constexpr char kFS[] = "void main() {}";
416 
417     GLuint program = glCreateProgram();
418 
419     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
420     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
421 
422     EXPECT_NE(0u, vs);
423     EXPECT_NE(0u, fs);
424 
425     glAttachShader(program, vs);
426     glDeleteShader(vs);
427 
428     glAttachShader(program, fs);
429     glDeleteShader(fs);
430 
431     glLinkProgram(program);
432     glDetachShader(program, vs);
433     glDetachShader(program, fs);
434     GLint linkStatus;
435     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
436     EXPECT_GL_TRUE(linkStatus);
437 
438     EXPECT_GL_NO_ERROR();
439 
440     glUseProgram(program);
441     EXPECT_GL_NO_ERROR();
442     glDrawArrays(GL_POINTS, 0, 1);
443     EXPECT_GL_NO_ERROR();
444 
445     glDispatchCompute(8, 4, 2);
446     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
447 
448     constexpr char kCS[] = R"(#version 310 es
449 layout(local_size_x=1) in;
450 void main()
451 {
452 })";
453 
454     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
455     EXPECT_NE(0u, cs);
456 
457     glAttachShader(program, cs);
458     glDeleteShader(cs);
459 
460     glLinkProgram(program);
461     glDetachShader(program, cs);
462     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
463     EXPECT_GL_TRUE(linkStatus);
464 
465     EXPECT_GL_NO_ERROR();
466 
467     glDispatchCompute(8, 4, 2);
468     EXPECT_GL_NO_ERROR();
469 
470     glDrawArrays(GL_POINTS, 0, 1);
471     EXPECT_GL_NO_ERROR();
472 }
473 
474 // Parallel link should continue unscathed even if the attached shaders to the program are modified.
TEST_P(LinkAndRelinkTestES31,ReattachShadersWhileParallelLinking)475 TEST_P(LinkAndRelinkTestES31, ReattachShadersWhileParallelLinking)
476 {
477     constexpr char kVS[]      = R"(#version 300 es
478 void main()
479 {
480     vec2 position = vec2(-1, -1);
481     if (gl_VertexID == 1)
482         position = vec2(3, -1);
483     else if (gl_VertexID == 2)
484         position = vec2(-1, 3);
485     gl_Position = vec4(position, 0, 1);
486 })";
487     constexpr char kFSGreen[] = R"(#version 300 es
488 out mediump vec4 color;
489 void main()
490 {
491     color = vec4(0, 1, 0, 1);
492 })";
493     constexpr char kFSRed[]   = R"(#version 300 es
494 out mediump vec4 color;
495 void main()
496 {
497     color = vec4(1, 0, 0, 1);
498 })";
499 
500     GLuint program = glCreateProgram();
501 
502     GLuint vs    = CompileShader(GL_VERTEX_SHADER, kVS);
503     GLuint green = CompileShader(GL_FRAGMENT_SHADER, kFSGreen);
504     GLuint red   = CompileShader(GL_FRAGMENT_SHADER, kFSRed);
505 
506     EXPECT_NE(0u, vs);
507     EXPECT_NE(0u, green);
508     EXPECT_NE(0u, red);
509 
510     glAttachShader(program, vs);
511     glAttachShader(program, green);
512     glLinkProgram(program);
513     ASSERT_GL_NO_ERROR();
514 
515     // Immediately reattach another shader
516     glDetachShader(program, green);
517     glAttachShader(program, red);
518     ASSERT_GL_NO_ERROR();
519 
520     // Make sure the linked program draws with green
521     glUseProgram(program);
522     ASSERT_GL_NO_ERROR();
523 
524     glDrawArrays(GL_TRIANGLES, 0, 3);
525     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
526     ASSERT_GL_NO_ERROR();
527 
528     glDeleteShader(vs);
529     glDeleteShader(green);
530     glDeleteShader(red);
531     ASSERT_GL_NO_ERROR();
532 }
533 
534 // Parallel link should continue unscathed even if new shaders are attached to the program.
TEST_P(LinkAndRelinkTestES31,AttachNewShadersWhileParallelLinking)535 TEST_P(LinkAndRelinkTestES31, AttachNewShadersWhileParallelLinking)
536 {
537     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
538 
539     constexpr char kVS[] = R"(#version 310 es
540 #extension GL_EXT_geometry_shader : require
541 void main()
542 {
543     vec2 position = vec2(-1, -1);
544     if (gl_VertexID == 1)
545         position = vec2(3, -1);
546     else if (gl_VertexID == 2)
547         position = vec2(-1, 3);
548     gl_Position = vec4(position, 0, 1);
549 })";
550     constexpr char kFS[] = R"(#version 310 es
551 #extension GL_EXT_geometry_shader : require
552 out mediump vec4 color;
553 void main()
554 {
555     color = vec4(0, 1, 0, 1);
556 })";
557     constexpr char kGS[] = R"(#version 310 es
558 #extension GL_EXT_geometry_shader : require
559 layout (invocations = 3, triangles) in;
560 layout (triangle_strip, max_vertices = 3) out;
561 void main()
562 {
563 })";
564 
565     GLuint program = glCreateProgram();
566 
567     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
568     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
569     GLuint gs = CompileShader(GL_GEOMETRY_SHADER, kGS);
570 
571     EXPECT_NE(0u, vs);
572     EXPECT_NE(0u, fs);
573     EXPECT_NE(0u, gs);
574 
575     glAttachShader(program, vs);
576     glAttachShader(program, fs);
577     glLinkProgram(program);
578     ASSERT_GL_NO_ERROR();
579 
580     // Immediately attach another shader
581     glAttachShader(program, gs);
582     ASSERT_GL_NO_ERROR();
583 
584     // Make sure the linked program draws with green
585     glUseProgram(program);
586     ASSERT_GL_NO_ERROR();
587 
588     glDrawArrays(GL_TRIANGLES, 0, 3);
589     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
590     ASSERT_GL_NO_ERROR();
591 
592     glDeleteShader(vs);
593     glDeleteShader(fs);
594     glDeleteShader(gs);
595     ASSERT_GL_NO_ERROR();
596 }
597 
598 // Make sure the shader can be compiled in between attach and link
TEST_P(LinkAndRelinkTest,AttachShaderThenCompile)599 TEST_P(LinkAndRelinkTest, AttachShaderThenCompile)
600 {
601     GLuint program = glCreateProgram();
602 
603     GLShader vs(GL_VERTEX_SHADER);
604     GLShader fs(GL_FRAGMENT_SHADER);
605 
606     // Attach the shaders to the program first.  This makes sure the program doesn't prematurely
607     // attempt to look into the shader's compilation result.
608     glAttachShader(program, vs);
609     glAttachShader(program, fs);
610 
611     // Compile the shaders after that.
612     const char *kVS = essl1_shaders::vs::Simple();
613     const char *kFS = essl1_shaders::fs::Green();
614     glShaderSource(vs, 1, &kVS, nullptr);
615     glShaderSource(fs, 1, &kFS, nullptr);
616     EXPECT_GL_NO_ERROR();
617 
618     glCompileShader(vs);
619     glCompileShader(fs);
620 
621     // Then link
622     glLinkProgram(program);
623     ASSERT_GL_NO_ERROR();
624 
625     // Make sure it works
626     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5);
627     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
628     ASSERT_GL_NO_ERROR();
629 
630     glDeleteProgram(program);
631     ASSERT_GL_NO_ERROR();
632 }
633 
634 // If a program is linked successfully once, it should retain its executable if a relink fails.
TEST_P(LinkAndRelinkTestES3,SuccessfulLinkThenFailingRelink)635 TEST_P(LinkAndRelinkTestES3, SuccessfulLinkThenFailingRelink)
636 {
637     // Install a render program in current GL state via UseProgram, then render.
638     // It should succeed.
639     constexpr char kVS[]    = R"(#version 300 es
640 out vec4 color;
641 void main()
642 {
643     vec2 position = vec2(-1, -1);
644     if (gl_VertexID == 1)
645         position = vec2(3, -1);
646     else if (gl_VertexID == 2)
647         position = vec2(-1, 3);
648 
649     gl_Position = vec4(position, 0, 1);
650     color = vec4(0, 1, 0, 1);
651 })";
652     constexpr char kBadFS[] = R"(#version 300 es
653 flat in uvec2 color;
654 out mediump vec4 colorOut;
655 void main()
656 {
657     colorOut = vec4(1, color, 1);
658 })";
659 
660     GLuint program = glCreateProgram();
661     GLuint vs      = CompileShader(GL_VERTEX_SHADER, kVS);
662     GLuint fs      = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Green());
663     GLuint badfs   = CompileShader(GL_FRAGMENT_SHADER, kBadFS);
664 
665     EXPECT_NE(0u, vs);
666     EXPECT_NE(0u, fs);
667     EXPECT_NE(0u, badfs);
668 
669     glAttachShader(program, vs);
670     glAttachShader(program, fs);
671 
672     glLinkProgram(program);
673 
674     GLint linkStatus;
675     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
676     EXPECT_GL_TRUE(linkStatus);
677 
678     EXPECT_GL_NO_ERROR();
679 
680     const int w = getWindowWidth();
681     const int h = getWindowHeight();
682 
683     glViewport(0, 0, w, h);
684 
685     glClearColor(0, 0, 0, 1);
686     glClear(GL_COLOR_BUFFER_BIT);
687 
688     glEnable(GL_SCISSOR_TEST);
689     glScissor(0, 0, w / 2, h / 2);
690 
691     glUseProgram(program);
692     glDrawArrays(GL_TRIANGLES, 0, 3);
693     EXPECT_GL_NO_ERROR();
694 
695     // Cause the program to fail linking
696     glDetachShader(program, fs);
697     glAttachShader(program, badfs);
698 
699     glLinkProgram(program);
700 
701     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
702     EXPECT_GL_FALSE(linkStatus);
703 
704     // Link failed, but the program should still be usable.
705     glScissor(w / 2, h / 2, w / 2, h / 2);
706     glDrawArrays(GL_TRIANGLES, 0, 3);
707     EXPECT_GL_NO_ERROR();
708 
709     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::green);
710     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
711     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
712     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::green);
713 
714     glDeleteShader(vs);
715     glDeleteShader(fs);
716     glDeleteShader(badfs);
717     glDeleteProgram(program);
718 }
719 
720 // Similar to SuccessfulLinkThenFailingRelink, but with a more complicated mix of resources.
TEST_P(LinkAndRelinkTestES31,SuccessfulLinkThenFailingRelink2)721 TEST_P(LinkAndRelinkTestES31, SuccessfulLinkThenFailingRelink2)
722 {
723     GLint maxFragmentShaderStorageBlocks;
724     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
725 
726     ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
727 
728     // Install a render program in current GL state via UseProgram, then render.
729     // It should succeed.
730     constexpr char kVS[]     = R"(#version 310 es
731 out vec4 color;
732 void main()
733 {
734     vec2 position = vec2(-1, -1);
735     if (gl_VertexID == 1)
736         position = vec2(3, -1);
737     else if (gl_VertexID == 2)
738         position = vec2(-1, 3);
739 
740     gl_Position = vec4(position, 0, 1);
741     color = vec4(0, 1, 0, 1);
742 })";
743     constexpr char kGoodFS[] = R"(#version 310 es
744 in mediump vec4 color;
745 out mediump vec4 colorOut;
746 mediump uniform float u;  // should be 0.5;
747 uniform UBO
748 {
749     highp float b;  // should be 1.75
750 };
751 layout(std140, binding = 1) buffer SSBO
752 {
753     uint s;  // should be 0x12345678
754 };
755 void main()
756 {
757     if (abs(u - 0.5) > 0.01)
758         colorOut = vec4(1, 0, 0, 1);
759     else if (abs(b - 1.75) > 0.01)
760         colorOut = vec4(0, 0, 1, 1);
761     else if (s != 0x12345678u)
762         colorOut = vec4(1, 0, 1, 1);
763     else
764         colorOut = color;
765 })";
766     constexpr char kBadFS[]  = R"(#version 310 es
767 flat in uvec2 color;
768 layout(location = 0) out mediump vec4 colorOut;
769 layout(location = 1) out mediump vec4 colorOut2;
770 void main()
771 {
772     colorOut = vec4(1, color, 1);
773     colorOut2 = vec4(color, 0, 1);
774 })";
775 
776     GLuint program = glCreateProgram();
777     GLuint vs      = CompileShader(GL_VERTEX_SHADER, kVS);
778     GLuint fs      = CompileShader(GL_FRAGMENT_SHADER, kGoodFS);
779     GLuint badfs   = CompileShader(GL_FRAGMENT_SHADER, kBadFS);
780 
781     EXPECT_NE(0u, vs);
782     EXPECT_NE(0u, fs);
783     EXPECT_NE(0u, badfs);
784 
785     glAttachShader(program, vs);
786     glAttachShader(program, fs);
787 
788     glLinkProgram(program);
789 
790     GLint linkStatus;
791     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
792     EXPECT_GL_TRUE(linkStatus);
793 
794     EXPECT_GL_NO_ERROR();
795 
796     constexpr float kUBOValue = 1.75;
797     GLBuffer ubo;
798     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
799     glBufferData(GL_UNIFORM_BUFFER, sizeof(kUBOValue), &kUBOValue, GL_STATIC_DRAW);
800     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
801 
802     constexpr uint32_t kSSBOValue = 0x12345678;
803     GLBuffer ssbo;
804     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
805     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kSSBOValue), &kSSBOValue, GL_STATIC_DRAW);
806     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo);
807 
808     EXPECT_GL_NO_ERROR();
809 
810     const int w = getWindowWidth();
811     const int h = getWindowHeight();
812 
813     glViewport(0, 0, w, h);
814 
815     glClearColor(0, 0, 0, 1);
816     glClear(GL_COLOR_BUFFER_BIT);
817 
818     glEnable(GL_SCISSOR_TEST);
819     glScissor(0, 0, w / 2, h / 2);
820 
821     glUseProgram(program);
822 
823     const GLint uniLoc = glGetUniformLocation(program, "u");
824     ASSERT_NE(uniLoc, -1);
825     glUniform1f(uniLoc, 0.5);
826 
827     const GLint uboIndex = glGetUniformBlockIndex(program, "UBO");
828     ASSERT_NE(uboIndex, -1);
829     glUniformBlockBinding(program, uboIndex, 0);
830 
831     glDrawArrays(GL_TRIANGLES, 0, 3);
832     EXPECT_GL_NO_ERROR();
833 
834     // Cause the program to fail linking
835     glDetachShader(program, fs);
836     glAttachShader(program, badfs);
837 
838     glLinkProgram(program);
839 
840     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
841     EXPECT_GL_FALSE(linkStatus);
842 
843     // Link failed, but the program should still be usable.
844     glScissor(w / 2, h / 2, w / 2, h / 2);
845     glDrawArrays(GL_TRIANGLES, 0, 3);
846     EXPECT_GL_NO_ERROR();
847 
848     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::green);
849     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
850     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
851     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::green);
852 
853     glDeleteShader(vs);
854     glDeleteShader(fs);
855     glDeleteShader(badfs);
856     glDeleteProgram(program);
857 }
858 
859 // Same as SuccessfulLinkThenFailingRelink, but with PPOs.
TEST_P(LinkAndRelinkTestES31,SuccessfulLinkThenFailingRelinkWithPPO)860 TEST_P(LinkAndRelinkTestES31, SuccessfulLinkThenFailingRelinkWithPPO)
861 {
862     // Only the Vulkan backend supports PPOs.
863     ANGLE_SKIP_TEST_IF(!IsVulkan());
864     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_geometry_shader"));
865 
866     // Install a render program in current GL state via UseProgram, then render.
867     // It should succeed.
868     constexpr char kVS[]    = R"(#version 300 es
869 void main()
870 {
871     vec2 position = vec2(-1, -1);
872     if (gl_VertexID == 1)
873         position = vec2(3, -1);
874     else if (gl_VertexID == 2)
875         position = vec2(-1, 3);
876 
877     gl_Position = vec4(position, 0, 1);
878 })";
879     constexpr char kBadGS[] = R"(#version 310 es
880 #extension GL_EXT_geometry_shader : require
881 layout (invocations = 3, triangles) in;
882 layout (triangle_strip, max_vertices = 3) out;
883 void main()
884 {
885 })";
886 
887     GLuint vs    = CompileShader(GL_VERTEX_SHADER, kVS);
888     GLuint fs    = CompileShader(GL_FRAGMENT_SHADER, essl3_shaders::fs::Green());
889     GLuint badgs = CompileShader(GL_GEOMETRY_SHADER, kBadGS);
890 
891     EXPECT_NE(0u, vs);
892     EXPECT_NE(0u, fs);
893     EXPECT_NE(0u, badgs);
894 
895     GLuint vsProg = glCreateProgram();
896     GLuint fsProg = glCreateProgram();
897 
898     glProgramParameteri(vsProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
899     glAttachShader(vsProg, vs);
900     glLinkProgram(vsProg);
901     EXPECT_GL_NO_ERROR();
902 
903     glProgramParameteri(fsProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
904     glAttachShader(fsProg, fs);
905     glLinkProgram(fsProg);
906     EXPECT_GL_NO_ERROR();
907 
908     GLuint pipeline;
909     glGenProgramPipelines(1, &pipeline);
910     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vsProg);
911     glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fsProg);
912     EXPECT_GL_NO_ERROR();
913 
914     const int w = getWindowWidth();
915     const int h = getWindowHeight();
916 
917     glViewport(0, 0, w, h);
918 
919     glClearColor(0, 0, 0, 1);
920     glClear(GL_COLOR_BUFFER_BIT);
921 
922     glEnable(GL_SCISSOR_TEST);
923     glScissor(0, 0, w / 2, h / 2);
924 
925     glUseProgram(0);
926     glBindProgramPipeline(pipeline);
927     glDrawArrays(GL_TRIANGLES, 0, 3);
928     EXPECT_GL_NO_ERROR();
929 
930     // Cause the fs program to fail linking
931     glAttachShader(fsProg, badgs);
932     glLinkProgram(fsProg);
933     glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT, fsProg);
934     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
935 
936     GLint linkStatus;
937     glGetProgramiv(fsProg, GL_LINK_STATUS, &linkStatus);
938     EXPECT_GL_FALSE(linkStatus);
939 
940     // Program link failed, but the program pipeline should still be usable.
941     glScissor(w / 2, h / 2, w / 2, h / 2);
942     glDrawArrays(GL_TRIANGLES, 0, 3);
943     EXPECT_GL_NO_ERROR();
944 
945     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::green);
946     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w / 2, h / 2, GLColor::black);
947     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h / 2, GLColor::black);
948     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w / 2, h / 2, GLColor::green);
949 
950     glDeleteShader(vs);
951     glDeleteShader(fs);
952     glDeleteShader(badgs);
953     glDeleteProgram(vsProg);
954     glDeleteProgram(fsProg);
955     glDeleteProgramPipelines(1, &pipeline);
956 }
957 
958 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(LinkAndRelinkTest);
959 
960 ANGLE_INSTANTIATE_TEST_ES3(LinkAndRelinkTestES3);
961 
962 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LinkAndRelinkTestES31);
963 ANGLE_INSTANTIATE_TEST_ES31(LinkAndRelinkTestES31);
964 
965 }  // namespace
966