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