xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ProgramInterfaceTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // ProgramInterfaceTest: Tests of program interfaces.
8 
9 #include "common/string_utils.h"
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
18 // Variations:
19 //
20 // - bool: whether the program must be created and recreated, so that it's reloaded from cache.
21 using ProgramInterfaceTestParams = std::tuple<angle::PlatformParameters, bool>;
22 
ProgramInterfaceTestPrint(const::testing::TestParamInfo<ProgramInterfaceTestParams> & paramsInfo)23 std::string ProgramInterfaceTestPrint(
24     const ::testing::TestParamInfo<ProgramInterfaceTestParams> &paramsInfo)
25 {
26     const ProgramInterfaceTestParams &params = paramsInfo.param;
27     std::ostringstream out;
28 
29     out << std::get<0>(params);
30 
31     if (std::get<1>(params))
32     {
33         out << "__cached";
34     }
35 
36     return out.str();
37 }
38 
39 class ProgramInterfaceTestES31 : public ANGLETest<ProgramInterfaceTestParams>
40 {
41   protected:
ProgramInterfaceTestES31()42     ProgramInterfaceTestES31()
43     {
44         setWindowWidth(64);
45         setWindowHeight(64);
46         setConfigRedBits(8);
47         setConfigGreenBits(8);
48         setConfigBlueBits(8);
49         setConfigAlphaBits(8);
50     }
51 
52     void createGraphicsProgram(GLProgram &program,
53                                const char *vs,
54                                const char *fs,
55                                bool cacheAndReload);
56     void createComputeProgram(GLProgram &program, const char *cs, bool cacheAndReload);
57 };
58 
createGraphicsProgram(GLProgram & program,const char * vs,const char * fs,bool cacheAndReload)59 void ProgramInterfaceTestES31::createGraphicsProgram(GLProgram &program,
60                                                      const char *vs,
61                                                      const char *fs,
62                                                      bool cacheAndReload)
63 {
64     program.makeRaster(vs, fs);
65     ASSERT_TRUE(program.valid());
66 
67     if (cacheAndReload)
68     {
69         program.reset();
70         program.makeRaster(vs, fs);
71         ASSERT_TRUE(program.valid());
72     }
73 }
74 
createComputeProgram(GLProgram & program,const char * cs,bool cacheAndReload)75 void ProgramInterfaceTestES31::createComputeProgram(GLProgram &program,
76                                                     const char *cs,
77                                                     bool cacheAndReload)
78 {
79     program.makeCompute(cs);
80     ASSERT_TRUE(program.valid());
81 
82     if (cacheAndReload)
83     {
84         program.reset();
85         program.makeCompute(cs);
86         ASSERT_TRUE(program.valid());
87     }
88 }
89 
90 // Tests glGetProgramResourceIndex.
TEST_P(ProgramInterfaceTestES31,GetResourceIndex)91 TEST_P(ProgramInterfaceTestES31, GetResourceIndex)
92 {
93     constexpr char kFS[] =
94         "#version 310 es\n"
95         "precision highp float;\n"
96         "uniform vec4 color;\n"
97         "out vec4 oColor;\n"
98         "void main()\n"
99         "{\n"
100         "    oColor = color;\n"
101         "}";
102 
103     GLProgram program;
104     createGraphicsProgram(program, essl31_shaders::vs::Simple(), kFS, std::get<1>(GetParam()));
105 
106     GLuint index =
107         glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib());
108     EXPECT_GL_NO_ERROR();
109     EXPECT_NE(GL_INVALID_INDEX, index);
110 
111     index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "missing");
112     EXPECT_GL_NO_ERROR();
113     EXPECT_EQ(GL_INVALID_INDEX, index);
114 
115     index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
116     EXPECT_GL_NO_ERROR();
117     EXPECT_NE(GL_INVALID_INDEX, index);
118 
119     index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "missing");
120     EXPECT_GL_NO_ERROR();
121     EXPECT_EQ(GL_INVALID_INDEX, index);
122 
123     index = glGetProgramResourceIndex(program, GL_ATOMIC_COUNTER_BUFFER, "missing");
124     EXPECT_GL_ERROR(GL_INVALID_ENUM);
125 }
126 
127 // Tests glGetProgramResourceName.
TEST_P(ProgramInterfaceTestES31,GetResourceName)128 TEST_P(ProgramInterfaceTestES31, GetResourceName)
129 {
130     constexpr char kFS[] =
131         "#version 310 es\n"
132         "precision highp float;\n"
133         "uniform vec4 color;\n"
134         "out vec4 oColor[4];\n"
135         "void main()\n"
136         "{\n"
137         "    oColor[0] = color;\n"
138         "}";
139 
140     GLProgram program;
141     createGraphicsProgram(program, essl31_shaders::vs::Simple(), kFS, std::get<1>(GetParam()));
142 
143     GLuint index =
144         glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, essl31_shaders::PositionAttrib());
145     EXPECT_GL_NO_ERROR();
146     EXPECT_NE(GL_INVALID_INDEX, index);
147 
148     GLchar name[64];
149     GLsizei length;
150     glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, sizeof(name), &length, name);
151     EXPECT_GL_NO_ERROR();
152     EXPECT_EQ(static_cast<int>(strlen(essl31_shaders::PositionAttrib())), length);
153     EXPECT_EQ(essl31_shaders::PositionAttrib(), std::string(name));
154 
155     glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, 4, &length, name);
156     EXPECT_GL_NO_ERROR();
157     EXPECT_EQ(3, length);
158     EXPECT_TRUE(angle::BeginsWith(essl31_shaders::PositionAttrib(), name));
159 
160     glGetProgramResourceName(program, GL_PROGRAM_INPUT, index, -1, &length, name);
161     EXPECT_GL_ERROR(GL_INVALID_VALUE);
162 
163     glGetProgramResourceName(program, GL_PROGRAM_INPUT, GL_INVALID_INDEX, sizeof(name), &length,
164                              name);
165     EXPECT_GL_ERROR(GL_INVALID_VALUE);
166 
167     index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor");
168     EXPECT_GL_NO_ERROR();
169     EXPECT_NE(GL_INVALID_INDEX, index);
170 
171     glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, sizeof(name), &length, name);
172     EXPECT_GL_NO_ERROR();
173     EXPECT_EQ(9, length);
174     EXPECT_EQ("oColor[0]", std::string(name));
175 
176     glGetProgramResourceName(program, GL_PROGRAM_OUTPUT, index, 8, &length, name);
177     EXPECT_GL_NO_ERROR();
178     EXPECT_EQ(7, length);
179     EXPECT_EQ("oColor[", std::string(name));
180 }
181 
182 // Tests glGetProgramResourceLocation.
TEST_P(ProgramInterfaceTestES31,GetResourceLocation)183 TEST_P(ProgramInterfaceTestES31, GetResourceLocation)
184 {
185     constexpr char kVS[] =
186         "#version 310 es\n"
187         "precision highp float;\n"
188         "layout(location = 3) in highp vec4 position;\n"
189         "in highp vec4 noLocationSpecified;\n"
190         "void main()\n"
191         "{\n"
192         "    gl_Position = position;\n"
193         "}";
194 
195     constexpr char kFS[] =
196         "#version 310 es\n"
197         "precision highp float;\n"
198         "uniform vec4 color;\n"
199         "layout(location = 1) out vec4 oColor[3];\n"
200         "void main()\n"
201         "{\n"
202         "    oColor[0] = color;\n"
203         "}";
204 
205     GLProgram program;
206     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
207 
208     GLenum invalidInterfaces[] = {GL_UNIFORM_BLOCK, GL_TRANSFORM_FEEDBACK_VARYING,
209                                   GL_BUFFER_VARIABLE, GL_SHADER_STORAGE_BLOCK,
210                                   GL_ATOMIC_COUNTER_BUFFER};
211     GLint location;
212     for (auto &invalidInterface : invalidInterfaces)
213     {
214         location = glGetProgramResourceLocation(program, invalidInterface, "any");
215         EXPECT_GL_ERROR(GL_INVALID_ENUM);
216         EXPECT_EQ(-1, location);
217     }
218 
219     location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position");
220     EXPECT_GL_NO_ERROR();
221     EXPECT_EQ(3, location);
222 
223     location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "noLocationSpecified");
224     EXPECT_GL_NO_ERROR();
225     EXPECT_EQ(-1, location);
226 
227     location = glGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "missing");
228     EXPECT_GL_NO_ERROR();
229     EXPECT_EQ(-1, location);
230 
231     location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor");
232     EXPECT_GL_NO_ERROR();
233     EXPECT_EQ(1, location);
234     location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor[0]");
235     EXPECT_GL_NO_ERROR();
236     EXPECT_EQ(1, location);
237     location = glGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "oColor[2]");
238     EXPECT_GL_NO_ERROR();
239     EXPECT_EQ(3, location);
240 }
241 
242 // Tests glGetProgramResource.
TEST_P(ProgramInterfaceTestES31,GetResource)243 TEST_P(ProgramInterfaceTestES31, GetResource)
244 {
245     constexpr char kVS[] =
246         "#version 310 es\n"
247         "precision highp float;\n"
248         "layout(location = 3) in highp vec4 position;\n"
249         "void main()\n"
250         "{\n"
251         "    gl_Position = position;\n"
252         "}";
253 
254     constexpr char kFS[] =
255         "#version 310 es\n"
256         "precision highp float;\n"
257         "uniform vec4 color;\n"
258         "layout(location = 1) out vec4 oColor[3];\n"
259         "void main()\n"
260         "{\n"
261         "    oColor[0] = color;\n"
262         "}";
263 
264     GLProgram program;
265     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
266 
267     GLuint index = glGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position");
268     EXPECT_GL_NO_ERROR();
269     EXPECT_NE(GL_INVALID_INDEX, index);
270 
271     GLenum props[]    = {GL_TYPE,
272                          GL_ARRAY_SIZE,
273                          GL_LOCATION,
274                          GL_NAME_LENGTH,
275                          GL_REFERENCED_BY_VERTEX_SHADER,
276                          GL_REFERENCED_BY_FRAGMENT_SHADER,
277                          GL_REFERENCED_BY_COMPUTE_SHADER};
278     GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
279     GLint params[ArraySize(props)];
280     GLsizei length;
281 
282     glGetProgramResourceiv(program, GL_PROGRAM_INPUT, index, propCount, props, propCount, &length,
283                            params);
284     EXPECT_GL_NO_ERROR();
285     EXPECT_EQ(propCount, length);
286     EXPECT_EQ(GL_FLOAT_VEC4, params[0]);  // type
287     EXPECT_EQ(1, params[1]);              // array_size
288     EXPECT_EQ(3, params[2]);              // location
289     EXPECT_EQ(9, params[3]);              // name_length
290     EXPECT_EQ(1, params[4]);              // referenced_by_vertex_shader
291     EXPECT_EQ(0, params[5]);              // referenced_by_fragment_shader
292     EXPECT_EQ(0, params[6]);              // referenced_by_compute_shader
293 
294     index = glGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "oColor[0]");
295     EXPECT_GL_NO_ERROR();
296     EXPECT_NE(index, GL_INVALID_INDEX);
297     // bufSize is smaller than propCount.
298     glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, propCount, props, propCount - 1,
299                            &length, params);
300     EXPECT_GL_NO_ERROR();
301     EXPECT_EQ(propCount - 1, length);
302     EXPECT_EQ(GL_FLOAT_VEC4, params[0]);  // type
303     EXPECT_EQ(3, params[1]);              // array_size
304     EXPECT_EQ(1, params[2]);              // location
305     EXPECT_EQ(10, params[3]);             // name_length
306     EXPECT_EQ(0, params[4]);              // referenced_by_vertex_shader
307     EXPECT_EQ(1, params[5]);              // referenced_by_fragment_shader
308 
309     GLenum invalidOutputProp = GL_OFFSET;
310     glGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, index, 1, &invalidOutputProp, 1, &length,
311                            params);
312     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
313 }
314 
315 // Tests glGetProgramInterfaceiv.
TEST_P(ProgramInterfaceTestES31,GetProgramInterface)316 TEST_P(ProgramInterfaceTestES31, GetProgramInterface)
317 {
318     // TODO([email protected]): Don't skip this test once SSBO are supported on render pipeline.
319     // http://anglebug.com/40644618
320     ANGLE_SKIP_TEST_IF(IsD3D11());
321 
322     constexpr char kFS[] =
323         "#version 310 es\n"
324         "precision highp float;\n"
325         "uniform vec4 color;\n"
326         "out vec4 oColor;\n"
327         "uniform ub {\n"
328         "    vec4 mem0;\n"
329         "    vec4 mem1;\n"
330         "} instance;\n"
331         "layout(std430) buffer shaderStorageBlock1 {\n"
332         "    vec3 target;\n"
333         "};\n"
334         "layout(std430) buffer shaderStorageBlock2 {\n"
335         "    vec3 target;\n"
336         "} blockInstance2[1];\n"
337         "void main()\n"
338         "{\n"
339         "    oColor = color;\n"
340         "    target = vec3(0, 0, 0);\n"
341         "    blockInstance2[0].target = vec3(1, 1, 1);\n"
342         "}";
343 
344     GLProgram program;
345     createGraphicsProgram(program, essl31_shaders::vs::Simple(), kFS, std::get<1>(GetParam()));
346 
347     GLint num;
348     glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, &num);
349     EXPECT_GL_NO_ERROR();
350     EXPECT_EQ(1, num);
351 
352     glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, &num);
353     EXPECT_GL_NO_ERROR();
354     EXPECT_EQ(static_cast<GLint>(strlen(essl3_shaders::PositionAttrib())) + 1, num);
355 
356     glGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
357     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
358 
359     glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, &num);
360     EXPECT_GL_NO_ERROR();
361     EXPECT_EQ(1, num);
362 
363     glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, &num);
364     EXPECT_GL_NO_ERROR();
365     EXPECT_EQ(7, num);
366 
367     glGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
368     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
369 
370     glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &num);
371     EXPECT_GL_NO_ERROR();
372     EXPECT_EQ(1, num);
373 
374     glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NAME_LENGTH, &num);
375     EXPECT_GL_NO_ERROR();
376     EXPECT_EQ(3, num);
377 
378     glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
379     EXPECT_GL_NO_ERROR();
380     EXPECT_EQ(2, num);  // mem0, mem1
381 
382     glGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES, &num);
383     EXPECT_GL_NO_ERROR();
384     EXPECT_EQ(3, num);
385 
386     glGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, &num);
387     EXPECT_GL_NO_ERROR();
388     EXPECT_EQ(8, num);  // "ub.mem0"
389 
390     glGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
391     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
392 
393     glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &num);
394     EXPECT_GL_NO_ERROR();
395     EXPECT_EQ(2, num);
396 
397     glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &num);
398     EXPECT_GL_NO_ERROR();
399     EXPECT_EQ(23, num);  // "shaderStorageBlock2[0]"
400 
401     glGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
402     EXPECT_GL_NO_ERROR();
403     EXPECT_EQ(1, num);
404 }
405 
406 // Tests the resource property query for uniform can be done correctly.
TEST_P(ProgramInterfaceTestES31,GetUniformProperties)407 TEST_P(ProgramInterfaceTestES31, GetUniformProperties)
408 {
409     // Check atomic support.
410     GLint numSupported;
411     glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &numSupported);
412     EXPECT_GL_NO_ERROR();
413     ANGLE_SKIP_TEST_IF(numSupported < 1);
414 
415     constexpr char kVS[] =
416         "#version 310 es\n"
417         "precision highp float;\n"
418         "uniform layout(location=12) vec4 color;\n"
419         "layout(binding = 2, offset = 4) uniform atomic_uint foo;\n"
420         "void main()\n"
421         "{\n"
422         "    atomicCounterIncrement(foo);\n"
423         "}";
424 
425     constexpr char kFS[] =
426         "#version 310 es\n"
427         "precision highp float;\n"
428         "uniform vec4 color;\n"
429         "out vec4 oColor;\n"
430         "void main()\n"
431         "{\n"
432         "    oColor = color;\n"
433         "}";
434 
435     GLProgram program;
436     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
437 
438     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "color");
439     EXPECT_GL_NO_ERROR();
440     EXPECT_NE(GL_INVALID_INDEX, index);
441 
442     GLchar name[64];
443     GLsizei length;
444     glGetProgramResourceName(program, GL_UNIFORM, index, sizeof(name), &length, name);
445     EXPECT_GL_NO_ERROR();
446     EXPECT_EQ(5, length);
447     EXPECT_EQ("color", std::string(name));
448 
449     GLint location = glGetProgramResourceLocation(program, GL_UNIFORM, "color");
450     EXPECT_GL_NO_ERROR();
451     EXPECT_EQ(12, location);
452 
453     GLenum props[]    = {GL_TYPE,
454                          GL_ARRAY_SIZE,
455                          GL_LOCATION,
456                          GL_NAME_LENGTH,
457                          GL_REFERENCED_BY_VERTEX_SHADER,
458                          GL_REFERENCED_BY_FRAGMENT_SHADER,
459                          GL_REFERENCED_BY_COMPUTE_SHADER,
460                          GL_ARRAY_STRIDE,
461                          GL_BLOCK_INDEX,
462                          GL_IS_ROW_MAJOR,
463                          GL_MATRIX_STRIDE,
464                          GL_OFFSET,
465                          GL_ATOMIC_COUNTER_BUFFER_INDEX};
466     GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
467     GLint params[ArraySize(props)];
468     glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, propCount, &length,
469                            params);
470     EXPECT_GL_NO_ERROR();
471     EXPECT_EQ(propCount, length);
472     EXPECT_EQ(GL_FLOAT_VEC4, params[0]);  // type
473     EXPECT_EQ(1, params[1]);              // array_size
474     EXPECT_EQ(12, params[2]);             // location
475     EXPECT_EQ(6, params[3]);              // name_length
476     EXPECT_EQ(0, params[4]);              // referenced_by_vertex_shader
477     EXPECT_EQ(1, params[5]);              // referenced_by_fragment_shader
478     EXPECT_EQ(0, params[6]);              // referenced_by_compute_shader
479     EXPECT_EQ(-1, params[7]);             // array_stride
480     EXPECT_EQ(-1, params[8]);             // block_index
481     EXPECT_EQ(0, params[9]);              // is_row_major
482     EXPECT_EQ(-1, params[10]);            // matrix_stride
483     EXPECT_EQ(-1, params[11]);            // offset
484     EXPECT_EQ(-1, params[12]);            // atomic_counter_buffer_index
485 
486     index = glGetProgramResourceIndex(program, GL_UNIFORM, "foo");
487     EXPECT_GL_NO_ERROR();
488     EXPECT_NE(GL_INVALID_INDEX, index);
489 
490     glGetProgramResourceName(program, GL_UNIFORM, index, sizeof(name), &length, name);
491     EXPECT_GL_NO_ERROR();
492     EXPECT_EQ(3, length);
493     EXPECT_EQ("foo", std::string(name));
494 
495     location = glGetProgramResourceLocation(program, GL_UNIFORM, "foo");
496     EXPECT_GL_NO_ERROR();
497     EXPECT_EQ(-1, location);
498 
499     glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, propCount, &length,
500                            params);
501     EXPECT_GL_NO_ERROR();
502     EXPECT_EQ(propCount, length);
503     EXPECT_EQ(GL_UNSIGNED_INT_ATOMIC_COUNTER, params[0]);  // type
504     EXPECT_EQ(1, params[1]);                               // array_size
505     EXPECT_EQ(-1, params[2]);                              // location
506     EXPECT_EQ(4, params[3]);                               // name_length
507     EXPECT_EQ(1, params[4]);                               // referenced_by_vertex_shader
508     EXPECT_EQ(0, params[5]);                               // referenced_by_fragment_shader
509     EXPECT_EQ(0, params[6]);                               // referenced_by_compute_shader
510     EXPECT_EQ(0, params[7]);                               // array_stride
511     EXPECT_EQ(-1, params[8]);                              // block_index
512     EXPECT_EQ(0, params[9]);                               // is_row_major
513     EXPECT_EQ(0, params[10]);                              // matrix_stride
514     EXPECT_EQ(4, params[11]);                              // offset
515     EXPECT_NE(-1, params[12]);                             // atomic_counter_buffer_index
516 }
517 
518 // Tests the resource property query for uniform block can be done correctly.
TEST_P(ProgramInterfaceTestES31,GetUniformBlockProperties)519 TEST_P(ProgramInterfaceTestES31, GetUniformBlockProperties)
520 {
521     constexpr char kVS[] =
522         "#version 310 es\n"
523         "in vec2 position;\n"
524         "out vec2 v;\n"
525         "layout(binding = 2) uniform blockName {\n"
526         "  float f1;\n"
527         "  float f2;\n"
528         "} instanceName;\n"
529         "void main() {\n"
530         "  v = vec2(instanceName.f1, instanceName.f2);\n"
531         "  gl_Position = vec4(position, 0, 1);\n"
532         "}";
533 
534     constexpr char kFS[] =
535         "#version 310 es\n"
536         "precision highp float;\n"
537         "in vec2 v;\n"
538         "out vec4 color;\n"
539         "void main() {\n"
540         "  color = vec4(v, 0, 1);\n"
541         "}";
542 
543     GLProgram program;
544     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
545 
546     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, "blockName");
547     EXPECT_GL_NO_ERROR();
548     EXPECT_NE(GL_INVALID_INDEX, index);
549 
550     GLchar name[64];
551     GLsizei length;
552     glGetProgramResourceName(program, GL_UNIFORM_BLOCK, index, sizeof(name), &length, name);
553     EXPECT_GL_NO_ERROR();
554     EXPECT_EQ(9, length);
555     EXPECT_EQ("blockName", std::string(name));
556 
557     GLenum props[]         = {GL_BUFFER_BINDING,
558                               GL_BUFFER_DATA_SIZE,
559                               GL_NAME_LENGTH,
560                               GL_NUM_ACTIVE_VARIABLES,
561                               GL_ACTIVE_VARIABLES,
562                               GL_REFERENCED_BY_VERTEX_SHADER,
563                               GL_REFERENCED_BY_FRAGMENT_SHADER,
564                               GL_REFERENCED_BY_COMPUTE_SHADER};
565     GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
566     constexpr int kBufSize = 256;
567     GLint params[kBufSize];
568     GLint magic = 0xBEEF;
569 
570     // Tests bufSize is respected even some prop returns more than one value.
571     params[propCount] = magic;
572     glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, propCount, props, propCount, &length,
573                            params);
574     EXPECT_GL_NO_ERROR();
575     EXPECT_EQ(propCount, length);
576     EXPECT_EQ(2, params[0]);   // buffer_binding
577     EXPECT_NE(0, params[1]);   // buffer_data_size
578     EXPECT_EQ(10, params[2]);  // name_length
579     EXPECT_EQ(2, params[3]);   // num_active_variables
580     EXPECT_LE(0, params[4]);   // index of 'f1' or 'f2'
581     EXPECT_LE(0, params[5]);   // index of 'f1' or 'f2'
582     EXPECT_EQ(1, params[6]);   // referenced_by_vertex_shader
583     EXPECT_EQ(0, params[7]);   // referenced_by_fragment_shader
584     EXPECT_EQ(magic, params[8]);
585 
586     glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, propCount, props, kBufSize, &length,
587                            params);
588     EXPECT_GL_NO_ERROR();
589     EXPECT_EQ(propCount + 1, length);
590     EXPECT_EQ(0, params[8]);  // referenced_by_compute_shader
591 
592     // bufSize is reached in middle of outputting values for GL_ACTIVE_VARIABLES.
593     GLenum actvieVariablesProperty = GL_ACTIVE_VARIABLES;
594     params[1]                      = magic;
595     glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, index, 1, &actvieVariablesProperty, 1,
596                            &length, params);
597     EXPECT_GL_NO_ERROR();
598     EXPECT_EQ(1, length);
599     EXPECT_LE(0, params[0]);  // index of 'f1' or 'f2'
600     EXPECT_EQ(magic, params[1]);
601 }
602 
603 // Tests atomic counter buffer qeury works correctly.
TEST_P(ProgramInterfaceTestES31,QueryAtomicCounteBuffer)604 TEST_P(ProgramInterfaceTestES31, QueryAtomicCounteBuffer)
605 {
606     // Check atomic support.
607     GLint numSupportedInVertex;
608     GLint numSupportedInFragment;
609     glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &numSupportedInVertex);
610     glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &numSupportedInFragment);
611     EXPECT_GL_NO_ERROR();
612     ANGLE_SKIP_TEST_IF(numSupportedInVertex < 1 || numSupportedInFragment < 1);
613 
614     constexpr char kVS[] =
615         "#version 310 es\n"
616         "precision highp float;\n"
617         "layout(binding = 2, offset = 0) uniform atomic_uint vcounter;\n"
618         "in highp vec4 a_position;\n"
619         "void main()\n"
620         "{\n"
621         "    atomicCounterIncrement(vcounter);\n"
622         "    gl_Position = a_position;\n"
623         "}\n";
624 
625     constexpr char kFS[] =
626         "#version 310 es\n"
627         "precision highp float;\n"
628         "layout(binding = 2, offset = 4) uniform atomic_uint fcounter;\n"
629         "out highp vec4 my_color;\n"
630         "void main()\n"
631         "{\n"
632         "    atomicCounterDecrement(fcounter);\n"
633         "    my_color = vec4(0.0);\n"
634         "}\n";
635 
636     GLProgram program;
637     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
638 
639     GLint num;
640     glGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, &num);
641     EXPECT_GL_NO_ERROR();
642     EXPECT_EQ(1, num);
643 
644     glGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, &num);
645     EXPECT_GL_NO_ERROR();
646     EXPECT_EQ(2, num);
647 
648     GLenum props[]    = {GL_BUFFER_BINDING, GL_NUM_ACTIVE_VARIABLES, GL_REFERENCED_BY_VERTEX_SHADER,
649                          GL_REFERENCED_BY_FRAGMENT_SHADER, GL_REFERENCED_BY_COMPUTE_SHADER};
650     GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
651     GLint params[ArraySize(props)];
652     GLsizei length = 0;
653     glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, 0, propCount, props, propCount,
654                            &length, params);
655     EXPECT_GL_NO_ERROR();
656     EXPECT_EQ(propCount, length);
657     EXPECT_EQ(2, params[0]);  // buffer_binding
658     EXPECT_EQ(2, params[1]);  // num_active_variables
659     EXPECT_EQ(1, params[2]);  // referenced_by_vertex_shader
660     EXPECT_EQ(1, params[3]);  // referenced_by_fragment_shader
661     EXPECT_EQ(0, params[4]);  // referenced_by_compute_shader
662 }
663 
664 // Tests the resource property query for buffer variable can be done correctly.
TEST_P(ProgramInterfaceTestES31,GetBufferVariableProperties)665 TEST_P(ProgramInterfaceTestES31, GetBufferVariableProperties)
666 {
667     // TODO([email protected]): Don't skip this test once non-simple SSBO sentences are supported
668     // on d3d backend. http://anglebug.com/40644618
669     ANGLE_SKIP_TEST_IF(IsD3D11());
670 
671     // Check SSBO support
672     GLint numSupported;
673     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &numSupported);
674     EXPECT_GL_NO_ERROR();
675     ANGLE_SKIP_TEST_IF(numSupported < 2);
676 
677     constexpr char kVS[] =
678         "#version 310 es\n"
679         "precision highp float;\n"
680         "struct S {\n"
681         "    vec3 a;\n"
682         "    ivec2 b[4];\n"
683         "};\n"
684         "layout(std140) buffer blockName0 {\n"
685         "    S s0;\n"
686         "    vec2 v0;\n"
687         "    S s1[2];\n"
688         "    uint u0;\n"
689         "};\n"
690         "layout(binding = 1) buffer blockName1 {\n"
691         "    uint u1[2];\n"
692         "    float f1;\n"
693         "} instanceName1[2];\n"
694         "void main()\n"
695         "{\n"
696         "    gl_Position = vec4(instanceName1[0].f1, s1[0].a);\n"
697         "}\n";
698 
699     constexpr char kFS[] =
700         "#version 310 es\n"
701         "precision highp float;\n"
702         "layout(binding = 1) buffer blockName1 {\n"
703         "    uint u1[2];\n"
704         "    float f1;\n"
705         "} instanceName1[2];\n"
706         "out vec4 oColor;\n"
707         "void main()\n"
708         "{\n"
709         "    oColor = vec4(instanceName1[0].f1, 0, 0, 1);\n"
710         "}";
711 
712     GLProgram program;
713     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
714 
715     GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockName1.f1");
716     EXPECT_GL_NO_ERROR();
717     EXPECT_NE(GL_INVALID_INDEX, index);
718 
719     GLchar name[64];
720     GLsizei length;
721     glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
722     EXPECT_GL_NO_ERROR();
723     EXPECT_EQ(13, length);
724     EXPECT_EQ("blockName1.f1", std::string(name));
725 
726     GLenum props[]         = {GL_ARRAY_SIZE,
727                               GL_ARRAY_STRIDE,
728                               GL_BLOCK_INDEX,
729                               GL_IS_ROW_MAJOR,
730                               GL_MATRIX_STRIDE,
731                               GL_NAME_LENGTH,
732                               GL_OFFSET,
733                               GL_REFERENCED_BY_VERTEX_SHADER,
734                               GL_REFERENCED_BY_FRAGMENT_SHADER,
735                               GL_REFERENCED_BY_COMPUTE_SHADER,
736                               GL_TOP_LEVEL_ARRAY_SIZE,
737                               GL_TOP_LEVEL_ARRAY_STRIDE,
738                               GL_TYPE};
739     GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
740     constexpr int kBufSize = 256;
741     GLint params[kBufSize];
742 
743     glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
744                            params);
745     EXPECT_GL_NO_ERROR();
746     EXPECT_EQ(propCount, length);
747     EXPECT_EQ(1, params[0]);   // array_size
748     EXPECT_LE(0, params[1]);   // array_stride
749     EXPECT_LE(0, params[2]);   // block_index
750     EXPECT_EQ(0, params[3]);   // is_row_major
751     EXPECT_EQ(0, params[4]);   // matrix_stride
752     EXPECT_EQ(14, params[5]);  // name_length
753     EXPECT_LE(0, params[6]);   // offset
754 
755     EXPECT_EQ(1, params[7]);  // referenced_by_vertex_shader
756     EXPECT_EQ(1, params[8]);  // referenced_by_fragment_shader
757     EXPECT_EQ(0, params[9]);  // referenced_by_compute_shader
758 
759     EXPECT_EQ(1, params[10]);  // top_level_array_size
760     EXPECT_LE(0, params[11]);  // top_level_array_stride
761 
762     EXPECT_EQ(GL_FLOAT, params[12]);  // type
763 
764     index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "s1[0].a");
765     EXPECT_GL_NO_ERROR();
766     EXPECT_NE(GL_INVALID_INDEX, index);
767 
768     glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
769     EXPECT_GL_NO_ERROR();
770     EXPECT_EQ(7, length);
771     EXPECT_EQ("s1[0].a", std::string(name));
772 
773     glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
774                            params);
775     EXPECT_GL_NO_ERROR();
776     EXPECT_EQ(propCount, length);
777     EXPECT_EQ(1, params[0]);  // array_size
778     EXPECT_LE(0, params[1]);  // array_stride
779     EXPECT_LE(0, params[2]);  // block_index
780     EXPECT_EQ(0, params[3]);  // is_row_major
781     EXPECT_EQ(0, params[4]);  // matrix_stride
782     EXPECT_EQ(8, params[5]);  // name_length
783     EXPECT_LE(0, params[6]);  // offset
784 
785     EXPECT_EQ(1, params[7]);  // referenced_by_vertex_shader
786     EXPECT_EQ(0, params[8]);  // referenced_by_fragment_shader
787     EXPECT_EQ(0, params[9]);  // referenced_by_compute_shader
788 
789     EXPECT_EQ(2, params[10]);   // top_level_array_size
790     EXPECT_EQ(80, params[11]);  // top_level_array_stride
791 
792     EXPECT_EQ(GL_FLOAT_VEC3, params[12]);  // type
793 }
794 
795 // Tests the resource property querying for buffer variable in std430 SSBO works correctly.
TEST_P(ProgramInterfaceTestES31,GetStd430BufferVariableProperties)796 TEST_P(ProgramInterfaceTestES31, GetStd430BufferVariableProperties)
797 {
798     ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
799 
800     constexpr char kComputeShaderSource[] =
801         R"(#version 310 es
802 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
803 struct S
804 {
805     uvec2 v;
806     mat2 m;
807 };
808 layout(std430, binding = 0) buffer blockIn {
809     uint u;
810     uint a[2];
811     S s;
812 } instanceIn;
813 layout(std430, binding = 1) buffer blockOut {
814     uint u;
815     uint a[2];
816     S s;
817 } instanceOut;
818 void main()
819 {
820     instanceOut.u = instanceIn.u;
821     instanceOut.a[0] = instanceIn.a[0];
822     instanceOut.a[1] = instanceIn.a[1];
823     instanceOut.s.v = instanceIn.s.v;
824     instanceOut.s.m = instanceIn.s.m;
825 }
826 )";
827 
828     GLProgram program;
829     createComputeProgram(program, kComputeShaderSource, std::get<1>(GetParam()));
830 
831     GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockIn.a");
832     EXPECT_GL_NO_ERROR();
833     EXPECT_NE(GL_INVALID_INDEX, index);
834 
835     GLchar name[64];
836     GLsizei length;
837     glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
838     EXPECT_GL_NO_ERROR();
839     EXPECT_EQ(12, length);
840     EXPECT_EQ("blockIn.a[0]", std::string(name));
841 
842     GLenum props[]         = {GL_ARRAY_SIZE,
843                               GL_ARRAY_STRIDE,
844                               GL_BLOCK_INDEX,
845                               GL_IS_ROW_MAJOR,
846                               GL_MATRIX_STRIDE,
847                               GL_NAME_LENGTH,
848                               GL_OFFSET,
849                               GL_REFERENCED_BY_VERTEX_SHADER,
850                               GL_REFERENCED_BY_FRAGMENT_SHADER,
851                               GL_REFERENCED_BY_COMPUTE_SHADER,
852                               GL_TOP_LEVEL_ARRAY_SIZE,
853                               GL_TOP_LEVEL_ARRAY_STRIDE,
854                               GL_TYPE};
855     GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
856     constexpr int kBufSize = 256;
857     GLint params[kBufSize];
858 
859     glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
860                            params);
861     EXPECT_GL_NO_ERROR();
862     EXPECT_EQ(propCount, length);
863     EXPECT_EQ(2, params[0]);   // array_size
864     EXPECT_LE(4, params[1]);   // array_stride
865     EXPECT_LE(0, params[2]);   // block_index
866     EXPECT_EQ(0, params[3]);   // is_row_major
867     EXPECT_EQ(0, params[4]);   // matrix_stride
868     EXPECT_EQ(13, params[5]);  // name_length
869     EXPECT_EQ(4, params[6]);   // offset
870 
871     EXPECT_EQ(0, params[7]);  // referenced_by_vertex_shader
872     EXPECT_EQ(0, params[8]);  // referenced_by_fragment_shader
873     EXPECT_EQ(1, params[9]);  // referenced_by_compute_shader
874 
875     EXPECT_EQ(1, params[10]);                // top_level_array_size
876     EXPECT_EQ(0, params[11]);                // top_level_array_stride
877     EXPECT_EQ(GL_UNSIGNED_INT, params[12]);  // type
878 
879     index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockIn.s.m");
880     EXPECT_GL_NO_ERROR();
881     EXPECT_NE(GL_INVALID_INDEX, index);
882 
883     glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
884     EXPECT_GL_NO_ERROR();
885     EXPECT_EQ(11, length);
886     EXPECT_EQ("blockIn.s.m", std::string(name));
887 
888     glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
889                            params);
890     EXPECT_GL_NO_ERROR();
891     EXPECT_EQ(propCount, length);
892     EXPECT_EQ(1, params[0]);   // array_size
893     EXPECT_LE(0, params[1]);   // array_stride
894     EXPECT_LE(0, params[2]);   // block_index
895     EXPECT_EQ(0, params[3]);   // is_row_major
896     EXPECT_EQ(8, params[4]);   // matrix_stride
897     EXPECT_EQ(12, params[5]);  // name_length
898     EXPECT_EQ(24, params[6]);  // offset
899 
900     EXPECT_EQ(0, params[7]);  // referenced_by_vertex_shader
901     EXPECT_EQ(0, params[8]);  // referenced_by_fragment_shader
902     // TODO([email protected]): referenced_by_compute_shader is not
903     // correctly handled. http://anglebug.com/42260711.
904     // EXPECT_EQ(1, params[9]);   // referenced_by_compute_shader
905 
906     EXPECT_EQ(1, params[10]);              // top_level_array_size
907     EXPECT_EQ(0, params[11]);              // top_level_array_stride
908     EXPECT_EQ(GL_FLOAT_MAT2, params[12]);  // type
909 }
910 
911 // Test that TOP_LEVEL_ARRAY_STRIDE for buffer variable with aggregate type works correctly.
TEST_P(ProgramInterfaceTestES31,TopLevelArrayStrideWithAggregateType)912 TEST_P(ProgramInterfaceTestES31, TopLevelArrayStrideWithAggregateType)
913 {
914     constexpr char kComputeShaderSource[] =
915         R"(#version 310 es
916 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
917 struct S
918 {
919     uvec2 v;
920     mat2 m;
921 };
922 layout(std430, binding = 0) buffer blockIn {
923     uint u;
924     uint a[2];
925     S s;
926 } instanceIn;
927 layout(std430, binding = 1) buffer blockOut {
928     uint u;
929     uint a[4][3];
930     S s[3][2];
931 } instanceOut;
932 void main()
933 {
934     instanceOut.u = instanceIn.u;
935     instanceOut.a[0][0] = instanceIn.a[0];
936     instanceOut.a[0][1] = instanceIn.a[1];
937     instanceOut.s[0][0].v = instanceIn.s.v;
938     instanceOut.s[0][0].m = instanceIn.s.m;
939 }
940 )";
941 
942     GLProgram program;
943     createComputeProgram(program, kComputeShaderSource, std::get<1>(GetParam()));
944 
945     GLuint index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockOut.s[0][0].m");
946     EXPECT_GL_NO_ERROR();
947     EXPECT_NE(GL_INVALID_INDEX, index);
948 
949     GLchar name[64];
950     GLsizei length;
951     glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
952     EXPECT_GL_NO_ERROR();
953     EXPECT_EQ(18, length);
954     EXPECT_EQ("blockOut.s[0][0].m", std::string(name));
955 
956     GLenum props[]         = {GL_ARRAY_SIZE,
957                               GL_ARRAY_STRIDE,
958                               GL_BLOCK_INDEX,
959                               GL_IS_ROW_MAJOR,
960                               GL_MATRIX_STRIDE,
961                               GL_NAME_LENGTH,
962                               GL_OFFSET,
963                               GL_REFERENCED_BY_VERTEX_SHADER,
964                               GL_REFERENCED_BY_FRAGMENT_SHADER,
965                               GL_REFERENCED_BY_COMPUTE_SHADER,
966                               GL_TOP_LEVEL_ARRAY_SIZE,
967                               GL_TOP_LEVEL_ARRAY_STRIDE,
968                               GL_TYPE};
969     GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
970     constexpr int kBufSize = 256;
971     GLint params[kBufSize];
972     glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
973                            params);
974     EXPECT_GL_NO_ERROR();
975     EXPECT_EQ(propCount, length);
976     EXPECT_EQ(1, params[0]);   // array_size
977     EXPECT_LE(0, params[1]);   // array_stride
978     EXPECT_LE(0, params[2]);   // block_index
979     EXPECT_EQ(0, params[3]);   // is_row_major
980     EXPECT_EQ(8, params[4]);   // matrix_stride
981     EXPECT_EQ(19, params[5]);  // name_length
982     EXPECT_EQ(64, params[6]);  // offset
983 
984     EXPECT_EQ(0, params[7]);  // referenced_by_vertex_shader
985     EXPECT_EQ(0, params[8]);  // referenced_by_fragment_shader
986     // TODO([email protected]): referenced_by_compute_shader is not
987     // correctly handled. http://anglebug.com/42260711.
988     // EXPECT_EQ(1, params[9]);   // referenced_by_compute_shader
989     EXPECT_EQ(3, params[10]);              // top_level_array_size
990     EXPECT_EQ(48, params[11]);             // top_level_array_stride
991     EXPECT_EQ(GL_FLOAT_MAT2, params[12]);  // type
992 
993     index = glGetProgramResourceIndex(program, GL_BUFFER_VARIABLE, "blockOut.a[0][0]");
994     EXPECT_GL_NO_ERROR();
995     EXPECT_NE(GL_INVALID_INDEX, index);
996 
997     glGetProgramResourceName(program, GL_BUFFER_VARIABLE, index, sizeof(name), &length, name);
998     EXPECT_GL_NO_ERROR();
999     EXPECT_EQ(16, length);
1000     EXPECT_EQ("blockOut.a[0][0]", std::string(name));
1001 
1002     glGetProgramResourceiv(program, GL_BUFFER_VARIABLE, index, propCount, props, kBufSize, &length,
1003                            params);
1004     EXPECT_GL_NO_ERROR();
1005     EXPECT_EQ(propCount, length);
1006     EXPECT_EQ(3, params[0]);   // array_size
1007     EXPECT_LE(0, params[1]);   // array_stride
1008     EXPECT_LE(0, params[2]);   // block_index
1009     EXPECT_EQ(0, params[3]);   // is_row_major
1010     EXPECT_EQ(0, params[4]);   // matrix_stride
1011     EXPECT_EQ(17, params[5]);  // name_length
1012     EXPECT_EQ(4, params[6]);   // offset
1013 
1014     EXPECT_EQ(0, params[7]);                 // referenced_by_vertex_shader
1015     EXPECT_EQ(0, params[8]);                 // referenced_by_fragment_shader
1016     EXPECT_EQ(1, params[9]);                 // referenced_by_compute_shader
1017     EXPECT_EQ(4, params[10]);                // top_level_array_size
1018     EXPECT_EQ(12, params[11]);               // top_level_array_stride
1019     EXPECT_EQ(GL_UNSIGNED_INT, params[12]);  // type
1020 }
1021 
1022 // Tests the resource property query for shader storage block can be done correctly.
TEST_P(ProgramInterfaceTestES31,GetShaderStorageBlockProperties)1023 TEST_P(ProgramInterfaceTestES31, GetShaderStorageBlockProperties)
1024 {
1025     // TODO([email protected]): Don't skip this test once non-simple SSBO sentences are supported
1026     // on d3d backend. http://anglebug.com/40644618
1027     ANGLE_SKIP_TEST_IF(IsD3D11());
1028 
1029     // Check SSBO support
1030     GLint numSupported;
1031     glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &numSupported);
1032     EXPECT_GL_NO_ERROR();
1033     ANGLE_SKIP_TEST_IF(numSupported < 3);
1034 
1035     constexpr char kVS[] =
1036         "#version 310 es\n"
1037         "precision highp float;\n"
1038         "struct S {\n"
1039         "    vec3 a;\n"
1040         "    ivec2 b[4];\n"
1041         "};\n"
1042         "layout(std140) buffer blockName0 {\n"
1043         "    S s0;\n"
1044         "    vec2 v0;\n"
1045         "    S s1[2];\n"
1046         "    uint u0;\n"
1047         "};\n"
1048         "layout(binding = 1) buffer blockName1 {\n"
1049         "    uint u1[2];\n"
1050         "    float f1;\n"
1051         "} instanceName1[2];\n"
1052         "layout(binding = 2) buffer blockName2 {\n"
1053         "    uint u2;\n"
1054         "    float f2;\n"
1055         "};\n"
1056         "void main()\n"
1057         "{\n"
1058         "    gl_Position = vec4(instanceName1[0].f1, s1[0].a);\n"
1059         "}\n";
1060 
1061     constexpr char kFS[] =
1062         "#version 310 es\n"
1063         "precision highp float;\n"
1064         "uniform vec4 color;\n"
1065         "out vec4 oColor;\n"
1066         "void main()\n"
1067         "{\n"
1068         "    oColor = color;\n"
1069         "}";
1070 
1071     GLProgram program;
1072     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
1073 
1074     GLuint index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "blockName0");
1075     EXPECT_GL_NO_ERROR();
1076     EXPECT_NE(GL_INVALID_INDEX, index);
1077 
1078     GLchar name[64];
1079     GLsizei length;
1080     glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, index, sizeof(name), &length, name);
1081     EXPECT_GL_NO_ERROR();
1082     EXPECT_EQ(10, length);
1083     EXPECT_EQ("blockName0", std::string(name));
1084 
1085     GLenum props[]         = {GL_ACTIVE_VARIABLES,
1086                               GL_BUFFER_BINDING,
1087                               GL_NUM_ACTIVE_VARIABLES,
1088                               GL_BUFFER_DATA_SIZE,
1089                               GL_NAME_LENGTH,
1090                               GL_REFERENCED_BY_VERTEX_SHADER,
1091                               GL_REFERENCED_BY_FRAGMENT_SHADER,
1092                               GL_REFERENCED_BY_COMPUTE_SHADER};
1093     GLsizei propCount      = static_cast<GLsizei>(ArraySize(props));
1094     constexpr int kBufSize = 256;
1095     GLint params[kBufSize];
1096 
1097     glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, index, propCount, props, kBufSize,
1098                            &length, params);
1099     EXPECT_GL_NO_ERROR();
1100     EXPECT_EQ(13, length);
1101     EXPECT_LE(0, params[0]);   // active_variables s0.a
1102     EXPECT_LE(0, params[1]);   // active_variables s0.b
1103     EXPECT_LE(0, params[2]);   // active_variables v0
1104     EXPECT_LE(0, params[3]);   // active_variables s1[0].a
1105     EXPECT_LE(0, params[4]);   // active_variables s1[0].b
1106     EXPECT_LE(0, params[5]);   // active_variables u0
1107     EXPECT_EQ(0, params[6]);   // buffer_binding
1108     EXPECT_EQ(6, params[7]);   // num_active_variables
1109     EXPECT_LE(0, params[8]);   // buffer_data_size
1110     EXPECT_EQ(11, params[9]);  // name_length
1111 
1112     EXPECT_EQ(1, params[10]);  // referenced_by_vertex_shader
1113     EXPECT_EQ(0, params[11]);  // referenced_by_fragment_shader
1114     EXPECT_EQ(0, params[12]);  // referenced_by_compute_shader
1115 
1116     index = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "blockName1");
1117     EXPECT_GL_NO_ERROR();
1118     EXPECT_NE(GL_INVALID_INDEX, index);
1119 
1120     glGetProgramResourceName(program, GL_SHADER_STORAGE_BLOCK, index, sizeof(name), &length, name);
1121     EXPECT_GL_NO_ERROR();
1122     EXPECT_EQ(13, length);
1123     EXPECT_EQ("blockName1[0]", std::string(name));
1124 }
1125 
1126 // Tests querying the program resources of atomic counter buffers.
TEST_P(ProgramInterfaceTestES31,GetAtomicCounterProperties)1127 TEST_P(ProgramInterfaceTestES31, GetAtomicCounterProperties)
1128 {
1129     constexpr char kCSSource[] = R"(#version 310 es
1130 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1131 layout(binding = 0) uniform atomic_uint acbase;
1132 layout(binding = 0, offset = 8) uniform atomic_uint ac[1];
1133 layout(binding = 0) uniform atomic_uint ac2;
1134 
1135 void main()
1136 {
1137     atomicCounterIncrement(acbase);
1138     atomicCounterIncrement(ac[0]);
1139     atomicCounterIncrement(ac2);
1140 })";
1141 
1142     GLProgram program;
1143     createComputeProgram(program, kCSSource, std::get<1>(GetParam()));
1144 
1145     GLuint index = glGetProgramResourceIndex(program, GL_UNIFORM, "ac");
1146     EXPECT_GL_NO_ERROR();
1147     EXPECT_NE(GL_INVALID_INDEX, index);
1148 
1149     GLenum props[]    = {GL_ATOMIC_COUNTER_BUFFER_INDEX};
1150     GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
1151     GLint atomicIndex;
1152     GLsizei length;
1153 
1154     glGetProgramResourceiv(program, GL_UNIFORM, index, propCount, props, 1, &length, &atomicIndex);
1155     EXPECT_GL_NO_ERROR();
1156     EXPECT_EQ(1, length);
1157     EXPECT_LE(0, atomicIndex);
1158 
1159     GLenum atomicProps[] = {GL_ACTIVE_VARIABLES,
1160                             GL_BUFFER_BINDING,
1161                             GL_NUM_ACTIVE_VARIABLES,
1162                             GL_BUFFER_DATA_SIZE,
1163                             GL_REFERENCED_BY_VERTEX_SHADER,
1164                             GL_REFERENCED_BY_FRAGMENT_SHADER,
1165                             GL_REFERENCED_BY_COMPUTE_SHADER};
1166 
1167     GLsizei atomicPropsCount = static_cast<GLsizei>(ArraySize(atomicProps));
1168     constexpr int kBufSize   = 256;
1169     GLint params[kBufSize];
1170     GLsizei length2;
1171 
1172     glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, atomicIndex, atomicPropsCount,
1173                            atomicProps, kBufSize, &length2, params);
1174     EXPECT_GL_NO_ERROR();
1175     EXPECT_EQ(9, length2);
1176 
1177     EXPECT_LE(0, params[0]);   // active_variables acbase
1178     EXPECT_LE(0, params[1]);   // active_variables ac[1]
1179     EXPECT_LE(0, params[2]);   // active_variables ac2
1180     EXPECT_EQ(0, params[3]);   // buffer_binding
1181     EXPECT_EQ(3, params[4]);   // num_active_variables
1182     EXPECT_EQ(16, params[5]);  // buffer_data_size
1183 
1184     EXPECT_EQ(0, params[6]);  // referenced_by_vertex_shader
1185     EXPECT_EQ(0, params[7]);  // referenced_by_fragment_shader
1186     EXPECT_EQ(1, params[8]);  // referenced_by_compute_shader
1187 }
1188 
1189 // Tests transform feedback varying qeury works correctly.
TEST_P(ProgramInterfaceTestES31,QueryTransformFeedbackVarying)1190 TEST_P(ProgramInterfaceTestES31, QueryTransformFeedbackVarying)
1191 {
1192     constexpr char kVS[] = R"(#version 310 es
1193 in vec3 position;
1194 out float outSingleType;
1195 out vec2 outWholeArray[2];
1196 out vec3 outArrayElements[16];
1197 void main() {
1198     outSingleType = 0.0;
1199     outWholeArray[0] = vec2(position);
1200     outArrayElements[7] = vec3(0, 0, 0);
1201     outArrayElements[15] = position;
1202     gl_Position = vec4(position, 1);
1203 })";
1204 
1205     constexpr char kFS[] = R"(#version 310 es
1206 precision mediump float;
1207 out vec4 color;
1208 in float outSingleType;
1209 in vec2 outWholeArray[2];
1210 in vec3 outArrayElements[16];
1211 void main() {
1212     color = vec4(0);
1213 })";
1214 
1215     std::vector<std::string> tfVaryings;
1216     tfVaryings.push_back("outArrayElements[7]");
1217     tfVaryings.push_back("outArrayElements[15]");
1218     tfVaryings.push_back("outSingleType");
1219     tfVaryings.push_back("outWholeArray");
1220 
1221     GLuint program =
1222         CompileProgramWithTransformFeedback(kVS, kFS, tfVaryings, GL_INTERLEAVED_ATTRIBS);
1223     ASSERT_NE(0u, program);
1224 
1225     GLint num;
1226     glGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, &num);
1227     EXPECT_GL_NO_ERROR();
1228     EXPECT_EQ(4, num);
1229 
1230     glGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, &num);
1231     EXPECT_GL_NO_ERROR();
1232     EXPECT_EQ(21, num);  // outArrayElements[15]
1233 
1234     // GLES 3.10, Page 77:
1235     // For TRANSFORM_FEEDBACK_VARYING, the active resource list will use the variable order
1236     // specified in the most recent call to TransformFeedbackVaryings before the last call to
1237     // LinkProgram.
1238     GLuint index =
1239         glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outArrayElements[7]");
1240     EXPECT_GL_NO_ERROR();
1241     EXPECT_EQ(0u, index);
1242     index =
1243         glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outArrayElements[15]");
1244     EXPECT_GL_NO_ERROR();
1245     EXPECT_EQ(1u, index);
1246     index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outSingleType");
1247     EXPECT_GL_NO_ERROR();
1248     EXPECT_EQ(2u, index);
1249     index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outWholeArray");
1250     EXPECT_GL_NO_ERROR();
1251     EXPECT_EQ(3u, index);
1252 
1253     // GLES 3.10, Page 80:
1254     // For TRANSFORM_FEEDBACK_VARYING resources, name must match one of the variables to be captured
1255     // as specified by a previous call to TransformFeedbackVaryings. Otherwise, INVALID_INDEX is
1256     // returned.
1257     // If name does not match a resource as described above, the value INVALID_INDEX is returned,
1258     // but no GL error is generated.
1259     index = glGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, "outWholeArray[0]");
1260     EXPECT_GL_NO_ERROR();
1261     EXPECT_EQ(GL_INVALID_INDEX, index);
1262 
1263     GLenum props[]    = {GL_TYPE, GL_ARRAY_SIZE, GL_NAME_LENGTH};
1264     GLsizei propCount = static_cast<GLsizei>(ArraySize(props));
1265     GLint params[ArraySize(props)];
1266     GLsizei length = 0;
1267     // Query properties of 'outArrayElements[15]'.
1268     glGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, 1, propCount, props, propCount,
1269                            &length, params);
1270     EXPECT_GL_NO_ERROR();
1271     EXPECT_EQ(propCount, length);
1272     EXPECT_EQ(GL_FLOAT_VEC3, params[0]);  // type
1273     EXPECT_EQ(1, params[1]);              // array_size
1274     EXPECT_EQ(21, params[2]);             // name_length
1275 
1276     // Query properties of 'outWholeArray'.
1277     glGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, 3, propCount, props, propCount,
1278                            &length, params);
1279     EXPECT_GL_NO_ERROR();
1280     EXPECT_EQ(propCount, length);
1281     EXPECT_EQ(GL_FLOAT_VEC2, params[0]);  // type
1282     EXPECT_EQ(2, params[1]);              // array_size
1283     EXPECT_EQ(14, params[2]);             // name_length
1284 
1285     glDeleteProgram(program);
1286 }
1287 
1288 // Regression test for crash report in http://anglebug.com/42264603.
TEST_P(ProgramInterfaceTestES31,ReloadFromCacheShouldNotCrash)1289 TEST_P(ProgramInterfaceTestES31, ReloadFromCacheShouldNotCrash)
1290 {
1291     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_multi_draw"));
1292 
1293     // TODO([email protected]): Don't skip this test once non-simple SSBO sentences are supported
1294     // on d3d backend. http://anglebug.com/40644618
1295     ANGLE_SKIP_TEST_IF(IsD3D11());
1296 
1297     constexpr char kVS[] = R"(#version 310 es
1298 #extension GL_ANGLE_multi_draw : require
1299 precision highp int;
1300 precision highp float;
1301 layout(std140) buffer;
1302 struct TransformInfo
1303 {
1304     mat4 mvp;
1305 };
1306 layout(binding = 0) buffer pe_transforms
1307 {
1308     TransformInfo transforms[];
1309 };
1310 out vec2 texCoord;
1311 uniform int pe_base_draw_id;
1312 layout(location = 0) in vec3 pe_vertex;
1313 layout(location = 1) in vec3 pe_normal;
1314 layout(location = 2) in vec2 pe_tex_coord;
1315 void main()
1316 {
1317     vec4 v = vec4(pe_vertex, 1.0);
1318     texCoord = pe_tex_coord;
1319     gl_Position = transforms[(gl_DrawID + pe_base_draw_id)].mvp * v;
1320 })";
1321 
1322     constexpr char kFS[] = R"(#version 310 es
1323 #extension GL_ANGLE_multi_draw : require
1324 precision highp int;
1325 precision highp float;
1326 layout(std140) buffer;
1327 in vec2 texCoord;
1328 layout(binding = 0) uniform sampler2D pe_tex_main;
1329 out vec4 pe_frag_color;
1330 void main()
1331 {
1332     vec4 u = texture(pe_tex_main, texCoord);
1333     if(u.a < 0.05)
1334         discard;
1335     pe_frag_color = u;
1336 }
1337 )";
1338 
1339     GLProgram program;
1340     createGraphicsProgram(program, kVS, kFS, std::get<1>(GetParam()));
1341     EXPECT_GL_NO_ERROR();
1342 }
1343 
1344 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ProgramInterfaceTestES31);
1345 ANGLE_INSTANTIATE_TEST_COMBINE_1(ProgramInterfaceTestES31,
1346                                  ProgramInterfaceTestPrint,
1347                                  testing::Bool(),
1348                                  ANGLE_ALL_TEST_PLATFORMS_ES31);
1349 
1350 }  // anonymous namespace
1351