• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 LinkAndRelinkTestES31 : public ANGLETest
25 {
26   protected:
LinkAndRelinkTestES31()27     LinkAndRelinkTestES31() {}
28 };
29 
30 // When a program link or relink fails, if you try to install the unsuccessfully
31 // linked program (via UseProgram) and start rendering or dispatch compute,
32 // We can not always report INVALID_OPERATION for rendering/compute pipeline.
33 // The result depends on the previous state: Whether a valid program is
34 // installed in current GL state before the link.
35 // If a program successfully relinks when it is in use, the program might
36 // change from a rendering program to a compute program in theory,
37 // or vice versa.
38 
39 // When program link fails and no valid rendering program is installed in the GL
40 // state before the link, it should report an error for UseProgram
TEST_P(LinkAndRelinkTest,RenderingProgramFailsWithoutProgramInstalled)41 TEST_P(LinkAndRelinkTest, RenderingProgramFailsWithoutProgramInstalled)
42 {
43     glUseProgram(0);
44     GLuint program = glCreateProgram();
45 
46     glLinkProgram(program);
47     GLint linkStatus;
48     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
49     EXPECT_GL_FALSE(linkStatus);
50 
51     glUseProgram(program);
52     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
53 
54     glDrawArrays(GL_POINTS, 0, 1);
55     EXPECT_GL_NO_ERROR();
56 }
57 
58 // When program link or relink fails and a valid rendering program is installed
59 // in the GL state before the link, using the failed program via UseProgram
60 // should report an error, but starting rendering should succeed.
61 // However, dispatching compute always fails.
TEST_P(LinkAndRelinkTest,RenderingProgramFailsWithProgramInstalled)62 TEST_P(LinkAndRelinkTest, RenderingProgramFailsWithProgramInstalled)
63 {
64     // Install a render program in current GL state via UseProgram, then render.
65     // It should succeed.
66     constexpr char kVS[] = "void main() {}";
67     constexpr char kFS[] = "void main() {}";
68 
69     GLuint program = glCreateProgram();
70 
71     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
72     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
73 
74     EXPECT_NE(0u, vs);
75     EXPECT_NE(0u, fs);
76 
77     glAttachShader(program, vs);
78     glDeleteShader(vs);
79 
80     glAttachShader(program, fs);
81     glDeleteShader(fs);
82 
83     glLinkProgram(program);
84 
85     GLint linkStatus;
86     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
87     EXPECT_GL_TRUE(linkStatus);
88 
89     EXPECT_GL_NO_ERROR();
90 
91     glUseProgram(program);
92     EXPECT_GL_NO_ERROR();
93     glDrawArrays(GL_POINTS, 0, 1);
94     EXPECT_GL_NO_ERROR();
95 
96     glDispatchCompute(8, 4, 2);
97     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
98 
99     // Link failure, and a valid program has been installed in the GL state.
100     GLuint programNull = glCreateProgram();
101 
102     glLinkProgram(programNull);
103     glGetProgramiv(programNull, GL_LINK_STATUS, &linkStatus);
104     EXPECT_GL_FALSE(linkStatus);
105 
106     // Starting rendering should succeed.
107     glDrawArrays(GL_POINTS, 0, 1);
108     EXPECT_GL_NO_ERROR();
109 
110     glDispatchCompute(8, 4, 2);
111     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
112 
113     // Using the unsuccessfully linked program should report an error.
114     glUseProgram(programNull);
115     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
116 
117     // Using the unsuccessfully linked program, that program should not
118     // replace the program binary residing in the GL state. It will not make
119     // the installed program invalid either, like what UseProgram(0) can do.
120     // So, starting rendering should succeed.
121     glDrawArrays(GL_POINTS, 0, 1);
122     EXPECT_GL_NO_ERROR();
123 
124     glDispatchCompute(8, 4, 2);
125     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
126 
127     // We try to relink the installed program, but make it fail.
128 
129     // No vertex shader, relink fails.
130     glDetachShader(program, vs);
131     glLinkProgram(program);
132     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
133     EXPECT_GL_FALSE(linkStatus);
134     EXPECT_GL_NO_ERROR();
135 
136     // Starting rendering should succeed.
137     glDrawArrays(GL_POINTS, 0, 1);
138     EXPECT_GL_NO_ERROR();
139 
140     glDispatchCompute(8, 4, 2);
141     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
142 
143     // Using the unsuccessfully relinked program should report an error.
144     glUseProgram(program);
145     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
146 
147     // Using the unsuccessfully relinked program, that program should not
148     // replace the program binary residing in the GL state. It will not make
149     // the installed program invalid either, like what UseProgram(0) can do.
150     // So, starting rendering should succeed.
151     glDrawArrays(GL_POINTS, 0, 1);
152     EXPECT_GL_NO_ERROR();
153 
154     glDispatchCompute(8, 4, 2);
155     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
156 }
157 
158 // Tests uniform default values.
TEST_P(LinkAndRelinkTest,UniformDefaultValues)159 TEST_P(LinkAndRelinkTest, UniformDefaultValues)
160 {
161     // TODO(anglebug.com/3969): Understand why rectangle texture CLs made this fail.
162     ANGLE_SKIP_TEST_IF(IsOzone() && IsIntel());
163     constexpr char kFS[] = R"(precision mediump float;
164 uniform vec4 u_uniform;
165 
166 bool isZero(vec4 value) {
167     return value == vec4(0,0,0,0);
168 }
169 
170 void main()
171 {
172     gl_FragColor = isZero(u_uniform) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
173 })";
174 
175     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), kFS);
176     glUseProgram(program);
177 
178     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
179     ASSERT_GL_NO_ERROR();
180     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
181 
182     GLint loc = glGetUniformLocation(program, "u_uniform");
183     ASSERT_NE(-1, loc);
184     glUniform4f(loc, 0.1f, 0.2f, 0.3f, 0.4f);
185 
186     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
187     ASSERT_GL_NO_ERROR();
188     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
189 
190     glLinkProgram(program);
191     ASSERT_GL_NO_ERROR();
192 
193     drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f, 1.0f, true);
194     ASSERT_GL_NO_ERROR();
195     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
196 }
197 
198 // When program link fails and no valid compute program is installed in the GL
199 // state before the link, it should report an error for UseProgram and
200 // DispatchCompute.
TEST_P(LinkAndRelinkTestES31,ComputeProgramFailsWithoutProgramInstalled)201 TEST_P(LinkAndRelinkTestES31, ComputeProgramFailsWithoutProgramInstalled)
202 {
203     glUseProgram(0);
204     GLuint program = glCreateProgram();
205 
206     glLinkProgram(program);
207     GLint linkStatus;
208     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
209     EXPECT_GL_FALSE(linkStatus);
210 
211     glUseProgram(program);
212     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
213 
214     glDispatchCompute(8, 4, 2);
215     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
216 }
217 
218 // When program link or relink fails and a valid compute program is installed in
219 // the GL state before the link, using the failed program via UseProgram should
220 // report an error, but dispatching compute should succeed.
TEST_P(LinkAndRelinkTestES31,ComputeProgramFailsWithProgramInstalled)221 TEST_P(LinkAndRelinkTestES31, ComputeProgramFailsWithProgramInstalled)
222 {
223     // Install a compute program in the GL state via UseProgram, then dispatch
224     // compute. It should succeed.
225     constexpr char kCS[] =
226         R"(#version 310 es
227         layout(local_size_x=1) in;
228         void main()
229         {
230         })";
231 
232     GLuint program = glCreateProgram();
233 
234     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
235     EXPECT_NE(0u, cs);
236 
237     glAttachShader(program, cs);
238     glDeleteShader(cs);
239 
240     glLinkProgram(program);
241     GLint linkStatus;
242     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
243     EXPECT_GL_TRUE(linkStatus);
244 
245     EXPECT_GL_NO_ERROR();
246 
247     glUseProgram(program);
248     EXPECT_GL_NO_ERROR();
249     glDispatchCompute(8, 4, 2);
250     EXPECT_GL_NO_ERROR();
251 
252     glDrawArrays(GL_POINTS, 0, 1);
253     EXPECT_GL_NO_ERROR();
254 
255     // Link failure, and a valid program has been installed in the GL state.
256     GLuint programNull = glCreateProgram();
257 
258     glLinkProgram(programNull);
259     glGetProgramiv(programNull, GL_LINK_STATUS, &linkStatus);
260     EXPECT_GL_FALSE(linkStatus);
261 
262     // Dispatching compute should succeed.
263     glDispatchCompute(8, 4, 2);
264     EXPECT_GL_NO_ERROR();
265 
266     glDrawArrays(GL_POINTS, 0, 1);
267     EXPECT_GL_NO_ERROR();
268 
269     // Using the unsuccessfully linked program should report an error.
270     glUseProgram(programNull);
271     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
272 
273     // Using the unsuccessfully linked program, that program should not
274     // replace the program binary residing in the GL state. It will not make
275     // the installed program invalid either, like what UseProgram(0) can do.
276     // So, dispatching compute should succeed.
277     glDispatchCompute(8, 4, 2);
278     EXPECT_GL_NO_ERROR();
279 
280     glDrawArrays(GL_POINTS, 0, 1);
281     EXPECT_GL_NO_ERROR();
282 
283     // We try to relink the installed program, but make it fail.
284 
285     // No compute shader, relink fails.
286     glDetachShader(program, cs);
287     glLinkProgram(program);
288     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
289     EXPECT_GL_FALSE(linkStatus);
290     EXPECT_GL_NO_ERROR();
291 
292     // Dispatching compute should succeed.
293     glDispatchCompute(8, 4, 2);
294     EXPECT_GL_NO_ERROR();
295 
296     glDrawArrays(GL_POINTS, 0, 1);
297     EXPECT_GL_NO_ERROR();
298 
299     // Using the unsuccessfully relinked program should report an error.
300     glUseProgram(program);
301     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
302 
303     // Using the unsuccessfully relinked program, that program should not
304     // replace the program binary residing in the GL state. It will not make
305     // the installed program invalid either, like what UseProgram(0) can do.
306     // So, dispatching compute should succeed.
307     glDispatchCompute(8, 4, 2);
308     EXPECT_GL_NO_ERROR();
309 
310     glDrawArrays(GL_POINTS, 0, 1);
311     EXPECT_GL_NO_ERROR();
312 }
313 
314 // If you compile and link a compute program successfully and use the program,
315 // then dispatching compute and rendering can succeed (with undefined behavior).
316 // If you relink the compute program to a rendering program when it is in use,
317 // then dispatching compute will fail, but starting rendering can succeed.
TEST_P(LinkAndRelinkTestES31,RelinkProgramSucceedsFromComputeToRendering)318 TEST_P(LinkAndRelinkTestES31, RelinkProgramSucceedsFromComputeToRendering)
319 {
320     constexpr char kCS[] = R"(#version 310 es
321 layout(local_size_x=1) in;
322 void main()
323 {
324 })";
325 
326     GLuint program = glCreateProgram();
327 
328     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
329     EXPECT_NE(0u, cs);
330 
331     glAttachShader(program, cs);
332     glDeleteShader(cs);
333 
334     glLinkProgram(program);
335     glDetachShader(program, cs);
336     GLint linkStatus;
337     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
338     EXPECT_GL_TRUE(linkStatus);
339 
340     EXPECT_GL_NO_ERROR();
341 
342     glUseProgram(program);
343     EXPECT_GL_NO_ERROR();
344     glDispatchCompute(8, 4, 2);
345     EXPECT_GL_NO_ERROR();
346 
347     glDrawArrays(GL_POINTS, 0, 1);
348     EXPECT_GL_NO_ERROR();
349 
350     constexpr char kVS[] = "void main() {}";
351     constexpr char kFS[] = "void main() {}";
352 
353     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
354     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
355     EXPECT_NE(0u, vs);
356     EXPECT_NE(0u, fs);
357 
358     glAttachShader(program, vs);
359     glDeleteShader(vs);
360 
361     glAttachShader(program, fs);
362     glDeleteShader(fs);
363 
364     glLinkProgram(program);
365     glDetachShader(program, vs);
366     glDetachShader(program, fs);
367     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
368     EXPECT_GL_TRUE(linkStatus);
369 
370     EXPECT_GL_NO_ERROR();
371 
372     glDrawArrays(GL_POINTS, 0, 1);
373     EXPECT_GL_NO_ERROR();
374 
375     glDispatchCompute(8, 4, 2);
376     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
377 }
378 
379 // If you compile and link a rendering program successfully and use the program,
380 // then starting rendering can succeed, while dispatching compute will fail.
381 // If you relink the rendering program to a compute program when it is in use,
382 // then starting rendering will fail, but dispatching compute can succeed.
TEST_P(LinkAndRelinkTestES31,RelinkProgramSucceedsFromRenderingToCompute)383 TEST_P(LinkAndRelinkTestES31, RelinkProgramSucceedsFromRenderingToCompute)
384 {
385     constexpr char kVS[] = "void main() {}";
386     constexpr char kFS[] = "void main() {}";
387 
388     GLuint program = glCreateProgram();
389 
390     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
391     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
392 
393     EXPECT_NE(0u, vs);
394     EXPECT_NE(0u, fs);
395 
396     glAttachShader(program, vs);
397     glDeleteShader(vs);
398 
399     glAttachShader(program, fs);
400     glDeleteShader(fs);
401 
402     glLinkProgram(program);
403     glDetachShader(program, vs);
404     glDetachShader(program, fs);
405     GLint linkStatus;
406     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
407     EXPECT_GL_TRUE(linkStatus);
408 
409     EXPECT_GL_NO_ERROR();
410 
411     glUseProgram(program);
412     EXPECT_GL_NO_ERROR();
413     glDrawArrays(GL_POINTS, 0, 1);
414     EXPECT_GL_NO_ERROR();
415 
416     glDispatchCompute(8, 4, 2);
417     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
418 
419     constexpr char kCS[] = R"(#version 310 es
420 layout(local_size_x=1) in;
421 void main()
422 {
423 })";
424 
425     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
426     EXPECT_NE(0u, cs);
427 
428     glAttachShader(program, cs);
429     glDeleteShader(cs);
430 
431     glLinkProgram(program);
432     glDetachShader(program, cs);
433     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
434     EXPECT_GL_TRUE(linkStatus);
435 
436     EXPECT_GL_NO_ERROR();
437 
438     glDispatchCompute(8, 4, 2);
439     EXPECT_GL_NO_ERROR();
440 
441     glDrawArrays(GL_POINTS, 0, 1);
442     EXPECT_GL_NO_ERROR();
443 }
444 
445 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(LinkAndRelinkTest);
446 ANGLE_INSTANTIATE_TEST_ES31(LinkAndRelinkTestES31);
447 
448 }  // namespace
449