xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ProgramPipelineTest.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 // ProgramPipelineTest:
7*8975f5c5SAndroid Build Coastguard Worker //   Various tests related to Program Pipeline.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
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 ProgramPipelineTest : public ANGLETest<>
19*8975f5c5SAndroid Build Coastguard Worker {
20*8975f5c5SAndroid Build Coastguard Worker   protected:
ProgramPipelineTest()21*8975f5c5SAndroid Build Coastguard Worker     ProgramPipelineTest()
22*8975f5c5SAndroid Build Coastguard Worker     {
23*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(64);
24*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(64);
25*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
26*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
27*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
28*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
29*8975f5c5SAndroid Build Coastguard Worker     }
30*8975f5c5SAndroid Build Coastguard Worker };
31*8975f5c5SAndroid Build Coastguard Worker 
32*8975f5c5SAndroid Build Coastguard Worker // Verify that program pipeline is not supported in version lower than ES31.
TEST_P(ProgramPipelineTest,GenerateProgramPipelineObject)33*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest, GenerateProgramPipelineObject)
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
38*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &pipeline);
39*8975f5c5SAndroid Build Coastguard Worker     if (getClientMajorVersion() < 3 || getClientMinorVersion() < 1)
40*8975f5c5SAndroid Build Coastguard Worker     {
41*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
42*8975f5c5SAndroid Build Coastguard Worker     }
43*8975f5c5SAndroid Build Coastguard Worker     else
44*8975f5c5SAndroid Build Coastguard Worker     {
45*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgramPipelines(1, &pipeline);
48*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
49*8975f5c5SAndroid Build Coastguard Worker     }
50*8975f5c5SAndroid Build Coastguard Worker }
51*8975f5c5SAndroid Build Coastguard Worker 
52*8975f5c5SAndroid Build Coastguard Worker // Verify that program pipeline errors out without GL_EXT_separate_shader_objects extension.
TEST_P(ProgramPipelineTest,GenerateProgramPipelineObjectEXT)53*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest, GenerateProgramPipelineObjectEXT)
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
56*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelinesEXT(1, &pipeline);
57*8975f5c5SAndroid Build Coastguard Worker     if (!IsGLExtensionEnabled("GL_EXT_separate_shader_objects"))
58*8975f5c5SAndroid Build Coastguard Worker     {
59*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
60*8975f5c5SAndroid Build Coastguard Worker     }
61*8975f5c5SAndroid Build Coastguard Worker     else
62*8975f5c5SAndroid Build Coastguard Worker     {
63*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
64*8975f5c5SAndroid Build Coastguard Worker 
65*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgramPipelinesEXT(1, &pipeline);
66*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
67*8975f5c5SAndroid Build Coastguard Worker     }
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker 
70*8975f5c5SAndroid Build Coastguard Worker class ProgramPipelineTest31 : public ProgramPipelineTest
71*8975f5c5SAndroid Build Coastguard Worker {
72*8975f5c5SAndroid Build Coastguard Worker   protected:
testTearDown()73*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
74*8975f5c5SAndroid Build Coastguard Worker     {
75*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mVertProg);
76*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mFragProg);
77*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgramPipelines(1, &mPipeline);
78*8975f5c5SAndroid Build Coastguard Worker     }
79*8975f5c5SAndroid Build Coastguard Worker 
80*8975f5c5SAndroid Build Coastguard Worker     void bindProgramPipeline(const GLchar *vertString, const GLchar *fragString);
81*8975f5c5SAndroid Build Coastguard Worker     void drawQuadWithPPO(const std::string &positionAttribName,
82*8975f5c5SAndroid Build Coastguard Worker                          const GLfloat positionAttribZ,
83*8975f5c5SAndroid Build Coastguard Worker                          const GLfloat positionAttribXYScale);
84*8975f5c5SAndroid Build Coastguard Worker     GLint getAvailableProgramBinaryFormatCount() const;
85*8975f5c5SAndroid Build Coastguard Worker 
86*8975f5c5SAndroid Build Coastguard Worker     GLuint mVertProg = 0;
87*8975f5c5SAndroid Build Coastguard Worker     GLuint mFragProg = 0;
88*8975f5c5SAndroid Build Coastguard Worker     GLuint mPipeline = 0;
89*8975f5c5SAndroid Build Coastguard Worker };
90*8975f5c5SAndroid Build Coastguard Worker 
91*8975f5c5SAndroid Build Coastguard Worker class ProgramPipelineXFBTest31 : public ProgramPipelineTest31
92*8975f5c5SAndroid Build Coastguard Worker {
93*8975f5c5SAndroid Build Coastguard Worker   protected:
testSetUp()94*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
95*8975f5c5SAndroid Build Coastguard Worker     {
96*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mTransformFeedbackBuffer);
97*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
98*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBufferSize, nullptr,
99*8975f5c5SAndroid Build Coastguard Worker                      GL_STATIC_DRAW);
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker         glGenTransformFeedbacks(1, &mTransformFeedback);
102*8975f5c5SAndroid Build Coastguard Worker 
103*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
104*8975f5c5SAndroid Build Coastguard Worker     }
testTearDown()105*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
106*8975f5c5SAndroid Build Coastguard Worker     {
107*8975f5c5SAndroid Build Coastguard Worker         if (mTransformFeedbackBuffer != 0)
108*8975f5c5SAndroid Build Coastguard Worker         {
109*8975f5c5SAndroid Build Coastguard Worker             glDeleteBuffers(1, &mTransformFeedbackBuffer);
110*8975f5c5SAndroid Build Coastguard Worker             mTransformFeedbackBuffer = 0;
111*8975f5c5SAndroid Build Coastguard Worker         }
112*8975f5c5SAndroid Build Coastguard Worker 
113*8975f5c5SAndroid Build Coastguard Worker         if (mTransformFeedback != 0)
114*8975f5c5SAndroid Build Coastguard Worker         {
115*8975f5c5SAndroid Build Coastguard Worker             glDeleteTransformFeedbacks(1, &mTransformFeedback);
116*8975f5c5SAndroid Build Coastguard Worker             mTransformFeedback = 0;
117*8975f5c5SAndroid Build Coastguard Worker         }
118*8975f5c5SAndroid Build Coastguard Worker     }
119*8975f5c5SAndroid Build Coastguard Worker 
120*8975f5c5SAndroid Build Coastguard Worker     void bindProgramPipelineWithXFBVaryings(const GLchar *vertString,
121*8975f5c5SAndroid Build Coastguard Worker                                             const GLchar *fragStringconst,
122*8975f5c5SAndroid Build Coastguard Worker                                             const std::vector<std::string> &tfVaryings,
123*8975f5c5SAndroid Build Coastguard Worker                                             GLenum bufferMode);
124*8975f5c5SAndroid Build Coastguard Worker 
125*8975f5c5SAndroid Build Coastguard Worker     static const size_t mTransformFeedbackBufferSize = 1 << 24;
126*8975f5c5SAndroid Build Coastguard Worker     GLuint mTransformFeedbackBuffer;
127*8975f5c5SAndroid Build Coastguard Worker     GLuint mTransformFeedback;
128*8975f5c5SAndroid Build Coastguard Worker };
129*8975f5c5SAndroid Build Coastguard Worker 
bindProgramPipeline(const GLchar * vertString,const GLchar * fragString)130*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineTest31::bindProgramPipeline(const GLchar *vertString, const GLchar *fragString)
131*8975f5c5SAndroid Build Coastguard Worker {
132*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
133*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
134*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
135*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
138*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
139*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
140*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
141*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
142*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
143*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
144*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
145*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
146*8975f5c5SAndroid Build Coastguard Worker }
147*8975f5c5SAndroid Build Coastguard Worker 
bindProgramPipelineWithXFBVaryings(const GLchar * vertString,const GLchar * fragString,const std::vector<std::string> & tfVaryings,GLenum bufferMode)148*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineXFBTest31::bindProgramPipelineWithXFBVaryings(
149*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString,
150*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString,
151*8975f5c5SAndroid Build Coastguard Worker     const std::vector<std::string> &tfVaryings,
152*8975f5c5SAndroid Build Coastguard Worker     GLenum bufferMode)
153*8975f5c5SAndroid Build Coastguard Worker {
154*8975f5c5SAndroid Build Coastguard Worker     GLShader vertShader(GL_VERTEX_SHADER);
155*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateProgram();
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(vertShader, 1, &vertString, nullptr);
158*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(vertShader);
159*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mVertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
160*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mVertProg, vertShader);
161*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mVertProg);
162*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
163*8975f5c5SAndroid Build Coastguard Worker 
164*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
165*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
166*8975f5c5SAndroid Build Coastguard Worker 
167*8975f5c5SAndroid Build Coastguard Worker     if (tfVaryings.size() > 0)
168*8975f5c5SAndroid Build Coastguard Worker     {
169*8975f5c5SAndroid Build Coastguard Worker         std::vector<const char *> constCharTFVaryings;
170*8975f5c5SAndroid Build Coastguard Worker 
171*8975f5c5SAndroid Build Coastguard Worker         for (const std::string &transformFeedbackVarying : tfVaryings)
172*8975f5c5SAndroid Build Coastguard Worker         {
173*8975f5c5SAndroid Build Coastguard Worker             constCharTFVaryings.push_back(transformFeedbackVarying.c_str());
174*8975f5c5SAndroid Build Coastguard Worker         }
175*8975f5c5SAndroid Build Coastguard Worker 
176*8975f5c5SAndroid Build Coastguard Worker         glTransformFeedbackVaryings(mVertProg, static_cast<GLsizei>(tfVaryings.size()),
177*8975f5c5SAndroid Build Coastguard Worker                                     &constCharTFVaryings[0], bufferMode);
178*8975f5c5SAndroid Build Coastguard Worker         glLinkProgram(mVertProg);
179*8975f5c5SAndroid Build Coastguard Worker     }
180*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
181*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
182*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
183*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
184*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
185*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
186*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
187*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
188*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
189*8975f5c5SAndroid Build Coastguard Worker }
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker // Test generate or delete program pipeline.
TEST_P(ProgramPipelineTest31,GenOrDeleteProgramPipelineTest)192*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, GenOrDeleteProgramPipelineTest)
193*8975f5c5SAndroid Build Coastguard Worker {
194*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
195*8975f5c5SAndroid Build Coastguard Worker 
196*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
197*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(-1, &pipeline);
198*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
199*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(0, &pipeline);
200*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
201*8975f5c5SAndroid Build Coastguard Worker 
202*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgramPipelines(-1, &pipeline);
203*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
204*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgramPipelines(0, &pipeline);
205*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
206*8975f5c5SAndroid Build Coastguard Worker }
207*8975f5c5SAndroid Build Coastguard Worker 
208*8975f5c5SAndroid Build Coastguard Worker // Test BindProgramPipeline.
TEST_P(ProgramPipelineTest31,BindProgramPipelineTest)209*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, BindProgramPipelineTest)
210*8975f5c5SAndroid Build Coastguard Worker {
211*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(0);
214*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
215*8975f5c5SAndroid Build Coastguard Worker 
216*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(2);
217*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
218*8975f5c5SAndroid Build Coastguard Worker 
219*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
220*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &pipeline);
221*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
222*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
223*8975f5c5SAndroid Build Coastguard Worker 
224*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgramPipelines(1, &pipeline);
225*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
226*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker 
229*8975f5c5SAndroid Build Coastguard Worker // Test IsProgramPipeline
TEST_P(ProgramPipelineTest31,IsProgramPipelineTest)230*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, IsProgramPipelineTest)
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
233*8975f5c5SAndroid Build Coastguard Worker 
234*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_FALSE(glIsProgramPipeline(0));
235*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
236*8975f5c5SAndroid Build Coastguard Worker 
237*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_FALSE(glIsProgramPipeline(2));
238*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
239*8975f5c5SAndroid Build Coastguard Worker 
240*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
241*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &pipeline);
242*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
243*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_TRUE(glIsProgramPipeline(pipeline));
244*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
245*8975f5c5SAndroid Build Coastguard Worker 
246*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(0);
247*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgramPipelines(1, &pipeline);
248*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_FALSE(glIsProgramPipeline(pipeline));
249*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
250*8975f5c5SAndroid Build Coastguard Worker }
251*8975f5c5SAndroid Build Coastguard Worker 
252*8975f5c5SAndroid Build Coastguard Worker // Simulates a call to glCreateShaderProgramv()
createShaderProgram(GLenum type,const GLchar * shaderString,unsigned int varyingsCount,const char * const * varyings)253*8975f5c5SAndroid Build Coastguard Worker GLuint createShaderProgram(GLenum type,
254*8975f5c5SAndroid Build Coastguard Worker                            const GLchar *shaderString,
255*8975f5c5SAndroid Build Coastguard Worker                            unsigned int varyingsCount,
256*8975f5c5SAndroid Build Coastguard Worker                            const char *const *varyings)
257*8975f5c5SAndroid Build Coastguard Worker {
258*8975f5c5SAndroid Build Coastguard Worker     GLShader shader(type);
259*8975f5c5SAndroid Build Coastguard Worker     if (!shader)
260*8975f5c5SAndroid Build Coastguard Worker     {
261*8975f5c5SAndroid Build Coastguard Worker         return 0;
262*8975f5c5SAndroid Build Coastguard Worker     }
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(shader, 1, &shaderString, nullptr);
265*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
266*8975f5c5SAndroid Build Coastguard Worker 
267*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(shader);
268*8975f5c5SAndroid Build Coastguard Worker 
269*8975f5c5SAndroid Build Coastguard Worker     GLint compiled;
270*8975f5c5SAndroid Build Coastguard Worker     glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
271*8975f5c5SAndroid Build Coastguard Worker 
272*8975f5c5SAndroid Build Coastguard Worker     if (!compiled)
273*8975f5c5SAndroid Build Coastguard Worker     {
274*8975f5c5SAndroid Build Coastguard Worker         GLint infoLogLength;
275*8975f5c5SAndroid Build Coastguard Worker         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
276*8975f5c5SAndroid Build Coastguard Worker         std::vector<GLchar> infoLog(infoLogLength);
277*8975f5c5SAndroid Build Coastguard Worker         glGetShaderInfoLog(shader, infoLogLength, NULL, infoLog.data());
278*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Compilation failed:\n"
279*8975f5c5SAndroid Build Coastguard Worker                << (infoLogLength > 0 ? infoLog.data() : "") << "\n for shader:\n"
280*8975f5c5SAndroid Build Coastguard Worker                << shaderString << "\n";
281*8975f5c5SAndroid Build Coastguard Worker         return 0;
282*8975f5c5SAndroid Build Coastguard Worker     }
283*8975f5c5SAndroid Build Coastguard Worker 
284*8975f5c5SAndroid Build Coastguard Worker     GLuint program = glCreateProgram();
285*8975f5c5SAndroid Build Coastguard Worker 
286*8975f5c5SAndroid Build Coastguard Worker     if (program)
287*8975f5c5SAndroid Build Coastguard Worker     {
288*8975f5c5SAndroid Build Coastguard Worker         glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
289*8975f5c5SAndroid Build Coastguard Worker         if (compiled)
290*8975f5c5SAndroid Build Coastguard Worker         {
291*8975f5c5SAndroid Build Coastguard Worker             glAttachShader(program, shader);
292*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
293*8975f5c5SAndroid Build Coastguard Worker 
294*8975f5c5SAndroid Build Coastguard Worker             if (varyingsCount > 0)
295*8975f5c5SAndroid Build Coastguard Worker             {
296*8975f5c5SAndroid Build Coastguard Worker                 glTransformFeedbackVaryings(program, varyingsCount, varyings, GL_SEPARATE_ATTRIBS);
297*8975f5c5SAndroid Build Coastguard Worker                 EXPECT_GL_NO_ERROR();
298*8975f5c5SAndroid Build Coastguard Worker             }
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker             glLinkProgram(program);
301*8975f5c5SAndroid Build Coastguard Worker 
302*8975f5c5SAndroid Build Coastguard Worker             GLint linked = 0;
303*8975f5c5SAndroid Build Coastguard Worker             glGetProgramiv(program, GL_LINK_STATUS, &linked);
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker             if (linked == 0)
306*8975f5c5SAndroid Build Coastguard Worker             {
307*8975f5c5SAndroid Build Coastguard Worker                 glDeleteProgram(program);
308*8975f5c5SAndroid Build Coastguard Worker                 return 0;
309*8975f5c5SAndroid Build Coastguard Worker             }
310*8975f5c5SAndroid Build Coastguard Worker             glDetachShader(program, shader);
311*8975f5c5SAndroid Build Coastguard Worker         }
312*8975f5c5SAndroid Build Coastguard Worker     }
313*8975f5c5SAndroid Build Coastguard Worker 
314*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
315*8975f5c5SAndroid Build Coastguard Worker 
316*8975f5c5SAndroid Build Coastguard Worker     return program;
317*8975f5c5SAndroid Build Coastguard Worker }
318*8975f5c5SAndroid Build Coastguard Worker 
createShaderProgram(GLenum type,const GLchar * shaderString)319*8975f5c5SAndroid Build Coastguard Worker GLuint createShaderProgram(GLenum type, const GLchar *shaderString)
320*8975f5c5SAndroid Build Coastguard Worker {
321*8975f5c5SAndroid Build Coastguard Worker     return createShaderProgram(type, shaderString, 0, nullptr);
322*8975f5c5SAndroid Build Coastguard Worker }
323*8975f5c5SAndroid Build Coastguard Worker 
drawQuadWithPPO(const std::string & positionAttribName,const GLfloat positionAttribZ,const GLfloat positionAttribXYScale)324*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineTest31::drawQuadWithPPO(const std::string &positionAttribName,
325*8975f5c5SAndroid Build Coastguard Worker                                             const GLfloat positionAttribZ,
326*8975f5c5SAndroid Build Coastguard Worker                                             const GLfloat positionAttribXYScale)
327*8975f5c5SAndroid Build Coastguard Worker {
328*8975f5c5SAndroid Build Coastguard Worker     return drawQuadPPO(mVertProg, positionAttribName, positionAttribZ, positionAttribXYScale);
329*8975f5c5SAndroid Build Coastguard Worker }
330*8975f5c5SAndroid Build Coastguard Worker 
getAvailableProgramBinaryFormatCount() const331*8975f5c5SAndroid Build Coastguard Worker GLint ProgramPipelineTest31::getAvailableProgramBinaryFormatCount() const
332*8975f5c5SAndroid Build Coastguard Worker {
333*8975f5c5SAndroid Build Coastguard Worker     GLint formatCount = 0;
334*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &formatCount);
335*8975f5c5SAndroid Build Coastguard Worker     return formatCount;
336*8975f5c5SAndroid Build Coastguard Worker }
337*8975f5c5SAndroid Build Coastguard Worker 
338*8975f5c5SAndroid Build Coastguard Worker // Test glUseProgramStages
TEST_P(ProgramPipelineTest31,UseProgramStages)339*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, UseProgramStages)
340*8975f5c5SAndroid Build Coastguard Worker {
341*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
342*8975f5c5SAndroid Build Coastguard Worker 
343*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
344*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
345*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
346*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = essl31_shaders::fs::Red();
347*8975f5c5SAndroid Build Coastguard Worker 
348*8975f5c5SAndroid Build Coastguard Worker     mVertProg = createShaderProgram(GL_VERTEX_SHADER, vertString);
349*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
350*8975f5c5SAndroid Build Coastguard Worker     mFragProg = createShaderProgram(GL_FRAGMENT_SHADER, fragString);
351*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
352*8975f5c5SAndroid Build Coastguard Worker 
353*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
354*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
355*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &pipeline);
356*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
357*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, mVertProg);
358*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
359*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
360*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
361*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
362*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
363*8975f5c5SAndroid Build Coastguard Worker 
364*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
365*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
366*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
367*8975f5c5SAndroid Build Coastguard Worker }
368*8975f5c5SAndroid Build Coastguard Worker 
369*8975f5c5SAndroid Build Coastguard Worker // Test glUseProgramStages with different programs
TEST_P(ProgramPipelineTest31,UseProgramStagesWithDifferentPrograms)370*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, UseProgramStagesWithDifferentPrograms)
371*8975f5c5SAndroid Build Coastguard Worker {
372*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
373*8975f5c5SAndroid Build Coastguard Worker 
374*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
375*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
376*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString  = essl31_shaders::vs::Simple();
377*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString1 = R"(#version 310 es
378*8975f5c5SAndroid Build Coastguard Worker precision highp float;
379*8975f5c5SAndroid Build Coastguard Worker uniform float redColorIn;
380*8975f5c5SAndroid Build Coastguard Worker uniform float greenColorIn;
381*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
382*8975f5c5SAndroid Build Coastguard Worker void main()
383*8975f5c5SAndroid Build Coastguard Worker {
384*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, 0.0, 1.0);
385*8975f5c5SAndroid Build Coastguard Worker })";
386*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString2 = R"(#version 310 es
387*8975f5c5SAndroid Build Coastguard Worker precision highp float;
388*8975f5c5SAndroid Build Coastguard Worker uniform float greenColorIn;
389*8975f5c5SAndroid Build Coastguard Worker uniform float blueColorIn;
390*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
391*8975f5c5SAndroid Build Coastguard Worker void main()
392*8975f5c5SAndroid Build Coastguard Worker {
393*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(0.0, greenColorIn, blueColorIn, 1.0);
394*8975f5c5SAndroid Build Coastguard Worker })";
395*8975f5c5SAndroid Build Coastguard Worker 
396*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString1);
397*8975f5c5SAndroid Build Coastguard Worker 
398*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to red
399*8975f5c5SAndroid Build Coastguard Worker     GLint location = glGetUniformLocation(mFragProg, "redColorIn");
400*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
401*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 1.0);
402*8975f5c5SAndroid Build Coastguard Worker     location = glGetUniformLocation(mFragProg, "greenColorIn");
403*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
404*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 0.0);
405*8975f5c5SAndroid Build Coastguard Worker 
406*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
407*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
408*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
409*8975f5c5SAndroid Build Coastguard Worker 
410*8975f5c5SAndroid Build Coastguard Worker     GLuint fragProg;
411*8975f5c5SAndroid Build Coastguard Worker     fragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString2);
412*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(fragProg, 0u);
413*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
414*8975f5c5SAndroid Build Coastguard Worker 
415*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, fragProg);
416*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
417*8975f5c5SAndroid Build Coastguard Worker 
418*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
419*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
420*8975f5c5SAndroid Build Coastguard Worker 
421*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to blue
422*8975f5c5SAndroid Build Coastguard Worker     location = glGetUniformLocation(fragProg, "greenColorIn");
423*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, fragProg);
424*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 0.0);
425*8975f5c5SAndroid Build Coastguard Worker     location = glGetUniformLocation(fragProg, "blueColorIn");
426*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, fragProg);
427*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 1.0);
428*8975f5c5SAndroid Build Coastguard Worker 
429*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
430*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
431*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
432*8975f5c5SAndroid Build Coastguard Worker 
433*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
434*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
435*8975f5c5SAndroid Build Coastguard Worker 
436*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
437*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
438*8975f5c5SAndroid Build Coastguard Worker 
439*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
440*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
441*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
442*8975f5c5SAndroid Build Coastguard Worker 
443*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mVertProg);
444*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mFragProg);
445*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(fragProg);
446*8975f5c5SAndroid Build Coastguard Worker }
447*8975f5c5SAndroid Build Coastguard Worker 
448*8975f5c5SAndroid Build Coastguard Worker // Test glUseProgramStages
TEST_P(ProgramPipelineTest31,UseCreateShaderProgramv)449*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, UseCreateShaderProgramv)
450*8975f5c5SAndroid Build Coastguard Worker {
451*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
452*8975f5c5SAndroid Build Coastguard Worker 
453*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
454*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
455*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
456*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = essl31_shaders::fs::Red();
457*8975f5c5SAndroid Build Coastguard Worker 
458*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
459*8975f5c5SAndroid Build Coastguard Worker 
460*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
461*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
462*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
463*8975f5c5SAndroid Build Coastguard Worker }
464*8975f5c5SAndroid Build Coastguard Worker 
465*8975f5c5SAndroid Build Coastguard Worker // Test pipeline without vertex shader
TEST_P(ProgramPipelineTest31,PipelineWithoutVertexShader)466*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, PipelineWithoutVertexShader)
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
469*8975f5c5SAndroid Build Coastguard Worker 
470*8975f5c5SAndroid Build Coastguard Worker     // Create a separable program object with a fragment shader
471*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = essl31_shaders::fs::Red();
472*8975f5c5SAndroid Build Coastguard Worker     mFragProg                = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
473*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
474*8975f5c5SAndroid Build Coastguard Worker 
475*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the program to it's respective stage
476*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
477*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
478*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
479*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
480*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
481*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
482*8975f5c5SAndroid Build Coastguard Worker 
483*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 3);
484*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
485*8975f5c5SAndroid Build Coastguard Worker }
486*8975f5c5SAndroid Build Coastguard Worker 
487*8975f5c5SAndroid Build Coastguard Worker // Test pipeline without any shaders
TEST_P(ProgramPipelineTest31,PipelineWithoutShaders)488*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, PipelineWithoutShaders)
489*8975f5c5SAndroid Build Coastguard Worker {
490*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
491*8975f5c5SAndroid Build Coastguard Worker 
492*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline
493*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
494*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
495*8975f5c5SAndroid Build Coastguard Worker 
496*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
497*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
498*8975f5c5SAndroid Build Coastguard Worker 
499*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 3);
500*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
501*8975f5c5SAndroid Build Coastguard Worker 
502*8975f5c5SAndroid Build Coastguard Worker     // Ensure validation fails
503*8975f5c5SAndroid Build Coastguard Worker     GLint value;
504*8975f5c5SAndroid Build Coastguard Worker     glValidateProgramPipeline(mPipeline);
505*8975f5c5SAndroid Build Coastguard Worker     glGetProgramPipelineiv(mPipeline, GL_VALIDATE_STATUS, &value);
506*8975f5c5SAndroid Build Coastguard Worker     EXPECT_FALSE(value);
507*8975f5c5SAndroid Build Coastguard Worker }
508*8975f5c5SAndroid Build Coastguard Worker 
509*8975f5c5SAndroid Build Coastguard Worker // Test glUniform
TEST_P(ProgramPipelineTest31,FragmentStageUniformTest)510*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, FragmentStageUniformTest)
511*8975f5c5SAndroid Build Coastguard Worker {
512*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
513*8975f5c5SAndroid Build Coastguard Worker 
514*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
515*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
516*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
517*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
518*8975f5c5SAndroid Build Coastguard Worker precision highp float;
519*8975f5c5SAndroid Build Coastguard Worker uniform float redColorIn;
520*8975f5c5SAndroid Build Coastguard Worker uniform float greenColorIn;
521*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
522*8975f5c5SAndroid Build Coastguard Worker void main()
523*8975f5c5SAndroid Build Coastguard Worker {
524*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, 0.0, 1.0);
525*8975f5c5SAndroid Build Coastguard Worker })";
526*8975f5c5SAndroid Build Coastguard Worker 
527*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
528*8975f5c5SAndroid Build Coastguard Worker 
529*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to yellow
530*8975f5c5SAndroid Build Coastguard Worker     GLint location = glGetUniformLocation(mFragProg, "redColorIn");
531*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
532*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 1.0);
533*8975f5c5SAndroid Build Coastguard Worker     location = glGetUniformLocation(mFragProg, "greenColorIn");
534*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
535*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 1.0);
536*8975f5c5SAndroid Build Coastguard Worker 
537*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
538*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
539*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
540*8975f5c5SAndroid Build Coastguard Worker 
541*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
542*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
543*8975f5c5SAndroid Build Coastguard Worker 
544*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
545*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
546*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
547*8975f5c5SAndroid Build Coastguard Worker 
548*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
549*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
550*8975f5c5SAndroid Build Coastguard Worker 
551*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to red
552*8975f5c5SAndroid Build Coastguard Worker     location = glGetUniformLocation(mFragProg, "redColorIn");
553*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
554*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 1.0);
555*8975f5c5SAndroid Build Coastguard Worker     location = glGetUniformLocation(mFragProg, "greenColorIn");
556*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
557*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 0.0);
558*8975f5c5SAndroid Build Coastguard Worker 
559*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
560*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
561*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
562*8975f5c5SAndroid Build Coastguard Worker 
563*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mVertProg);
564*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mFragProg);
565*8975f5c5SAndroid Build Coastguard Worker }
566*8975f5c5SAndroid Build Coastguard Worker 
567*8975f5c5SAndroid Build Coastguard Worker // Test glUniformBlockBinding and then glBufferData
TEST_P(ProgramPipelineTest31,FragmentStageUniformBlockBufferDataTest)568*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, FragmentStageUniformBlockBufferDataTest)
569*8975f5c5SAndroid Build Coastguard Worker {
570*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
571*8975f5c5SAndroid Build Coastguard Worker 
572*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
573*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
574*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
575*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
576*8975f5c5SAndroid Build Coastguard Worker precision highp float;
577*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform color_ubo
578*8975f5c5SAndroid Build Coastguard Worker {
579*8975f5c5SAndroid Build Coastguard Worker     float redColorIn;
580*8975f5c5SAndroid Build Coastguard Worker     float greenColorIn;
581*8975f5c5SAndroid Build Coastguard Worker };
582*8975f5c5SAndroid Build Coastguard Worker 
583*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
584*8975f5c5SAndroid Build Coastguard Worker void main()
585*8975f5c5SAndroid Build Coastguard Worker {
586*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, 0.0, 1.0);
587*8975f5c5SAndroid Build Coastguard Worker })";
588*8975f5c5SAndroid Build Coastguard Worker 
589*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
590*8975f5c5SAndroid Build Coastguard Worker 
591*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to yellow
592*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
593*8975f5c5SAndroid Build Coastguard Worker     GLint uboIndex = glGetUniformBlockIndex(mFragProg, "color_ubo");
594*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBuf;
595*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf);
596*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
597*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 0);
598*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
599*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
600*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
601*8975f5c5SAndroid Build Coastguard Worker 
602*8975f5c5SAndroid Build Coastguard Worker     // Clear and test again
603*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
604*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
605*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
606*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to red
607*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
608*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBuf);
609*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
610*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
611*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
612*8975f5c5SAndroid Build Coastguard Worker 
613*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mVertProg);
614*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mFragProg);
615*8975f5c5SAndroid Build Coastguard Worker }
616*8975f5c5SAndroid Build Coastguard Worker 
617*8975f5c5SAndroid Build Coastguard Worker // Test glUniformBlockBinding followed by glBindBufferRange
TEST_P(ProgramPipelineTest31,FragmentStageUniformBlockBindBufferRangeTest)618*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, FragmentStageUniformBlockBindBufferRangeTest)
619*8975f5c5SAndroid Build Coastguard Worker {
620*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
621*8975f5c5SAndroid Build Coastguard Worker 
622*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
623*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
624*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
625*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
626*8975f5c5SAndroid Build Coastguard Worker precision highp float;
627*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform color_ubo
628*8975f5c5SAndroid Build Coastguard Worker {
629*8975f5c5SAndroid Build Coastguard Worker     float redColorIn;
630*8975f5c5SAndroid Build Coastguard Worker     float greenColorIn;
631*8975f5c5SAndroid Build Coastguard Worker     float blueColorIn;
632*8975f5c5SAndroid Build Coastguard Worker };
633*8975f5c5SAndroid Build Coastguard Worker 
634*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
635*8975f5c5SAndroid Build Coastguard Worker void main()
636*8975f5c5SAndroid Build Coastguard Worker {
637*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, blueColorIn, 1.0);
638*8975f5c5SAndroid Build Coastguard Worker })";
639*8975f5c5SAndroid Build Coastguard Worker 
640*8975f5c5SAndroid Build Coastguard Worker     // Setup three uniform buffers, one with red, one with green, and one with blue
641*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufRed;
642*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufRed);
643*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
644*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufGreen;
645*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufGreen);
646*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
647*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufBlue;
648*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufBlue);
649*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatBlue, GL_STATIC_DRAW);
650*8975f5c5SAndroid Build Coastguard Worker 
651*8975f5c5SAndroid Build Coastguard Worker     // Setup pipeline program using red uniform buffer
652*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
653*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
654*8975f5c5SAndroid Build Coastguard Worker     GLint uboIndex = glGetUniformBlockIndex(mFragProg, "color_ubo");
655*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBufRed);
656*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 0);
657*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
658*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
659*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
660*8975f5c5SAndroid Build Coastguard Worker 
661*8975f5c5SAndroid Build Coastguard Worker     // Clear and test again
662*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
663*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
664*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
665*8975f5c5SAndroid Build Coastguard Worker     // bind to green uniform buffer
666*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBufGreen);
667*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
668*8975f5c5SAndroid Build Coastguard Worker     // bind to blue uniform buffer
669*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBufBlue);
670*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
671*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
672*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
673*8975f5c5SAndroid Build Coastguard Worker 
674*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mVertProg);
675*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mFragProg);
676*8975f5c5SAndroid Build Coastguard Worker }
677*8975f5c5SAndroid Build Coastguard Worker 
678*8975f5c5SAndroid Build Coastguard Worker // Test that glUniformBlockBinding can successfully change the binding for PPOs
TEST_P(ProgramPipelineTest31,FragmentStageUniformBlockBinding)679*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, FragmentStageUniformBlockBinding)
680*8975f5c5SAndroid Build Coastguard Worker {
681*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
684*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
685*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
686*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
687*8975f5c5SAndroid Build Coastguard Worker precision highp float;
688*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform color_ubo
689*8975f5c5SAndroid Build Coastguard Worker {
690*8975f5c5SAndroid Build Coastguard Worker     float redColorIn;
691*8975f5c5SAndroid Build Coastguard Worker     float greenColorIn;
692*8975f5c5SAndroid Build Coastguard Worker     float blueColorIn;
693*8975f5c5SAndroid Build Coastguard Worker };
694*8975f5c5SAndroid Build Coastguard Worker 
695*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
696*8975f5c5SAndroid Build Coastguard Worker void main()
697*8975f5c5SAndroid Build Coastguard Worker {
698*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, blueColorIn, 1.0);
699*8975f5c5SAndroid Build Coastguard Worker })";
700*8975f5c5SAndroid Build Coastguard Worker 
701*8975f5c5SAndroid Build Coastguard Worker     // Setup three uniform buffers, one with red, one with green, and one with blue
702*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufRed;
703*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufRed);
704*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
705*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufGreen;
706*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufGreen);
707*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
708*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufBlue;
709*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufBlue);
710*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatBlue, GL_STATIC_DRAW);
711*8975f5c5SAndroid Build Coastguard Worker 
712*8975f5c5SAndroid Build Coastguard Worker     // Setup pipeline program using red uniform buffer
713*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
714*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
715*8975f5c5SAndroid Build Coastguard Worker     GLint uboIndex = glGetUniformBlockIndex(mFragProg, "color_ubo");
716*8975f5c5SAndroid Build Coastguard Worker 
717*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBufRed);
718*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboBufGreen);
719*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboBufBlue);
720*8975f5c5SAndroid Build Coastguard Worker 
721*8975f5c5SAndroid Build Coastguard Worker     // Bind the UBO to binding 0 and draw, should be red
722*8975f5c5SAndroid Build Coastguard Worker     const int w = getWindowWidth();
723*8975f5c5SAndroid Build Coastguard Worker     const int h = getWindowHeight();
724*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_SCISSOR_TEST);
725*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, 0, w / 2, h / 2);
726*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 0);
727*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
728*8975f5c5SAndroid Build Coastguard Worker 
729*8975f5c5SAndroid Build Coastguard Worker     // Bind it to binding 1 and draw, should be green
730*8975f5c5SAndroid Build Coastguard Worker     glScissor(w / 2, 0, w - w / 2, h / 2);
731*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 1);
732*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
733*8975f5c5SAndroid Build Coastguard Worker 
734*8975f5c5SAndroid Build Coastguard Worker     // Bind it to binding 2 and draw, should be blue
735*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, h / 2, w, h);
736*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 2);
737*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
738*8975f5c5SAndroid Build Coastguard Worker 
739*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
740*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w - w / 2, h / 2, GLColor::green);
741*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, h / 2, w, h - h / 2, GLColor::blue);
742*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
743*8975f5c5SAndroid Build Coastguard Worker }
744*8975f5c5SAndroid Build Coastguard Worker 
745*8975f5c5SAndroid Build Coastguard Worker // Test that dirty bits related to UBOs propagates to the PPO.
TEST_P(ProgramPipelineTest31,UniformBufferUpdatesBeforeBindToPPO)746*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, UniformBufferUpdatesBeforeBindToPPO)
747*8975f5c5SAndroid Build Coastguard Worker {
748*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
749*8975f5c5SAndroid Build Coastguard Worker 
750*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
751*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
752*8975f5c5SAndroid Build Coastguard Worker precision highp float;
753*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform color_ubo
754*8975f5c5SAndroid Build Coastguard Worker {
755*8975f5c5SAndroid Build Coastguard Worker     float redColorIn;
756*8975f5c5SAndroid Build Coastguard Worker     float greenColorIn;
757*8975f5c5SAndroid Build Coastguard Worker     float blueColorIn;
758*8975f5c5SAndroid Build Coastguard Worker };
759*8975f5c5SAndroid Build Coastguard Worker 
760*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
761*8975f5c5SAndroid Build Coastguard Worker void main()
762*8975f5c5SAndroid Build Coastguard Worker {
763*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, blueColorIn, 1.0);
764*8975f5c5SAndroid Build Coastguard Worker })";
765*8975f5c5SAndroid Build Coastguard Worker 
766*8975f5c5SAndroid Build Coastguard Worker     GLuint vs = CompileShader(GL_VERTEX_SHADER, vertString);
767*8975f5c5SAndroid Build Coastguard Worker     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fragString);
768*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateProgram();
769*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateProgram();
770*8975f5c5SAndroid Build Coastguard Worker 
771*8975f5c5SAndroid Build Coastguard Worker     // Compile and link a separable vertex shader
772*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mVertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
773*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mVertProg, vs);
774*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mVertProg);
775*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
776*8975f5c5SAndroid Build Coastguard Worker 
777*8975f5c5SAndroid Build Coastguard Worker     // Compile and link a separable fragment shader
778*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
779*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mFragProg, fs);
780*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mFragProg);
781*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
782*8975f5c5SAndroid Build Coastguard Worker 
783*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs
784*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
785*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
786*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
787*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
788*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
789*8975f5c5SAndroid Build Coastguard Worker 
790*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufRed;
791*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufRed);
792*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
793*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufGreen;
794*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufGreen);
795*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatGreen, GL_STATIC_DRAW);
796*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uboBufBlue;
797*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uboBufBlue);
798*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatBlue, GL_STATIC_DRAW);
799*8975f5c5SAndroid Build Coastguard Worker 
800*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
801*8975f5c5SAndroid Build Coastguard Worker     GLint uboIndex = glGetUniformBlockIndex(mFragProg, "color_ubo");
802*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 0);
803*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboBufRed);
804*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboBufGreen);
805*8975f5c5SAndroid Build Coastguard Worker 
806*8975f5c5SAndroid Build Coastguard Worker     // Draw once so all dirty bits are handled.  Should be red
807*8975f5c5SAndroid Build Coastguard Worker     const int w = getWindowWidth();
808*8975f5c5SAndroid Build Coastguard Worker     const int h = getWindowHeight();
809*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_SCISSOR_TEST);
810*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, 0, w / 2, h / 2);
811*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
812*8975f5c5SAndroid Build Coastguard Worker 
813*8975f5c5SAndroid Build Coastguard Worker     // Unbind the fragment program from the PPO
814*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, 0);
815*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
816*8975f5c5SAndroid Build Coastguard Worker 
817*8975f5c5SAndroid Build Coastguard Worker     // Modify the UBO bindings, reattach the program and draw again.  Should be green
818*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, uboIndex, 1);
819*8975f5c5SAndroid Build Coastguard Worker 
820*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
821*8975f5c5SAndroid Build Coastguard Worker     glScissor(w / 2, 0, w - w / 2, h / 2);
822*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
823*8975f5c5SAndroid Build Coastguard Worker 
824*8975f5c5SAndroid Build Coastguard Worker     // Unbind the fragment program from the PPO again, and modify the UBO bindings differently.
825*8975f5c5SAndroid Build Coastguard Worker     // Draw again, which should be blue.
826*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, 0);
827*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboBufBlue);
828*8975f5c5SAndroid Build Coastguard Worker 
829*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
830*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, h / 2, w, h);
831*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
832*8975f5c5SAndroid Build Coastguard Worker 
833*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
834*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w - w / 2, h / 2, GLColor::green);
835*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, h / 2, w, h - h / 2, GLColor::blue);
836*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
837*8975f5c5SAndroid Build Coastguard Worker }
838*8975f5c5SAndroid Build Coastguard Worker 
839*8975f5c5SAndroid Build Coastguard Worker // Test glBindBufferRange between draw calls in the presence of multiple UBOs between VS and FS
TEST_P(ProgramPipelineTest31,BindBufferRangeForMultipleUBOsInMultipleStages)840*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, BindBufferRangeForMultipleUBOsInMultipleStages)
841*8975f5c5SAndroid Build Coastguard Worker {
842*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
843*8975f5c5SAndroid Build Coastguard Worker 
844*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
845*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
846*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
847*8975f5c5SAndroid Build Coastguard Worker precision highp float;
848*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform vsUBO1
849*8975f5c5SAndroid Build Coastguard Worker {
850*8975f5c5SAndroid Build Coastguard Worker     float redIn;
851*8975f5c5SAndroid Build Coastguard Worker };
852*8975f5c5SAndroid Build Coastguard Worker 
853*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform vsUBO2
854*8975f5c5SAndroid Build Coastguard Worker {
855*8975f5c5SAndroid Build Coastguard Worker     float greenIn;
856*8975f5c5SAndroid Build Coastguard Worker };
857*8975f5c5SAndroid Build Coastguard Worker 
858*8975f5c5SAndroid Build Coastguard Worker out float red;
859*8975f5c5SAndroid Build Coastguard Worker out float green;
860*8975f5c5SAndroid Build Coastguard Worker 
861*8975f5c5SAndroid Build Coastguard Worker void main()
862*8975f5c5SAndroid Build Coastguard Worker {
863*8975f5c5SAndroid Build Coastguard Worker     vec2 pos = vec2(0.0);
864*8975f5c5SAndroid Build Coastguard Worker     switch (gl_VertexID) {
865*8975f5c5SAndroid Build Coastguard Worker         case 0: pos = vec2(-1.0, -1.0); break;
866*8975f5c5SAndroid Build Coastguard Worker         case 1: pos = vec2(3.0, -1.0); break;
867*8975f5c5SAndroid Build Coastguard Worker         case 2: pos = vec2(-1.0, 3.0); break;
868*8975f5c5SAndroid Build Coastguard Worker     };
869*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(pos, 0.0, 1.0);
870*8975f5c5SAndroid Build Coastguard Worker     red = redIn;
871*8975f5c5SAndroid Build Coastguard Worker     green = greenIn;
872*8975f5c5SAndroid Build Coastguard Worker })";
873*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
874*8975f5c5SAndroid Build Coastguard Worker precision highp float;
875*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform fsUBO1
876*8975f5c5SAndroid Build Coastguard Worker {
877*8975f5c5SAndroid Build Coastguard Worker     float blueIn;
878*8975f5c5SAndroid Build Coastguard Worker };
879*8975f5c5SAndroid Build Coastguard Worker 
880*8975f5c5SAndroid Build Coastguard Worker layout (std140) uniform fsUBO2
881*8975f5c5SAndroid Build Coastguard Worker {
882*8975f5c5SAndroid Build Coastguard Worker     float alphaIn;
883*8975f5c5SAndroid Build Coastguard Worker };
884*8975f5c5SAndroid Build Coastguard Worker 
885*8975f5c5SAndroid Build Coastguard Worker in float red;
886*8975f5c5SAndroid Build Coastguard Worker in float green;
887*8975f5c5SAndroid Build Coastguard Worker 
888*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
889*8975f5c5SAndroid Build Coastguard Worker void main()
890*8975f5c5SAndroid Build Coastguard Worker {
891*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(red, green, blueIn, alphaIn);
892*8975f5c5SAndroid Build Coastguard Worker })";
893*8975f5c5SAndroid Build Coastguard Worker 
894*8975f5c5SAndroid Build Coastguard Worker     // Setup two uniform buffers, one with 1, one with 0
895*8975f5c5SAndroid Build Coastguard Worker     GLBuffer ubo0;
896*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, ubo0);
897*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatBlack, GL_STATIC_DRAW);
898*8975f5c5SAndroid Build Coastguard Worker     GLBuffer ubo1;
899*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, ubo1);
900*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLColor32F), &kFloatRed, GL_STATIC_DRAW);
901*8975f5c5SAndroid Build Coastguard Worker 
902*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
903*8975f5c5SAndroid Build Coastguard Worker 
904*8975f5c5SAndroid Build Coastguard Worker     // Setup the initial bindings to draw red
905*8975f5c5SAndroid Build Coastguard Worker     const GLint vsUBO1 = glGetUniformBlockIndex(mVertProg, "vsUBO1");
906*8975f5c5SAndroid Build Coastguard Worker     const GLint vsUBO2 = glGetUniformBlockIndex(mVertProg, "vsUBO2");
907*8975f5c5SAndroid Build Coastguard Worker     const GLint fsUBO1 = glGetUniformBlockIndex(mFragProg, "fsUBO1");
908*8975f5c5SAndroid Build Coastguard Worker     const GLint fsUBO2 = glGetUniformBlockIndex(mFragProg, "fsUBO2");
909*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mVertProg, vsUBO1, 0);
910*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mVertProg, vsUBO2, 1);
911*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, fsUBO1, 2);
912*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(mFragProg, fsUBO2, 3);
913*8975f5c5SAndroid Build Coastguard Worker 
914*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo1);
915*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo0);
916*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 2, ubo0);
917*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 3, ubo1);
918*8975f5c5SAndroid Build Coastguard Worker 
919*8975f5c5SAndroid Build Coastguard Worker     const int w = getWindowWidth();
920*8975f5c5SAndroid Build Coastguard Worker     const int h = getWindowHeight();
921*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_SCISSOR_TEST);
922*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, 0, w / 2, h / 2);
923*8975f5c5SAndroid Build Coastguard Worker 
924*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
925*8975f5c5SAndroid Build Coastguard Worker 
926*8975f5c5SAndroid Build Coastguard Worker     // Change the bindings in the vertex shader UBO binding and draw again, should be yellow.
927*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo1);
928*8975f5c5SAndroid Build Coastguard Worker     glScissor(w / 2, 0, w - w / 2, h / 2);
929*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
930*8975f5c5SAndroid Build Coastguard Worker 
931*8975f5c5SAndroid Build Coastguard Worker     // Change the bindings in the fragment shader UBO binding and draw again, should be white.
932*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 2, ubo1);
933*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, h / 2, w / 2, h - h / 2);
934*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
935*8975f5c5SAndroid Build Coastguard Worker 
936*8975f5c5SAndroid Build Coastguard Worker     // Change the bindings in both shader UBO bindings and draw again, should be green.
937*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo0);
938*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 2, ubo0);
939*8975f5c5SAndroid Build Coastguard Worker     glScissor(w / 2, h / 2, w - w / 2, h - h / 2);
940*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
941*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
942*8975f5c5SAndroid Build Coastguard Worker 
943*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, w / 2, h / 2, GLColor::red);
944*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(w / 2, 0, w - w / 2, h / 2, GLColor::yellow);
945*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, h / 2, w / 2, h - h / 2, GLColor::white);
946*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(w / 2, h / 2, w - w / 2, h - h / 2, GLColor::green);
947*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
948*8975f5c5SAndroid Build Coastguard Worker }
949*8975f5c5SAndroid Build Coastguard Worker 
950*8975f5c5SAndroid Build Coastguard Worker // Test varyings
TEST_P(ProgramPipelineTest31,ProgramPipelineVaryings)951*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, ProgramPipelineVaryings)
952*8975f5c5SAndroid Build Coastguard Worker {
953*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
954*8975f5c5SAndroid Build Coastguard Worker 
955*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
956*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
957*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Passthrough();
958*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
959*8975f5c5SAndroid Build Coastguard Worker precision highp float;
960*8975f5c5SAndroid Build Coastguard Worker in vec4 v_position;
961*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
962*8975f5c5SAndroid Build Coastguard Worker void main()
963*8975f5c5SAndroid Build Coastguard Worker {
964*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = round(v_position);
965*8975f5c5SAndroid Build Coastguard Worker })";
966*8975f5c5SAndroid Build Coastguard Worker 
967*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
968*8975f5c5SAndroid Build Coastguard Worker 
969*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
970*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
971*8975f5c5SAndroid Build Coastguard Worker 
972*8975f5c5SAndroid Build Coastguard Worker     int w = getWindowWidth() - 2;
973*8975f5c5SAndroid Build Coastguard Worker     int h = getWindowHeight() - 2;
974*8975f5c5SAndroid Build Coastguard Worker 
975*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
976*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::red);
977*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::green);
978*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
979*8975f5c5SAndroid Build Coastguard Worker }
980*8975f5c5SAndroid Build Coastguard Worker 
981*8975f5c5SAndroid Build Coastguard Worker // Creates a program pipeline with a 2D texture and renders with it.
TEST_P(ProgramPipelineTest31,DrawWith2DTexture)982*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, DrawWith2DTexture)
983*8975f5c5SAndroid Build Coastguard Worker {
984*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
985*8975f5c5SAndroid Build Coastguard Worker 
986*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
987*8975f5c5SAndroid Build Coastguard Worker precision highp float;
988*8975f5c5SAndroid Build Coastguard Worker in vec4 a_position;
989*8975f5c5SAndroid Build Coastguard Worker out vec2 texCoord;
990*8975f5c5SAndroid Build Coastguard Worker void main()
991*8975f5c5SAndroid Build Coastguard Worker {
992*8975f5c5SAndroid Build Coastguard Worker     gl_Position = a_position;
993*8975f5c5SAndroid Build Coastguard Worker     texCoord = vec2(a_position.x, a_position.y) * 0.5 + vec2(0.5);
994*8975f5c5SAndroid Build Coastguard Worker })";
995*8975f5c5SAndroid Build Coastguard Worker 
996*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
997*8975f5c5SAndroid Build Coastguard Worker precision highp float;
998*8975f5c5SAndroid Build Coastguard Worker in vec2 texCoord;
999*8975f5c5SAndroid Build Coastguard Worker uniform sampler2D tex;
1000*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1001*8975f5c5SAndroid Build Coastguard Worker void main()
1002*8975f5c5SAndroid Build Coastguard Worker {
1003*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = texture(tex, texCoord);
1004*8975f5c5SAndroid Build Coastguard Worker })";
1005*8975f5c5SAndroid Build Coastguard Worker 
1006*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, 4> colors = {
1007*8975f5c5SAndroid Build Coastguard Worker         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
1008*8975f5c5SAndroid Build Coastguard Worker 
1009*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
1010*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, tex);
1011*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
1012*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1013*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1014*8975f5c5SAndroid Build Coastguard Worker 
1015*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
1016*8975f5c5SAndroid Build Coastguard Worker 
1017*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
1018*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1019*8975f5c5SAndroid Build Coastguard Worker 
1020*8975f5c5SAndroid Build Coastguard Worker     int w = getWindowWidth() - 2;
1021*8975f5c5SAndroid Build Coastguard Worker     int h = getWindowHeight() - 2;
1022*8975f5c5SAndroid Build Coastguard Worker 
1023*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1024*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
1025*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
1026*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
1027*8975f5c5SAndroid Build Coastguard Worker }
1028*8975f5c5SAndroid Build Coastguard Worker 
1029*8975f5c5SAndroid Build Coastguard Worker // Test modifying a shader after it has been detached from a pipeline
TEST_P(ProgramPipelineTest31,DetachAndModifyShader)1030*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, DetachAndModifyShader)
1031*8975f5c5SAndroid Build Coastguard Worker {
1032*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1033*8975f5c5SAndroid Build Coastguard Worker 
1034*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1035*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = essl31_shaders::fs::Green();
1036*8975f5c5SAndroid Build Coastguard Worker 
1037*8975f5c5SAndroid Build Coastguard Worker     GLShader vertShader(GL_VERTEX_SHADER);
1038*8975f5c5SAndroid Build Coastguard Worker     GLShader fragShader(GL_FRAGMENT_SHADER);
1039*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateProgram();
1040*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateProgram();
1041*8975f5c5SAndroid Build Coastguard Worker 
1042*8975f5c5SAndroid Build Coastguard Worker     // Compile and link a separable vertex shader
1043*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(vertShader, 1, &vertString, nullptr);
1044*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(vertShader);
1045*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mVertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1046*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mVertProg, vertShader);
1047*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mVertProg);
1048*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1049*8975f5c5SAndroid Build Coastguard Worker 
1050*8975f5c5SAndroid Build Coastguard Worker     // Compile and link a separable fragment shader
1051*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &fragString, nullptr);
1052*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
1053*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1054*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mFragProg, fragShader);
1055*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mFragProg);
1056*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1057*8975f5c5SAndroid Build Coastguard Worker 
1058*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs
1059*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
1060*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
1061*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
1062*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
1063*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1064*8975f5c5SAndroid Build Coastguard Worker 
1065*8975f5c5SAndroid Build Coastguard Worker     // Draw once to ensure this worked fine
1066*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
1067*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1068*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1069*8975f5c5SAndroid Build Coastguard Worker 
1070*8975f5c5SAndroid Build Coastguard Worker     // Detach the fragment shader and modify it such that it no longer fits with this pipeline
1071*8975f5c5SAndroid Build Coastguard Worker     glDetachShader(mFragProg, fragShader);
1072*8975f5c5SAndroid Build Coastguard Worker 
1073*8975f5c5SAndroid Build Coastguard Worker     // Add an input to the fragment shader, which will make it incompatible
1074*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString2 = R"(#version 310 es
1075*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1076*8975f5c5SAndroid Build Coastguard Worker in vec4 color;
1077*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1078*8975f5c5SAndroid Build Coastguard Worker void main()
1079*8975f5c5SAndroid Build Coastguard Worker {
1080*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = color;
1081*8975f5c5SAndroid Build Coastguard Worker })";
1082*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &fragString2, nullptr);
1083*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
1084*8975f5c5SAndroid Build Coastguard Worker 
1085*8975f5c5SAndroid Build Coastguard Worker     // Link and draw with the program again, which should be fine since the shader was detached
1086*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mFragProg);
1087*8975f5c5SAndroid Build Coastguard Worker 
1088*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
1089*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1090*8975f5c5SAndroid Build Coastguard Worker }
1091*8975f5c5SAndroid Build Coastguard Worker 
1092*8975f5c5SAndroid Build Coastguard Worker // Test binding two programs that use a texture as different types
TEST_P(ProgramPipelineTest31,DifferentTextureTypes)1093*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, DifferentTextureTypes)
1094*8975f5c5SAndroid Build Coastguard Worker {
1095*8975f5c5SAndroid Build Coastguard Worker     // Only the Vulkan backend supports PPO
1096*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1097*8975f5c5SAndroid Build Coastguard Worker 
1098*8975f5c5SAndroid Build Coastguard Worker     // Per the OpenGL ES 3.1 spec:
1099*8975f5c5SAndroid Build Coastguard Worker     //
1100*8975f5c5SAndroid Build Coastguard Worker     // It is not allowed to have variables of different sampler types pointing to the same texture
1101*8975f5c5SAndroid Build Coastguard Worker     // image unit within a program object. This situation can only be detected at the next rendering
1102*8975f5c5SAndroid Build Coastguard Worker     // command issued which triggers shader invocations, and an INVALID_OPERATION error will then
1103*8975f5c5SAndroid Build Coastguard Worker     // be generated
1104*8975f5c5SAndroid Build Coastguard Worker     //
1105*8975f5c5SAndroid Build Coastguard Worker 
1106*8975f5c5SAndroid Build Coastguard Worker     // Create a vertex shader that uses the texture as 2D
1107*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
1108*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1109*8975f5c5SAndroid Build Coastguard Worker in vec4 a_position;
1110*8975f5c5SAndroid Build Coastguard Worker uniform sampler2D tex2D;
1111*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out vec4 texColorOut;
1112*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) out vec2 texCoordOut;
1113*8975f5c5SAndroid Build Coastguard Worker void main()
1114*8975f5c5SAndroid Build Coastguard Worker {
1115*8975f5c5SAndroid Build Coastguard Worker     gl_Position = a_position;
1116*8975f5c5SAndroid Build Coastguard Worker     vec2 texCoord = vec2(a_position.x, a_position.y) * 0.5 + vec2(0.5);
1117*8975f5c5SAndroid Build Coastguard Worker     texColorOut = textureLod(tex2D, texCoord, 0.0);
1118*8975f5c5SAndroid Build Coastguard Worker     texCoordOut = texCoord;
1119*8975f5c5SAndroid Build Coastguard Worker })";
1120*8975f5c5SAndroid Build Coastguard Worker 
1121*8975f5c5SAndroid Build Coastguard Worker     // Create a fragment shader that uses the texture as Cube
1122*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1123*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1124*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec4 texColor;
1125*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) in vec2 texCoord;
1126*8975f5c5SAndroid Build Coastguard Worker uniform samplerCube texCube;
1127*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1128*8975f5c5SAndroid Build Coastguard Worker void main()
1129*8975f5c5SAndroid Build Coastguard Worker {
1130*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = texture(texCube, vec3(texCoord.x, texCoord.y, 0.0));
1131*8975f5c5SAndroid Build Coastguard Worker })";
1132*8975f5c5SAndroid Build Coastguard Worker 
1133*8975f5c5SAndroid Build Coastguard Worker     // Create and populate the 2D texture
1134*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, 4> colors = {
1135*8975f5c5SAndroid Build Coastguard Worker         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
1136*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
1137*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, tex);
1138*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
1139*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1140*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1141*8975f5c5SAndroid Build Coastguard Worker 
1142*8975f5c5SAndroid Build Coastguard Worker     // Create a pipeline that uses the bad combination.  This should fail to link the pipeline.
1143*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
1144*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
1145*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1146*8975f5c5SAndroid Build Coastguard Worker 
1147*8975f5c5SAndroid Build Coastguard Worker     // Update the fragment shader to correctly use 2D texture
1148*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString2 = R"(#version 310 es
1149*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1150*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec4 texColor;
1151*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) in vec2 texCoord;
1152*8975f5c5SAndroid Build Coastguard Worker uniform sampler2D tex2D;
1153*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1154*8975f5c5SAndroid Build Coastguard Worker void main()
1155*8975f5c5SAndroid Build Coastguard Worker {
1156*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = texture(tex2D, texCoord);
1157*8975f5c5SAndroid Build Coastguard Worker })";
1158*8975f5c5SAndroid Build Coastguard Worker 
1159*8975f5c5SAndroid Build Coastguard Worker     // Bind the pipeline again, which should succeed.
1160*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString2);
1161*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
1162*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1163*8975f5c5SAndroid Build Coastguard Worker }
1164*8975f5c5SAndroid Build Coastguard Worker 
1165*8975f5c5SAndroid Build Coastguard Worker // Tests that we receive a PPO link validation error when attempting to draw with the bad PPO
TEST_P(ProgramPipelineTest31,VerifyPpoLinkErrorSignalledCorrectly)1166*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, VerifyPpoLinkErrorSignalledCorrectly)
1167*8975f5c5SAndroid Build Coastguard Worker {
1168*8975f5c5SAndroid Build Coastguard Worker     // Create pipeline that should fail link
1169*8975f5c5SAndroid Build Coastguard Worker     // Bind program
1170*8975f5c5SAndroid Build Coastguard Worker     // Draw
1171*8975f5c5SAndroid Build Coastguard Worker     // Unbind program
1172*8975f5c5SAndroid Build Coastguard Worker     // Draw  <<--- expect a link validation error here
1173*8975f5c5SAndroid Build Coastguard Worker 
1174*8975f5c5SAndroid Build Coastguard Worker     // Only the Vulkan backend supports PPOs
1175*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1176*8975f5c5SAndroid Build Coastguard Worker 
1177*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
1178*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
1179*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1180*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = essl31_shaders::fs::Red();
1181*8975f5c5SAndroid Build Coastguard Worker     // Create a fragment shader that takes a color input
1182*8975f5c5SAndroid Build Coastguard Worker     // This should cause the PPO link to fail, since the varyings don't match (no output from VS).
1183*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragStringBad = R"(#version 310 es
1184*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1185*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec4 colorIn;
1186*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1187*8975f5c5SAndroid Build Coastguard Worker void main()
1188*8975f5c5SAndroid Build Coastguard Worker {
1189*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = colorIn;
1190*8975f5c5SAndroid Build Coastguard Worker })";
1191*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragStringBad);
1192*8975f5c5SAndroid Build Coastguard Worker 
1193*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, vertString, fragString);
1194*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f, 1.0f, true);
1195*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1196*8975f5c5SAndroid Build Coastguard Worker 
1197*8975f5c5SAndroid Build Coastguard Worker     // Draw with the PPO, which should generate an error due to the link failure.
1198*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(0);
1199*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1200*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl1_shaders::PositionAttrib(), 0.5f, 1.0f);
1201*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_ERROR(GL_INVALID_OPERATION);
1202*8975f5c5SAndroid Build Coastguard Worker }
1203*8975f5c5SAndroid Build Coastguard Worker 
1204*8975f5c5SAndroid Build Coastguard Worker // Tests creating two program pipelines with a common shader and a varying location mismatch.
TEST_P(ProgramPipelineTest31,VaryingLocationMismatch)1205*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, VaryingLocationMismatch)
1206*8975f5c5SAndroid Build Coastguard Worker {
1207*8975f5c5SAndroid Build Coastguard Worker     // Only the Vulkan backend supports PPOs
1208*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1209*8975f5c5SAndroid Build Coastguard Worker 
1210*8975f5c5SAndroid Build Coastguard Worker     // Create a fragment shader using the varying location "5".
1211*8975f5c5SAndroid Build Coastguard Worker     const char *kFS = R"(#version 310 es
1212*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1213*8975f5c5SAndroid Build Coastguard Worker layout(location = 5) in vec4 color;
1214*8975f5c5SAndroid Build Coastguard Worker out vec4 colorOut;
1215*8975f5c5SAndroid Build Coastguard Worker void main()
1216*8975f5c5SAndroid Build Coastguard Worker {
1217*8975f5c5SAndroid Build Coastguard Worker     colorOut = color;
1218*8975f5c5SAndroid Build Coastguard Worker })";
1219*8975f5c5SAndroid Build Coastguard Worker 
1220*8975f5c5SAndroid Build Coastguard Worker     // Create a pipeline with a vertex shader using varying location "5". Should succeed.
1221*8975f5c5SAndroid Build Coastguard Worker     const char *kVSGood = R"(#version 310 es
1222*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1223*8975f5c5SAndroid Build Coastguard Worker layout(location = 5) out vec4 color;
1224*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
1225*8975f5c5SAndroid Build Coastguard Worker uniform float uniOne;
1226*8975f5c5SAndroid Build Coastguard Worker void main()
1227*8975f5c5SAndroid Build Coastguard Worker {
1228*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
1229*8975f5c5SAndroid Build Coastguard Worker     color = vec4(0, uniOne, 0, 1);
1230*8975f5c5SAndroid Build Coastguard Worker })";
1231*8975f5c5SAndroid Build Coastguard Worker 
1232*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &kVSGood);
1233*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
1234*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &kFS);
1235*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
1236*8975f5c5SAndroid Build Coastguard Worker 
1237*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
1238*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
1239*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
1240*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
1241*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
1242*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1243*8975f5c5SAndroid Build Coastguard Worker 
1244*8975f5c5SAndroid Build Coastguard Worker     GLint location = glGetUniformLocation(mVertProg, "uniOne");
1245*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, location);
1246*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mVertProg);
1247*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(location, 1.0);
1248*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1249*8975f5c5SAndroid Build Coastguard Worker 
1250*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("position", 0.5f, 1.0f);
1251*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1252*8975f5c5SAndroid Build Coastguard Worker 
1253*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1254*8975f5c5SAndroid Build Coastguard Worker 
1255*8975f5c5SAndroid Build Coastguard Worker     // Create a pipeline with a vertex shader using varying location "3". Should fail.
1256*8975f5c5SAndroid Build Coastguard Worker     const char *kVSBad = R"(#version 310 es
1257*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1258*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) out vec4 color;
1259*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
1260*8975f5c5SAndroid Build Coastguard Worker uniform float uniOne;
1261*8975f5c5SAndroid Build Coastguard Worker void main()
1262*8975f5c5SAndroid Build Coastguard Worker {
1263*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
1264*8975f5c5SAndroid Build Coastguard Worker     color = vec4(0, uniOne, 0, 1);
1265*8975f5c5SAndroid Build Coastguard Worker })";
1266*8975f5c5SAndroid Build Coastguard Worker 
1267*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(mVertProg);
1268*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &kVSBad);
1269*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
1270*8975f5c5SAndroid Build Coastguard Worker 
1271*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
1272*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1273*8975f5c5SAndroid Build Coastguard Worker 
1274*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("position", 0.5f, 1.0f);
1275*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1276*8975f5c5SAndroid Build Coastguard Worker }
1277*8975f5c5SAndroid Build Coastguard Worker 
1278*8975f5c5SAndroid Build Coastguard Worker // Test that uniform updates are propagated with minimal state changes.
TEST_P(ProgramPipelineTest31,UniformUpdate)1279*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, UniformUpdate)
1280*8975f5c5SAndroid Build Coastguard Worker {
1281*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1282*8975f5c5SAndroid Build Coastguard Worker 
1283*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
1284*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
1285*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1286*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1287*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1288*8975f5c5SAndroid Build Coastguard Worker uniform float redColorIn;
1289*8975f5c5SAndroid Build Coastguard Worker uniform float greenColorIn;
1290*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1291*8975f5c5SAndroid Build Coastguard Worker void main()
1292*8975f5c5SAndroid Build Coastguard Worker {
1293*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, 0.0, 1.0);
1294*8975f5c5SAndroid Build Coastguard Worker })";
1295*8975f5c5SAndroid Build Coastguard Worker 
1296*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
1297*8975f5c5SAndroid Build Coastguard Worker 
1298*8975f5c5SAndroid Build Coastguard Worker     GLint redLoc = glGetUniformLocation(mFragProg, "redColorIn");
1299*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, redLoc);
1300*8975f5c5SAndroid Build Coastguard Worker     GLint greenLoc = glGetUniformLocation(mFragProg, "greenColorIn");
1301*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, greenLoc);
1302*8975f5c5SAndroid Build Coastguard Worker 
1303*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
1304*8975f5c5SAndroid Build Coastguard Worker 
1305*8975f5c5SAndroid Build Coastguard Worker     std::array<Vector3, 6> verts = GetQuadVertices();
1306*8975f5c5SAndroid Build Coastguard Worker 
1307*8975f5c5SAndroid Build Coastguard Worker     GLBuffer vbo;
1308*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vbo);
1309*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(verts[0]), verts.data(), GL_STATIC_DRAW);
1310*8975f5c5SAndroid Build Coastguard Worker 
1311*8975f5c5SAndroid Build Coastguard Worker     GLint posLoc = glGetAttribLocation(mVertProg, essl31_shaders::PositionAttrib());
1312*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1313*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(posLoc);
1314*8975f5c5SAndroid Build Coastguard Worker 
1315*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
1316*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1317*8975f5c5SAndroid Build Coastguard Worker 
1318*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to red, draw to left half of window.
1319*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(redLoc, 1.0);
1320*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(greenLoc, 0.0);
1321*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
1322*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1323*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1324*8975f5c5SAndroid Build Coastguard Worker 
1325*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to green, draw to right half of window.
1326*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(redLoc, 0.0);
1327*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(greenLoc, 1.0);
1328*8975f5c5SAndroid Build Coastguard Worker 
1329*8975f5c5SAndroid Build Coastguard Worker     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
1330*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1331*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1332*8975f5c5SAndroid Build Coastguard Worker 
1333*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1334*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 + 1, 0, GLColor::green);
1335*8975f5c5SAndroid Build Coastguard Worker }
1336*8975f5c5SAndroid Build Coastguard Worker 
1337*8975f5c5SAndroid Build Coastguard Worker // Test that uniform updates propagate to two pipelines.
TEST_P(ProgramPipelineTest31,UniformUpdateTwoPipelines)1338*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, UniformUpdateTwoPipelines)
1339*8975f5c5SAndroid Build Coastguard Worker {
1340*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1341*8975f5c5SAndroid Build Coastguard Worker 
1342*8975f5c5SAndroid Build Coastguard Worker     // Create two separable program objects from a
1343*8975f5c5SAndroid Build Coastguard Worker     // single source string respectively (vertSrc and fragSrc)
1344*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1345*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1346*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1347*8975f5c5SAndroid Build Coastguard Worker uniform float redColorIn;
1348*8975f5c5SAndroid Build Coastguard Worker uniform float greenColorIn;
1349*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1350*8975f5c5SAndroid Build Coastguard Worker void main()
1351*8975f5c5SAndroid Build Coastguard Worker {
1352*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(redColorIn, greenColorIn, 0.0, 1.0);
1353*8975f5c5SAndroid Build Coastguard Worker })";
1354*8975f5c5SAndroid Build Coastguard Worker 
1355*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
1356*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
1357*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
1358*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
1359*8975f5c5SAndroid Build Coastguard Worker 
1360*8975f5c5SAndroid Build Coastguard Worker     GLint redLoc = glGetUniformLocation(mFragProg, "redColorIn");
1361*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, redLoc);
1362*8975f5c5SAndroid Build Coastguard Worker     GLint greenLoc = glGetUniformLocation(mFragProg, "greenColorIn");
1363*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, greenLoc);
1364*8975f5c5SAndroid Build Coastguard Worker 
1365*8975f5c5SAndroid Build Coastguard Worker     GLProgramPipeline ppo1;
1366*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(ppo1, GL_VERTEX_SHADER_BIT, mVertProg);
1367*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(ppo1, GL_FRAGMENT_SHADER_BIT, mFragProg);
1368*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo1);
1369*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(ppo1, mFragProg);
1370*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1371*8975f5c5SAndroid Build Coastguard Worker 
1372*8975f5c5SAndroid Build Coastguard Worker     GLProgramPipeline ppo2;
1373*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(ppo2, GL_VERTEX_SHADER_BIT, mVertProg);
1374*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(ppo2, GL_FRAGMENT_SHADER_BIT, mFragProg);
1375*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo2);
1376*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(ppo2, mFragProg);
1377*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1378*8975f5c5SAndroid Build Coastguard Worker 
1379*8975f5c5SAndroid Build Coastguard Worker     std::array<Vector3, 6> verts = GetQuadVertices();
1380*8975f5c5SAndroid Build Coastguard Worker 
1381*8975f5c5SAndroid Build Coastguard Worker     GLBuffer vbo;
1382*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vbo);
1383*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(verts[0]), verts.data(), GL_STATIC_DRAW);
1384*8975f5c5SAndroid Build Coastguard Worker 
1385*8975f5c5SAndroid Build Coastguard Worker     GLint posLoc = glGetAttribLocation(mVertProg, essl31_shaders::PositionAttrib());
1386*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1387*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(posLoc);
1388*8975f5c5SAndroid Build Coastguard Worker 
1389*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0.0, 0.0, 0.0, 0.0);
1390*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1391*8975f5c5SAndroid Build Coastguard Worker 
1392*8975f5c5SAndroid Build Coastguard Worker     const GLsizei w = getWindowWidth() / 2;
1393*8975f5c5SAndroid Build Coastguard Worker     const GLsizei h = getWindowHeight() / 2;
1394*8975f5c5SAndroid Build Coastguard Worker 
1395*8975f5c5SAndroid Build Coastguard Worker     // Set the output color to red, draw to UL quad of window with first PPO.
1396*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(redLoc, 1.0);
1397*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(greenLoc, 0.0);
1398*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo1);
1399*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, 0, w, h);
1400*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1401*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1402*8975f5c5SAndroid Build Coastguard Worker 
1403*8975f5c5SAndroid Build Coastguard Worker     // Draw red to UR half of window with second PPO.
1404*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo2);
1405*8975f5c5SAndroid Build Coastguard Worker     glViewport(w, 0, w, h);
1406*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1407*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1408*8975f5c5SAndroid Build Coastguard Worker 
1409*8975f5c5SAndroid Build Coastguard Worker     // Draw green to LL corner of window with first PPO.
1410*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(redLoc, 0.0);
1411*8975f5c5SAndroid Build Coastguard Worker     glUniform1f(greenLoc, 1.0);
1412*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo1);
1413*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, h, w, h);
1414*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1415*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1416*8975f5c5SAndroid Build Coastguard Worker 
1417*8975f5c5SAndroid Build Coastguard Worker     // Draw green to LR half of window with second PPO.
1418*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo2);
1419*8975f5c5SAndroid Build Coastguard Worker     glViewport(w, h, w, h);
1420*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1421*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1422*8975f5c5SAndroid Build Coastguard Worker 
1423*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1424*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w + 1, 0, GLColor::red);
1425*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, h + 1, GLColor::green);
1426*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w + 1, h + 1, GLColor::green);
1427*8975f5c5SAndroid Build Coastguard Worker }
1428*8975f5c5SAndroid Build Coastguard Worker 
1429*8975f5c5SAndroid Build Coastguard Worker // Tests that setting sampler bindings on a program before the pipeline works as expected.
TEST_P(ProgramPipelineTest31,BindSamplerBeforeCreatingPipeline)1430*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, BindSamplerBeforeCreatingPipeline)
1431*8975f5c5SAndroid Build Coastguard Worker {
1432*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1433*8975f5c5SAndroid Build Coastguard Worker 
1434*8975f5c5SAndroid Build Coastguard Worker     // Create two textures - red and green.
1435*8975f5c5SAndroid Build Coastguard Worker     GLTexture redTex;
1436*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, redTex);
1437*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
1438*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1439*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1440*8975f5c5SAndroid Build Coastguard Worker 
1441*8975f5c5SAndroid Build Coastguard Worker     GLTexture greenTex;
1442*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, greenTex);
1443*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
1444*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1445*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1446*8975f5c5SAndroid Build Coastguard Worker 
1447*8975f5c5SAndroid Build Coastguard Worker     // Bind red to texture unit 0 and green to unit 1.
1448*8975f5c5SAndroid Build Coastguard Worker     glActiveTexture(GL_TEXTURE0);
1449*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, redTex);
1450*8975f5c5SAndroid Build Coastguard Worker 
1451*8975f5c5SAndroid Build Coastguard Worker     glActiveTexture(GL_TEXTURE1);
1452*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, greenTex);
1453*8975f5c5SAndroid Build Coastguard Worker 
1454*8975f5c5SAndroid Build Coastguard Worker     // Create the separable programs.
1455*8975f5c5SAndroid Build Coastguard Worker     const char *vsSource = essl1_shaders::vs::Texture2D();
1456*8975f5c5SAndroid Build Coastguard Worker     mVertProg            = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vsSource);
1457*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, mVertProg);
1458*8975f5c5SAndroid Build Coastguard Worker 
1459*8975f5c5SAndroid Build Coastguard Worker     const char *fsSource = essl1_shaders::fs::Texture2D();
1460*8975f5c5SAndroid Build Coastguard Worker     mFragProg            = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fsSource);
1461*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, mFragProg);
1462*8975f5c5SAndroid Build Coastguard Worker 
1463*8975f5c5SAndroid Build Coastguard Worker     // Set the program to sample from the green texture.
1464*8975f5c5SAndroid Build Coastguard Worker     GLint texLoc = glGetUniformLocation(mFragProg, essl1_shaders::Texture2DUniform());
1465*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, texLoc);
1466*8975f5c5SAndroid Build Coastguard Worker 
1467*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mFragProg);
1468*8975f5c5SAndroid Build Coastguard Worker     glUniform1i(texLoc, 1);
1469*8975f5c5SAndroid Build Coastguard Worker 
1470*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1471*8975f5c5SAndroid Build Coastguard Worker 
1472*8975f5c5SAndroid Build Coastguard Worker     // Create and draw with the pipeline.
1473*8975f5c5SAndroid Build Coastguard Worker     GLProgramPipeline ppo;
1474*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(ppo, GL_VERTEX_SHADER_BIT, mVertProg);
1475*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(ppo, GL_FRAGMENT_SHADER_BIT, mFragProg);
1476*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(ppo);
1477*8975f5c5SAndroid Build Coastguard Worker 
1478*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1479*8975f5c5SAndroid Build Coastguard Worker 
1480*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl1_shaders::PositionAttrib(), 0.5f, 1.0f);
1481*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1482*8975f5c5SAndroid Build Coastguard Worker 
1483*8975f5c5SAndroid Build Coastguard Worker     // We should have sampled from the second texture bound to unit 1.
1484*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1485*8975f5c5SAndroid Build Coastguard Worker }
1486*8975f5c5SAndroid Build Coastguard Worker 
1487*8975f5c5SAndroid Build Coastguard Worker // Test that a shader IO block varying with separable program links
1488*8975f5c5SAndroid Build Coastguard Worker // successfully.
TEST_P(ProgramPipelineTest31,VaryingIOBlockSeparableProgram)1489*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, VaryingIOBlockSeparableProgram)
1490*8975f5c5SAndroid Build Coastguard Worker {
1491*8975f5c5SAndroid Build Coastguard Worker     // Only the Vulkan backend supports PPOs
1492*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1493*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1494*8975f5c5SAndroid Build Coastguard Worker 
1495*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] =
1496*8975f5c5SAndroid Build Coastguard Worker         R"(#version 310 es
1497*8975f5c5SAndroid Build Coastguard Worker         #extension GL_EXT_shader_io_blocks : require
1498*8975f5c5SAndroid Build Coastguard Worker 
1499*8975f5c5SAndroid Build Coastguard Worker         precision highp float;
1500*8975f5c5SAndroid Build Coastguard Worker         in vec4 inputAttribute;
1501*8975f5c5SAndroid Build Coastguard Worker         out Block_inout { vec4 value; } user_out;
1502*8975f5c5SAndroid Build Coastguard Worker 
1503*8975f5c5SAndroid Build Coastguard Worker         void main()
1504*8975f5c5SAndroid Build Coastguard Worker         {
1505*8975f5c5SAndroid Build Coastguard Worker             gl_Position    = inputAttribute;
1506*8975f5c5SAndroid Build Coastguard Worker             user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
1507*8975f5c5SAndroid Build Coastguard Worker         })";
1508*8975f5c5SAndroid Build Coastguard Worker 
1509*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
1510*8975f5c5SAndroid Build Coastguard Worker         R"(#version 310 es
1511*8975f5c5SAndroid Build Coastguard Worker         #extension GL_EXT_shader_io_blocks : require
1512*8975f5c5SAndroid Build Coastguard Worker 
1513*8975f5c5SAndroid Build Coastguard Worker         precision highp float;
1514*8975f5c5SAndroid Build Coastguard Worker         layout(location = 0) out mediump vec4 color;
1515*8975f5c5SAndroid Build Coastguard Worker         in Block_inout { vec4 value; } user_in;
1516*8975f5c5SAndroid Build Coastguard Worker 
1517*8975f5c5SAndroid Build Coastguard Worker         void main()
1518*8975f5c5SAndroid Build Coastguard Worker         {
1519*8975f5c5SAndroid Build Coastguard Worker             color = vec4(1, 0, 0, 1);
1520*8975f5c5SAndroid Build Coastguard Worker         })";
1521*8975f5c5SAndroid Build Coastguard Worker 
1522*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(kVS, kFS);
1523*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("inputAttribute", 0.5f, 1.0f);
1524*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1525*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1526*8975f5c5SAndroid Build Coastguard Worker }
1527*8975f5c5SAndroid Build Coastguard Worker 
1528*8975f5c5SAndroid Build Coastguard Worker // Test that a shader IO block varying with separable program links
1529*8975f5c5SAndroid Build Coastguard Worker // successfully.
TEST_P(ProgramPipelineXFBTest31,VaryingIOBlockSeparableProgramWithXFB)1530*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineXFBTest31, VaryingIOBlockSeparableProgramWithXFB)
1531*8975f5c5SAndroid Build Coastguard Worker {
1532*8975f5c5SAndroid Build Coastguard Worker     // Only the Vulkan backend supports PPOs
1533*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1534*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_shader_io_blocks"));
1535*8975f5c5SAndroid Build Coastguard Worker 
1536*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVS[] =
1537*8975f5c5SAndroid Build Coastguard Worker         R"(#version 310 es
1538*8975f5c5SAndroid Build Coastguard Worker         #extension GL_EXT_shader_io_blocks : require
1539*8975f5c5SAndroid Build Coastguard Worker 
1540*8975f5c5SAndroid Build Coastguard Worker         precision highp float;
1541*8975f5c5SAndroid Build Coastguard Worker         in vec4 inputAttribute;
1542*8975f5c5SAndroid Build Coastguard Worker         out Block_inout { vec4 value; vec4 value2; } user_out;
1543*8975f5c5SAndroid Build Coastguard Worker 
1544*8975f5c5SAndroid Build Coastguard Worker         void main()
1545*8975f5c5SAndroid Build Coastguard Worker         {
1546*8975f5c5SAndroid Build Coastguard Worker             gl_Position    = inputAttribute;
1547*8975f5c5SAndroid Build Coastguard Worker             user_out.value = vec4(4.0, 5.0, 6.0, 7.0);
1548*8975f5c5SAndroid Build Coastguard Worker             user_out.value2 = vec4(8.0, 9.0, 10.0, 11.0);
1549*8975f5c5SAndroid Build Coastguard Worker         })";
1550*8975f5c5SAndroid Build Coastguard Worker 
1551*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
1552*8975f5c5SAndroid Build Coastguard Worker         R"(#version 310 es
1553*8975f5c5SAndroid Build Coastguard Worker         #extension GL_EXT_shader_io_blocks : require
1554*8975f5c5SAndroid Build Coastguard Worker 
1555*8975f5c5SAndroid Build Coastguard Worker         precision highp float;
1556*8975f5c5SAndroid Build Coastguard Worker         layout(location = 0) out mediump vec4 color;
1557*8975f5c5SAndroid Build Coastguard Worker         in Block_inout { vec4 value; vec4 value2; } user_in;
1558*8975f5c5SAndroid Build Coastguard Worker 
1559*8975f5c5SAndroid Build Coastguard Worker         void main()
1560*8975f5c5SAndroid Build Coastguard Worker         {
1561*8975f5c5SAndroid Build Coastguard Worker             color = vec4(1, 0, 0, 1);
1562*8975f5c5SAndroid Build Coastguard Worker         })";
1563*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::string> tfVaryings;
1564*8975f5c5SAndroid Build Coastguard Worker     tfVaryings.push_back("Block_inout.value");
1565*8975f5c5SAndroid Build Coastguard Worker     tfVaryings.push_back("Block_inout.value2");
1566*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipelineWithXFBVaryings(kVS, kFS, tfVaryings, GL_INTERLEAVED_ATTRIBS);
1567*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
1568*8975f5c5SAndroid Build Coastguard Worker 
1569*8975f5c5SAndroid Build Coastguard Worker     // Make sure reconfiguring the vertex shader's transform feedback varyings without a link does
1570*8975f5c5SAndroid Build Coastguard Worker     // not affect the pipeline.  Same with changing buffer modes
1571*8975f5c5SAndroid Build Coastguard Worker     std::vector<const char *> tfVaryingsBogus = {"some", "invalid[0]", "names"};
1572*8975f5c5SAndroid Build Coastguard Worker     glTransformFeedbackVaryings(mVertProg, static_cast<GLsizei>(tfVaryingsBogus.size()),
1573*8975f5c5SAndroid Build Coastguard Worker                                 tfVaryingsBogus.data(), GL_SEPARATE_ATTRIBS);
1574*8975f5c5SAndroid Build Coastguard Worker 
1575*8975f5c5SAndroid Build Coastguard Worker     glBeginTransformFeedback(GL_TRIANGLES);
1576*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("inputAttribute", 0.5f, 1.0f);
1577*8975f5c5SAndroid Build Coastguard Worker     glEndTransformFeedback();
1578*8975f5c5SAndroid Build Coastguard Worker 
1579*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1580*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1581*8975f5c5SAndroid Build Coastguard Worker 
1582*8975f5c5SAndroid Build Coastguard Worker     void *mappedBuffer =
1583*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(float) * 8, GL_MAP_READ_BIT);
1584*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mappedBuffer);
1585*8975f5c5SAndroid Build Coastguard Worker 
1586*8975f5c5SAndroid Build Coastguard Worker     float *mappedFloats = static_cast<float *>(mappedBuffer);
1587*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int cnt = 0; cnt < 8; ++cnt)
1588*8975f5c5SAndroid Build Coastguard Worker     {
1589*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(4 + cnt, mappedFloats[cnt]);
1590*8975f5c5SAndroid Build Coastguard Worker     }
1591*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1592*8975f5c5SAndroid Build Coastguard Worker 
1593*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1594*8975f5c5SAndroid Build Coastguard Worker }
1595*8975f5c5SAndroid Build Coastguard Worker 
1596*8975f5c5SAndroid Build Coastguard Worker // Test modifying a shader and re-linking it updates the PPO too
TEST_P(ProgramPipelineTest31,ModifyAndRelinkShader)1597*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, ModifyAndRelinkShader)
1598*8975f5c5SAndroid Build Coastguard Worker {
1599*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1600*8975f5c5SAndroid Build Coastguard Worker 
1601*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString      = essl31_shaders::vs::Simple();
1602*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragStringGreen = essl31_shaders::fs::Green();
1603*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragStringRed   = essl31_shaders::fs::Red();
1604*8975f5c5SAndroid Build Coastguard Worker 
1605*8975f5c5SAndroid Build Coastguard Worker     GLShader vertShader(GL_VERTEX_SHADER);
1606*8975f5c5SAndroid Build Coastguard Worker     GLShader fragShader(GL_FRAGMENT_SHADER);
1607*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateProgram();
1608*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateProgram();
1609*8975f5c5SAndroid Build Coastguard Worker 
1610*8975f5c5SAndroid Build Coastguard Worker     // Compile and link a separable vertex shader
1611*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(vertShader, 1, &vertString, nullptr);
1612*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(vertShader);
1613*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mVertProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1614*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mVertProg, vertShader);
1615*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mVertProg);
1616*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1617*8975f5c5SAndroid Build Coastguard Worker 
1618*8975f5c5SAndroid Build Coastguard Worker     // Compile and link a separable fragment shader
1619*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &fragStringGreen, nullptr);
1620*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
1621*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1622*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mFragProg, fragShader);
1623*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mFragProg);
1624*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1625*8975f5c5SAndroid Build Coastguard Worker 
1626*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs
1627*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
1628*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
1629*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
1630*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
1631*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1632*8975f5c5SAndroid Build Coastguard Worker 
1633*8975f5c5SAndroid Build Coastguard Worker     // Draw once to ensure this worked fine
1634*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
1635*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1636*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1637*8975f5c5SAndroid Build Coastguard Worker 
1638*8975f5c5SAndroid Build Coastguard Worker     // Detach the fragment shader and modify it such that it no longer fits with this pipeline
1639*8975f5c5SAndroid Build Coastguard Worker     glDetachShader(mFragProg, fragShader);
1640*8975f5c5SAndroid Build Coastguard Worker 
1641*8975f5c5SAndroid Build Coastguard Worker     // Modify the FS and re-link it
1642*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &fragStringRed, nullptr);
1643*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
1644*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mFragProg, GL_PROGRAM_SEPARABLE, GL_TRUE);
1645*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mFragProg, fragShader);
1646*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mFragProg);
1647*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1648*8975f5c5SAndroid Build Coastguard Worker 
1649*8975f5c5SAndroid Build Coastguard Worker     // Draw with the PPO again and verify it's now red
1650*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO(essl31_shaders::PositionAttrib(), 0.5f, 1.0f);
1651*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1652*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1653*8975f5c5SAndroid Build Coastguard Worker }
1654*8975f5c5SAndroid Build Coastguard Worker 
1655*8975f5c5SAndroid Build Coastguard Worker // Test that a PPO can be used when the attached shader programs are created with glProgramBinary().
1656*8975f5c5SAndroid Build Coastguard Worker // This validates the necessary programs' information is serialized/deserialized so they can be
1657*8975f5c5SAndroid Build Coastguard Worker // linked by the PPO during glDrawArrays.
TEST_P(ProgramPipelineTest31,ProgramBinary)1658*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, ProgramBinary)
1659*8975f5c5SAndroid Build Coastguard Worker {
1660*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1661*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getAvailableProgramBinaryFormatCount() == 0);
1662*8975f5c5SAndroid Build Coastguard Worker 
1663*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
1664*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1665*8975f5c5SAndroid Build Coastguard Worker in vec4 a_position;
1666*8975f5c5SAndroid Build Coastguard Worker out vec2 texCoord;
1667*8975f5c5SAndroid Build Coastguard Worker void main()
1668*8975f5c5SAndroid Build Coastguard Worker {
1669*8975f5c5SAndroid Build Coastguard Worker     gl_Position = a_position;
1670*8975f5c5SAndroid Build Coastguard Worker     texCoord = vec2(a_position.x, a_position.y) * 0.5 + vec2(0.5);
1671*8975f5c5SAndroid Build Coastguard Worker })";
1672*8975f5c5SAndroid Build Coastguard Worker 
1673*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1674*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1675*8975f5c5SAndroid Build Coastguard Worker in vec2 texCoord;
1676*8975f5c5SAndroid Build Coastguard Worker uniform sampler2D tex;
1677*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1678*8975f5c5SAndroid Build Coastguard Worker void main()
1679*8975f5c5SAndroid Build Coastguard Worker {
1680*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = texture(tex, texCoord);
1681*8975f5c5SAndroid Build Coastguard Worker })";
1682*8975f5c5SAndroid Build Coastguard Worker 
1683*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, 4> colors = {
1684*8975f5c5SAndroid Build Coastguard Worker         {GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow}};
1685*8975f5c5SAndroid Build Coastguard Worker 
1686*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
1687*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, tex);
1688*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors.data());
1689*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1690*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1691*8975f5c5SAndroid Build Coastguard Worker 
1692*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vertString);
1693*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
1694*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragString);
1695*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
1696*8975f5c5SAndroid Build Coastguard Worker 
1697*8975f5c5SAndroid Build Coastguard Worker     // Save the VS program binary out
1698*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> vsBinary(0);
1699*8975f5c5SAndroid Build Coastguard Worker     GLint vsProgramLength = 0;
1700*8975f5c5SAndroid Build Coastguard Worker     GLint vsWrittenLength = 0;
1701*8975f5c5SAndroid Build Coastguard Worker     GLenum vsBinaryFormat = 0;
1702*8975f5c5SAndroid Build Coastguard Worker     glGetProgramiv(mVertProg, GL_PROGRAM_BINARY_LENGTH, &vsProgramLength);
1703*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1704*8975f5c5SAndroid Build Coastguard Worker     vsBinary.resize(vsProgramLength);
1705*8975f5c5SAndroid Build Coastguard Worker     glGetProgramBinary(mVertProg, vsProgramLength, &vsWrittenLength, &vsBinaryFormat,
1706*8975f5c5SAndroid Build Coastguard Worker                        vsBinary.data());
1707*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1708*8975f5c5SAndroid Build Coastguard Worker 
1709*8975f5c5SAndroid Build Coastguard Worker     // Save the FS program binary out
1710*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> fsBinary(0);
1711*8975f5c5SAndroid Build Coastguard Worker     GLint fsProgramLength = 0;
1712*8975f5c5SAndroid Build Coastguard Worker     GLint fsWrittenLength = 0;
1713*8975f5c5SAndroid Build Coastguard Worker     GLenum fsBinaryFormat = 0;
1714*8975f5c5SAndroid Build Coastguard Worker     glGetProgramiv(mFragProg, GL_PROGRAM_BINARY_LENGTH, &fsProgramLength);
1715*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1716*8975f5c5SAndroid Build Coastguard Worker     fsBinary.resize(fsProgramLength);
1717*8975f5c5SAndroid Build Coastguard Worker     glGetProgramBinary(mFragProg, fsProgramLength, &fsWrittenLength, &fsBinaryFormat,
1718*8975f5c5SAndroid Build Coastguard Worker                        fsBinary.data());
1719*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1720*8975f5c5SAndroid Build Coastguard Worker 
1721*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateProgram();
1722*8975f5c5SAndroid Build Coastguard Worker     glProgramBinary(mVertProg, vsBinaryFormat, vsBinary.data(), vsWrittenLength);
1723*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateProgram();
1724*8975f5c5SAndroid Build Coastguard Worker     glProgramBinary(mFragProg, fsBinaryFormat, fsBinary.data(), fsWrittenLength);
1725*8975f5c5SAndroid Build Coastguard Worker 
1726*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
1727*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
1728*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1729*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
1730*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1731*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
1732*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1733*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
1734*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1735*8975f5c5SAndroid Build Coastguard Worker 
1736*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
1737*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1738*8975f5c5SAndroid Build Coastguard Worker 
1739*8975f5c5SAndroid Build Coastguard Worker     int w = getWindowWidth() - 2;
1740*8975f5c5SAndroid Build Coastguard Worker     int h = getWindowHeight() - 2;
1741*8975f5c5SAndroid Build Coastguard Worker 
1742*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1743*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w, 0, GLColor::green);
1744*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, h, GLColor::blue);
1745*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w, h, GLColor::yellow);
1746*8975f5c5SAndroid Build Coastguard Worker }
1747*8975f5c5SAndroid Build Coastguard Worker 
1748*8975f5c5SAndroid Build Coastguard Worker // Test that updating a sampler uniform in a separable program behaves correctly with PPOs.
TEST_P(ProgramPipelineTest31,SampleTextureAThenTextureB)1749*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, SampleTextureAThenTextureB)
1750*8975f5c5SAndroid Build Coastguard Worker {
1751*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1752*8975f5c5SAndroid Build Coastguard Worker 
1753*8975f5c5SAndroid Build Coastguard Worker     constexpr int kWidth  = 2;
1754*8975f5c5SAndroid Build Coastguard Worker     constexpr int kHeight = 2;
1755*8975f5c5SAndroid Build Coastguard Worker 
1756*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
1757*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1758*8975f5c5SAndroid Build Coastguard Worker in vec2 a_position;
1759*8975f5c5SAndroid Build Coastguard Worker out vec2 texCoord;
1760*8975f5c5SAndroid Build Coastguard Worker void main()
1761*8975f5c5SAndroid Build Coastguard Worker {
1762*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(a_position, 0, 1);
1763*8975f5c5SAndroid Build Coastguard Worker     texCoord = a_position * 0.5 + vec2(0.5);
1764*8975f5c5SAndroid Build Coastguard Worker })";
1765*8975f5c5SAndroid Build Coastguard Worker 
1766*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1767*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1768*8975f5c5SAndroid Build Coastguard Worker in vec2 texCoord;
1769*8975f5c5SAndroid Build Coastguard Worker uniform sampler2D tex;
1770*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1771*8975f5c5SAndroid Build Coastguard Worker void main()
1772*8975f5c5SAndroid Build Coastguard Worker {
1773*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = texture(tex, texCoord);
1774*8975f5c5SAndroid Build Coastguard Worker })";
1775*8975f5c5SAndroid Build Coastguard Worker 
1776*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, kWidth * kHeight> redColor = {
1777*8975f5c5SAndroid Build Coastguard Worker         {GLColor::red, GLColor::red, GLColor::red, GLColor::red}};
1778*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, kWidth * kHeight> greenColor = {
1779*8975f5c5SAndroid Build Coastguard Worker         {GLColor::green, GLColor::green, GLColor::green, GLColor::green}};
1780*8975f5c5SAndroid Build Coastguard Worker 
1781*8975f5c5SAndroid Build Coastguard Worker     // Create a red texture and bind to texture unit 0
1782*8975f5c5SAndroid Build Coastguard Worker     GLTexture redTex;
1783*8975f5c5SAndroid Build Coastguard Worker     glActiveTexture(GL_TEXTURE0);
1784*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, redTex);
1785*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1786*8975f5c5SAndroid Build Coastguard Worker                  redColor.data());
1787*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1788*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1789*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1790*8975f5c5SAndroid Build Coastguard Worker     // Create a green texture and bind to texture unit 1
1791*8975f5c5SAndroid Build Coastguard Worker     GLTexture greenTex;
1792*8975f5c5SAndroid Build Coastguard Worker     glActiveTexture(GL_TEXTURE1);
1793*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, greenTex);
1794*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1795*8975f5c5SAndroid Build Coastguard Worker                  greenColor.data());
1796*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1797*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1798*8975f5c5SAndroid Build Coastguard Worker     glActiveTexture(GL_TEXTURE0);
1799*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1800*8975f5c5SAndroid Build Coastguard Worker 
1801*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
1802*8975f5c5SAndroid Build Coastguard Worker 
1803*8975f5c5SAndroid Build Coastguard Worker     GLint location1 = glGetUniformLocation(mFragProg, "tex");
1804*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(location1, -1);
1805*8975f5c5SAndroid Build Coastguard Worker     glActiveShaderProgram(mPipeline, mFragProg);
1806*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1807*8975f5c5SAndroid Build Coastguard Worker 
1808*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_BLEND);
1809*8975f5c5SAndroid Build Coastguard Worker     glBlendEquation(GL_FUNC_ADD);
1810*8975f5c5SAndroid Build Coastguard Worker     glBlendFunc(GL_ONE, GL_ONE);
1811*8975f5c5SAndroid Build Coastguard Worker 
1812*8975f5c5SAndroid Build Coastguard Worker     // Draw red
1813*8975f5c5SAndroid Build Coastguard Worker     glUniform1i(location1, 0);
1814*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1815*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
1816*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1817*8975f5c5SAndroid Build Coastguard Worker 
1818*8975f5c5SAndroid Build Coastguard Worker     // Draw green
1819*8975f5c5SAndroid Build Coastguard Worker     glUniform1i(location1, 1);
1820*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1821*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
1822*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1823*8975f5c5SAndroid Build Coastguard Worker 
1824*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::yellow);
1825*8975f5c5SAndroid Build Coastguard Worker }
1826*8975f5c5SAndroid Build Coastguard Worker 
1827*8975f5c5SAndroid Build Coastguard Worker // Verify that image uniforms can be used with separable programs
TEST_P(ProgramPipelineTest31,ImageUniforms)1828*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, ImageUniforms)
1829*8975f5c5SAndroid Build Coastguard Worker {
1830*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1831*8975f5c5SAndroid Build Coastguard Worker 
1832*8975f5c5SAndroid Build Coastguard Worker     GLint maxVertexImageUniforms;
1833*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
1834*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxVertexImageUniforms == 0);
1835*8975f5c5SAndroid Build Coastguard Worker 
1836*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
1837*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1838*8975f5c5SAndroid Build Coastguard Worker precision highp image2D;
1839*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0, r32f) uniform image2D img;
1840*8975f5c5SAndroid Build Coastguard Worker 
1841*8975f5c5SAndroid Build Coastguard Worker void main()
1842*8975f5c5SAndroid Build Coastguard Worker {
1843*8975f5c5SAndroid Build Coastguard Worker     gl_Position = imageLoad(img, ivec2(0, 0));
1844*8975f5c5SAndroid Build Coastguard Worker })";
1845*8975f5c5SAndroid Build Coastguard Worker 
1846*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = essl31_shaders::fs::Red();
1847*8975f5c5SAndroid Build Coastguard Worker 
1848*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
1849*8975f5c5SAndroid Build Coastguard Worker 
1850*8975f5c5SAndroid Build Coastguard Worker     GLTexture texture;
1851*8975f5c5SAndroid Build Coastguard Worker     GLfloat value = 1.0;
1852*8975f5c5SAndroid Build Coastguard Worker 
1853*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, texture);
1854*8975f5c5SAndroid Build Coastguard Worker     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
1855*8975f5c5SAndroid Build Coastguard Worker     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
1856*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1857*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1858*8975f5c5SAndroid Build Coastguard Worker 
1859*8975f5c5SAndroid Build Coastguard Worker     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
1860*8975f5c5SAndroid Build Coastguard Worker 
1861*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 6);
1862*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1863*8975f5c5SAndroid Build Coastguard Worker }
1864*8975f5c5SAndroid Build Coastguard Worker 
1865*8975f5c5SAndroid Build Coastguard Worker // Verify that image uniforms can link in separable programs
TEST_P(ProgramPipelineTest31,LinkedImageUniforms)1866*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, LinkedImageUniforms)
1867*8975f5c5SAndroid Build Coastguard Worker {
1868*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1869*8975f5c5SAndroid Build Coastguard Worker 
1870*8975f5c5SAndroid Build Coastguard Worker     GLint maxVertexImageUniforms;
1871*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexImageUniforms);
1872*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(maxVertexImageUniforms == 0);
1873*8975f5c5SAndroid Build Coastguard Worker 
1874*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
1875*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1876*8975f5c5SAndroid Build Coastguard Worker precision highp image2D;
1877*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0, r32f) uniform image2D img;
1878*8975f5c5SAndroid Build Coastguard Worker 
1879*8975f5c5SAndroid Build Coastguard Worker void main()
1880*8975f5c5SAndroid Build Coastguard Worker {
1881*8975f5c5SAndroid Build Coastguard Worker     vec2 position = -imageLoad(img, ivec2(0, 0)).rr;
1882*8975f5c5SAndroid Build Coastguard Worker     if (gl_VertexID == 1)
1883*8975f5c5SAndroid Build Coastguard Worker         position = vec2(3, -1);
1884*8975f5c5SAndroid Build Coastguard Worker     else if (gl_VertexID == 2)
1885*8975f5c5SAndroid Build Coastguard Worker         position = vec2(-1, 3);
1886*8975f5c5SAndroid Build Coastguard Worker 
1887*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(position, 0, 1);
1888*8975f5c5SAndroid Build Coastguard Worker })";
1889*8975f5c5SAndroid Build Coastguard Worker 
1890*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
1891*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1892*8975f5c5SAndroid Build Coastguard Worker precision highp image2D;
1893*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0, r32f) uniform image2D img;
1894*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out vec4 color;
1895*8975f5c5SAndroid Build Coastguard Worker 
1896*8975f5c5SAndroid Build Coastguard Worker void main()
1897*8975f5c5SAndroid Build Coastguard Worker {
1898*8975f5c5SAndroid Build Coastguard Worker     color = imageLoad(img, ivec2(0, 0));
1899*8975f5c5SAndroid Build Coastguard Worker })";
1900*8975f5c5SAndroid Build Coastguard Worker 
1901*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString);
1902*8975f5c5SAndroid Build Coastguard Worker 
1903*8975f5c5SAndroid Build Coastguard Worker     GLTexture texture;
1904*8975f5c5SAndroid Build Coastguard Worker     GLfloat value = 1.0;
1905*8975f5c5SAndroid Build Coastguard Worker 
1906*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, texture);
1907*8975f5c5SAndroid Build Coastguard Worker     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, 1, 1);
1908*8975f5c5SAndroid Build Coastguard Worker     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED, GL_FLOAT, &value);
1909*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1910*8975f5c5SAndroid Build Coastguard Worker     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1911*8975f5c5SAndroid Build Coastguard Worker 
1912*8975f5c5SAndroid Build Coastguard Worker     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
1913*8975f5c5SAndroid Build Coastguard Worker 
1914*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
1915*8975f5c5SAndroid Build Coastguard Worker 
1916*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1917*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1918*8975f5c5SAndroid Build Coastguard Worker }
1919*8975f5c5SAndroid Build Coastguard Worker 
1920*8975f5c5SAndroid Build Coastguard Worker // Verify that we can have the max amount of uniform buffer objects as part of a program
1921*8975f5c5SAndroid Build Coastguard Worker // pipeline.
TEST_P(ProgramPipelineTest31,MaxFragmentUniformBufferObjects)1922*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, MaxFragmentUniformBufferObjects)
1923*8975f5c5SAndroid Build Coastguard Worker {
1924*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1925*8975f5c5SAndroid Build Coastguard Worker 
1926*8975f5c5SAndroid Build Coastguard Worker     GLint maxUniformBlocks;
1927*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &maxUniformBlocks);
1928*8975f5c5SAndroid Build Coastguard Worker 
1929*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1930*8975f5c5SAndroid Build Coastguard Worker     std::stringstream fragStringStream;
1931*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << R"(#version 310 es
1932*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1933*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1934*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0) uniform block {
1935*8975f5c5SAndroid Build Coastguard Worker     float data;
1936*8975f5c5SAndroid Build Coastguard Worker } ubo[)";
1937*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << maxUniformBlocks;
1938*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << R"(];
1939*8975f5c5SAndroid Build Coastguard Worker void main()
1940*8975f5c5SAndroid Build Coastguard Worker {
1941*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(1.0);
1942*8975f5c5SAndroid Build Coastguard Worker )";
1943*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxUniformBlocks; index++)
1944*8975f5c5SAndroid Build Coastguard Worker     {
1945*8975f5c5SAndroid Build Coastguard Worker         fragStringStream << "my_FragColor.x + ubo[" << index << "].data;" << std::endl;
1946*8975f5c5SAndroid Build Coastguard Worker     }
1947*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << "}" << std::endl;
1948*8975f5c5SAndroid Build Coastguard Worker 
1949*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragStringStream.str().c_str());
1950*8975f5c5SAndroid Build Coastguard Worker 
1951*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLBuffer> buffers(maxUniformBlocks);
1952*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxUniformBlocks; ++index)
1953*8975f5c5SAndroid Build Coastguard Worker     {
1954*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_UNIFORM_BUFFER, buffers[index]);
1955*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat), NULL, GL_STATIC_DRAW);
1956*8975f5c5SAndroid Build Coastguard Worker         glBindBufferBase(GL_UNIFORM_BUFFER, index, buffers[index]);
1957*8975f5c5SAndroid Build Coastguard Worker     }
1958*8975f5c5SAndroid Build Coastguard Worker 
1959*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 6);
1960*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1961*8975f5c5SAndroid Build Coastguard Worker }
1962*8975f5c5SAndroid Build Coastguard Worker 
1963*8975f5c5SAndroid Build Coastguard Worker // Verify that we can have the max amount of shader storage buffer objects as part of a program
1964*8975f5c5SAndroid Build Coastguard Worker // pipeline.
TEST_P(ProgramPipelineTest31,MaxFragmentShaderStorageBufferObjects)1965*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, MaxFragmentShaderStorageBufferObjects)
1966*8975f5c5SAndroid Build Coastguard Worker {
1967*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
1968*8975f5c5SAndroid Build Coastguard Worker 
1969*8975f5c5SAndroid Build Coastguard Worker     GLint maxShaderStorageBuffers;
1970*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxShaderStorageBuffers);
1971*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
1972*8975f5c5SAndroid Build Coastguard Worker     std::stringstream fragStringStream;
1973*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << R"(#version 310 es
1974*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1975*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
1976*8975f5c5SAndroid Build Coastguard Worker layout(binding = 0) buffer buf {
1977*8975f5c5SAndroid Build Coastguard Worker     float data;
1978*8975f5c5SAndroid Build Coastguard Worker } ssbo[)";
1979*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << maxShaderStorageBuffers;
1980*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << R"(];
1981*8975f5c5SAndroid Build Coastguard Worker void main()
1982*8975f5c5SAndroid Build Coastguard Worker {
1983*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(1.0);
1984*8975f5c5SAndroid Build Coastguard Worker )";
1985*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxShaderStorageBuffers; index++)
1986*8975f5c5SAndroid Build Coastguard Worker     {
1987*8975f5c5SAndroid Build Coastguard Worker         fragStringStream << "my_FragColor.x + ssbo[" << index << "].data;" << std::endl;
1988*8975f5c5SAndroid Build Coastguard Worker     }
1989*8975f5c5SAndroid Build Coastguard Worker     fragStringStream << "}" << std::endl;
1990*8975f5c5SAndroid Build Coastguard Worker 
1991*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragStringStream.str().c_str());
1992*8975f5c5SAndroid Build Coastguard Worker 
1993*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLBuffer> buffers(maxShaderStorageBuffers);
1994*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxShaderStorageBuffers; ++index)
1995*8975f5c5SAndroid Build Coastguard Worker     {
1996*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffers[index]);
1997*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLfloat), NULL, GL_STATIC_DRAW);
1998*8975f5c5SAndroid Build Coastguard Worker         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffers[index]);
1999*8975f5c5SAndroid Build Coastguard Worker     }
2000*8975f5c5SAndroid Build Coastguard Worker 
2001*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 6);
2002*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2003*8975f5c5SAndroid Build Coastguard Worker }
2004*8975f5c5SAndroid Build Coastguard Worker 
2005*8975f5c5SAndroid Build Coastguard Worker // Test validation of redefinition of gl_Position and gl_PointSize in the vertex shader when
2006*8975f5c5SAndroid Build Coastguard Worker // GL_EXT_separate_shader_objects is enabled.
TEST_P(ProgramPipelineTest31,ValidatePositionPointSizeRedefinition)2007*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, ValidatePositionPointSizeRedefinition)
2008*8975f5c5SAndroid Build Coastguard Worker {
2009*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_separate_shader_objects"));
2010*8975f5c5SAndroid Build Coastguard Worker 
2011*8975f5c5SAndroid Build Coastguard Worker     {
2012*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] = R"(#version 310 es
2013*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_separate_shader_objects: require
2014*8975f5c5SAndroid Build Coastguard Worker 
2015*8975f5c5SAndroid Build Coastguard Worker out float gl_PointSize;
2016*8975f5c5SAndroid Build Coastguard Worker 
2017*8975f5c5SAndroid Build Coastguard Worker void main()
2018*8975f5c5SAndroid Build Coastguard Worker {
2019*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0);
2020*8975f5c5SAndroid Build Coastguard Worker     gl_PointSize = 1.;
2021*8975f5c5SAndroid Build Coastguard Worker })";
2022*8975f5c5SAndroid Build Coastguard Worker 
2023*8975f5c5SAndroid Build Coastguard Worker         // Should fail because gl_Position is not declared.
2024*8975f5c5SAndroid Build Coastguard Worker         GLuint shader = createShaderProgram(GL_VERTEX_SHADER, kVS);
2025*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(shader, 0u);
2026*8975f5c5SAndroid Build Coastguard Worker     }
2027*8975f5c5SAndroid Build Coastguard Worker 
2028*8975f5c5SAndroid Build Coastguard Worker     {
2029*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] = R"(#version 310 es
2030*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_separate_shader_objects: require
2031*8975f5c5SAndroid Build Coastguard Worker 
2032*8975f5c5SAndroid Build Coastguard Worker out float gl_PointSize;
2033*8975f5c5SAndroid Build Coastguard Worker 
2034*8975f5c5SAndroid Build Coastguard Worker void f()
2035*8975f5c5SAndroid Build Coastguard Worker {
2036*8975f5c5SAndroid Build Coastguard Worker     gl_PointSize = 1.;
2037*8975f5c5SAndroid Build Coastguard Worker }
2038*8975f5c5SAndroid Build Coastguard Worker 
2039*8975f5c5SAndroid Build Coastguard Worker out vec4 gl_Position;
2040*8975f5c5SAndroid Build Coastguard Worker 
2041*8975f5c5SAndroid Build Coastguard Worker void main()
2042*8975f5c5SAndroid Build Coastguard Worker {
2043*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0);
2044*8975f5c5SAndroid Build Coastguard Worker })";
2045*8975f5c5SAndroid Build Coastguard Worker 
2046*8975f5c5SAndroid Build Coastguard Worker         // Should fail because gl_PointSize is used before gl_Position is declared.
2047*8975f5c5SAndroid Build Coastguard Worker         GLuint shader = createShaderProgram(GL_VERTEX_SHADER, kVS);
2048*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(shader, 0u);
2049*8975f5c5SAndroid Build Coastguard Worker     }
2050*8975f5c5SAndroid Build Coastguard Worker 
2051*8975f5c5SAndroid Build Coastguard Worker     {
2052*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] = R"(#version 310 es
2053*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_separate_shader_objects: require
2054*8975f5c5SAndroid Build Coastguard Worker 
2055*8975f5c5SAndroid Build Coastguard Worker out float gl_PointSize;
2056*8975f5c5SAndroid Build Coastguard Worker out vec4 gl_Position;
2057*8975f5c5SAndroid Build Coastguard Worker 
2058*8975f5c5SAndroid Build Coastguard Worker void main()
2059*8975f5c5SAndroid Build Coastguard Worker {
2060*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0);
2061*8975f5c5SAndroid Build Coastguard Worker     gl_PointSize = 1.;
2062*8975f5c5SAndroid Build Coastguard Worker })";
2063*8975f5c5SAndroid Build Coastguard Worker 
2064*8975f5c5SAndroid Build Coastguard Worker         // Should compile.
2065*8975f5c5SAndroid Build Coastguard Worker         GLuint shader = createShaderProgram(GL_VERTEX_SHADER, kVS);
2066*8975f5c5SAndroid Build Coastguard Worker         EXPECT_NE(shader, 0u);
2067*8975f5c5SAndroid Build Coastguard Worker     }
2068*8975f5c5SAndroid Build Coastguard Worker }
2069*8975f5c5SAndroid Build Coastguard Worker 
2070*8975f5c5SAndroid Build Coastguard Worker // Basic draw test with GL_EXT_separate_shader_objects enabled in the vertex shader
TEST_P(ProgramPipelineTest31,BasicDrawWithPositionPointSizeRedefinition)2071*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, BasicDrawWithPositionPointSizeRedefinition)
2072*8975f5c5SAndroid Build Coastguard Worker {
2073*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_separate_shader_objects"));
2074*8975f5c5SAndroid Build Coastguard Worker 
2075*8975f5c5SAndroid Build Coastguard Worker     const char kVS[] = R"(#version 310 es
2076*8975f5c5SAndroid Build Coastguard Worker #extension GL_EXT_separate_shader_objects: require
2077*8975f5c5SAndroid Build Coastguard Worker 
2078*8975f5c5SAndroid Build Coastguard Worker out float gl_PointSize;
2079*8975f5c5SAndroid Build Coastguard Worker out vec4 gl_Position;
2080*8975f5c5SAndroid Build Coastguard Worker 
2081*8975f5c5SAndroid Build Coastguard Worker in vec4 a_position;
2082*8975f5c5SAndroid Build Coastguard Worker 
2083*8975f5c5SAndroid Build Coastguard Worker void main()
2084*8975f5c5SAndroid Build Coastguard Worker {
2085*8975f5c5SAndroid Build Coastguard Worker     gl_Position = a_position;
2086*8975f5c5SAndroid Build Coastguard Worker })";
2087*8975f5c5SAndroid Build Coastguard Worker 
2088*8975f5c5SAndroid Build Coastguard Worker     mVertProg = createShaderProgram(GL_VERTEX_SHADER, kVS);
2089*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
2090*8975f5c5SAndroid Build Coastguard Worker     mFragProg = createShaderProgram(GL_FRAGMENT_SHADER, essl31_shaders::fs::Red());
2091*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
2092*8975f5c5SAndroid Build Coastguard Worker 
2093*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
2094*8975f5c5SAndroid Build Coastguard Worker     GLuint pipeline;
2095*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &pipeline);
2096*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, mVertProg);
2097*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
2098*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(pipeline);
2099*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2100*8975f5c5SAndroid Build Coastguard Worker 
2101*8975f5c5SAndroid Build Coastguard Worker     drawQuadWithPPO("a_position", 0.5f, 1.0f);
2102*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2103*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2104*8975f5c5SAndroid Build Coastguard Worker }
2105*8975f5c5SAndroid Build Coastguard Worker 
2106*8975f5c5SAndroid Build Coastguard Worker // Test a PPO scenario from a game, calling glBindBufferRange between two draws with
2107*8975f5c5SAndroid Build Coastguard Worker // multiple binding points, some unused.  This would result in a crash without the fix.
2108*8975f5c5SAndroid Build Coastguard Worker // https://issuetracker.google.com/issues/299532942
TEST_P(ProgramPipelineTest31,ProgramPipelineBindBufferRange)2109*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest31, ProgramPipelineBindBufferRange)
2110*8975f5c5SAndroid Build Coastguard Worker {
2111*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
2112*8975f5c5SAndroid Build Coastguard Worker 
2113*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = R"(#version 310 es
2114*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
2115*8975f5c5SAndroid Build Coastguard Worker layout(std140, binding = 0) uniform ubo1 {
2116*8975f5c5SAndroid Build Coastguard Worker     vec4 color;
2117*8975f5c5SAndroid Build Coastguard Worker };
2118*8975f5c5SAndroid Build Coastguard Worker layout(location=0) out vec4 vsColor;
2119*8975f5c5SAndroid Build Coastguard Worker void main()
2120*8975f5c5SAndroid Build Coastguard Worker {
2121*8975f5c5SAndroid Build Coastguard Worker     vsColor = color;
2122*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
2123*8975f5c5SAndroid Build Coastguard Worker })";
2124*8975f5c5SAndroid Build Coastguard Worker 
2125*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
2126*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
2127*8975f5c5SAndroid Build Coastguard Worker layout(std140, binding = 1) uniform globals {
2128*8975f5c5SAndroid Build Coastguard Worker     vec4 fsColor;
2129*8975f5c5SAndroid Build Coastguard Worker };
2130*8975f5c5SAndroid Build Coastguard Worker layout(std140, binding = 2) uniform params {
2131*8975f5c5SAndroid Build Coastguard Worker     vec4 foo;
2132*8975f5c5SAndroid Build Coastguard Worker };
2133*8975f5c5SAndroid Build Coastguard Worker layout(std140, binding = 3) uniform layer {
2134*8975f5c5SAndroid Build Coastguard Worker     vec4 bar;
2135*8975f5c5SAndroid Build Coastguard Worker };
2136*8975f5c5SAndroid Build Coastguard Worker layout(location=0) highp in vec4 vsColor;
2137*8975f5c5SAndroid Build Coastguard Worker layout(location=0) out vec4 diffuse;
2138*8975f5c5SAndroid Build Coastguard Worker void main()
2139*8975f5c5SAndroid Build Coastguard Worker {
2140*8975f5c5SAndroid Build Coastguard Worker     diffuse = vsColor + fsColor;
2141*8975f5c5SAndroid Build Coastguard Worker })";
2142*8975f5c5SAndroid Build Coastguard Worker 
2143*8975f5c5SAndroid Build Coastguard Worker     // Create the pipeline
2144*8975f5c5SAndroid Build Coastguard Worker     GLProgramPipeline programPipeline;
2145*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(programPipeline);
2146*8975f5c5SAndroid Build Coastguard Worker 
2147*8975f5c5SAndroid Build Coastguard Worker     // Create the vertex shader
2148*8975f5c5SAndroid Build Coastguard Worker     GLShader vertShader(GL_VERTEX_SHADER);
2149*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(vertShader, 1, &vertString, nullptr);
2150*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(vertShader);
2151*8975f5c5SAndroid Build Coastguard Worker     mVertProg = glCreateProgram();
2152*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mVertProg, GL_PROGRAM_SEPARABLE, 1);
2153*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mVertProg, vertShader);
2154*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mVertProg);
2155*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(programPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
2156*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2157*8975f5c5SAndroid Build Coastguard Worker 
2158*8975f5c5SAndroid Build Coastguard Worker     // Create the fragment shader
2159*8975f5c5SAndroid Build Coastguard Worker     GLShader fragShader(GL_FRAGMENT_SHADER);
2160*8975f5c5SAndroid Build Coastguard Worker     glShaderSource(fragShader, 1, &fragString, nullptr);
2161*8975f5c5SAndroid Build Coastguard Worker     glCompileShader(fragShader);
2162*8975f5c5SAndroid Build Coastguard Worker     mFragProg = glCreateProgram();
2163*8975f5c5SAndroid Build Coastguard Worker     glProgramParameteri(mFragProg, GL_PROGRAM_SEPARABLE, 1);
2164*8975f5c5SAndroid Build Coastguard Worker     glAttachShader(mFragProg, fragShader);
2165*8975f5c5SAndroid Build Coastguard Worker     glLinkProgram(mFragProg);
2166*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(programPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
2167*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2168*8975f5c5SAndroid Build Coastguard Worker 
2169*8975f5c5SAndroid Build Coastguard Worker     // Set up a uniform buffer with room for five offsets, four active at a time
2170*8975f5c5SAndroid Build Coastguard Worker     GLBuffer ubo;
2171*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, ubo);
2172*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, 2048, 0, GL_DYNAMIC_DRAW);
2173*8975f5c5SAndroid Build Coastguard Worker     uint8_t *mappedBuffer =
2174*8975f5c5SAndroid Build Coastguard Worker         static_cast<uint8_t *>(glMapBufferRange(GL_UNIFORM_BUFFER, 0, 2048, GL_MAP_WRITE_BIT));
2175*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mappedBuffer);
2176*8975f5c5SAndroid Build Coastguard Worker 
2177*8975f5c5SAndroid Build Coastguard Worker     // Only set up three of the five offsets. The other two must be present, but unused.
2178*8975f5c5SAndroid Build Coastguard Worker     GLColor32F *binding0 = reinterpret_cast<GLColor32F *>(mappedBuffer);
2179*8975f5c5SAndroid Build Coastguard Worker     GLColor32F *binding1 = reinterpret_cast<GLColor32F *>(mappedBuffer + 256);
2180*8975f5c5SAndroid Build Coastguard Worker     GLColor32F *binding4 = reinterpret_cast<GLColor32F *>(mappedBuffer + 1024);
2181*8975f5c5SAndroid Build Coastguard Worker     *binding0            = kFloatRed;
2182*8975f5c5SAndroid Build Coastguard Worker     *binding1            = kFloatGreen;
2183*8975f5c5SAndroid Build Coastguard Worker     *binding4            = kFloatBlue;
2184*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_UNIFORM_BUFFER);
2185*8975f5c5SAndroid Build Coastguard Worker 
2186*8975f5c5SAndroid Build Coastguard Worker     // Start with binding0=red and binding1=green
2187*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 0, 256);
2188*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 1, ubo, 256, 512);
2189*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 2, ubo, 512, 768);
2190*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 3, ubo, 768, 1024);
2191*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2192*8975f5c5SAndroid Build Coastguard Worker 
2193*8975f5c5SAndroid Build Coastguard Worker     // Set up data for draw
2194*8975f5c5SAndroid Build Coastguard Worker     std::array<Vector3, 6> verts = GetQuadVertices();
2195*8975f5c5SAndroid Build Coastguard Worker     GLBuffer vbo;
2196*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vbo);
2197*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(verts[0]), verts.data(), GL_STATIC_DRAW);
2198*8975f5c5SAndroid Build Coastguard Worker     GLint posLoc = glGetAttribLocation(mVertProg, "position");
2199*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2200*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(posLoc);
2201*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2202*8975f5c5SAndroid Build Coastguard Worker 
2203*8975f5c5SAndroid Build Coastguard Worker     // Perform the first draw
2204*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
2205*8975f5c5SAndroid Build Coastguard Worker 
2206*8975f5c5SAndroid Build Coastguard Worker     // At this point we have red+green=yellow, but read-back changes dirty bits and breaks the test
2207*8975f5c5SAndroid Build Coastguard Worker     // EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
2208*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2209*8975f5c5SAndroid Build Coastguard Worker 
2210*8975f5c5SAndroid Build Coastguard Worker     // This is the key here - call glBindBufferRange between glDraw* calls, changing binding0=blue
2211*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, ubo, 1024, 1280);
2212*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2213*8975f5c5SAndroid Build Coastguard Worker 
2214*8975f5c5SAndroid Build Coastguard Worker     // The next draw would crash in handleDirtyGraphicsUniformBuffers without the accompanying fix
2215*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
2216*8975f5c5SAndroid Build Coastguard Worker 
2217*8975f5c5SAndroid Build Coastguard Worker     // We should now have green+blue=cyan
2218*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
2219*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2220*8975f5c5SAndroid Build Coastguard Worker }
2221*8975f5c5SAndroid Build Coastguard Worker 
2222*8975f5c5SAndroid Build Coastguard Worker class ProgramPipelineTest32 : public ProgramPipelineTest
2223*8975f5c5SAndroid Build Coastguard Worker {
2224*8975f5c5SAndroid Build Coastguard Worker   protected:
testTearDown()2225*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
2226*8975f5c5SAndroid Build Coastguard Worker     {
2227*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mVertProg);
2228*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mFragProg);
2229*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgramPipelines(1, &mPipeline);
2230*8975f5c5SAndroid Build Coastguard Worker     }
2231*8975f5c5SAndroid Build Coastguard Worker 
2232*8975f5c5SAndroid Build Coastguard Worker     void bindProgramPipeline(const GLchar *vertString,
2233*8975f5c5SAndroid Build Coastguard Worker                              const GLchar *fragString,
2234*8975f5c5SAndroid Build Coastguard Worker                              const GLchar *geomString);
2235*8975f5c5SAndroid Build Coastguard Worker     void drawQuadWithPPO(const std::string &positionAttribName,
2236*8975f5c5SAndroid Build Coastguard Worker                          const GLfloat positionAttribZ,
2237*8975f5c5SAndroid Build Coastguard Worker                          const GLfloat positionAttribXYScale);
2238*8975f5c5SAndroid Build Coastguard Worker 
2239*8975f5c5SAndroid Build Coastguard Worker     GLuint mVertProg = 0;
2240*8975f5c5SAndroid Build Coastguard Worker     GLuint mFragProg = 0;
2241*8975f5c5SAndroid Build Coastguard Worker     GLuint mGeomProg = 0;
2242*8975f5c5SAndroid Build Coastguard Worker     GLuint mPipeline = 0;
2243*8975f5c5SAndroid Build Coastguard Worker };
2244*8975f5c5SAndroid Build Coastguard Worker 
bindProgramPipeline(const GLchar * vertString,const GLchar * fragString,const GLchar * geomString)2245*8975f5c5SAndroid Build Coastguard Worker void ProgramPipelineTest32::bindProgramPipeline(const GLchar *vertString,
2246*8975f5c5SAndroid Build Coastguard Worker                                                 const GLchar *fragString,
2247*8975f5c5SAndroid Build Coastguard Worker                                                 const GLchar *geomString)
2248*8975f5c5SAndroid Build Coastguard Worker {
2249*8975f5c5SAndroid Build Coastguard Worker     mVertProg = createShaderProgram(GL_VERTEX_SHADER, vertString);
2250*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mVertProg, 0u);
2251*8975f5c5SAndroid Build Coastguard Worker     mFragProg = createShaderProgram(GL_FRAGMENT_SHADER, fragString);
2252*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mFragProg, 0u);
2253*8975f5c5SAndroid Build Coastguard Worker     mGeomProg = createShaderProgram(GL_GEOMETRY_SHADER, geomString);
2254*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mGeomProg, 0u);
2255*8975f5c5SAndroid Build Coastguard Worker 
2256*8975f5c5SAndroid Build Coastguard Worker     // Generate a program pipeline and attach the programs to their respective stages
2257*8975f5c5SAndroid Build Coastguard Worker     glGenProgramPipelines(1, &mPipeline);
2258*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2259*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_VERTEX_SHADER_BIT, mVertProg);
2260*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2261*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_FRAGMENT_SHADER_BIT, mFragProg);
2262*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2263*8975f5c5SAndroid Build Coastguard Worker     glUseProgramStages(mPipeline, GL_GEOMETRY_SHADER_BIT, mGeomProg);
2264*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2265*8975f5c5SAndroid Build Coastguard Worker     glBindProgramPipeline(mPipeline);
2266*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2267*8975f5c5SAndroid Build Coastguard Worker }
2268*8975f5c5SAndroid Build Coastguard Worker 
2269*8975f5c5SAndroid Build Coastguard Worker // Verify that we can have the max amount of uniforms with a geometry shader as part of a program
2270*8975f5c5SAndroid Build Coastguard Worker // pipeline.
TEST_P(ProgramPipelineTest32,MaxGeometryImageUniforms)2271*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest32, MaxGeometryImageUniforms)
2272*8975f5c5SAndroid Build Coastguard Worker {
2273*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan() || !IsGLExtensionEnabled("GL_EXT_geometry_shader"));
2274*8975f5c5SAndroid Build Coastguard Worker 
2275*8975f5c5SAndroid Build Coastguard Worker     GLint maxGeometryImageUnits;
2276*8975f5c5SAndroid Build Coastguard Worker     glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT, &maxGeometryImageUnits);
2277*8975f5c5SAndroid Build Coastguard Worker 
2278*8975f5c5SAndroid Build Coastguard Worker     const GLchar *vertString = essl31_shaders::vs::Simple();
2279*8975f5c5SAndroid Build Coastguard Worker     const GLchar *fragString = R"(#version 310 es
2280*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2281*8975f5c5SAndroid Build Coastguard Worker out vec4 my_FragColor;
2282*8975f5c5SAndroid Build Coastguard Worker void main()
2283*8975f5c5SAndroid Build Coastguard Worker {
2284*8975f5c5SAndroid Build Coastguard Worker     my_FragColor = vec4(1.0);
2285*8975f5c5SAndroid Build Coastguard Worker })";
2286*8975f5c5SAndroid Build Coastguard Worker 
2287*8975f5c5SAndroid Build Coastguard Worker     std::stringstream geomStringStream;
2288*8975f5c5SAndroid Build Coastguard Worker 
2289*8975f5c5SAndroid Build Coastguard Worker     geomStringStream << R"(#version 310 es
2290*8975f5c5SAndroid Build Coastguard Worker #extension GL_OES_geometry_shader : require
2291*8975f5c5SAndroid Build Coastguard Worker layout (points)                   in;
2292*8975f5c5SAndroid Build Coastguard Worker layout (points, max_vertices = 1) out;
2293*8975f5c5SAndroid Build Coastguard Worker 
2294*8975f5c5SAndroid Build Coastguard Worker precision highp iimage2D;
2295*8975f5c5SAndroid Build Coastguard Worker 
2296*8975f5c5SAndroid Build Coastguard Worker ivec4 counter = ivec4(0);
2297*8975f5c5SAndroid Build Coastguard Worker )";
2298*8975f5c5SAndroid Build Coastguard Worker 
2299*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxGeometryImageUnits; ++index)
2300*8975f5c5SAndroid Build Coastguard Worker     {
2301*8975f5c5SAndroid Build Coastguard Worker         geomStringStream << "layout(binding = " << index << ", r32i) uniform iimage2D img" << index
2302*8975f5c5SAndroid Build Coastguard Worker                          << ";" << std::endl;
2303*8975f5c5SAndroid Build Coastguard Worker     }
2304*8975f5c5SAndroid Build Coastguard Worker 
2305*8975f5c5SAndroid Build Coastguard Worker     geomStringStream << R"(
2306*8975f5c5SAndroid Build Coastguard Worker void main()
2307*8975f5c5SAndroid Build Coastguard Worker {
2308*8975f5c5SAndroid Build Coastguard Worker )";
2309*8975f5c5SAndroid Build Coastguard Worker 
2310*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxGeometryImageUnits; ++index)
2311*8975f5c5SAndroid Build Coastguard Worker     {
2312*8975f5c5SAndroid Build Coastguard Worker         geomStringStream << "counter += imageLoad(img" << index << ", ivec2(0, 0));" << std::endl;
2313*8975f5c5SAndroid Build Coastguard Worker     }
2314*8975f5c5SAndroid Build Coastguard Worker 
2315*8975f5c5SAndroid Build Coastguard Worker     geomStringStream << R"(
2316*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(float(counter.x), 0.0, 0.0, 1.0);
2317*8975f5c5SAndroid Build Coastguard Worker     EmitVertex();
2318*8975f5c5SAndroid Build Coastguard Worker }
2319*8975f5c5SAndroid Build Coastguard Worker )";
2320*8975f5c5SAndroid Build Coastguard Worker 
2321*8975f5c5SAndroid Build Coastguard Worker     bindProgramPipeline(vertString, fragString, geomStringStream.str().c_str());
2322*8975f5c5SAndroid Build Coastguard Worker 
2323*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLTexture> textures(maxGeometryImageUnits);
2324*8975f5c5SAndroid Build Coastguard Worker     for (GLint index = 0; index < maxGeometryImageUnits; ++index)
2325*8975f5c5SAndroid Build Coastguard Worker     {
2326*8975f5c5SAndroid Build Coastguard Worker         GLint value = index + 1;
2327*8975f5c5SAndroid Build Coastguard Worker 
2328*8975f5c5SAndroid Build Coastguard Worker         glBindTexture(GL_TEXTURE_2D, textures[index]);
2329*8975f5c5SAndroid Build Coastguard Worker         glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, 1, 1);
2330*8975f5c5SAndroid Build Coastguard Worker         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_INT, &value);
2331*8975f5c5SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2332*8975f5c5SAndroid Build Coastguard Worker         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2333*8975f5c5SAndroid Build Coastguard Worker 
2334*8975f5c5SAndroid Build Coastguard Worker         glBindImageTexture(index, textures[index], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32I);
2335*8975f5c5SAndroid Build Coastguard Worker     }
2336*8975f5c5SAndroid Build Coastguard Worker 
2337*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_POINTS, 0, 6);
2338*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2339*8975f5c5SAndroid Build Coastguard Worker }
2340*8975f5c5SAndroid Build Coastguard Worker 
2341*8975f5c5SAndroid Build Coastguard Worker // Verify creation of seperable tessellation control shader program with transform feeback varying
TEST_P(ProgramPipelineTest32,CreateProgramWithTransformFeedbackVarying)2342*8975f5c5SAndroid Build Coastguard Worker TEST_P(ProgramPipelineTest32, CreateProgramWithTransformFeedbackVarying)
2343*8975f5c5SAndroid Build Coastguard Worker {
2344*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_tessellation_shader"));
2345*8975f5c5SAndroid Build Coastguard Worker 
2346*8975f5c5SAndroid Build Coastguard Worker     const char *kVS =
2347*8975f5c5SAndroid Build Coastguard Worker         "#version 320 es\n"
2348*8975f5c5SAndroid Build Coastguard Worker         "\n"
2349*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_shader_io_blocks : require\n"
2350*8975f5c5SAndroid Build Coastguard Worker         "\n"
2351*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
2352*8975f5c5SAndroid Build Coastguard Worker 
2353*8975f5c5SAndroid Build Coastguard Worker         "out BLOCK_INOUT { vec4 value; } user_out;\n"
2354*8975f5c5SAndroid Build Coastguard Worker         "\n"
2355*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
2356*8975f5c5SAndroid Build Coastguard Worker         "{\n"
2357*8975f5c5SAndroid Build Coastguard Worker         "    gl_Position    = vec4(1.0, 0.0, 0.0, 1.0);\n"
2358*8975f5c5SAndroid Build Coastguard Worker         "    user_out.value = vec4(4.0, 5.0, 6.0, 7.0);\n"
2359*8975f5c5SAndroid Build Coastguard Worker         "}\n";
2360*8975f5c5SAndroid Build Coastguard Worker 
2361*8975f5c5SAndroid Build Coastguard Worker     // Fragment shader body
2362*8975f5c5SAndroid Build Coastguard Worker     const char *kFS =
2363*8975f5c5SAndroid Build Coastguard Worker         "#version 320 es\n"
2364*8975f5c5SAndroid Build Coastguard Worker         "\n"
2365*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_shader_io_blocks : require\n"
2366*8975f5c5SAndroid Build Coastguard Worker         "\n"
2367*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
2368*8975f5c5SAndroid Build Coastguard Worker         "in BLOCK_INOUT { vec4 value; } user_in;\n"
2369*8975f5c5SAndroid Build Coastguard Worker         "\n"
2370*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
2371*8975f5c5SAndroid Build Coastguard Worker         "{\n"
2372*8975f5c5SAndroid Build Coastguard Worker         "}\n";
2373*8975f5c5SAndroid Build Coastguard Worker 
2374*8975f5c5SAndroid Build Coastguard Worker     // Geometry shader body
2375*8975f5c5SAndroid Build Coastguard Worker     const char *kGS =
2376*8975f5c5SAndroid Build Coastguard Worker         "#version 320 es\n"
2377*8975f5c5SAndroid Build Coastguard Worker         "\n"
2378*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_geometry_shader : require\n"
2379*8975f5c5SAndroid Build Coastguard Worker         "\n"
2380*8975f5c5SAndroid Build Coastguard Worker         "layout(points)                   in;\n"
2381*8975f5c5SAndroid Build Coastguard Worker         "layout(points, max_vertices = 1) out;\n"
2382*8975f5c5SAndroid Build Coastguard Worker         "\n"
2383*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
2384*8975f5c5SAndroid Build Coastguard Worker         "//${IN_PER_VERTEX_DECL_ARRAY}\n"
2385*8975f5c5SAndroid Build Coastguard Worker         "//${OUT_PER_VERTEX_DECL}\n"
2386*8975f5c5SAndroid Build Coastguard Worker         "in  BLOCK_INOUT { vec4 value; } user_in[];\n"
2387*8975f5c5SAndroid Build Coastguard Worker         "out BLOCK_INOUT { vec4 value; } user_out;\n"
2388*8975f5c5SAndroid Build Coastguard Worker         "\n"
2389*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
2390*8975f5c5SAndroid Build Coastguard Worker         "{\n"
2391*8975f5c5SAndroid Build Coastguard Worker         "    user_out.value = vec4(1.0, 2.0, 3.0, 4.0);\n"
2392*8975f5c5SAndroid Build Coastguard Worker         "    gl_Position    = vec4(0.0, 0.0, 0.0, 1.0);\n"
2393*8975f5c5SAndroid Build Coastguard Worker         "\n"
2394*8975f5c5SAndroid Build Coastguard Worker         "    EmitVertex();\n"
2395*8975f5c5SAndroid Build Coastguard Worker         "}\n";
2396*8975f5c5SAndroid Build Coastguard Worker 
2397*8975f5c5SAndroid Build Coastguard Worker     // tessellation control shader body
2398*8975f5c5SAndroid Build Coastguard Worker     const char *kTCS =
2399*8975f5c5SAndroid Build Coastguard Worker         "#version 320 es\n"
2400*8975f5c5SAndroid Build Coastguard Worker         "\n"
2401*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_tessellation_shader : require\n"
2402*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_shader_io_blocks : require\n"
2403*8975f5c5SAndroid Build Coastguard Worker         "\n"
2404*8975f5c5SAndroid Build Coastguard Worker         "layout (vertices=4) out;\n"
2405*8975f5c5SAndroid Build Coastguard Worker         "\n"
2406*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
2407*8975f5c5SAndroid Build Coastguard Worker         "in  BLOCK_INOUT { vec4 value; } user_in[];\n"
2408*8975f5c5SAndroid Build Coastguard Worker         "out BLOCK_INOUT { vec4 value; } user_out[];\n"
2409*8975f5c5SAndroid Build Coastguard Worker         "\n"
2410*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
2411*8975f5c5SAndroid Build Coastguard Worker         "{\n"
2412*8975f5c5SAndroid Build Coastguard Worker         "    gl_out   [gl_InvocationID].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
2413*8975f5c5SAndroid Build Coastguard Worker         "    user_out [gl_InvocationID].value       = vec4(2.0, 3.0, 4.0, 5.0);\n"
2414*8975f5c5SAndroid Build Coastguard Worker         "\n"
2415*8975f5c5SAndroid Build Coastguard Worker         "    gl_TessLevelOuter[0] = 1.0;\n"
2416*8975f5c5SAndroid Build Coastguard Worker         "    gl_TessLevelOuter[1] = 1.0;\n"
2417*8975f5c5SAndroid Build Coastguard Worker         "}\n";
2418*8975f5c5SAndroid Build Coastguard Worker 
2419*8975f5c5SAndroid Build Coastguard Worker     // Tessellation evaluation shader
2420*8975f5c5SAndroid Build Coastguard Worker     const char *kTES =
2421*8975f5c5SAndroid Build Coastguard Worker         "#version 320 es\n"
2422*8975f5c5SAndroid Build Coastguard Worker         "\n"
2423*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_tessellation_shader : require\n"
2424*8975f5c5SAndroid Build Coastguard Worker         "#extension GL_EXT_shader_io_blocks : require\n"
2425*8975f5c5SAndroid Build Coastguard Worker         "\n"
2426*8975f5c5SAndroid Build Coastguard Worker         "layout (isolines, point_mode) in;\n"
2427*8975f5c5SAndroid Build Coastguard Worker         "\n"
2428*8975f5c5SAndroid Build Coastguard Worker         "precision highp float;\n"
2429*8975f5c5SAndroid Build Coastguard Worker         "in  BLOCK_INOUT { vec4 value; } user_in[];\n"
2430*8975f5c5SAndroid Build Coastguard Worker         "out BLOCK_INOUT { vec4 value; } user_out;\n"
2431*8975f5c5SAndroid Build Coastguard Worker         "\n"
2432*8975f5c5SAndroid Build Coastguard Worker         "void main()\n"
2433*8975f5c5SAndroid Build Coastguard Worker         "{\n"
2434*8975f5c5SAndroid Build Coastguard Worker         "    gl_Position     = gl_in[0].gl_Position;\n"
2435*8975f5c5SAndroid Build Coastguard Worker         "    user_out.value = vec4(3.0, 4.0, 5.0, 6.0);\n"
2436*8975f5c5SAndroid Build Coastguard Worker         "}\n";
2437*8975f5c5SAndroid Build Coastguard Worker     const GLchar *kVaryingName = "BLOCK_INOUT.value";
2438*8975f5c5SAndroid Build Coastguard Worker 
2439*8975f5c5SAndroid Build Coastguard Worker     GLuint fsProgram = createShaderProgram(GL_FRAGMENT_SHADER, kFS);
2440*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, fsProgram);
2441*8975f5c5SAndroid Build Coastguard Worker 
2442*8975f5c5SAndroid Build Coastguard Worker     GLuint vsProgram = createShaderProgram(GL_VERTEX_SHADER, kVS, 1, &kVaryingName);
2443*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, vsProgram);
2444*8975f5c5SAndroid Build Coastguard Worker 
2445*8975f5c5SAndroid Build Coastguard Worker     GLuint gsProgram = 0u;
2446*8975f5c5SAndroid Build Coastguard Worker     if (IsGLExtensionEnabled("GL_EXT_geometry_shader"))
2447*8975f5c5SAndroid Build Coastguard Worker     {
2448*8975f5c5SAndroid Build Coastguard Worker         gsProgram = createShaderProgram(GL_GEOMETRY_SHADER, kGS, 1, &kVaryingName);
2449*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(0u, gsProgram);
2450*8975f5c5SAndroid Build Coastguard Worker     }
2451*8975f5c5SAndroid Build Coastguard Worker 
2452*8975f5c5SAndroid Build Coastguard Worker     GLuint tcsProgram = createShaderProgram(GL_TESS_CONTROL_SHADER, kTCS, 1, &kVaryingName);
2453*8975f5c5SAndroid Build Coastguard Worker     // Should fail here.
2454*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(0u, tcsProgram);
2455*8975f5c5SAndroid Build Coastguard Worker 
2456*8975f5c5SAndroid Build Coastguard Worker     // try compiling without transform feedback varying it should pass
2457*8975f5c5SAndroid Build Coastguard Worker     tcsProgram = createShaderProgram(GL_TESS_CONTROL_SHADER, kTCS);
2458*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, tcsProgram);
2459*8975f5c5SAndroid Build Coastguard Worker 
2460*8975f5c5SAndroid Build Coastguard Worker     GLuint tesProgram = createShaderProgram(GL_TESS_EVALUATION_SHADER, kTES, 1, &kVaryingName);
2461*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(0u, tesProgram);
2462*8975f5c5SAndroid Build Coastguard Worker 
2463*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(fsProgram);
2464*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(vsProgram);
2465*8975f5c5SAndroid Build Coastguard Worker     if (gsProgram != 0u)
2466*8975f5c5SAndroid Build Coastguard Worker     {
2467*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(gsProgram);
2468*8975f5c5SAndroid Build Coastguard Worker     }
2469*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(tcsProgram);
2470*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(tesProgram);
2471*8975f5c5SAndroid Build Coastguard Worker }
2472*8975f5c5SAndroid Build Coastguard Worker 
2473*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProgramPipelineTest);
2474*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(ProgramPipelineTest);
2475*8975f5c5SAndroid Build Coastguard Worker 
2476*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProgramPipelineTest31);
2477*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31(ProgramPipelineTest31);
2478*8975f5c5SAndroid Build Coastguard Worker 
2479*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProgramPipelineXFBTest31);
2480*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31(ProgramPipelineXFBTest31);
2481*8975f5c5SAndroid Build Coastguard Worker 
2482*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProgramPipelineTest32);
2483*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES32(ProgramPipelineTest32);
2484*8975f5c5SAndroid Build Coastguard Worker 
2485*8975f5c5SAndroid Build Coastguard Worker }  // namespace
2486