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