xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ComputeShaderTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 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 // ComputeShaderTest:
7 //   Compute shader specific tests.
8 
9 #include <vector>
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
18 class ComputeShaderTest : public ANGLETest<>
19 {
20   protected:
ComputeShaderTest()21     ComputeShaderTest() {}
22 
createMockOutputImage(GLuint texture,GLenum internalFormat,GLint width,GLint height)23     void createMockOutputImage(GLuint texture, GLenum internalFormat, GLint width, GLint height)
24     {
25         glBindTexture(GL_TEXTURE_2D, texture);
26         glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, width, height);
27         EXPECT_GL_NO_ERROR();
28 
29         glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);
30         EXPECT_GL_NO_ERROR();
31     }
32 
33     template <class T, GLint kWidth, GLint kHeight>
runSharedMemoryTest(const char * kCS,GLenum internalFormat,GLenum format,const std::array<T,kWidth * kHeight> & inputData,const std::array<T,kWidth * kHeight> & expectedValues)34     void runSharedMemoryTest(const char *kCS,
35                              GLenum internalFormat,
36                              GLenum format,
37                              const std::array<T, kWidth * kHeight> &inputData,
38                              const std::array<T, kWidth * kHeight> &expectedValues)
39     {
40         GLTexture texture[2];
41         GLFramebuffer framebuffer;
42 
43         glBindTexture(GL_TEXTURE_2D, texture[0]);
44         glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);
45         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format,
46                         inputData.data());
47         EXPECT_GL_NO_ERROR();
48 
49         constexpr T initData[kWidth * kHeight] = {};
50         glBindTexture(GL_TEXTURE_2D, texture[1]);
51         glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);
52         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format, initData);
53         EXPECT_GL_NO_ERROR();
54 
55         ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
56         glUseProgram(program);
57 
58         glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalFormat);
59         EXPECT_GL_NO_ERROR();
60 
61         glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);
62         EXPECT_GL_NO_ERROR();
63 
64         glDispatchCompute(1, 1, 1);
65         EXPECT_GL_NO_ERROR();
66 
67         glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
68 
69         T outputValues[kWidth * kHeight] = {};
70         glUseProgram(0);
71         glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
72 
73         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1],
74                                0);
75         EXPECT_GL_NO_ERROR();
76         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, format, outputValues);
77         EXPECT_GL_NO_ERROR();
78 
79         for (int i = 0; i < kWidth * kHeight; i++)
80         {
81             EXPECT_EQ(expectedValues[i], outputValues[i]);
82         }
83     }
84 };
85 
86 class ComputeShaderTestES3 : public ANGLETest<>
87 {
88   protected:
ComputeShaderTestES3()89     ComputeShaderTestES3() {}
90 };
91 
92 class WebGL2ComputeTest : public ComputeShaderTest
93 {
94   protected:
WebGL2ComputeTest()95     WebGL2ComputeTest() { setWebGLCompatibilityEnabled(true); }
96 };
97 
98 // link a simple compute program. It should be successful.
TEST_P(ComputeShaderTest,LinkComputeProgram)99 TEST_P(ComputeShaderTest, LinkComputeProgram)
100 {
101     constexpr char kCS[] = R"(#version 310 es
102 layout(local_size_x=1) in;
103 void main()
104 {
105 })";
106 
107     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
108 
109     EXPECT_GL_NO_ERROR();
110 }
111 
112 // Link a simple compute program. Then detach the shader and dispatch compute.
113 // It should be successful.
TEST_P(ComputeShaderTest,DetachShaderAfterLinkSuccess)114 TEST_P(ComputeShaderTest, DetachShaderAfterLinkSuccess)
115 {
116     constexpr char kCS[] = R"(#version 310 es
117 layout(local_size_x=1) in;
118 void main()
119 {
120 })";
121 
122     GLuint program = glCreateProgram();
123 
124     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
125     EXPECT_NE(0u, cs);
126 
127     glAttachShader(program, cs);
128     glDeleteShader(cs);
129 
130     glLinkProgram(program);
131     GLint linkStatus;
132     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
133     EXPECT_GL_TRUE(linkStatus);
134 
135     glDetachShader(program, cs);
136     EXPECT_GL_NO_ERROR();
137 
138     glUseProgram(program);
139     glDispatchCompute(8, 4, 2);
140     EXPECT_GL_NO_ERROR();
141 }
142 
143 // link a simple compute program. There is no local size and linking should fail.
TEST_P(ComputeShaderTest,LinkComputeProgramNoLocalSizeLinkError)144 TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)
145 {
146     constexpr char kCS[] = R"(#version 310 es
147 void main()
148 {
149 })";
150 
151     GLuint program = CompileComputeProgram(kCS, false);
152     EXPECT_EQ(0u, program);
153 
154     glDeleteProgram(program);
155 
156     EXPECT_GL_NO_ERROR();
157 }
158 
159 // link a simple compute program.
160 // make sure that uniforms and uniform samplers get recorded
TEST_P(ComputeShaderTest,LinkComputeProgramWithUniforms)161 TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)
162 {
163     constexpr char kCS[] = R"(#version 310 es
164 precision mediump sampler2D;
165 layout(local_size_x=1) in;
166 uniform int myUniformInt;
167 uniform sampler2D myUniformSampler;
168 layout(rgba32i) uniform highp writeonly iimage2D imageOut;
169 void main()
170 {
171     int q = myUniformInt;
172     vec4 v = textureLod(myUniformSampler, vec2(0.0), 0.0);
173     imageStore(imageOut, ivec2(0), ivec4(v) * q);
174 })";
175 
176     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
177 
178     GLint uniformLoc = glGetUniformLocation(program, "myUniformInt");
179     EXPECT_NE(-1, uniformLoc);
180 
181     uniformLoc = glGetUniformLocation(program, "myUniformSampler");
182     EXPECT_NE(-1, uniformLoc);
183 
184     EXPECT_GL_NO_ERROR();
185 }
186 
187 // Attach both compute and non-compute shaders. A link time error should occur.
188 // OpenGL ES 3.10, 7.3 Program Objects
TEST_P(ComputeShaderTest,AttachMultipleShaders)189 TEST_P(ComputeShaderTest, AttachMultipleShaders)
190 {
191     constexpr char kCS[] = R"(#version 310 es
192 layout(local_size_x=1) in;
193 void main()
194 {
195 })";
196 
197     constexpr char kVS[] = R"(#version 310 es
198 void main()
199 {
200 })";
201 
202     constexpr char kFS[] = R"(#version 310 es
203 void main()
204 {
205 })";
206 
207     GLuint program = glCreateProgram();
208 
209     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
210     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
211     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
212 
213     EXPECT_NE(0u, vs);
214     EXPECT_NE(0u, fs);
215     EXPECT_NE(0u, cs);
216 
217     glAttachShader(program, vs);
218     glDeleteShader(vs);
219 
220     glAttachShader(program, fs);
221     glDeleteShader(fs);
222 
223     glAttachShader(program, cs);
224     glDeleteShader(cs);
225 
226     glLinkProgram(program);
227 
228     GLint linkStatus;
229     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
230 
231     EXPECT_GL_FALSE(linkStatus);
232 
233     EXPECT_GL_NO_ERROR();
234 }
235 
236 // Attach a vertex, fragment and compute shader.
237 // Query for the number of attached shaders and check the count.
TEST_P(ComputeShaderTest,AttachmentCount)238 TEST_P(ComputeShaderTest, AttachmentCount)
239 {
240     constexpr char kCS[] = R"(#version 310 es
241 layout(local_size_x=1) in;
242 void main()
243 {
244 })";
245 
246     constexpr char kVS[] = R"(#version 310 es
247 void main()
248 {
249 })";
250 
251     constexpr char kFS[] = R"(#version 310 es
252 void main()
253 {
254 })";
255 
256     GLuint program = glCreateProgram();
257 
258     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
259     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
260     GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
261 
262     EXPECT_NE(0u, vs);
263     EXPECT_NE(0u, fs);
264     EXPECT_NE(0u, cs);
265 
266     glAttachShader(program, vs);
267     glDeleteShader(vs);
268 
269     glAttachShader(program, fs);
270     glDeleteShader(fs);
271 
272     glAttachShader(program, cs);
273     glDeleteShader(cs);
274 
275     GLint numAttachedShaders;
276     glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
277 
278     EXPECT_EQ(3, numAttachedShaders);
279 
280     glDeleteProgram(program);
281 
282     EXPECT_GL_NO_ERROR();
283 }
284 
285 // Attach a compute shader and link, but start rendering.
TEST_P(ComputeShaderTest,StartRenderingWithComputeProgram)286 TEST_P(ComputeShaderTest, StartRenderingWithComputeProgram)
287 {
288     constexpr char kCS[] = R"(#version 310 es
289 layout(local_size_x=1) in;
290 void main()
291 {
292 })";
293 
294     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
295     EXPECT_GL_NO_ERROR();
296 
297     glUseProgram(program);
298     glDrawArrays(GL_POINTS, 0, 2);
299     EXPECT_GL_NO_ERROR();
300 }
301 
302 // Attach a vertex and fragment shader and link, but dispatch compute.
TEST_P(ComputeShaderTest,DispatchComputeWithRenderingProgram)303 TEST_P(ComputeShaderTest, DispatchComputeWithRenderingProgram)
304 {
305     constexpr char kVS[] = R"(#version 310 es
306 void main() {})";
307 
308     constexpr char kFS[] = R"(#version 310 es
309 void main() {})";
310 
311     GLuint program = glCreateProgram();
312 
313     GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
314     GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
315 
316     EXPECT_NE(0u, vs);
317     EXPECT_NE(0u, fs);
318 
319     glAttachShader(program, vs);
320     glDeleteShader(vs);
321 
322     glAttachShader(program, fs);
323     glDeleteShader(fs);
324 
325     glLinkProgram(program);
326 
327     GLint linkStatus;
328     glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
329     EXPECT_GL_TRUE(linkStatus);
330 
331     EXPECT_GL_NO_ERROR();
332 
333     glUseProgram(program);
334     glDispatchCompute(8, 4, 2);
335     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
336 }
337 
338 // Access all compute shader special variables.
TEST_P(ComputeShaderTest,AccessAllSpecialVariables)339 TEST_P(ComputeShaderTest, AccessAllSpecialVariables)
340 {
341     constexpr char kCS[] = R"(#version 310 es
342 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
343 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
344 void main()
345 {
346     uvec3 temp1 = gl_NumWorkGroups;
347     uvec3 temp2 = gl_WorkGroupSize;
348     uvec3 temp3 = gl_WorkGroupID;
349     uvec3 temp4 = gl_LocalInvocationID;
350     uvec3 temp5 = gl_GlobalInvocationID;
351     uint  temp6 = gl_LocalInvocationIndex;
352     imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));
353 })";
354 
355     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
356 }
357 
358 // Access part compute shader special variables.
TEST_P(ComputeShaderTest,AccessPartSpecialVariables)359 TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
360 {
361     constexpr char kCS[] = R"(#version 310 es
362 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
363 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
364 void main()
365 {
366     uvec3 temp1 = gl_WorkGroupSize;
367     uvec3 temp2 = gl_WorkGroupID;
368     uint  temp3 = gl_LocalInvocationIndex;
369     imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2, temp3));
370 })";
371 
372     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
373 }
374 
375 // Use glDispatchCompute to define work group count.
TEST_P(ComputeShaderTest,DispatchCompute)376 TEST_P(ComputeShaderTest, DispatchCompute)
377 {
378     constexpr char kCS[] = R"(#version 310 es
379 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
380 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
381 void main()
382 {
383     uvec3 temp = gl_NumWorkGroups;
384     imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));
385 })";
386 
387     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
388 
389     GLTexture texture;
390     createMockOutputImage(texture, GL_RGBA32UI, 4, 3);
391 
392     glUseProgram(program);
393     glDispatchCompute(8, 4, 2);
394     EXPECT_GL_NO_ERROR();
395 }
396 
397 // Binds a storage buffer to slot 0, then binds a storage image to slot 0, then buffer again.
TEST_P(ComputeShaderTest,BufferImageBuffer)398 TEST_P(ComputeShaderTest, BufferImageBuffer)
399 {
400     constexpr char kCS0[] = R"(#version 310 es
401 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
402 layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
403 void main()
404 {
405     atomicCounterIncrement(ac[0]);
406     atomicCounterDecrement(ac[1]);
407 })";
408 
409     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
410     glUseProgram(program0);
411 
412     unsigned int bufferData[3] = {11u, 4u, 4u};
413     GLBuffer atomicCounterBuffer;
414     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
415     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
416 
417     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
418 
419     glDispatchCompute(1, 1, 1);
420     EXPECT_GL_NO_ERROR();
421 
422     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
423     void *mappedBuffer =
424         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
425     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
426     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
427 
428     EXPECT_EQ(11u, bufferData[0]);
429     EXPECT_EQ(5u, bufferData[1]);
430     EXPECT_EQ(3u, bufferData[2]);
431 
432     constexpr char kCS1[] = R"(#version 310 es
433 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
434 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
435 void main()
436 {
437     uvec3 temp = gl_NumWorkGroups;
438     imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));
439 })";
440 
441     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
442 
443     GLTexture texture;
444     createMockOutputImage(texture, GL_RGBA32UI, 4, 3);
445 
446     glUseProgram(program1);
447     glDispatchCompute(8, 4, 2);
448 
449     glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
450     glUseProgram(program0);
451     glDispatchCompute(1, 1, 1);
452     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
453     mappedBuffer =
454         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
455     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
456     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
457 
458     EXPECT_EQ(11u, bufferData[0]);
459     EXPECT_EQ(6u, bufferData[1]);
460     EXPECT_EQ(2u, bufferData[2]);
461 
462     EXPECT_GL_NO_ERROR();
463 }
464 
465 // Test that the buffer written to by imageStore() in the CS does not race with writing to the
466 // buffer when it's mapped.
TEST_P(ComputeShaderTest,BufferImageBufferMapWrite)467 TEST_P(ComputeShaderTest, BufferImageBufferMapWrite)
468 {
469     constexpr char kCS0[] = R"(#version 310 es
470 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
471 layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
472 void main()
473 {
474     atomicCounterIncrement(ac[0]);
475     atomicCounterDecrement(ac[1]);
476 })";
477 
478     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
479     glUseProgram(program0);
480 
481     unsigned int expectedBufferData[3] = {11u, 4u, 4u};
482     unsigned int bufferData[3]         = {0};
483     memcpy(bufferData, expectedBufferData, sizeof(bufferData));
484 
485     GLBuffer atomicCounterBuffer;
486     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
487     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
488 
489     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
490 
491     glDispatchCompute(1, 1, 1);
492     EXPECT_GL_NO_ERROR();
493 
494     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
495     void *mappedBuffer =
496         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
497     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
498     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
499 
500     EXPECT_EQ(11u, bufferData[0]);
501     EXPECT_EQ(5u, bufferData[1]);
502     EXPECT_EQ(3u, bufferData[2]);
503 
504     constexpr char kCS1[] = R"(#version 310 es
505 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
506 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
507 void main()
508 {
509     uvec3 temp = gl_NumWorkGroups;
510     imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));
511 })";
512 
513     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
514 
515     GLTexture texture;
516     createMockOutputImage(texture, GL_RGBA32UI, 4, 3);
517 
518     glUseProgram(program1);
519     glDispatchCompute(8, 4, 2);
520 
521     glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
522     glUseProgram(program0);
523     glDispatchCompute(1, 1, 1);
524     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
525     mappedBuffer =
526         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_WRITE_BIT);
527 
528     memcpy(mappedBuffer, expectedBufferData, sizeof(expectedBufferData));
529     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
530 
531     // Force the CS imageStore() writes to the buffer to complete.
532     glFinish();
533     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
534 
535     mappedBuffer =
536         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
537     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
538     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
539 
540     EXPECT_EQ(expectedBufferData[0], bufferData[0]);
541     EXPECT_EQ(expectedBufferData[1], bufferData[1]);
542     EXPECT_EQ(expectedBufferData[2], bufferData[2]);
543 
544     EXPECT_GL_NO_ERROR();
545 }
546 
547 // Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.
TEST_P(ComputeShaderTest,ImageAtomicCounterBuffer)548 TEST_P(ComputeShaderTest, ImageAtomicCounterBuffer)
549 {
550     // Flaky hang. http://anglebug.com/40644695
551     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsDesktopOpenGL());
552 
553     constexpr char kCS0[] = R"(#version 310 es
554 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
555 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
556 void main()
557 {
558     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
559 0, 0));
560     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
561 0, 0));
562 })";
563 
564     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
565     glUseProgram(program0);
566     int width = 1, height = 1;
567     GLuint inputValues[] = {200};
568     GLTexture mTexture[2];
569     glBindTexture(GL_TEXTURE_2D, mTexture[0]);
570     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
571     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
572                     inputValues);
573 
574     glBindTexture(GL_TEXTURE_2D, mTexture[1]);
575     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
576     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
577                     inputValues);
578 
579     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
580     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
581 
582     glDispatchCompute(1, 1, 1);
583     EXPECT_GL_NO_ERROR();
584 
585     constexpr char kCS1[] = R"(#version 310 es
586 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
587 layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
588 void main()
589 {
590     atomicCounterIncrement(ac[0]);
591     atomicCounterDecrement(ac[1]);
592 })";
593 
594     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
595 
596     unsigned int bufferData[3] = {11u, 4u, 4u};
597     GLBuffer atomicCounterBuffer;
598     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
599     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
600 
601     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
602 
603     glUseProgram(program1);
604     glDispatchCompute(1, 1, 1);
605     EXPECT_GL_NO_ERROR();
606 
607     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
608     void *mappedBuffer =
609         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
610     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
611     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
612 
613     EXPECT_EQ(11u, bufferData[0]);
614     EXPECT_EQ(5u, bufferData[1]);
615     EXPECT_EQ(3u, bufferData[2]);
616 
617     EXPECT_GL_NO_ERROR();
618 }
619 
620 // Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.
TEST_P(ComputeShaderTest,ImageShaderStorageBuffer)621 TEST_P(ComputeShaderTest, ImageShaderStorageBuffer)
622 {
623     constexpr char kCS0[] = R"(#version 310 es
624 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
625 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
626 void main()
627 {
628     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
629 0, 0));
630     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
631 0, 0));
632 })";
633 
634     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
635     glUseProgram(program0);
636     int width = 1, height = 1;
637     GLuint inputValues[] = {200};
638     GLTexture mTexture[2];
639     glBindTexture(GL_TEXTURE_2D, mTexture[0]);
640     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
641     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
642                     inputValues);
643 
644     glBindTexture(GL_TEXTURE_2D, mTexture[1]);
645     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
646     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
647                     inputValues);
648 
649     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
650     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
651 
652     glDispatchCompute(1, 1, 1);
653     EXPECT_GL_NO_ERROR();
654 
655     constexpr char kCS1[] =
656         R"(#version 310 es
657  layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
658  layout(std140, binding = 0) buffer blockOut {
659      uvec2 data;
660  } instanceOut;
661  layout(std140, binding = 1) buffer blockIn {
662      uvec2 data;
663  } instanceIn;
664  void main()
665  {
666      instanceOut.data = instanceIn.data;
667  }
668  )";
669 
670     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
671 
672     constexpr unsigned int kBufferSize              = 2;
673     constexpr unsigned int kBufferData[kBufferSize] = {10, 20};
674 
675     GLBuffer blockIn;
676     glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockIn);
677     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
678     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, blockIn);
679 
680     GLBuffer blockOut;
681     glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);
682     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), nullptr, GL_STATIC_DRAW);
683     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, blockOut);
684 
685     glUseProgram(program1);
686     glDispatchCompute(1, 1, 1);
687     EXPECT_GL_NO_ERROR();
688 
689     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
690 
691     glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);
692     unsigned int bufferDataOut[kBufferSize] = {};
693     const GLColor *ptr                      = reinterpret_cast<GLColor *>(
694         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferData), GL_MAP_READ_BIT));
695     memcpy(bufferDataOut, ptr, sizeof(kBufferData));
696     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
697 
698     for (unsigned int index = 0; index < kBufferSize; ++index)
699     {
700         EXPECT_EQ(bufferDataOut[index], kBufferData[index]) << " index " << index;
701     }
702 }
703 
704 // Basic test for DispatchComputeIndirect.
TEST_P(ComputeShaderTest,DispatchComputeIndirect)705 TEST_P(ComputeShaderTest, DispatchComputeIndirect)
706 {
707     // Flaky crash on teardown, see http://anglebug.com/40096579
708     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
709 
710     const char kCSSource[] = R"(#version 310 es
711 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
712 layout(r32ui, binding = 0) uniform highp uimage2D uImage;
713 void main()
714 {
715     imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
716 })";
717 
718     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
719     glUseProgram(program);
720     const int kWidth = 4, kHeight = 6;
721     GLuint inputValues[kWidth][kHeight] = {};
722 
723     GLBuffer buffer;
724     glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
725     GLuint params[] = {kWidth, kHeight, 1};
726     glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(params), params, GL_STATIC_DRAW);
727 
728     GLTexture texture;
729     glBindTexture(GL_TEXTURE_2D, texture);
730     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
731     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
732                     inputValues);
733     EXPECT_GL_NO_ERROR();
734 
735     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
736     EXPECT_GL_NO_ERROR();
737 
738     glDispatchComputeIndirect(0);
739     EXPECT_GL_NO_ERROR();
740 
741     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
742 
743     GLuint outputValues[kWidth][kHeight];
744 
745     GLFramebuffer framebuffer;
746     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
747     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
748     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
749     EXPECT_GL_NO_ERROR();
750 
751     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
752     EXPECT_GL_NO_ERROR();
753 
754     constexpr GLuint kExpectedValue = 100u;
755     for (int x = 0; x < kWidth; x++)
756     {
757         for (int y = 0; y < kHeight; y++)
758         {
759             EXPECT_EQ(kExpectedValue, outputValues[x][y]);
760         }
761     }
762 }
763 
764 // Test that uploading data to buffer that's in use then using it as indirect buffer works.
TEST_P(ComputeShaderTest,UseAsUBOThenUpdateThenDispatchComputeIndirect)765 TEST_P(ComputeShaderTest, UseAsUBOThenUpdateThenDispatchComputeIndirect)
766 {
767     // Flaky crash on teardown, see http://anglebug.com/40096579
768     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
769 
770     constexpr GLsizei kWidth = 4, kHeight = 6;
771 
772     const std::array<uint32_t, 4> kInitialData = {1, 2, 3, 4};
773     const std::array<uint32_t, 4> kUpdateData  = {kWidth, kHeight, 1, 0};
774 
775     GLBuffer buffer;
776     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
777     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
778     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
779     EXPECT_GL_NO_ERROR();
780 
781     constexpr char kVerifyUBO[] = R"(#version 310 es
782 precision mediump float;
783 layout(binding = 0) uniform block {
784     uvec4 data;
785 } ubo;
786 out vec4 colorOut;
787 void main()
788 {
789     if (all(equal(ubo.data, uvec4(1, 2, 3, 4))))
790         colorOut = vec4(0, 1.0, 0, 1.0);
791     else
792         colorOut = vec4(1.0, 0, 0, 1.0);
793 })";
794 
795     ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
796     drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
797     EXPECT_GL_NO_ERROR();
798 
799     // Update buffer data
800     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
801     EXPECT_GL_NO_ERROR();
802 
803     const char kCS[] = R"(#version 310 es
804 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
805 layout(r32ui, binding = 0) uniform highp uimage2D uImage;
806 void main()
807 {
808     imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
809 })";
810 
811     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
812     glUseProgram(program);
813 
814     glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
815 
816     const std::vector<GLuint> inputValues(kWidth * kHeight, 0);
817 
818     GLTexture texture;
819     glBindTexture(GL_TEXTURE_2D, texture);
820     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
821     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
822                     inputValues.data());
823     EXPECT_GL_NO_ERROR();
824 
825     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
826     EXPECT_GL_NO_ERROR();
827 
828     glDispatchComputeIndirect(0);
829     EXPECT_GL_NO_ERROR();
830 
831     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
832 
833     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
834 
835     GLuint outputValues[kWidth][kHeight];
836 
837     GLFramebuffer framebuffer;
838     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
839     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
840     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
841     EXPECT_GL_NO_ERROR();
842 
843     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
844     EXPECT_GL_NO_ERROR();
845 
846     constexpr GLuint kExpectedValue = 100u;
847     for (int x = 0; x < kWidth; x++)
848     {
849         for (int y = 0; y < kHeight; y++)
850         {
851             EXPECT_EQ(kExpectedValue, outputValues[x][y]);
852         }
853     }
854 }
855 
856 // Use image uniform to write texture in compute shader, and verify the content is expected.
TEST_P(ComputeShaderTest,BindImageTexture)857 TEST_P(ComputeShaderTest, BindImageTexture)
858 {
859     GLTexture mTexture[2];
860     GLFramebuffer mFramebuffer;
861     constexpr char kCS[] = R"(#version 310 es
862 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
863 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
864 void main()
865 {
866     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
867 0, 0));
868     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
869 0, 0));
870 })";
871 
872     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
873     glUseProgram(program);
874     int width = 1, height = 1;
875     GLuint inputValues[] = {200};
876 
877     glBindTexture(GL_TEXTURE_2D, mTexture[0]);
878     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
879     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
880                     inputValues);
881     EXPECT_GL_NO_ERROR();
882 
883     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
884     EXPECT_GL_NO_ERROR();
885 
886     glBindTexture(GL_TEXTURE_2D, mTexture[1]);
887     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
888     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
889                     inputValues);
890     EXPECT_GL_NO_ERROR();
891 
892     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
893     EXPECT_GL_NO_ERROR();
894 
895     glDispatchCompute(1, 1, 1);
896     EXPECT_GL_NO_ERROR();
897 
898     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
899     glUseProgram(0);
900     GLuint outputValues[2][1];
901     GLuint expectedValue = 100;
902     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
903 
904     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
905                            0);
906     EXPECT_GL_NO_ERROR();
907     glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
908     EXPECT_GL_NO_ERROR();
909 
910     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
911                            0);
912     EXPECT_GL_NO_ERROR();
913     glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
914     EXPECT_GL_NO_ERROR();
915 
916     for (int i = 0; i < width * height; i++)
917     {
918         EXPECT_EQ(expectedValue, outputValues[0][i]);
919         EXPECT_EQ(expectedValue, outputValues[1][i]);
920     }
921 }
922 
923 // Test that binding a 2D slice of a 3D texture works with compute shader
TEST_P(ComputeShaderTest,BindImageTexture3D)924 TEST_P(ComputeShaderTest, BindImageTexture3D)
925 {
926     GLTexture mTexture[2];
927     GLFramebuffer mFramebuffer;
928     constexpr char kCS[] = R"(#version 310 es
929 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
930 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
931 void main()
932 {
933     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
934 0, 0));
935     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
936 0, 0));
937 })";
938 
939     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
940     glUseProgram(program);
941     int width = 1, height = 1, depth = 1;
942     GLuint inputValues[] = {200};
943 
944     glBindTexture(GL_TEXTURE_3D, mTexture[0]);
945     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, width, height, depth);
946     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, width, height, depth, GL_RED_INTEGER,
947                     GL_UNSIGNED_INT, inputValues);
948     EXPECT_GL_NO_ERROR();
949 
950     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
951     EXPECT_GL_NO_ERROR();
952 
953     glBindTexture(GL_TEXTURE_3D, mTexture[1]);
954     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, width, height, depth);
955     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, width, height, depth, GL_RED_INTEGER,
956                     GL_UNSIGNED_INT, inputValues);
957     EXPECT_GL_NO_ERROR();
958 
959     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
960     EXPECT_GL_NO_ERROR();
961 
962     glDispatchCompute(1, 1, 1);
963     EXPECT_GL_NO_ERROR();
964 
965     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
966     glUseProgram(0);
967     GLuint outputValues[2][1];
968     GLuint expectedValue = 100;
969     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
970 
971     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture[0], 0, 0);
972     EXPECT_GL_NO_ERROR();
973     glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
974     EXPECT_GL_NO_ERROR();
975 
976     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture[1], 0, 0);
977     EXPECT_GL_NO_ERROR();
978     glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
979     EXPECT_GL_NO_ERROR();
980 
981     for (int i = 0; i < width * height; i++)
982     {
983         EXPECT_EQ(expectedValue, outputValues[0][i]);
984         EXPECT_EQ(expectedValue, outputValues[1][i]);
985     }
986 }
987 
988 // When declare a image array without a binding qualifier, all elements are bound to unit zero.
TEST_P(ComputeShaderTest,ImageArrayWithoutBindingQualifier)989 TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
990 {
991     ANGLE_SKIP_TEST_IF(IsD3D11());
992 
993     // TODO([email protected]): On AMD desktop OpenGL, bind two image variables to unit 0,
994     // only one variable is valid.
995     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
996 
997     GLTexture mTexture;
998     GLFramebuffer mFramebuffer;
999     constexpr char kCS[] = R"(#version 310 es
1000 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1001 layout(r32ui) writeonly uniform highp uimage2D uImage[2];
1002 void main()
1003 {
1004     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
1005     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
1006 })";
1007 
1008     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1009     glUseProgram(program);
1010     constexpr int kTextureWidth = 1, kTextureHeight = 2;
1011     GLuint inputValues[] = {200, 200};
1012 
1013     glBindTexture(GL_TEXTURE_2D, mTexture);
1014     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
1015     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
1016                     GL_UNSIGNED_INT, inputValues);
1017     EXPECT_GL_NO_ERROR();
1018 
1019     glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1020     glDispatchCompute(1, 1, 1);
1021     EXPECT_GL_NO_ERROR();
1022 
1023     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1024     glUseProgram(0);
1025     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
1026 
1027     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
1028     GLuint outputValues[kTextureWidth * kTextureHeight];
1029     glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1030                  outputValues);
1031     EXPECT_GL_NO_ERROR();
1032 
1033     GLuint expectedValue = 100;
1034     for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
1035     {
1036         EXPECT_EQ(expectedValue, outputValues[i]);
1037     }
1038 }
1039 
1040 // When an image array is declared without a binding qualifier, all elements are bound to unit zero.
1041 // Check that the unused uniform image array element does not cause any corruption. Checks for a bug
1042 // where unused element could make the whole array seem as unused.
TEST_P(ComputeShaderTest,ImageArrayUnusedElement)1043 TEST_P(ComputeShaderTest, ImageArrayUnusedElement)
1044 {
1045     ANGLE_SKIP_TEST_IF(IsD3D11());
1046 
1047     // TODO([email protected]): On AMD desktop OpenGL, bind two image variables to unit 0,
1048     // only one variable is valid.
1049     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
1050 
1051     // Vulkan is currently unable to handle unbound image units in compute shaders.
1052     // http://anglebug.com/42263596
1053     ANGLE_SKIP_TEST_IF(IsVulkan());
1054 
1055     GLFramebuffer framebuffer;
1056     constexpr char kCS[] = R"(#version 310 es
1057 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1058 layout(r32ui, binding=0) writeonly uniform highp uimage2D uOut;
1059 layout(r32ui, binding=1) readonly uniform highp uimage2D uIn[2];
1060 
1061 void main()
1062 {
1063     uvec4 inValue = imageLoad(uIn[0], ivec2(gl_LocalInvocationID.xy));
1064     imageStore(uOut, ivec2(gl_LocalInvocationIndex, 0), inValue);
1065     imageStore(uOut, ivec2(gl_LocalInvocationIndex, 1), inValue);
1066 })";
1067 
1068     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1069     glUseProgram(program);
1070     constexpr int kTextureWidth = 1, kTextureHeight = 2;
1071     GLuint inputValues[] = {100, 100};
1072     GLTexture in;
1073     glBindTexture(GL_TEXTURE_2D, in);
1074     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
1075     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
1076                     GL_UNSIGNED_INT, inputValues);
1077     EXPECT_GL_NO_ERROR();
1078     glBindImageTexture(1, in, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1079 
1080     GLuint initValues[] = {111, 111};
1081     GLTexture out;
1082     glBindTexture(GL_TEXTURE_2D, out);
1083     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
1084     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
1085                     GL_UNSIGNED_INT, initValues);
1086     EXPECT_GL_NO_ERROR();
1087 
1088     glBindImageTexture(0, out, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1089     glDispatchCompute(1, 1, 1);
1090     EXPECT_GL_NO_ERROR();
1091 
1092     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1093     glUseProgram(0);
1094     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1095 
1096     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, out, 0);
1097     GLuint outputValues[kTextureWidth * kTextureHeight];
1098     glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1099                  outputValues);
1100     EXPECT_GL_NO_ERROR();
1101 
1102     GLuint expectedValue = 100;
1103     for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
1104     {
1105         EXPECT_EQ(expectedValue, outputValues[i]);
1106     }
1107 }
1108 // imageLoad functions
TEST_P(ComputeShaderTest,ImageLoad)1109 TEST_P(ComputeShaderTest, ImageLoad)
1110 {
1111     constexpr char kCS[] = R"(#version 310 es
1112 layout(local_size_x=8) in;
1113 layout(rgba8) uniform highp readonly image2D mImage2DInput;
1114 layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
1115 layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
1116 layout(r32i) uniform highp writeonly iimage2D imageOut;
1117 void main()
1118 {
1119     vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
1120     ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
1121     uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
1122     imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
1123 })";
1124 
1125     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1126     EXPECT_GL_NO_ERROR();
1127 }
1128 
1129 // imageStore functions
TEST_P(ComputeShaderTest,ImageStore)1130 TEST_P(ComputeShaderTest, ImageStore)
1131 {
1132     constexpr char kCS[] = R"(#version 310 es
1133 layout(local_size_x=8) in;
1134 layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
1135 layout(r32f) uniform highp writeonly image3D mImage3DOutput;
1136 layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
1137 void main()
1138 {
1139     imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
1140     imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
1141     imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
1142 })";
1143 
1144     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1145     EXPECT_GL_NO_ERROR();
1146 }
1147 
1148 // imageSize functions
TEST_P(ComputeShaderTest,ImageSize)1149 TEST_P(ComputeShaderTest, ImageSize)
1150 {
1151     constexpr char kCS[] = R"(#version 310 es
1152 layout(local_size_x=8) in;
1153 layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
1154 layout(r32i) uniform highp readonly iimage2D mImage2DInput;
1155 layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
1156 layout(r32i) uniform highp writeonly iimage2D imageOut;
1157 void main()
1158 {
1159     ivec2 sizeCube = imageSize(mImageCubeInput);
1160     ivec2 size2D = imageSize(mImage2DInput);
1161     ivec3 size2DArray = imageSize(mImage2DArrayInput);
1162     imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
1163 })";
1164 
1165     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1166     EXPECT_GL_NO_ERROR();
1167 }
1168 
1169 // Test that texelFetch works well in compute shader.
TEST_P(ComputeShaderTest,TexelFetchFunction)1170 TEST_P(ComputeShaderTest, TexelFetchFunction)
1171 {
1172     constexpr char kCS[] = R"(#version 310 es
1173 layout(local_size_x=16, local_size_y=12) in;
1174 precision highp usampler2D;
1175 uniform usampler2D tex;
1176 layout(std140, binding = 0) buffer buf {
1177     uint outData[12][16];
1178 };
1179 
1180 void main()
1181 {
1182     uint x = gl_LocalInvocationID.x;
1183     uint y = gl_LocalInvocationID.y;
1184     outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;
1185 })";
1186 
1187     constexpr unsigned int kWidth  = 16;
1188     constexpr unsigned int kHeight = 12;
1189     GLTexture tex;
1190     glBindTexture(GL_TEXTURE_2D, tex);
1191     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1192     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1193     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1194     GLuint texels[kHeight][kWidth] = {{0}};
1195     for (unsigned int y = 0; y < kHeight; ++y)
1196     {
1197         for (unsigned int x = 0; x < kWidth; ++x)
1198         {
1199             texels[y][x] = x + y * kWidth;
1200         }
1201     }
1202     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1203     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1204                     texels);
1205     glBindTexture(GL_TEXTURE_2D, 0);
1206 
1207     // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1208     constexpr unsigned int kArrayStride = 16;
1209     GLBuffer ssbo;
1210     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1211     glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
1212                  GL_STREAM_DRAW);
1213     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1214     EXPECT_GL_NO_ERROR();
1215 
1216     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1217     glUseProgram(program);
1218 
1219     glActiveTexture(GL_TEXTURE0);
1220     glBindTexture(GL_TEXTURE_2D, tex);
1221     glUniform1i(glGetUniformLocation(program, "tex"), 0);
1222     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1223     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
1224 
1225     glDispatchCompute(1, 1, 1);
1226 
1227     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1228 
1229     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1230     const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1231         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
1232     EXPECT_GL_NO_ERROR();
1233     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
1234     {
1235         EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));
1236     }
1237 }
1238 
1239 // Test that texture function works well in compute shader.
TEST_P(ComputeShaderTest,TextureFunction)1240 TEST_P(ComputeShaderTest, TextureFunction)
1241 {
1242     constexpr char kCS[] = R"(#version 310 es
1243 layout(local_size_x=16, local_size_y=16) in;
1244 precision highp usampler2D;
1245 uniform usampler2D tex;
1246 layout(std140, binding = 0) buffer buf {
1247     uint outData[16][16];
1248 };
1249 
1250 void main()
1251 {
1252     uint x = gl_LocalInvocationID.x;
1253     uint y = gl_LocalInvocationID.y;
1254     float xCoord = float(x) / float(16);
1255     float yCoord = float(y) / float(16);
1256     outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x;
1257 })";
1258 
1259     constexpr unsigned int kWidth  = 16;
1260     constexpr unsigned int kHeight = 16;
1261     GLTexture tex;
1262     glBindTexture(GL_TEXTURE_2D, tex);
1263     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1264     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1265     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1266     GLuint texels[kHeight][kWidth] = {{0}};
1267     for (unsigned int y = 0; y < kHeight; ++y)
1268     {
1269         for (unsigned int x = 0; x < kWidth; ++x)
1270         {
1271             texels[y][x] = x + y * kWidth;
1272         }
1273     }
1274     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1275     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1276                     texels);
1277     glBindTexture(GL_TEXTURE_2D, 0);
1278 
1279     // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1280     constexpr unsigned int kArrayStride = 16;
1281     GLBuffer ssbo;
1282     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1283     glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
1284                  GL_STREAM_DRAW);
1285     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1286     EXPECT_GL_NO_ERROR();
1287 
1288     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1289     glUseProgram(program);
1290 
1291     glActiveTexture(GL_TEXTURE0);
1292     glBindTexture(GL_TEXTURE_2D, tex);
1293     glUniform1i(glGetUniformLocation(program, "tex"), 0);
1294     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1295     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
1296 
1297     glDispatchCompute(1, 1, 1);
1298 
1299     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1300 
1301     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1302     const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1303         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
1304     EXPECT_GL_NO_ERROR();
1305     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
1306     {
1307         EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));
1308     }
1309 }
1310 
1311 // Test mixed use of sampler and image.
TEST_P(ComputeShaderTest,SamplingAndImageReadWrite)1312 TEST_P(ComputeShaderTest, SamplingAndImageReadWrite)
1313 {
1314     GLTexture texture[3];
1315     GLFramebuffer framebuffer;
1316     constexpr char kCS[] = R"(#version 310 es
1317 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1318 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1319 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1320 precision highp usampler2D;
1321 uniform usampler2D tex;
1322 void main()
1323 {
1324     uvec4 value_1 = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
1325     uvec4 value_2 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1326     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value_1 + value_2);
1327 })";
1328 
1329     constexpr int kWidth = 1, kHeight = 1;
1330     constexpr GLuint kInputValues[3][1] = {{50}, {100}, {20}};
1331 
1332     glBindTexture(GL_TEXTURE_2D, texture[0]);
1333     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1334     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1335                     kInputValues[0]);
1336     glBindTexture(GL_TEXTURE_2D, texture[2]);
1337     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1338     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1339                     kInputValues[2]);
1340     EXPECT_GL_NO_ERROR();
1341     glBindTexture(GL_TEXTURE_2D, 0);
1342 
1343     glBindTexture(GL_TEXTURE_2D, texture[1]);
1344     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1345     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1346     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1347     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1348     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1349                     kInputValues[1]);
1350 
1351     EXPECT_GL_NO_ERROR();
1352 
1353     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1354     glUseProgram(program);
1355 
1356     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1357     glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1358     EXPECT_GL_NO_ERROR();
1359 
1360     glDispatchCompute(1, 1, 1);
1361     EXPECT_GL_NO_ERROR();
1362 
1363     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1364     GLuint outputValues[kWidth * kHeight];
1365     constexpr GLuint expectedValue = 150;
1366     glUseProgram(0);
1367     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1368 
1369     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
1370     EXPECT_GL_NO_ERROR();
1371     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1372     EXPECT_GL_NO_ERROR();
1373 
1374     for (int i = 0; i < kWidth * kHeight; i++)
1375     {
1376         EXPECT_EQ(expectedValue, outputValues[i]);
1377     }
1378 }
1379 
1380 // Use image uniform to read and write Texture2D in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTexture2D)1381 TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
1382 {
1383     GLTexture texture[2];
1384     GLFramebuffer framebuffer;
1385     constexpr char kCS[] = R"(#version 310 es
1386 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1387 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1388 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1389 void main()
1390 {
1391     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1392     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1393 })";
1394 
1395     constexpr int kWidth = 1, kHeight = 1;
1396     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1397 
1398     glBindTexture(GL_TEXTURE_2D, texture[0]);
1399     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1400     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1401                     kInputValues[0]);
1402     EXPECT_GL_NO_ERROR();
1403 
1404     glBindTexture(GL_TEXTURE_2D, texture[1]);
1405     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1406     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1407                     kInputValues[1]);
1408     EXPECT_GL_NO_ERROR();
1409 
1410     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1411     glUseProgram(program);
1412 
1413     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1414     EXPECT_GL_NO_ERROR();
1415 
1416     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1417     EXPECT_GL_NO_ERROR();
1418 
1419     glDispatchCompute(1, 1, 1);
1420     EXPECT_GL_NO_ERROR();
1421 
1422     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1423     GLuint outputValues[kWidth * kHeight];
1424     constexpr GLuint expectedValue = 200;
1425     glUseProgram(0);
1426     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1427 
1428     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
1429     EXPECT_GL_NO_ERROR();
1430     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1431     EXPECT_GL_NO_ERROR();
1432 
1433     for (int i = 0; i < kWidth * kHeight; i++)
1434     {
1435         EXPECT_EQ(expectedValue, outputValues[i]);
1436     }
1437 }
1438 
1439 // Use image uniform to read and write Texture2D with non-zero base in compute shader, and verify
1440 // the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithNonZeroBaseTexture2D)1441 TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2D)
1442 {
1443     GLTexture texture[2];
1444     GLFramebuffer framebuffer;
1445     constexpr char kCS[] = R"(#version 310 es
1446 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1447 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1448 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1449 void main()
1450 {
1451     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1452     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1453 })";
1454 
1455     constexpr int kWidth = 1, kHeight = 1;
1456     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1457 
1458     glBindTexture(GL_TEXTURE_2D, texture[0]);
1459     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
1460     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1461                     kInputValues[0]);
1462     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1463     EXPECT_GL_NO_ERROR();
1464 
1465     glBindTexture(GL_TEXTURE_2D, texture[1]);
1466     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
1467     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1468                     kInputValues[1]);
1469     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1470     EXPECT_GL_NO_ERROR();
1471 
1472     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1473     glUseProgram(program);
1474 
1475     glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1476     EXPECT_GL_NO_ERROR();
1477 
1478     glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1479     EXPECT_GL_NO_ERROR();
1480 
1481     glDispatchCompute(1, 1, 1);
1482     EXPECT_GL_NO_ERROR();
1483 
1484     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1485     GLuint outputValues[kWidth * kHeight];
1486     constexpr GLuint expectedValue = 200;
1487     glUseProgram(0);
1488     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1489 
1490     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
1491     EXPECT_GL_NO_ERROR();
1492     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1493     EXPECT_GL_NO_ERROR();
1494 
1495     for (int i = 0; i < kWidth * kHeight; i++)
1496     {
1497         EXPECT_EQ(expectedValue, outputValues[i]) << "  at index: " << i;
1498     }
1499 }
1500 
1501 // Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTexture2DArray)1502 TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
1503 {
1504     GLTexture texture[2];
1505     GLFramebuffer framebuffer;
1506     constexpr char kCS[] = R"(#version 310 es
1507 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
1508 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
1509 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
1510 void main()
1511 {
1512     uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1513     imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1514 })";
1515 
1516     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1517     constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1518 
1519     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1520     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1521     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1522                     GL_UNSIGNED_INT, kInputValues[0]);
1523     EXPECT_GL_NO_ERROR();
1524 
1525     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1526     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1527     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1528                     GL_UNSIGNED_INT, kInputValues[1]);
1529     EXPECT_GL_NO_ERROR();
1530 
1531     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1532     glUseProgram(program);
1533 
1534     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1535     EXPECT_GL_NO_ERROR();
1536 
1537     glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1538     EXPECT_GL_NO_ERROR();
1539 
1540     glDispatchCompute(1, 1, 1);
1541     EXPECT_GL_NO_ERROR();
1542 
1543     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1544     GLuint outputValues[kWidth * kHeight];
1545     constexpr GLuint expectedValue = 200;
1546     glUseProgram(0);
1547     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1548 
1549     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1550     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1551     EXPECT_GL_NO_ERROR();
1552     glReadBuffer(GL_COLOR_ATTACHMENT0);
1553     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1554     EXPECT_GL_NO_ERROR();
1555     for (int i = 0; i < kWidth * kHeight; i++)
1556     {
1557         EXPECT_EQ(expectedValue, outputValues[i]);
1558     }
1559     glReadBuffer(GL_COLOR_ATTACHMENT1);
1560     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1561     EXPECT_GL_NO_ERROR();
1562     for (int i = 0; i < kWidth * kHeight; i++)
1563     {
1564         EXPECT_EQ(expectedValue, outputValues[i]);
1565     }
1566 }
1567 
1568 // Use image uniform to read and write Texture2DArray with non-zero base in compute shader, and
1569 // verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithNonZeroBaseTexture2DArray)1570 TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2DArray)
1571 {
1572     GLTexture texture[2];
1573     GLFramebuffer framebuffer;
1574     constexpr char kCS[] = R"(#version 310 es
1575 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
1576 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
1577 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
1578 void main()
1579 {
1580     uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1581     imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1582 })";
1583 
1584     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1585     constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1586 
1587     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1588     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
1589     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1590                     GL_UNSIGNED_INT, kInputValues[0]);
1591     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
1592     EXPECT_GL_NO_ERROR();
1593 
1594     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1595     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
1596     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1597                     GL_UNSIGNED_INT, kInputValues[1]);
1598     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
1599     EXPECT_GL_NO_ERROR();
1600 
1601     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1602     glUseProgram(program);
1603 
1604     glBindImageTexture(0, texture[0], 1, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1605     EXPECT_GL_NO_ERROR();
1606 
1607     glBindImageTexture(1, texture[1], 1, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1608     EXPECT_GL_NO_ERROR();
1609 
1610     glDispatchCompute(1, 1, 1);
1611     EXPECT_GL_NO_ERROR();
1612 
1613     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1614     GLuint outputValues[kWidth * kHeight];
1615     constexpr GLuint expectedValue = 200;
1616     glUseProgram(0);
1617     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1618 
1619     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 1, 0);
1620     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 1, 1);
1621     EXPECT_GL_NO_ERROR();
1622     glReadBuffer(GL_COLOR_ATTACHMENT0);
1623     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1624     EXPECT_GL_NO_ERROR();
1625     for (int i = 0; i < kWidth * kHeight; i++)
1626     {
1627         EXPECT_EQ(expectedValue, outputValues[i]);
1628     }
1629     glReadBuffer(GL_COLOR_ATTACHMENT1);
1630     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1631     EXPECT_GL_NO_ERROR();
1632     for (int i = 0; i < kWidth * kHeight; i++)
1633     {
1634         EXPECT_EQ(expectedValue, outputValues[i]);
1635     }
1636 }
1637 
1638 // Use image uniform to read and write Texture3D in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTexture3D)1639 TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
1640 {
1641     GLTexture texture[2];
1642     GLFramebuffer framebuffer;
1643     constexpr char kCS[] = R"(#version 310 es
1644 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
1645 layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
1646 layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
1647 void main()
1648 {
1649     uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1650     imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1651 })";
1652 
1653     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1654     constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1655 
1656     glBindTexture(GL_TEXTURE_3D, texture[0]);
1657     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1658     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1659                     GL_UNSIGNED_INT, kInputValues[0]);
1660     EXPECT_GL_NO_ERROR();
1661 
1662     glBindTexture(GL_TEXTURE_3D, texture[1]);
1663     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1664     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1665                     GL_UNSIGNED_INT, kInputValues[1]);
1666     EXPECT_GL_NO_ERROR();
1667 
1668     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1669     glUseProgram(program);
1670 
1671     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1672     EXPECT_GL_NO_ERROR();
1673 
1674     glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1675     EXPECT_GL_NO_ERROR();
1676 
1677     glDispatchCompute(1, 1, 1);
1678     EXPECT_GL_NO_ERROR();
1679 
1680     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1681     GLuint outputValues[kWidth * kHeight];
1682     constexpr GLuint expectedValue = 200;
1683     glUseProgram(0);
1684     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1685 
1686     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1687     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1688     EXPECT_GL_NO_ERROR();
1689     glReadBuffer(GL_COLOR_ATTACHMENT0);
1690     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1691     EXPECT_GL_NO_ERROR();
1692     for (int i = 0; i < kWidth * kHeight; i++)
1693     {
1694         EXPECT_EQ(expectedValue, outputValues[i]);
1695     }
1696     glReadBuffer(GL_COLOR_ATTACHMENT1);
1697     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1698     EXPECT_GL_NO_ERROR();
1699     for (int i = 0; i < kWidth * kHeight; i++)
1700     {
1701         EXPECT_EQ(expectedValue, outputValues[i]);
1702     }
1703 }
1704 
1705 // Use image uniform to read and write TextureCube in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTextureCube)1706 TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
1707 {
1708     GLTexture texture[2];
1709     GLFramebuffer framebuffer;
1710     constexpr char kCS[] = R"(#version 310 es
1711 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1712 layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
1713 layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
1714 void main()
1715 {
1716     for (int i = 0; i < 6; i++)
1717     {
1718         uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
1719         imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
1720     }
1721 })";
1722 
1723     constexpr int kWidth = 1, kHeight = 1;
1724     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1725 
1726     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1727     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1728     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1729          face++)
1730     {
1731         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1732                         kInputValues[0]);
1733     }
1734     EXPECT_GL_NO_ERROR();
1735 
1736     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1737     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1738     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1739          face++)
1740     {
1741         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1742                         kInputValues[1]);
1743     }
1744     EXPECT_GL_NO_ERROR();
1745 
1746     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1747     glUseProgram(program);
1748 
1749     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1750     EXPECT_GL_NO_ERROR();
1751 
1752     glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1753     EXPECT_GL_NO_ERROR();
1754 
1755     glDispatchCompute(1, 1, 1);
1756     EXPECT_GL_NO_ERROR();
1757 
1758     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1759     GLuint outputValues[kWidth * kHeight];
1760     constexpr GLuint expectedValue = 200;
1761     glUseProgram(0);
1762     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1763 
1764     for (GLenum face = 0; face < 6; face++)
1765     {
1766         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1767                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1768         EXPECT_GL_NO_ERROR();
1769         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1770         EXPECT_GL_NO_ERROR();
1771 
1772         for (int i = 0; i < kWidth * kHeight; i++)
1773         {
1774             EXPECT_EQ(expectedValue, outputValues[i]);
1775         }
1776     }
1777 }
1778 
1779 // Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
1780 // contents.
TEST_P(ComputeShaderTest,BindImageTextureWithOneLayerTexture2DArray)1781 TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
1782 {
1783     GLTexture texture[2];
1784     GLFramebuffer framebuffer;
1785     constexpr char kCS[] = R"(#version 310 es
1786 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1787 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1788 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1789 void main()
1790 {
1791     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1792     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1793 })";
1794 
1795     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1796     constexpr int kResultSize           = kWidth * kHeight;
1797     constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1798     constexpr GLuint expectedValue_1    = 200;
1799     constexpr GLuint expectedValue_2    = 100;
1800     GLuint outputValues[kResultSize];
1801 
1802     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1803     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1804     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1805                     GL_UNSIGNED_INT, kInputValues[0]);
1806     EXPECT_GL_NO_ERROR();
1807 
1808     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1809     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1810     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1811                     GL_UNSIGNED_INT, kInputValues[1]);
1812     EXPECT_GL_NO_ERROR();
1813 
1814     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1815     glUseProgram(program);
1816 
1817     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1818     EXPECT_GL_NO_ERROR();
1819     glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
1820     EXPECT_GL_NO_ERROR();
1821     glDispatchCompute(1, 1, 1);
1822     EXPECT_GL_NO_ERROR();
1823 
1824     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1825     glUseProgram(0);
1826     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1827     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1828     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1829     EXPECT_GL_NO_ERROR();
1830     glReadBuffer(GL_COLOR_ATTACHMENT0);
1831     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1832     EXPECT_GL_NO_ERROR();
1833     for (int i = 0; i < kResultSize; i++)
1834     {
1835         EXPECT_EQ(expectedValue_2, outputValues[i]);
1836     }
1837     glReadBuffer(GL_COLOR_ATTACHMENT1);
1838     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1839     EXPECT_GL_NO_ERROR();
1840     for (int i = 0; i < kResultSize; i++)
1841     {
1842         EXPECT_EQ(expectedValue_1, outputValues[i]);
1843     }
1844 }
1845 
1846 // Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
1847 // contents.
TEST_P(ComputeShaderTest,BindImageTextureWithOneLayerTexture3D)1848 TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
1849 {
1850     // Vulkan validation error creating a 2D image view of a 3D image layer.
1851     // http://anglebug.com/42262531
1852     ANGLE_SKIP_TEST_IF(IsVulkan());
1853 
1854     GLTexture texture[2];
1855     GLFramebuffer framebuffer;
1856     constexpr char kCS[] = R"(#version 310 es
1857 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1858 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1859 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1860 void main()
1861 {
1862     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1863     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1864 })";
1865 
1866     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1867     constexpr int kResultSize           = kWidth * kHeight;
1868     constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1869     constexpr GLuint expectedValue_1    = 150;
1870     constexpr GLuint expectedValue_2    = 50;
1871     GLuint outputValues[kResultSize];
1872 
1873     glBindTexture(GL_TEXTURE_3D, texture[0]);
1874     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1875     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1876                     GL_UNSIGNED_INT, kInputValues[0]);
1877     EXPECT_GL_NO_ERROR();
1878 
1879     glBindTexture(GL_TEXTURE_3D, texture[1]);
1880     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1881     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1882                     GL_UNSIGNED_INT, kInputValues[1]);
1883     EXPECT_GL_NO_ERROR();
1884 
1885     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1886     glUseProgram(program);
1887 
1888     glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1889     EXPECT_GL_NO_ERROR();
1890     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1891     EXPECT_GL_NO_ERROR();
1892     glDispatchCompute(1, 1, 1);
1893     EXPECT_GL_NO_ERROR();
1894 
1895     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1896     glUseProgram(0);
1897     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1898     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1899     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1900     EXPECT_GL_NO_ERROR();
1901     glReadBuffer(GL_COLOR_ATTACHMENT0);
1902     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1903     EXPECT_GL_NO_ERROR();
1904     for (int i = 0; i < kResultSize; i++)
1905     {
1906         EXPECT_EQ(expectedValue_1, outputValues[i]);
1907     }
1908     glReadBuffer(GL_COLOR_ATTACHMENT1);
1909     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1910     EXPECT_GL_NO_ERROR();
1911     for (int i = 0; i < kResultSize; i++)
1912     {
1913         EXPECT_EQ(expectedValue_2, outputValues[i]);
1914     }
1915 }
1916 
1917 // Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1918 // contents.
TEST_P(ComputeShaderTest,BindImageTextureWithOneLayerTextureCube)1919 TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1920 {
1921     // GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.
1922     // http://anglebug.com/42262394
1923     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());
1924 
1925     GLTexture texture[2];
1926     GLFramebuffer framebuffer;
1927     constexpr char kCS[] = R"(#version 310 es
1928 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1929 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1930 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1931 void main()
1932 {
1933     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1934     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1935 })";
1936 
1937     constexpr int kWidth = 1, kHeight = 1;
1938     constexpr int kResultSize           = kWidth * kHeight;
1939     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1940     constexpr GLuint expectedValue_1    = 200;
1941     constexpr GLuint expectedValue_2    = 100;
1942     GLuint outputValues[kResultSize];
1943 
1944     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1945     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1946     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1947          face++)
1948     {
1949         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1950                         kInputValues[0]);
1951     }
1952     EXPECT_GL_NO_ERROR();
1953 
1954     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1955     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1956     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1957          face++)
1958     {
1959         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1960                         kInputValues[1]);
1961     }
1962     EXPECT_GL_NO_ERROR();
1963 
1964     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1965     glUseProgram(program);
1966 
1967     glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1968     EXPECT_GL_NO_ERROR();
1969     glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1970     EXPECT_GL_NO_ERROR();
1971     glDispatchCompute(1, 1, 1);
1972     EXPECT_GL_NO_ERROR();
1973 
1974     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1975     glUseProgram(0);
1976     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1977 
1978     for (GLenum face = 0; face < 6; face++)
1979     {
1980         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1981                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1982         EXPECT_GL_NO_ERROR();
1983         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1984         EXPECT_GL_NO_ERROR();
1985 
1986         if (face == 4)
1987         {
1988             for (int i = 0; i < kResultSize; i++)
1989             {
1990                 EXPECT_EQ(expectedValue_1, outputValues[i]);
1991             }
1992         }
1993         else
1994         {
1995             for (int i = 0; i < kResultSize; i++)
1996             {
1997                 EXPECT_EQ(expectedValue_2, outputValues[i]);
1998             }
1999         }
2000     }
2001 }
2002 
2003 // Test to bind kinds of texture types, bind either the entire texture
2004 // level or a single layer or face of the face level.
TEST_P(ComputeShaderTest,BindImageTextureWithMixTextureTypes)2005 TEST_P(ComputeShaderTest, BindImageTextureWithMixTextureTypes)
2006 {
2007     // GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.
2008     // http://anglebug.com/42262394
2009     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());
2010 
2011     // http://anglebug.com/42263641
2012     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2013 
2014     GLTexture texture[4];
2015     GLFramebuffer framebuffer;
2016     const char csSource[] =
2017         R"(#version 310 es
2018         layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2019         layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2020         layout(r32ui, binding = 1) readonly uniform highp uimage2D uImage_2;
2021         layout(r32ui, binding = 2) readonly uniform highp uimage3D uImage_3;
2022         layout(r32ui, binding = 3) writeonly uniform highp uimage2D uImage_4;
2023         void main()
2024         {
2025             uvec4 value_1 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2026             uvec4 value_2 = imageLoad(uImage_2, ivec2(gl_LocalInvocationID.xy));
2027             uvec4 value_3 = imageLoad(uImage_3, ivec3(gl_LocalInvocationID.xyz));
2028             imageStore(uImage_4, ivec2(gl_LocalInvocationID.xy), value_1 + value_2 + value_3);
2029         })";
2030 
2031     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
2032     constexpr int kResultSize               = kWidth * kHeight;
2033     constexpr GLuint kInputValues2D[1]      = {11};
2034     constexpr GLuint KInputValues2DArray[2] = {23, 35};
2035     constexpr GLuint KInputValues3D[2]      = {102, 67};
2036     constexpr GLuint KInputValuesCube[1]    = {232};
2037 
2038     constexpr GLuint expectedValue_1 = 148;
2039     constexpr GLuint expectedValue_2 = 232;
2040     GLuint outputValues[kResultSize];
2041 
2042     glBindTexture(GL_TEXTURE_2D, texture[0]);
2043     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
2044     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
2045                     kInputValues2D);
2046     EXPECT_GL_NO_ERROR();
2047 
2048     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
2049     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
2050     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
2051                     GL_UNSIGNED_INT, KInputValues2DArray);
2052     EXPECT_GL_NO_ERROR();
2053 
2054     glBindTexture(GL_TEXTURE_3D, texture[2]);
2055     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
2056     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
2057                     GL_UNSIGNED_INT, KInputValues3D);
2058     EXPECT_GL_NO_ERROR();
2059 
2060     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[3]);
2061     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
2062     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
2063          face++)
2064     {
2065         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
2066                         KInputValuesCube);
2067     }
2068     EXPECT_GL_NO_ERROR();
2069 
2070     ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
2071     glUseProgram(program);
2072 
2073     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
2074     EXPECT_GL_NO_ERROR();
2075     glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
2076     EXPECT_GL_NO_ERROR();
2077     glBindImageTexture(2, texture[2], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
2078     EXPECT_GL_NO_ERROR();
2079     glBindImageTexture(3, texture[3], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
2080     EXPECT_GL_NO_ERROR();
2081     glDispatchCompute(1, 1, 1);
2082     EXPECT_GL_NO_ERROR();
2083 
2084     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2085     glUseProgram(0);
2086     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2087 
2088     for (GLenum face = 0; face < 6; face++)
2089     {
2090         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2091                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[3], 0);
2092         EXPECT_GL_NO_ERROR();
2093         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
2094         EXPECT_GL_NO_ERROR();
2095 
2096         if (face == 4)
2097         {
2098             for (int i = 0; i < kResultSize; i++)
2099             {
2100                 EXPECT_EQ(expectedValue_1, outputValues[i]);
2101             }
2102         }
2103         else
2104         {
2105             for (int i = 0; i < kResultSize; i++)
2106             {
2107                 EXPECT_EQ(expectedValue_2, outputValues[i]);
2108             }
2109         }
2110     }
2111 }
2112 
2113 // Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
2114 // program which has not been linked successfully or which does not contain objects to form a
2115 // compute shader.
TEST_P(ComputeShaderTest,QueryComputeWorkGroupSize)2116 TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
2117 {
2118     constexpr char kVS[] = R"(#version 310 es
2119 void main()
2120 {
2121 })";
2122 
2123     constexpr char kFS[] = R"(#version 310 es
2124 void main()
2125 {
2126 })";
2127 
2128     GLint workGroupSize[3];
2129 
2130     ANGLE_GL_PROGRAM(graphicsProgram, kVS, kFS);
2131     glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
2132     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2133 
2134     GLuint computeProgram = glCreateProgram();
2135     GLShader computeShader(GL_COMPUTE_SHADER);
2136     glAttachShader(computeProgram, computeShader);
2137     glLinkProgram(computeProgram);
2138     glDetachShader(computeProgram, computeShader);
2139 
2140     GLint linkStatus;
2141     glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
2142     ASSERT_GL_FALSE(linkStatus);
2143 
2144     glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
2145     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2146 
2147     glDeleteProgram(computeProgram);
2148 
2149     ASSERT_GL_NO_ERROR();
2150 }
2151 
2152 // Use groupMemoryBarrier and barrier to sync reads/writes order and the execution
2153 // order of multiple shader invocations in compute shader.
TEST_P(ComputeShaderTest,GroupMemoryBarrierAndBarrierTest)2154 TEST_P(ComputeShaderTest, GroupMemoryBarrierAndBarrierTest)
2155 {
2156     // TODO([email protected]): Figure out why we get this error message
2157     // that shader uses features not recognized by this D3D version.
2158     ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());
2159     ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
2160 
2161     // http://anglebug.com/42263641
2162     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2163 
2164     GLTexture texture;
2165     GLFramebuffer framebuffer;
2166 
2167     // Each invocation first stores a single value in an image, then each invocation sums up
2168     // all the values in the image and stores the sum in the image. groupMemoryBarrier is
2169     // used to order reads/writes to variables stored in memory accessible to other shader
2170     // invocations, and barrier is used to control the relative execution order of multiple
2171     // shader invocations used to process a local work group.
2172     constexpr char kCS[] = R"(#version 310 es
2173 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
2174 layout(r32i, binding = 0) uniform highp iimage2D image;
2175 void main()
2176 {
2177     uint x = gl_LocalInvocationID.x;
2178     uint y = gl_LocalInvocationID.y;
2179     imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));
2180     groupMemoryBarrier();
2181     barrier();
2182     int sum = 0;
2183     for (int i = 0; i < 2; i++)
2184     {
2185         for(int j = 0; j < 2; j++)
2186         {
2187             sum += imageLoad(image, ivec2(i, j)).x;
2188         }
2189     }
2190     groupMemoryBarrier();
2191     barrier();
2192     imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));
2193 })";
2194 
2195     constexpr int kWidth = 2, kHeight = 2;
2196     glBindTexture(GL_TEXTURE_2D, texture);
2197     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);
2198     EXPECT_GL_NO_ERROR();
2199 
2200     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2201     glUseProgram(program);
2202 
2203     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
2204     EXPECT_GL_NO_ERROR();
2205 
2206     glDispatchCompute(1, 1, 1);
2207     EXPECT_GL_NO_ERROR();
2208 
2209     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2210     GLuint outputValues[kWidth * kHeight];
2211     constexpr GLuint kExpectedValue = 4;
2212     glUseProgram(0);
2213     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2214 
2215     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2216     EXPECT_GL_NO_ERROR();
2217     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);
2218     EXPECT_GL_NO_ERROR();
2219 
2220     for (int i = 0; i < kWidth * kHeight; i++)
2221     {
2222         EXPECT_EQ(kExpectedValue, outputValues[i]);
2223     }
2224 }
2225 
2226 // Verify that a link error is generated when the sum of the number of active image uniforms and
2227 // active shader storage blocks in a compute shader exceeds GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(ComputeShaderTest,ExceedCombinedShaderOutputResourcesInCS)2228 TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS)
2229 {
2230     GLint maxCombinedShaderOutputResources;
2231     GLint maxComputeShaderStorageBlocks;
2232     GLint maxComputeImageUniforms;
2233 
2234     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
2235     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
2236     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
2237 
2238     ANGLE_SKIP_TEST_IF(maxCombinedShaderOutputResources >=
2239                        maxComputeShaderStorageBlocks + maxComputeImageUniforms);
2240 
2241     std::ostringstream computeShaderStream;
2242     computeShaderStream << "#version 310 es\n"
2243                            "layout(local_size_x = 3, local_size_y = 1, local_size_z = 1) in;\n"
2244                            "layout(shared, binding = 0) buffer blockName"
2245                            "{\n"
2246                            "    uint data;\n"
2247                            "} instance["
2248                         << maxComputeShaderStorageBlocks << "];\n";
2249 
2250     ASSERT_GE(maxComputeImageUniforms, 4);
2251     int numImagesInArray  = maxComputeImageUniforms / 2;
2252     int numImagesNonArray = maxComputeImageUniforms - numImagesInArray;
2253     for (int i = 0; i < numImagesNonArray; ++i)
2254     {
2255         computeShaderStream << "layout(r32f, binding = " << i << ") uniform highp image2D image"
2256                             << i << ";\n";
2257     }
2258 
2259     computeShaderStream << "layout(r32f, binding = " << numImagesNonArray
2260                         << ") uniform highp image2D imageArray[" << numImagesInArray << "];\n";
2261 
2262     computeShaderStream << "void main()\n"
2263                            "{\n"
2264                            "    uint val = 0u;\n"
2265                            "    vec4 val2 = vec4(0.0);\n";
2266 
2267     for (int i = 0; i < maxComputeShaderStorageBlocks; ++i)
2268     {
2269         computeShaderStream << "    val += instance[" << i << "].data; \n";
2270     }
2271 
2272     for (int i = 0; i < numImagesNonArray; ++i)
2273     {
2274         computeShaderStream << "    val2 += imageLoad(image" << i
2275                             << ", ivec2(gl_LocalInvocationID.xy)); \n";
2276     }
2277 
2278     for (int i = 0; i < numImagesInArray; ++i)
2279     {
2280         computeShaderStream << "    val2 += imageLoad(imageArray[" << i << "]"
2281                             << ", ivec2(gl_LocalInvocationID.xy)); \n";
2282     }
2283 
2284     computeShaderStream << "    instance[0].data = val + uint(val2.x);\n"
2285                            "}\n";
2286 
2287     GLuint computeProgram = CompileComputeProgram(computeShaderStream.str().c_str());
2288     EXPECT_EQ(0u, computeProgram);
2289 }
2290 
2291 // Test that uniform block with struct member in compute shader is supported.
TEST_P(ComputeShaderTest,UniformBlockWithStructMember)2292 TEST_P(ComputeShaderTest, UniformBlockWithStructMember)
2293 {
2294     constexpr char kCS[] = R"(#version 310 es
2295 layout(local_size_x=8) in;
2296 layout(rgba8) uniform highp readonly image2D mImage2DInput;
2297 layout(rgba8) uniform highp writeonly image2D mImage2DOutput;
2298 struct S {
2299     ivec3 a;
2300     ivec2 b;
2301 };
2302 
2303 layout(std140, binding=0) uniform blockName {
2304     S bd;
2305 } instanceName;
2306 void main()
2307 {
2308     ivec2 t1 = instanceName.bd.b;
2309     vec4 result2d = imageLoad(mImage2DInput, t1);
2310     imageStore(mImage2DOutput, ivec2(gl_LocalInvocationID.xy), result2d);
2311 })";
2312 
2313     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2314     EXPECT_GL_NO_ERROR();
2315 }
2316 
2317 // Verify shared non-array variables can work correctly.
TEST_P(ComputeShaderTest,NonArraySharedVariable)2318 TEST_P(ComputeShaderTest, NonArraySharedVariable)
2319 {
2320     // http://anglebug.com/42263641
2321     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2322 
2323     const char kCSShader[] = R"(#version 310 es
2324 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2325 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2326 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2327 shared uint temp;
2328 void main()
2329 {
2330     if (gl_LocalInvocationID == uvec3(0, 0, 0))
2331     {
2332         temp = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2333     }
2334     groupMemoryBarrier();
2335     barrier();
2336     if (gl_LocalInvocationID == uvec3(1, 1, 0))
2337     {
2338         imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(temp));
2339     }
2340     else
2341     {
2342         uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2343         imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(inputValue));
2344     }
2345 })";
2346 
2347     const std::array<GLuint, 4> inputData      = {{250, 200, 150, 100}};
2348     const std::array<GLuint, 4> expectedValues = {{250, 200, 150, 250}};
2349     runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2350                                       expectedValues);
2351 }
2352 
2353 // Verify shared non-struct array variables can work correctly.
TEST_P(ComputeShaderTest,NonStructArrayAsSharedVariable)2354 TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)
2355 {
2356     // http://anglebug.com/42263641
2357     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2358 
2359     const char kCSShader[] = R"(#version 310 es
2360 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2361 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2362 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2363 shared uint sharedData[2][2];
2364 void main()
2365 {
2366     uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2367     sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = inputData;
2368     groupMemoryBarrier();
2369     barrier();
2370     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2371                 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x]));
2372 })";
2373 
2374     const std::array<GLuint, 4> inputData      = {{250, 200, 150, 100}};
2375     const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
2376     runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2377                                       expectedValues);
2378 }
2379 
2380 // Verify shared struct array variables work correctly.
TEST_P(ComputeShaderTest,StructArrayAsSharedVariable)2381 TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)
2382 {
2383     // http://anglebug.com/42263641
2384     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2385 
2386     const char kCSShader[] = R"(#version 310 es
2387 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2388 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2389 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2390 struct SharedStruct
2391 {
2392     uint data;
2393 };
2394 shared SharedStruct sharedData[2][2];
2395 void main()
2396 {
2397     uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2398     sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y].data = inputData;
2399     groupMemoryBarrier();
2400     barrier();
2401     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2402                 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x].data));
2403 })";
2404 
2405     const std::array<GLuint, 4> inputData      = {{250, 200, 150, 100}};
2406     const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
2407     runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2408                                       expectedValues);
2409 }
2410 
2411 // Verify using atomic functions without return value can work correctly.
TEST_P(ComputeShaderTest,AtomicFunctionsNoReturnValue)2412 TEST_P(ComputeShaderTest, AtomicFunctionsNoReturnValue)
2413 {
2414     // http://anglebug.com/42263641
2415     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2416 
2417     // Fails to link on Android.  http://anglebug.com/42262519
2418     ANGLE_SKIP_TEST_IF(IsAndroid());
2419 
2420     ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
2421 
2422     const char kCSShader[] = R"(#version 310 es
2423 layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in;
2424 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2425 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2426 
2427 const uint kSumIndex = 0u;
2428 const uint kMinIndex = 1u;
2429 const uint kMaxIndex = 2u;
2430 const uint kOrIndex = 3u;
2431 const uint kAndIndex = 4u;
2432 const uint kXorIndex = 5u;
2433 const uint kExchangeIndex = 6u;
2434 const uint kCompSwapIndex = 7u;
2435 
2436 shared highp uint results[8];
2437 
2438 void main()
2439 {
2440     if (gl_LocalInvocationID.x == kMinIndex || gl_LocalInvocationID.x == kAndIndex)
2441     {
2442         results[gl_LocalInvocationID.x] = 0xFFFFu;
2443     }
2444     else if (gl_LocalInvocationID.x == kCompSwapIndex)
2445     {
2446         results[gl_LocalInvocationID.x] = 1u;
2447     }
2448     else
2449     {
2450         results[gl_LocalInvocationID.x] = 0u;
2451     }
2452     memoryBarrierShared();
2453     barrier();
2454 
2455     uint value = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2456     atomicAdd(results[kSumIndex], value);
2457     atomicMin(results[kMinIndex], value);
2458     atomicMax(results[kMaxIndex], value);
2459     atomicOr(results[kOrIndex], value);
2460     atomicAnd(results[kAndIndex], value);
2461     atomicXor(results[kXorIndex], value);
2462     atomicExchange(results[kExchangeIndex], value);
2463     atomicCompSwap(results[kCompSwapIndex], value, 256u);
2464     memoryBarrierShared();
2465     barrier();
2466 
2467     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2468                 uvec4(results[gl_LocalInvocationID.x]));
2469 })";
2470 
2471     const std::array<GLuint, 8> inputData      = {{1, 2, 4, 8, 16, 32, 64, 128}};
2472     const std::array<GLuint, 8> expectedValues = {{255, 1, 128, 255, 0, 255, 128, 256}};
2473     runSharedMemoryTest<GLuint, 8, 1>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2474                                       expectedValues);
2475 }
2476 
2477 // Verify using atomic functions in a non-initializer single assignment can work correctly.
TEST_P(ComputeShaderTest,AtomicFunctionsInNonInitializerSingleAssignment)2478 TEST_P(ComputeShaderTest, AtomicFunctionsInNonInitializerSingleAssignment)
2479 {
2480     // http://anglebug.com/42263641
2481     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2482 
2483     const char kCSShader[] = R"(#version 310 es
2484 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2485 layout (r32i, binding = 0) readonly uniform highp iimage2D srcImage;
2486 layout (r32i, binding = 1) writeonly uniform highp iimage2D dstImage;
2487 
2488 shared highp int sharedVariable;
2489 
2490 shared highp int inputData[9];
2491 shared highp int outputData[9];
2492 
2493 void main()
2494 {
2495     int inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2496     inputData[gl_LocalInvocationID.x] = inputValue;
2497     memoryBarrierShared();
2498     barrier();
2499 
2500     if (gl_LocalInvocationID.x == 0u)
2501     {
2502         sharedVariable = 0;
2503 
2504         outputData[0] = atomicAdd(sharedVariable, inputData[0]);
2505         outputData[1] = atomicMin(sharedVariable, inputData[1]);
2506         outputData[2] = atomicMax(sharedVariable, inputData[2]);
2507         outputData[3] = atomicAnd(sharedVariable, inputData[3]);
2508         outputData[4] = atomicOr(sharedVariable, inputData[4]);
2509         outputData[5] = atomicXor(sharedVariable, inputData[5]);
2510         outputData[6] = atomicExchange(sharedVariable, inputData[6]);
2511         outputData[7] = atomicCompSwap(sharedVariable, 64, inputData[7]);
2512         outputData[8] = atomicAdd(sharedVariable, inputData[8]);
2513     }
2514     memoryBarrierShared();
2515     barrier();
2516 
2517     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2518                 ivec4(outputData[gl_LocalInvocationID.x]));
2519 })";
2520 
2521     const std::array<GLint, 9> inputData      = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2522     const std::array<GLint, 9> expectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
2523     runSharedMemoryTest<GLint, 9, 1>(kCSShader, GL_R32I, GL_INT, inputData, expectedValues);
2524 }
2525 
2526 // Verify using atomic functions in an initializers and using unsigned int works correctly.
TEST_P(ComputeShaderTest,AtomicFunctionsInitializerWithUnsigned)2527 TEST_P(ComputeShaderTest, AtomicFunctionsInitializerWithUnsigned)
2528 {
2529     // http://anglebug.com/42263641
2530     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2531 
2532     constexpr char kCShader[] = R"(#version 310 es
2533 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2534 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2535 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2536 
2537 shared highp uint sharedVariable;
2538 
2539 shared highp uint inputData[9];
2540 shared highp uint outputData[9];
2541 
2542 void main()
2543 {
2544     uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2545     inputData[gl_LocalInvocationID.x] = inputValue;
2546     memoryBarrierShared();
2547     barrier();
2548 
2549     if (gl_LocalInvocationID.x == 0u)
2550     {
2551         sharedVariable = 0u;
2552 
2553         uint addValue = atomicAdd(sharedVariable, inputData[0]);
2554         outputData[0] = addValue;
2555         uint minValue = atomicMin(sharedVariable, inputData[1]);
2556         outputData[1] = minValue;
2557         uint maxValue = atomicMax(sharedVariable, inputData[2]);
2558         outputData[2] = maxValue;
2559         uint andValue = atomicAnd(sharedVariable, inputData[3]);
2560         outputData[3] = andValue;
2561         uint orValue = atomicOr(sharedVariable, inputData[4]);
2562         outputData[4] = orValue;
2563         uint xorValue = atomicXor(sharedVariable, inputData[5]);
2564         outputData[5] = xorValue;
2565         uint exchangeValue = atomicExchange(sharedVariable, inputData[6]);
2566         outputData[6] = exchangeValue;
2567         uint compSwapValue = atomicCompSwap(sharedVariable, 64u, inputData[7]);
2568         outputData[7] = compSwapValue;
2569         uint sharedVariable = atomicAdd(sharedVariable, inputData[8]);
2570         outputData[8] = sharedVariable;
2571 
2572     }
2573     memoryBarrierShared();
2574     barrier();
2575 
2576     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2577                 uvec4(outputData[gl_LocalInvocationID.x]));
2578 })";
2579 
2580     constexpr std::array<GLuint, 9> kInputData      = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2581     constexpr std::array<GLuint, 9> kExpectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
2582     runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2583                                       kExpectedValues);
2584 }
2585 
2586 // Verify using atomic functions inside expressions as unsigned int.
TEST_P(ComputeShaderTest,AtomicFunctionsReturnWithUnsigned)2587 TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithUnsigned)
2588 {
2589     // http://anglebug.com/42263641
2590     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2591 
2592     constexpr char kCShader[] = R"(#version 310 es
2593 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2594 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2595 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2596 
2597 shared highp uint sharedVariable;
2598 
2599 shared highp uint inputData[9];
2600 shared highp uint outputData[9];
2601 
2602 void main()
2603 {
2604     uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2605     inputData[gl_LocalInvocationID.x] = inputValue;
2606     memoryBarrierShared();
2607     barrier();
2608 
2609     if (gl_LocalInvocationID.x == 0u)
2610     {
2611         sharedVariable = 0u;
2612 
2613         outputData[0] = 1u + atomicAdd(sharedVariable, inputData[0]);
2614         outputData[1] = 1u + atomicMin(sharedVariable, inputData[1]);
2615         outputData[2] = 1u + atomicMax(sharedVariable, inputData[2]);
2616         outputData[3] = 1u + atomicAnd(sharedVariable, inputData[3]);
2617         outputData[4] = 1u + atomicOr(sharedVariable, inputData[4]);
2618         outputData[5] = 1u + atomicXor(sharedVariable, inputData[5]);
2619         outputData[6] = 1u + atomicExchange(sharedVariable, inputData[6]);
2620         outputData[7] = 1u + atomicCompSwap(sharedVariable, 64u, inputData[7]);
2621         outputData[8] = 1u + atomicAdd(sharedVariable, inputData[8]);
2622     }
2623     memoryBarrierShared();
2624     barrier();
2625 
2626     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2627                 uvec4(outputData[gl_LocalInvocationID.x]));
2628 })";
2629 
2630     constexpr std::array<GLuint, 9> kInputData      = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2631     constexpr std::array<GLuint, 9> kExpectedValues = {{1, 2, 2, 5, 1, 17, 49, 65, 129}};
2632     runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2633                                       kExpectedValues);
2634 }
2635 
2636 // Verify using nested atomic functions in expressions.
TEST_P(ComputeShaderTest,AtomicFunctionsReturnWithMultipleTypes)2637 TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithMultipleTypes)
2638 {
2639     // http://anglebug.com/42263641
2640     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2641 
2642     constexpr char kCShader[] = R"(#version 310 es
2643 layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
2644 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2645 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2646 
2647 shared highp uint sharedVariable;
2648 shared highp int  indexVariable;
2649 
2650 shared highp uint inputData[4];
2651 shared highp uint outputData[4];
2652 
2653 void main()
2654 {
2655     uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2656     inputData[gl_LocalInvocationID.x] = inputValue;
2657     memoryBarrierShared();
2658     barrier();
2659 
2660     if (gl_LocalInvocationID.x == 0u)
2661     {
2662         sharedVariable = 0u;
2663         indexVariable = 2;
2664 
2665         outputData[0] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2666         outputData[1] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2667         outputData[2] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2668         outputData[3] = atomicAdd(sharedVariable, 0u);
2669 
2670     }
2671     memoryBarrierShared();
2672     barrier();
2673 
2674     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2675                 uvec4(outputData[gl_LocalInvocationID.x]));
2676 })";
2677 
2678     constexpr std::array<GLuint, 4> kInputData      = {{1, 2, 3, 0}};
2679     constexpr std::array<GLuint, 4> kExpectedValues = {{1, 4, 6, 6}};
2680     runSharedMemoryTest<GLuint, 4, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2681                                       kExpectedValues);
2682 }
2683 
2684 // Basic uniform buffer functionality.
TEST_P(ComputeShaderTest,UniformBuffer)2685 TEST_P(ComputeShaderTest, UniformBuffer)
2686 {
2687     // http://anglebug.com/42263641
2688     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2689 
2690     GLTexture texture;
2691     GLBuffer buffer;
2692     GLFramebuffer framebuffer;
2693     constexpr char kCS[] = R"(#version 310 es
2694 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2695 uniform uni
2696 {
2697     uvec4 value;
2698 };
2699 layout(rgba32ui, binding = 0) writeonly uniform highp uimage2D uImage;
2700 void main()
2701 {
2702     imageStore(uImage, ivec2(gl_LocalInvocationID.xy), value);
2703 })";
2704 
2705     constexpr int kWidth = 1, kHeight = 1;
2706     constexpr GLuint kInputValues[4] = {56, 57, 58, 59};
2707 
2708     glBindTexture(GL_TEXTURE_2D, texture);
2709     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth, kHeight);
2710     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
2711                     kInputValues);
2712     EXPECT_GL_NO_ERROR();
2713 
2714     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2715     glUseProgram(program);
2716 
2717     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
2718     EXPECT_NE(uniformBufferIndex, -1);
2719     GLuint data[4] = {201, 202, 203, 204};
2720     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
2721     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint) * 4, data, GL_STATIC_DRAW);
2722     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
2723     glUniformBlockBinding(program, uniformBufferIndex, 0);
2724     EXPECT_GL_NO_ERROR();
2725 
2726     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
2727     EXPECT_GL_NO_ERROR();
2728 
2729     glDispatchCompute(1, 1, 1);
2730     EXPECT_GL_NO_ERROR();
2731 
2732     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2733     GLuint outputValues[kWidth * kHeight * 4];
2734     glUseProgram(0);
2735     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2736 
2737     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2738     EXPECT_GL_NO_ERROR();
2739     glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
2740     EXPECT_GL_NO_ERROR();
2741 
2742     for (int i = 0; i < kWidth * kHeight * 4; i++)
2743     {
2744         EXPECT_EQ(data[i], outputValues[i]);
2745     }
2746 }
2747 
2748 // Test that storing data to image and then loading the same image data works correctly.
TEST_P(ComputeShaderTest,StoreImageThenLoad)2749 TEST_P(ComputeShaderTest, StoreImageThenLoad)
2750 {
2751     // http://anglebug.com/42263641
2752     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2753 
2754     const char kCSSource[] = R"(#version 310 es
2755 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2756 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2757 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
2758 void main()
2759 {
2760     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2761     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
2762 })";
2763 
2764     constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
2765     GLTexture texture[3];
2766     glBindTexture(GL_TEXTURE_2D, texture[0]);
2767     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2768     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
2769     EXPECT_GL_NO_ERROR();
2770 
2771     glBindTexture(GL_TEXTURE_2D, texture[1]);
2772     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2773     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
2774     EXPECT_GL_NO_ERROR();
2775 
2776     glBindTexture(GL_TEXTURE_2D, texture[2]);
2777     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2778     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
2779     EXPECT_GL_NO_ERROR();
2780 
2781     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2782     glUseProgram(program);
2783 
2784     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2785     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2786 
2787     glDispatchCompute(1, 1, 1);
2788     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2789     EXPECT_GL_NO_ERROR();
2790 
2791     glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2792     glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2793 
2794     glDispatchCompute(1, 1, 1);
2795     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2796     EXPECT_GL_NO_ERROR();
2797 
2798     GLuint outputValue;
2799     GLFramebuffer framebuffer;
2800     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2801     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
2802     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
2803     EXPECT_GL_NO_ERROR();
2804 
2805     EXPECT_EQ(300u, outputValue);
2806 }
2807 
2808 // Test that loading image data and then storing data to the same image works correctly.
TEST_P(ComputeShaderTest,LoadImageThenStore)2809 TEST_P(ComputeShaderTest, LoadImageThenStore)
2810 {
2811     // http://anglebug.com/42263641
2812     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2813 
2814     const char kCSSource[] = R"(#version 310 es
2815 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2816 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2817 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
2818 void main()
2819 {
2820     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2821     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
2822 })";
2823 
2824     constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
2825     GLTexture texture[3];
2826     glBindTexture(GL_TEXTURE_2D, texture[0]);
2827     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2828     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
2829     EXPECT_GL_NO_ERROR();
2830 
2831     glBindTexture(GL_TEXTURE_2D, texture[1]);
2832     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2833     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
2834     EXPECT_GL_NO_ERROR();
2835 
2836     glBindTexture(GL_TEXTURE_2D, texture[2]);
2837     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2838     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
2839     EXPECT_GL_NO_ERROR();
2840 
2841     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2842     glUseProgram(program);
2843 
2844     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2845     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2846 
2847     glDispatchCompute(1, 1, 1);
2848     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2849     EXPECT_GL_NO_ERROR();
2850 
2851     glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2852     glBindImageTexture(1, texture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2853 
2854     glDispatchCompute(1, 1, 1);
2855     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2856     EXPECT_GL_NO_ERROR();
2857 
2858     GLuint outputValue;
2859     GLFramebuffer framebuffer;
2860     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2861     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
2862     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
2863     EXPECT_GL_NO_ERROR();
2864 
2865     EXPECT_EQ(100u, outputValue);
2866 }
2867 
2868 // Test that the length of a struct buffer variable is supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksStructLength)2869 TEST_P(ComputeShaderTest, ShaderStorageBlocksStructLength)
2870 {
2871     const char kCSSource[] = R"(#version 310 es
2872 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
2873 
2874 struct Particle
2875 {
2876     int len;
2877 };
2878 
2879 layout(binding = 0, std430) readonly buffer Buf1
2880 {
2881     Particle particlesRead[];
2882 };
2883 
2884 layout(binding = 1, std430) buffer Buf2
2885 {
2886     Particle particlesWrite[];
2887 };
2888 
2889 void main()
2890 {
2891     int index = int(gl_GlobalInvocationID.x);
2892     particlesWrite[index].len = particlesRead.length();
2893 })";
2894 
2895     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2896     EXPECT_GL_NO_ERROR();
2897 }
2898 
2899 // Test that scalar buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksScalar)2900 TEST_P(ComputeShaderTest, ShaderStorageBlocksScalar)
2901 {
2902     const char kCSSource[] = R"(#version 310 es
2903 layout(local_size_x=1) in;
2904 layout(std140, binding = 0) buffer blockA {
2905     uvec3 uv;
2906     float f;
2907 } instanceA;
2908 layout(std140, binding = 1) buffer blockB {
2909     vec2 v;
2910     uint u[3];
2911     float f;
2912 };
2913 void main()
2914 {
2915     f = instanceA.f;
2916 })";
2917 
2918     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2919     EXPECT_GL_NO_ERROR();
2920 }
2921 
2922 // Test that vector buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksVector)2923 TEST_P(ComputeShaderTest, ShaderStorageBlocksVector)
2924 {
2925     const char kCSSource[] = R"(#version 310 es
2926 layout(local_size_x=1) in;
2927 layout(std140, binding = 0) buffer blockA {
2928     vec2 f;
2929 } instanceA;
2930 layout(std140, binding = 1) buffer blockB {
2931     vec3 f;
2932 };
2933 void main()
2934 {
2935     f[1] = instanceA.f[0];
2936 })";
2937 
2938     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2939     EXPECT_GL_NO_ERROR();
2940 }
2941 
2942 // Test that matrix buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksMatrix)2943 TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrix)
2944 {
2945     const char kCSSource[] = R"(#version 310 es
2946 layout(local_size_x=1) in;
2947 layout(std140, binding = 0) buffer blockA {
2948     mat3x4 m;
2949 } instanceA;
2950 layout(std140, binding = 1) buffer blockB {
2951     mat3x4 m;
2952 };
2953 void main()
2954 {
2955     m[0][1] = instanceA.m[0][1];
2956 })";
2957 
2958     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2959     EXPECT_GL_NO_ERROR();
2960 }
2961 
2962 // Test that scalar array buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksScalarArray)2963 TEST_P(ComputeShaderTest, ShaderStorageBlocksScalarArray)
2964 {
2965     const char kCSSource[] = R"(#version 310 es
2966 layout(local_size_x=8) in;
2967 layout(std140, binding = 0) buffer blockA {
2968     float f[8];
2969 } instanceA;
2970 layout(std140, binding = 1) buffer blockB {
2971     float f[8];
2972 };
2973 void main()
2974 {
2975     f[gl_LocalInvocationIndex] = instanceA.f[gl_LocalInvocationIndex];
2976 })";
2977 
2978     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2979     EXPECT_GL_NO_ERROR();
2980 }
2981 
2982 // Test that vector array buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksVectorArray)2983 TEST_P(ComputeShaderTest, ShaderStorageBlocksVectorArray)
2984 {
2985     const char kCSSource[] = R"(#version 310 es
2986 layout(local_size_x=4) in;
2987 layout(std140, binding = 0) buffer blockA {
2988     vec2 v[4];
2989 } instanceA;
2990 layout(std140, binding = 1) buffer blockB {
2991     vec4 v[4];
2992 };
2993 void main()
2994 {
2995     v[0][gl_LocalInvocationIndex] = instanceA.v[gl_LocalInvocationIndex][1];
2996 })";
2997 
2998     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2999     EXPECT_GL_NO_ERROR();
3000 }
3001 
3002 // Test that matrix array buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksMatrixArray)3003 TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrixArray)
3004 {
3005     const char kCSSource[] = R"(#version 310 es
3006 layout(local_size_x=8) in;
3007 layout(std140, binding = 0) buffer blockA {
3008     float v1[5];
3009     mat4 m[8];
3010 } instanceA;
3011 layout(std140, binding = 1) buffer blockB {
3012     vec2 v1[3];
3013     mat4 m[8];
3014 };
3015 void main()
3016 {
3017     float data = instanceA.m[gl_LocalInvocationIndex][0][0];
3018     m[gl_LocalInvocationIndex][gl_LocalInvocationIndex][gl_LocalInvocationIndex] = data;
3019 })";
3020 
3021     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
3022     EXPECT_GL_NO_ERROR();
3023 }
3024 
3025 // Test that shader storage blocks only in assignment right is supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksInAssignmentRight)3026 TEST_P(ComputeShaderTest, ShaderStorageBlocksInAssignmentRight)
3027 {
3028     const char kCSSource[] = R"(#version 310 es
3029 layout(local_size_x=8) in;
3030 layout(std140, binding = 0) buffer blockA {
3031     float data[8];
3032 } instanceA;
3033 layout(r32f, binding = 0) writeonly uniform highp image2D imageOut;
3034 
3035 void main()
3036 {
3037     float data = 1.0;
3038     data = instanceA.data[gl_LocalInvocationIndex];
3039     imageStore(imageOut, ivec2(gl_LocalInvocationID.xy), vec4(data));
3040 })";
3041 
3042     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
3043     EXPECT_GL_NO_ERROR();
3044 }
3045 
3046 // Test that shader storage blocks with unsized array are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksWithUnsizedArray)3047 TEST_P(ComputeShaderTest, ShaderStorageBlocksWithUnsizedArray)
3048 {
3049     const char kCSSource[] = R"(#version 310 es
3050 layout(local_size_x=8) in;
3051 layout(std140, binding = 0) buffer blockA {
3052     float v[];
3053 } instanceA;
3054 layout(std140, binding = 0) buffer blockB {
3055     float v[];
3056 } instanceB[1];
3057 
3058 void main()
3059 {
3060     float data = instanceA.v[gl_LocalInvocationIndex];
3061     instanceB[0].v[gl_LocalInvocationIndex * 2u + 1u] = data;
3062 }
3063 )";
3064 
3065     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
3066     EXPECT_GL_NO_ERROR();
3067 }
3068 
3069 // Test that EOpIndexDirect/EOpIndexIndirect/EOpIndexDirectStruct nodes in ssbo EOpIndexInDirect
3070 // don't need to calculate the offset and should be translated by OutputHLSL directly.
TEST_P(ComputeShaderTest,IndexAndDotOperatorsInSSBOIndexIndirectOperator)3071 TEST_P(ComputeShaderTest, IndexAndDotOperatorsInSSBOIndexIndirectOperator)
3072 {
3073     constexpr char kComputeShaderSource[] = R"(#version 310 es
3074 layout(local_size_x=1) in;
3075 layout(std140, binding = 0) buffer blockA {
3076     float v[4];
3077 };
3078 layout(std140, binding = 1) buffer blockB {
3079     float v[4];
3080 } instanceB[1];
3081 struct S
3082 {
3083     uvec4 index[2];
3084 } s;
3085 void main()
3086 {
3087         s.index[0] = uvec4(0u, 1u, 2u, 3u);
3088     float data = v[s.index[0].y];
3089     instanceB[0].v[s.index[0].x] = data;
3090 })";
3091 
3092     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3093     EXPECT_GL_NO_ERROR();
3094 }
3095 
3096 // Test that swizzle node in non-SSBO symbol works well.
TEST_P(ComputeShaderTest,ShaderStorageBlocksWithNonSSBOSwizzle)3097 TEST_P(ComputeShaderTest, ShaderStorageBlocksWithNonSSBOSwizzle)
3098 {
3099     constexpr char kComputeShaderSource[] = R"(#version 310 es
3100 layout(local_size_x=8) in;
3101 layout(std140, binding = 0) buffer blockA {
3102     float v[8];
3103 };
3104 layout(std140, binding = 1) buffer blockB {
3105     float v[8];
3106 } instanceB[1];
3107 
3108 void main()
3109 {
3110     float data = v[gl_GlobalInvocationID.x];
3111     instanceB[0].v[gl_GlobalInvocationID.x] = data;
3112 })";
3113 
3114     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3115     EXPECT_GL_NO_ERROR();
3116 }
3117 
3118 // Test that swizzle node in SSBO symbol works well.
TEST_P(ComputeShaderTest,ShaderStorageBlocksWithSSBOSwizzle)3119 TEST_P(ComputeShaderTest, ShaderStorageBlocksWithSSBOSwizzle)
3120 {
3121     constexpr char kComputeShaderSource[] = R"(#version 310 es
3122 layout(local_size_x=1) in;
3123 layout(std140, binding = 0) buffer blockA {
3124     vec2 v;
3125 };
3126 layout(std140, binding = 1) buffer blockB {
3127     float v;
3128 } instanceB[1];
3129 
3130 void main()
3131 {
3132     instanceB[0].v = v.x;
3133 })";
3134 
3135     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3136     EXPECT_GL_NO_ERROR();
3137 }
3138 
3139 // Test that a large struct array in std140 uniform block won't consume too much time.
TEST_P(ComputeShaderTest,LargeStructArraySize)3140 TEST_P(ComputeShaderTest, LargeStructArraySize)
3141 {
3142     constexpr char kComputeShaderSource[] = R"(#version 310 es
3143 layout(local_size_x=8) in;
3144 precision mediump float;
3145 
3146 struct InstancingData
3147 {
3148     mat4 transformation;
3149 };
3150 
3151 #define MAX_INSTANCE_COUNT 800
3152 
3153 layout(std140) uniform InstanceBlock
3154 {
3155     InstancingData instances[MAX_INSTANCE_COUNT];
3156 };
3157 
3158 layout(std140, binding = 1) buffer blockB {
3159     mat4 v[];
3160 } instanceB;
3161 
3162 void main()
3163 {
3164     instanceB.v[gl_GlobalInvocationID.x] = instances[gl_GlobalInvocationID.x].transformation;
3165 })";
3166 
3167     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3168     EXPECT_GL_NO_ERROR();
3169 }
3170 
3171 // Check that it is not possible to create a compute shader when the context does not support ES
3172 // 3.10
TEST_P(ComputeShaderTestES3,NotSupported)3173 TEST_P(ComputeShaderTestES3, NotSupported)
3174 {
3175     GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
3176     EXPECT_EQ(0u, computeShaderHandle);
3177     EXPECT_GL_ERROR(GL_INVALID_ENUM);
3178 }
3179 
3180 // The contents of shared variables should be cleared to zero at the beginning of shader execution.
TEST_P(WebGL2ComputeTest,sharedVariablesShouldBeZero)3181 TEST_P(WebGL2ComputeTest, sharedVariablesShouldBeZero)
3182 {
3183     // http://anglebug.com/40644676
3184     ANGLE_SKIP_TEST_IF(IsD3D11());
3185 
3186     // Fails on Android, AMD/windows and Intel/windows.  Probably works by chance on other
3187     // platforms, so suppressing on all platforms to avoid possible flakiness.
3188     // http://anglebug.com/42262513
3189     ANGLE_SKIP_TEST_IF(IsVulkan());
3190 
3191     // http://anglebug.com/40096654
3192     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3193     ANGLE_SKIP_TEST_IF(IsOpenGL() &&
3194                        ((getClientMajorVersion() == 3) && (getClientMinorVersion() >= 1)));
3195 
3196     const char kCSShader[] = R"(#version 310 es
3197 layout (local_size_x = 4, local_size_y = 4, local_size_z = 1) in;
3198 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
3199 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
3200 struct S {
3201     float f;
3202     int i;
3203     uint u;
3204     bool b;
3205     vec4 v[64];
3206 };
3207 
3208 shared S vars[16];
3209 void main()
3210 {
3211     S zeroS;
3212     zeroS.f = 0.0f;
3213     zeroS.i = 0;
3214     zeroS.u = 0u;
3215     zeroS.b = false;
3216     for (int i = 0; i < 64; i++)
3217     {
3218         zeroS.v[i] = vec4(0.0f);
3219     }
3220 
3221     uint tid = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4u;
3222     uint value = (zeroS == vars[tid] ? 127u : 0u);
3223     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(value));
3224 })";
3225 
3226     const std::array<GLuint, 16> inputData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
3227     const std::array<GLuint, 16> expectedValues = {
3228         {127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127}};
3229     runSharedMemoryTest<GLuint, 4, 4>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
3230                                       expectedValues);
3231 }
3232 
3233 // Test uniform dirty in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,UniformDirty)3234 TEST_P(ComputeShaderTest, UniformDirty)
3235 {
3236     // http://anglebug.com/42263641
3237     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3238 
3239     GLTexture texture[2];
3240     GLFramebuffer framebuffer;
3241     constexpr char kCS[] = R"(#version 310 es
3242 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3243 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3244 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3245 uniform uint factor;
3246 void main()
3247 {
3248     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3249     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value * factor);
3250 })";
3251 
3252     constexpr int kWidth = 1, kHeight = 1;
3253     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
3254 
3255     glBindTexture(GL_TEXTURE_2D, texture[0]);
3256     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3257     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3258                     kInputValues[0]);
3259     EXPECT_GL_NO_ERROR();
3260 
3261     glBindTexture(GL_TEXTURE_2D, texture[1]);
3262     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3263     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3264                     kInputValues[1]);
3265     EXPECT_GL_NO_ERROR();
3266 
3267     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3268     glUseProgram(program);
3269 
3270     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3271     EXPECT_GL_NO_ERROR();
3272 
3273     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3274     EXPECT_GL_NO_ERROR();
3275 
3276     glUniform1ui(glGetUniformLocation(program, "factor"), 2);
3277     EXPECT_GL_NO_ERROR();
3278 
3279     glDispatchCompute(1, 1, 1);
3280     EXPECT_GL_NO_ERROR();
3281 
3282     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3283 
3284     glUniform1ui(glGetUniformLocation(program, "factor"), 3);
3285     EXPECT_GL_NO_ERROR();
3286 
3287     glDispatchCompute(1, 1, 1);
3288     EXPECT_GL_NO_ERROR();
3289 
3290     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3291     GLuint outputValues[kWidth * kHeight];
3292     GLuint expectedValue = 600;
3293     glUseProgram(0);
3294     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3295 
3296     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3297     EXPECT_GL_NO_ERROR();
3298     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
3299     EXPECT_GL_NO_ERROR();
3300 
3301     for (int i = 0; i < kWidth * kHeight; i++)
3302     {
3303         EXPECT_EQ(expectedValue, outputValues[i]) << " index " << i;
3304     }
3305 }
3306 
3307 // Test storage buffer bound is unchanged, shader writes it, buffer content should be updated.
TEST_P(ComputeShaderTest,StorageBufferBoundUnchanged)3308 TEST_P(ComputeShaderTest, StorageBufferBoundUnchanged)
3309 {
3310     // http://anglebug.com/40096654
3311     ANGLE_SKIP_TEST_IF(isSwiftshader());
3312     constexpr char kCS[] = R"(#version 310 es
3313 layout(local_size_x=16, local_size_y=16) in;
3314 precision highp usampler2D;
3315 uniform usampler2D tex;
3316 uniform uint factor;
3317 layout(std140, binding = 0) buffer buf {
3318     uint outData[16][16];
3319 };
3320 
3321 void main()
3322 {
3323     uint x = gl_LocalInvocationID.x;
3324     uint y = gl_LocalInvocationID.y;
3325     float xCoord = float(x) / float(16);
3326     float yCoord = float(y) / float(16);
3327     outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x + factor;
3328 })";
3329 
3330     constexpr unsigned int kWidth  = 16;
3331     constexpr unsigned int kHeight = 16;
3332     GLTexture tex;
3333     glBindTexture(GL_TEXTURE_2D, tex);
3334     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3335     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3336     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3337     GLuint texels[kHeight][kWidth] = {{0}};
3338     for (unsigned int y = 0; y < kHeight; ++y)
3339     {
3340         for (unsigned int x = 0; x < kWidth; ++x)
3341         {
3342             texels[y][x] = x + y * kWidth;
3343         }
3344     }
3345     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3346     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3347                     texels);
3348     glBindTexture(GL_TEXTURE_2D, 0);
3349 
3350     // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
3351     constexpr unsigned int kArrayStride = 16;
3352     GLBuffer ssbo;
3353     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3354     glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
3355                  GL_STREAM_DRAW);
3356     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3357     EXPECT_GL_NO_ERROR();
3358 
3359     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3360     glUseProgram(program);
3361 
3362     glActiveTexture(GL_TEXTURE0);
3363     glBindTexture(GL_TEXTURE_2D, tex);
3364     glUniform1i(glGetUniformLocation(program, "tex"), 0);
3365     glUniform1ui(glGetUniformLocation(program, "factor"), 2);
3366     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3367     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
3368 
3369     glDispatchCompute(1, 1, 1);
3370 
3371     const GLuint *ptr1 = reinterpret_cast<const GLuint *>(glMapBufferRange(
3372         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
3373     EXPECT_GL_NO_ERROR();
3374     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
3375     {
3376         EXPECT_EQ(idx + 2, *(ptr1 + idx * kArrayStride / 4));
3377     }
3378     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3379     glUniform1ui(glGetUniformLocation(program, "factor"), 3);
3380     glDispatchCompute(1, 1, 1);
3381 
3382     const GLuint *ptr2 = reinterpret_cast<const GLuint *>(glMapBufferRange(
3383         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
3384     EXPECT_GL_NO_ERROR();
3385     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
3386     {
3387         EXPECT_EQ(idx + 3, *(ptr2 + idx * kArrayStride / 4));
3388     }
3389 }
3390 
3391 // Test imageSize to access mipmap slice.
TEST_P(ComputeShaderTest,ImageSizeMipmapSlice)3392 TEST_P(ComputeShaderTest, ImageSizeMipmapSlice)
3393 {
3394     // TODO([email protected]): http://anglebug.com/42261780
3395     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
3396 
3397     // http://anglebug.com/42263018
3398     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsD3D11());
3399 
3400     GLTexture texture[2];
3401     GLFramebuffer framebuffer;
3402     const char kCS[] = R"(#version 310 es
3403 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3404 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3405 layout(rgba32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3406 void main()
3407 {
3408     ivec2 size = imageSize(uImage_1);
3409     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), uvec4(size, 0, 0));
3410 })";
3411 
3412     constexpr int kWidth1 = 8, kHeight1 = 4, kWidth2 = 1, kHeight2 = 1;
3413     constexpr GLuint kInputValues[] = {0, 0, 0, 0};
3414 
3415     glBindTexture(GL_TEXTURE_2D, texture[0]);
3416     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);
3417     EXPECT_GL_NO_ERROR();
3418 
3419     glBindTexture(GL_TEXTURE_2D, texture[1]);
3420     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth2, kHeight2);
3421     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
3422                     kInputValues);
3423     EXPECT_GL_NO_ERROR();
3424 
3425     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3426     glUseProgram(program);
3427 
3428     glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3429     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
3430 
3431     glDispatchCompute(1, 1, 1);
3432     EXPECT_GL_NO_ERROR();
3433 
3434     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3435     GLuint outputValues[kWidth2 * kHeight2 * 4];
3436     constexpr GLuint expectedValue[] = {4, 2};
3437     glUseProgram(0);
3438     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3439 
3440     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3441     EXPECT_GL_NO_ERROR();
3442     glReadPixels(0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
3443     EXPECT_GL_NO_ERROR();
3444 
3445     for (int i = 0; i < kWidth2 * kHeight2; i++)
3446     {
3447         EXPECT_EQ(expectedValue[i], outputValues[i]);
3448         EXPECT_EQ(expectedValue[i + 1], outputValues[i + 1]);
3449     }
3450 }
3451 
3452 // Test imageLoad to access mipmap slice.
TEST_P(ComputeShaderTest,ImageLoadMipmapSlice)3453 TEST_P(ComputeShaderTest, ImageLoadMipmapSlice)
3454 {
3455     // TODO([email protected]): http://anglebug.com/42261780
3456     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
3457 
3458     GLTexture texture[2];
3459     GLFramebuffer framebuffer;
3460     constexpr char kCS[] = R"(#version 310 es
3461 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3462 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3463 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3464 void main()
3465 {
3466     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3467     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
3468 })";
3469 
3470     constexpr int kWidth1 = 2, kHeight1 = 2, kWidth2 = 1, kHeight2 = 1;
3471     constexpr GLuint kInputValues11[] = {3, 3, 3, 3};
3472     constexpr GLuint kInputValues12[] = {2};
3473     constexpr GLuint kInputValues2[]  = {1};
3474 
3475     glBindTexture(GL_TEXTURE_2D, texture[0]);
3476     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);
3477     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3478                     kInputValues11);
3479     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3480                     kInputValues12);
3481     EXPECT_GL_NO_ERROR();
3482 
3483     glBindTexture(GL_TEXTURE_2D, texture[1]);
3484     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth2, kHeight2);
3485     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3486                     kInputValues2);
3487     EXPECT_GL_NO_ERROR();
3488 
3489     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3490     glUseProgram(program);
3491 
3492     glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3493     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3494 
3495     glDispatchCompute(1, 1, 1);
3496     EXPECT_GL_NO_ERROR();
3497 
3498     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3499     GLuint outputValues;
3500     constexpr GLuint expectedValue = 2;
3501     glUseProgram(0);
3502     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3503 
3504     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3505     EXPECT_GL_NO_ERROR();
3506     glReadPixels(0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);
3507     EXPECT_GL_NO_ERROR();
3508     EXPECT_EQ(expectedValue, outputValues);
3509 }
3510 
3511 // Test imageStore to access mipmap slice.
TEST_P(ComputeShaderTest,ImageStoreMipmapSlice)3512 TEST_P(ComputeShaderTest, ImageStoreMipmapSlice)
3513 {
3514     // TODO([email protected]): http://anglebug.com/42261780
3515     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3516 
3517     GLTexture texture[2];
3518     GLFramebuffer framebuffer;
3519     constexpr char kCS[] = R"(#version 310 es
3520 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3521 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3522 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3523 void main()
3524 {
3525     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3526     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
3527 })";
3528 
3529     constexpr int kWidth1 = 1, kHeight1 = 1, kWidth2 = 2, kHeight2 = 2;
3530     constexpr GLuint kInputValues1[]  = {3};
3531     constexpr GLuint kInputValues21[] = {2, 2, 2, 2};
3532     constexpr GLuint kInputValues22[] = {1};
3533 
3534     glBindTexture(GL_TEXTURE_2D, texture[0]);
3535     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth1, kHeight1);
3536     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3537                     kInputValues1);
3538     EXPECT_GL_NO_ERROR();
3539 
3540     glBindTexture(GL_TEXTURE_2D, texture[1]);
3541     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth2, kHeight2);
3542     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3543                     kInputValues21);
3544     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3545                     kInputValues22);
3546     EXPECT_GL_NO_ERROR();
3547 
3548     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3549     glUseProgram(program);
3550 
3551     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3552     glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3553 
3554     glDispatchCompute(1, 1, 1);
3555     EXPECT_GL_NO_ERROR();
3556 
3557     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3558     GLuint outputValues;
3559     constexpr GLuint expectedValue = 3;
3560     glUseProgram(0);
3561     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3562 
3563     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
3564     EXPECT_GL_NO_ERROR();
3565     glReadPixels(0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);
3566     EXPECT_GL_NO_ERROR();
3567     EXPECT_EQ(expectedValue, outputValues);
3568 }
3569 
3570 // Test that a resource is bound on render pipeline output, and then it's bound as the compute
3571 // pipeline input. It works well. See http://anglebug.com/42262319
TEST_P(ComputeShaderTest,DrawTexture1DispatchTexture2)3572 TEST_P(ComputeShaderTest, DrawTexture1DispatchTexture2)
3573 {
3574     // http://anglebug.com/42263641
3575     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3576 
3577     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"));
3578 
3579     const char kCSSource[] = R"(#version 310 es
3580 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3581 precision highp sampler2D;
3582 uniform sampler2D tex;
3583 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3584 void main()
3585 {
3586     vec4 value = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
3587     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(value.x - 1.0, 1.0, 0.0, value.w - 1.0));
3588 })";
3589 
3590     const char kVSSource[] = R"(#version 310 es
3591 layout (location = 0) in vec2 pos;
3592 out vec2 texCoord;
3593 void main(void) {
3594     texCoord = 0.5*pos + 0.5;
3595     gl_Position = vec4(pos, 0.0, 1.0);
3596 })";
3597 
3598     const char kFSSource[] = R"(#version 310 es
3599 precision highp float;
3600 uniform sampler2D tex;
3601 in vec2 texCoord;
3602 out vec4 fragColor;
3603 void main(void) {
3604     fragColor = texture(tex, texCoord);
3605 })";
3606 
3607     GLuint aPosLoc = 0;
3608     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3609     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3610     glBindAttribLocation(program, aPosLoc, "pos");
3611     GLuint buffer;
3612     glGenBuffers(1, &buffer);
3613     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3614     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3615     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3616     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3617     glEnableVertexAttribArray(aPosLoc);
3618 
3619     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3620     constexpr GLfloat kZero[4]        = {0.0, 0.0, 0.0, 0.0};
3621     GLFramebuffer framebuffer;
3622     GLTexture texture[3];
3623     glBindTexture(GL_TEXTURE_2D, texture[0]);
3624     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3625     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3626     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3627     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3628 
3629     glBindTexture(GL_TEXTURE_2D, texture[1]);
3630     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3631     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);
3632     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3633     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3634 
3635     glBindTexture(GL_TEXTURE_2D, texture[2]);
3636     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3637     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);
3638     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3639     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3640 
3641     glUseProgram(program);
3642     glActiveTexture(GL_TEXTURE0);
3643     glBindTexture(GL_TEXTURE_2D, texture[0]);
3644     glUniform1i(glGetUniformLocation(program, "tex"), 0);
3645     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3646     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3647     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3648     EXPECT_GL_NO_ERROR();
3649     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3650     GLfloat actual[4];
3651     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);
3652     EXPECT_GL_NO_ERROR();
3653     EXPECT_EQ(1.0, actual[0]);
3654     EXPECT_EQ(0.0, actual[1]);
3655     EXPECT_EQ(0.0, actual[2]);
3656     EXPECT_EQ(1.0, actual[3]);
3657 
3658     glUseProgram(csProgram);
3659     glActiveTexture(GL_TEXTURE0);
3660     glBindTexture(GL_TEXTURE_2D, texture[1]);
3661     glUniform1i(glGetUniformLocation(program, "tex"), 0);
3662     glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3663     glDispatchCompute(1, 1, 1);
3664     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3665 
3666     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3667     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
3668     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);
3669     EXPECT_GL_NO_ERROR();
3670     EXPECT_EQ(0.0, actual[0]);
3671     EXPECT_EQ(1.0, actual[1]);
3672     EXPECT_EQ(0.0, actual[2]);
3673     EXPECT_EQ(0.0, actual[3]);
3674 }
3675 
3676 // Test that render pipeline and compute pipeline access to the same texture.
3677 // Steps:
3678 //   1. DispatchCompute.
3679 //   2. DrawArrays.
TEST_P(ComputeShaderTest,DispatchDraw)3680 TEST_P(ComputeShaderTest, DispatchDraw)
3681 {
3682     // http://anglebug.com/42263641
3683     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3684 
3685     const char kCSSource[] = R"(#version 310 es
3686 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3687 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3688 void main()
3689 {
3690     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));
3691 })";
3692 
3693     const char kVSSource[] = R"(#version 310 es
3694 layout (location = 0) in vec2 pos;
3695 out vec2 texCoord;
3696 void main(void) {
3697     texCoord = 0.5*pos + 0.5;
3698     gl_Position = vec4(pos, 0.0, 1.0);
3699 })";
3700 
3701     const char kFSSource[] = R"(#version 310 es
3702 precision highp float;
3703 uniform sampler2D tex;
3704 in vec2 texCoord;
3705 out vec4 fragColor;
3706 void main(void) {
3707     fragColor = texture(tex, texCoord);
3708 })";
3709 
3710     GLuint aPosLoc = 0;
3711     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3712     glBindAttribLocation(program, aPosLoc, "pos");
3713     GLuint buffer;
3714     glGenBuffers(1, &buffer);
3715     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3716     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3717     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3718     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3719     glEnableVertexAttribArray(aPosLoc);
3720 
3721     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3722     GLTexture texture;
3723     glBindTexture(GL_TEXTURE_2D, texture);
3724     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3725     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3726     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3727     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3728     EXPECT_GL_NO_ERROR();
3729 
3730     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3731     glUseProgram(csProgram);
3732 
3733     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3734 
3735     glDispatchCompute(1, 1, 1);
3736     EXPECT_GL_NO_ERROR();
3737 
3738     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3739     glUseProgram(program);
3740     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3741     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
3742 }
3743 
3744 // Test that render pipeline and compute pipeline access to the same texture.
3745 // Steps:
3746 //   1. DrawArrays.
3747 //   2. DispatchCompute.
3748 //   3. DispatchCompute.
3749 //   4. DrawArrays.
TEST_P(ComputeShaderTest,DrawDispatchDispatchDraw)3750 TEST_P(ComputeShaderTest, DrawDispatchDispatchDraw)
3751 {
3752     // http://anglebug.com/42263641
3753     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3754 
3755     const char kCSSource[] = R"(#version 310 es
3756 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3757 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3758 uniform float factor;
3759 void main()
3760 {
3761     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(factor, 0.0, 1.0, 1.0));
3762 })";
3763 
3764     const char kVSSource[] = R"(#version 310 es
3765 layout (location = 0) in vec2 pos;
3766 out vec2 texCoord;
3767 void main(void) {
3768     texCoord = 0.5*pos + 0.5;
3769     gl_Position = vec4(pos, 0.0, 1.0);
3770 })";
3771 
3772     const char kFSSource[] = R"(#version 310 es
3773 precision highp float;
3774 uniform sampler2D tex;
3775 in vec2 texCoord;
3776 out vec4 fragColor;
3777 void main(void) {
3778     fragColor = texture(tex, texCoord);
3779 })";
3780 
3781     GLuint aPosLoc = 0;
3782     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3783     glBindAttribLocation(program, aPosLoc, "pos");
3784     GLuint buffer;
3785     glGenBuffers(1, &buffer);
3786     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3787     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3788     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3789     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3790     glEnableVertexAttribArray(aPosLoc);
3791 
3792     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3793     GLTexture texture;
3794     glBindTexture(GL_TEXTURE_2D, texture);
3795     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3796     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3797     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3798     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3799     glUseProgram(program);
3800     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3801     EXPECT_GL_NO_ERROR();
3802 
3803     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3804     glUseProgram(csProgram);
3805     glUniform1f(glGetUniformLocation(csProgram, "factor"), 0.0);
3806     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3807     EXPECT_GL_NO_ERROR();
3808 
3809     glDispatchCompute(1, 1, 1);
3810     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3811     EXPECT_GL_NO_ERROR();
3812 
3813     glUniform1f(glGetUniformLocation(csProgram, "factor"), 1.0);
3814     glDispatchCompute(1, 1, 1);
3815     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3816     EXPECT_GL_NO_ERROR();
3817 
3818     glUseProgram(program);
3819     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3820     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::magenta);
3821 }
3822 
3823 // Test that render pipeline and compute pipeline access to the same texture.
3824 // Steps:
3825 //   1. DispatchCompute.
3826 //   2. DrawArrays.
3827 //   3. DrawArrays.
3828 //   4. DispatchCompute.
TEST_P(ComputeShaderTest,DispatchDrawDrawDispatch)3829 TEST_P(ComputeShaderTest, DispatchDrawDrawDispatch)
3830 {
3831     // http://anglebug.com/42263641
3832     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3833 
3834     const char kCSSource[] = R"(#version 310 es
3835 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3836 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3837 
3838 void main()
3839 {
3840     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));
3841 })";
3842 
3843     const char kVSSource[] = R"(#version 310 es
3844 layout (location = 0) in vec2 pos;
3845 out vec2 texCoord;
3846 void main(void) {
3847     texCoord = 0.5*pos + 0.5;
3848     gl_Position = vec4(pos, 0.0, 1.0);
3849 })";
3850 
3851     const char kFSSource[] = R"(#version 310 es
3852 precision highp float;
3853 uniform sampler2D tex;
3854 in vec2 texCoord;
3855 uniform float factor;
3856 out vec4 fragColor;
3857 void main(void) {
3858     fragColor = texture(tex, texCoord) + vec4(factor, 0.0, 0.0, 0.0);
3859 })";
3860 
3861     GLuint aPosLoc = 0;
3862     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3863     glBindAttribLocation(program, aPosLoc, "pos");
3864     GLuint buffer;
3865     glGenBuffers(1, &buffer);
3866     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3867     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3868     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3869     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3870     glEnableVertexAttribArray(aPosLoc);
3871 
3872     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3873     GLTexture texture;
3874     glBindTexture(GL_TEXTURE_2D, texture);
3875     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3876     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3877     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3878     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3879 
3880     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3881     glUseProgram(csProgram);
3882     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3883 
3884     glDispatchCompute(1, 1, 1);
3885     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3886     EXPECT_GL_NO_ERROR();
3887 
3888     glUseProgram(program);
3889     glUniform1f(glGetUniformLocation(program, "factor"), 0.0);
3890     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3891     EXPECT_GL_NO_ERROR();
3892 
3893     glUniform1f(glGetUniformLocation(program, "factor"), 1.0);
3894     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3895     EXPECT_GL_NO_ERROR();
3896 
3897     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3898     glUseProgram(csProgram);
3899     glDispatchCompute(1, 1, 1);
3900     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3901     EXPECT_GL_NO_ERROR();
3902 
3903     glUseProgram(program);
3904     glUniform1f(glGetUniformLocation(program, "factor"), 0.0);
3905     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3906     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
3907 }
3908 
3909 // Test color texture sample from fragment shader and then read access from compute
TEST_P(ComputeShaderTest,DrawReadDrawDispatch)3910 TEST_P(ComputeShaderTest, DrawReadDrawDispatch)
3911 {
3912     const char kVS[] = R"(#version 310 es
3913 layout (location = 0) in vec3 pos;
3914 void main(void) {
3915     gl_Position = vec4(pos, 1.0);
3916 })";
3917 
3918     const char kFS[] = R"(#version 310 es
3919 precision highp float;
3920 uniform sampler2D tex;
3921 out vec4 fragColor;
3922 void main(void) {
3923         fragColor = texture(tex,vec2(0,0));
3924 })";
3925 
3926     // Create color texture
3927     GLTexture colorTexture;
3928     glActiveTexture(GL_TEXTURE0);
3929     glBindTexture(GL_TEXTURE_2D, colorTexture);
3930     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3931     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3932     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
3933     const GLColor textureData = GLColor::green;
3934     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, textureData.data());
3935 
3936     // Render to surface with texture sample
3937     ANGLE_GL_PROGRAM(graphicsProgram, kVS, kFS);
3938     glUseProgram(graphicsProgram);
3939     const auto &quadVertices = GetQuadVertices();
3940     GLBuffer arrayBuffer;
3941     glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
3942     glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
3943                  GL_STATIC_DRAW);
3944     GLint positionAttributeLocation = 0;
3945     glBindAttribLocation(graphicsProgram, positionAttributeLocation, "pos");
3946     glVertexAttribPointer(positionAttributeLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3947     glEnableVertexAttribArray(positionAttributeLocation);
3948 
3949     GLint uTextureLocation = glGetUniformLocation(graphicsProgram, "tex");
3950     ASSERT_NE(-1, uTextureLocation);
3951     glActiveTexture(GL_TEXTURE0);
3952     glBindTexture(GL_TEXTURE_2D, colorTexture);
3953     glUniform1i(uTextureLocation, 0);
3954     // Sample the color texture from fragment shader and verify. This flushes out commands which
3955     // ensures there will be no layout transition in next renderPass.
3956     glDisable(GL_DEPTH_TEST);
3957     glDrawArrays(GL_TRIANGLES, 0, 6);
3958     EXPECT_PIXEL_COLOR_EQ(0, 0, textureData);
3959 
3960     // Sample the texture from fragment shader. No image layout transition expected here.
3961     glDrawArrays(GL_TRIANGLES, 0, 6);
3962 
3963     // Sample it from compute shader while the renderPass also sample from the same texture
3964     constexpr char kCS[] = R"(#version 310 es
3965 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3966 layout(std140, binding=0) buffer buf {
3967     vec4 outData;
3968 };
3969 uniform sampler2D u_tex2D;
3970 void main()
3971 {
3972     outData = texture(u_tex2D, vec2(gl_LocalInvocationID.xy));
3973 })";
3974     ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kCS);
3975     glUseProgram(computeProgram);
3976     uTextureLocation = glGetUniformLocation(computeProgram, "u_tex2D");
3977     ASSERT_NE(-1, uTextureLocation);
3978     glUniform1i(uTextureLocation, 0);
3979     GLBuffer ssbo;
3980     const std::vector<GLfloat> initialData(4, 0.0f);
3981     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3982     glBufferData(GL_SHADER_STORAGE_BUFFER, initialData.size() * sizeof(GLfloat), initialData.data(),
3983                  GL_STATIC_DRAW);
3984     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
3985     glDispatchCompute(1, 1, 1);
3986     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3987     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3988     const GLfloat *ptr      = reinterpret_cast<const GLfloat *>(glMapBufferRange(
3989         GL_SHADER_STORAGE_BUFFER, 0, initialData.size() * sizeof(GLfloat), GL_MAP_READ_BIT));
3990     angle::Vector4 expected = textureData.toNormalizedVector();
3991     EXPECT_NEAR(expected[0], ptr[0], 0.001);
3992     EXPECT_NEAR(expected[1], ptr[1], 0.001);
3993     EXPECT_NEAR(expected[2], ptr[2], 0.001);
3994     EXPECT_NEAR(expected[3], ptr[3], 0.001);
3995     EXPECT_GL_NO_ERROR();
3996 }
3997 
3998 // Test that invalid memory barrier will produce an error.
TEST_P(ComputeShaderTest,InvalidMemoryBarrier)3999 TEST_P(ComputeShaderTest, InvalidMemoryBarrier)
4000 {
4001     GLbitfield barriers = 0;
4002     glMemoryBarrier(barriers);
4003     EXPECT_GL_ERROR(GL_INVALID_VALUE);
4004 }
4005 
4006 // test atomic counter increment
4007 // http://anglebug.com/42261924
TEST_P(ComputeShaderTest,AtomicCounterIncrement)4008 TEST_P(ComputeShaderTest, AtomicCounterIncrement)
4009 {
4010     constexpr char kComputeShader[] = R"(#version 310 es
4011 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4012 layout(binding = 1, std430) buffer Output {
4013   uint preGet[1];
4014   uint increment[1];
4015   uint postGet[1];
4016 } sb_in;
4017 layout(binding=0) uniform atomic_uint counter0;
4018 
4019 void main(void)
4020 {
4021   uint id = (gl_GlobalInvocationID.x);
4022   sb_in.preGet[0u]    = atomicCounter(counter0);
4023   sb_in.increment[0u] = atomicCounterIncrement(counter0);
4024   sb_in.postGet[0u]   = atomicCounter(counter0);
4025 }
4026 )";
4027     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4028     EXPECT_GL_NO_ERROR();
4029 
4030     glUseProgram(program);
4031 
4032     constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
4033 
4034     GLBuffer shaderStorageBuffer;
4035     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4036     glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
4037     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
4038     EXPECT_GL_NO_ERROR();
4039 
4040     constexpr GLuint atomicBufferInitialData[] = {2u};
4041     GLuint atomicBuffer;
4042     glGenBuffers(1, &atomicBuffer);
4043     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicBuffer);
4044     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomicBufferInitialData), atomicBufferInitialData,
4045                  GL_DYNAMIC_DRAW);
4046     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicBuffer);
4047     EXPECT_GL_NO_ERROR();
4048 
4049     glDispatchCompute(1, 1, 1);
4050     glFinish();
4051     EXPECT_GL_NO_ERROR();
4052 
4053     // read back
4054     const GLuint *ptr = reinterpret_cast<const GLuint *>(
4055         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
4056     EXPECT_EQ(2u, ptr[0]);
4057     EXPECT_EQ(2u, ptr[1]);
4058     EXPECT_EQ(3u, ptr[2]);
4059 
4060     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4061 }
4062 
4063 // Create a 'very large' array inside of a function in a compute shader.
TEST_P(ComputeShaderTest,VeryLargeArrayInsideFunction)4064 TEST_P(ComputeShaderTest, VeryLargeArrayInsideFunction)
4065 {
4066     constexpr char kComputeShader[] = R"(#version 310 es
4067 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
4068 layout(binding = 0, std430) buffer Output {
4069   int value[1];
4070 } output_data;
4071 
4072 void main()
4073 {
4074     int values[1000];
4075     for (int i = 0; i < values.length(); i++)
4076     {
4077         values[i] = 0;
4078     }
4079 
4080     int total = 0;
4081     for (int i = 0; i < values.length(); i++)
4082     {
4083         total += i;
4084         values[i] = total;
4085     }
4086     output_data.value[0u] = values[1000-1];
4087 })";
4088 
4089     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
4090     EXPECT_GL_NO_ERROR();
4091 
4092     glUseProgram(program);
4093 
4094     constexpr unsigned int kBytesPerComponent = sizeof(GLint);
4095 
4096     GLBuffer shaderStorageBuffer;
4097     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
4098     glBufferData(GL_SHADER_STORAGE_BUFFER, 1 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
4099     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
4100     EXPECT_GL_NO_ERROR();
4101 
4102     glDispatchCompute(1, 1, 1);
4103     glFinish();
4104     EXPECT_GL_NO_ERROR();
4105 
4106     // read back
4107     const GLint *ptr = reinterpret_cast<const GLint *>(
4108         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 1 * kBytesPerComponent, GL_MAP_READ_BIT));
4109     EXPECT_EQ(499500, ptr[0]);
4110 
4111     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4112 }
4113 
4114 // Test that render pipeline and compute pipeline access to the same texture.
4115 // Steps:
4116 //   1. Clear the texture and DrawArrays.
4117 //   2. DispatchCompute to set the image's first pixel to a specific color.
4118 //   3. DrawArrays and check data.
TEST_P(ComputeShaderTest,DrawDispatchDrawPreserve)4119 TEST_P(ComputeShaderTest, DrawDispatchDrawPreserve)
4120 {
4121     // http://anglebug.com/42263641
4122     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4123 
4124     const char kCSSource[] = R"(#version 310 es
4125 layout(local_size_x=1, local_size_y=1) in;
4126 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4127 void main()
4128 {
4129     imageStore(image, ivec2(0, 0), vec4(0.0, 0.0, 1.0, 1.0));
4130 })";
4131 
4132     const char kVSSource[] = R"(#version 310 es
4133 layout (location = 0) in vec2 pos;
4134 in vec4 inTex;
4135 out vec4 texCoord;
4136 void main(void) {
4137     texCoord = inTex;
4138     gl_Position = vec4(pos, 0.0, 1.0);
4139 })";
4140 
4141     const char kFSSource[] = R"(#version 310 es
4142 precision highp float;
4143 uniform sampler2D tex;
4144 in vec4 texCoord;
4145 out vec4 fragColor;
4146 void main(void) {
4147     fragColor = texture(tex, texCoord.xy);
4148 })";
4149     GLuint aPosLoc         = 0;
4150     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
4151     glBindAttribLocation(program, aPosLoc, "pos");
4152 
4153     unsigned char *data = new unsigned char[4 * getWindowWidth() * getWindowHeight()];
4154     for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
4155     {
4156         data[i * 4]     = 0xff;
4157         data[i * 4 + 1] = 0;
4158         data[i * 4 + 2] = 0;
4159         data[i * 4 + 3] = 0xff;
4160     }
4161     GLTexture texture;
4162     glBindTexture(GL_TEXTURE_2D, texture);
4163     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth(), getWindowHeight());
4164     // Clear the texture level 0 to Red.
4165     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA,
4166                     GL_UNSIGNED_BYTE, data);
4167     for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
4168     {
4169         data[i * 4]     = 0;
4170         data[i * 4 + 1] = 0xff;
4171         data[i * 4 + 2] = 0;
4172         data[i * 4 + 3] = 0xff;
4173     }
4174     // Clear the texture level 1 to Green.
4175     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
4176                     GL_UNSIGNED_BYTE, data);
4177     delete[] data;
4178     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
4179     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4180     glUseProgram(program);
4181     GLfloat vertices[]  = {-1, -1, 1, -1, -1, 1, 1, 1};
4182     GLfloat texCoords[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
4183     GLint pos           = glGetAttribLocation(program, "pos");
4184     glEnableVertexAttribArray(pos);
4185     glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
4186     GLint posTex = glGetAttribLocation(program, "inTex");
4187     glEnableVertexAttribArray(posTex);
4188     glVertexAttribPointer(posTex, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
4189 
4190     // Draw with level 0, the whole framebuffer should be Red.
4191     glViewport(0, 0, getWindowWidth(), getWindowHeight());
4192     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4193     EXPECT_GL_NO_ERROR();
4194     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4195     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4196     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
4197     // Draw with level 1, a quarter of the framebuffer should be Green.
4198     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
4199     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4200     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4201     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
4202     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
4203 
4204     // Clear the texture level 0's (0, 0) position to Blue.
4205     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4206     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
4207     glUseProgram(csProgram);
4208     glDispatchCompute(1, 1, 1);
4209     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
4210     EXPECT_GL_NO_ERROR();
4211     glFinish();
4212 
4213     glUseProgram(program);
4214     // Draw with level 0, the first position should be Blue.
4215     glViewport(0, 0, getWindowWidth(), getWindowHeight());
4216     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4217     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4218     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4219     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
4220     // Draw with level 1, a quarter of the framebuffer should be Green.
4221     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
4222     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4223     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4224     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
4225     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
4226 }
4227 
4228 // Test that maxComputeWorkGroupCount is valid number.
TEST_P(ComputeShaderTest,ValidateMaxComputeWorkGroupCount)4229 TEST_P(ComputeShaderTest, ValidateMaxComputeWorkGroupCount)
4230 {
4231     constexpr char kCS[] = R"(#version 310 es
4232 layout(local_size_x=1) in;
4233 void main()
4234 {
4235 })";
4236 
4237     GLuint program = glCreateProgram();
4238     GLuint cs      = CompileShader(GL_COMPUTE_SHADER, kCS);
4239     EXPECT_NE(0u, cs);
4240 
4241     glAttachShader(program, cs);
4242     glDeleteShader(cs);
4243 
4244     GLint x, y, z;
4245     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &x);
4246     EXPECT_LE(65535, x);
4247     EXPECT_GE(std::numeric_limits<GLint>::max(), x);
4248 
4249     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &y);
4250     EXPECT_LE(65535, y);
4251     EXPECT_GE(std::numeric_limits<GLint>::max(), y);
4252 
4253     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &z);
4254     EXPECT_LE(65535, z);
4255     EXPECT_GE(std::numeric_limits<GLint>::max(), z);
4256 
4257     glDeleteProgram(program);
4258     EXPECT_GL_NO_ERROR();
4259 }
4260 
4261 // Validate that on Vulkan, compute pipeline driver uniforms descriptor set is updated after an
4262 // internal compute-based UtilsVk function is used.  The latter is achieved through a draw with a
4263 // vertex buffer whose format is not natively supported.  Atomic counters are used to make sure the
4264 // compute pipeline uses the driver uniforms descriptor set.
TEST_P(ComputeShaderTest,DispatchConvertVertexDispatch)4265 TEST_P(ComputeShaderTest, DispatchConvertVertexDispatch)
4266 {
4267     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_vertex_type_10_10_10_2"));
4268 
4269     constexpr uint32_t kVertexCount = 6;
4270 
4271     constexpr char kCS[] = R"(#version 310 es
4272 layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4273 
4274 layout(binding = 0) uniform atomic_uint ac;
4275 
4276 layout(binding=0, std140) buffer VertexData
4277 {
4278     uint data[];
4279 };
4280 
4281 void main()
4282 {
4283     atomicCounterIncrement(ac);
4284     data[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;
4285 })";
4286 
4287     constexpr char kVS[] = R"(#version 310 es
4288 precision mediump float;
4289 
4290 layout(location = 0) in vec4 position;
4291 layout(location = 1) in uvec4 data;
4292 
4293 out vec4 color;
4294 
4295 void main() {
4296     color = data.x < 6u && data.y == 0u && data.z == 0u && data.w == 0u
4297         ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
4298     gl_Position = position;
4299 })";
4300 
4301     constexpr char kFS[] = R"(#version 310 es
4302 precision mediump float;
4303 in vec4 color;
4304 out vec4 colorOut;
4305 void main() {
4306     colorOut = color;
4307 })";
4308 
4309     ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4310     ANGLE_GL_PROGRAM(programVSFS, kVS, kFS);
4311     EXPECT_GL_NO_ERROR();
4312 
4313     // Create atomic counter buffer
4314     GLBuffer atomicCounterBuffer;
4315     constexpr GLuint kInitialAcbData = 0;
4316     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4317     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kInitialAcbData), &kInitialAcbData,
4318                  GL_STATIC_DRAW);
4319     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4320     EXPECT_GL_NO_ERROR();
4321 
4322     // Create vertex buffer
4323     constexpr unsigned kVertexBufferInitData[kVertexCount] = {};
4324     GLBuffer vertexBuffer;
4325     glBindBuffer(GL_SHADER_STORAGE_BUFFER, vertexBuffer);
4326     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kVertexBufferInitData), kVertexBufferInitData,
4327                  GL_STATIC_DRAW);
4328     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vertexBuffer);
4329     EXPECT_GL_NO_ERROR();
4330 
4331     // Create position buffer
4332     constexpr GLfloat positions[kVertexCount * 2] = {1.0, 1.0, -1.0, 1.0,  -1.0, -1.0,
4333                                                      1.0, 1.0, -1.0, -1.0, 1.0,  -1.0};
4334     GLBuffer positionBuffer;
4335     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4336     glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
4337     EXPECT_GL_NO_ERROR();
4338 
4339     // Create vertex array
4340     GLVertexArray vao;
4341     glBindVertexArray(vao);
4342 
4343     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4344     glEnableVertexAttribArray(0);
4345     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
4346 
4347     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4348     glEnableVertexAttribArray(1);
4349     glVertexAttribPointer(1, 4, GL_UNSIGNED_INT_10_10_10_2_OES, false, 0, 0);
4350     EXPECT_GL_NO_ERROR();
4351 
4352     // Fill the vertex buffer with a dispatch call
4353     glUseProgram(programCS);
4354     glDispatchCompute(1, 1, 1);
4355     EXPECT_GL_NO_ERROR();
4356 
4357     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
4358 
4359     // Draw using the vertex buffer, causing vertex format conversion in compute (in the Vulkan
4360     // backend)
4361     glUseProgram(programVSFS);
4362     glBindVertexArray(vao);
4363     glDrawArrays(GL_TRIANGLES, 0, kVertexCount);
4364     EXPECT_GL_NO_ERROR();
4365 
4366     // Issue another dispatch call. The driver uniforms descriptor set must be rebound.
4367     glUseProgram(programCS);
4368     glDispatchCompute(1, 1, 1);
4369     EXPECT_GL_NO_ERROR();
4370 
4371     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4372 
4373     // Verify that the atomic counter has the expected value.
4374     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4375     GLuint *mappedBuffer = static_cast<GLuint *>(
4376         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4377     EXPECT_EQ(kVertexCount * 2, mappedBuffer[0]);
4378     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4379 }
4380 
4381 // Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
4382 // made.  Blit stencil may issue a dispatch call.
TEST_P(ComputeShaderTest,DispatchBlitStencilDispatch)4383 TEST_P(ComputeShaderTest, DispatchBlitStencilDispatch)
4384 {
4385     // http://anglebug.com/42264069
4386     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
4387 
4388     // http://anglebug.com/42263641
4389     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4390 
4391     constexpr GLsizei kSize = 1;
4392 
4393     constexpr char kCS[] = R"(#version 310 es
4394 layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4395 
4396 uniform vec4 data;
4397 
4398 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4399 
4400 void main()
4401 {
4402     imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4403 })";
4404 
4405     ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4406     EXPECT_GL_NO_ERROR();
4407 
4408     // Create a framebuffer with stencil buffer.  Use multisampled textures so the future blit
4409     // cannot use vkCmdBlitImage.
4410     GLTexture color;
4411     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color);
4412     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);
4413 
4414     GLTexture depthStencil;
4415     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depthStencil);
4416     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_DEPTH24_STENCIL8, kSize, kSize,
4417                               true);
4418 
4419     GLFramebuffer fbo;
4420     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4421     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color,
4422                            0);
4423     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
4424                            depthStencil, 0);
4425     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4426     ASSERT_GL_NO_ERROR();
4427 
4428     // Clear the stencil and make sure it's done.
4429     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
4430     glClearStencil(0x55);
4431     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4432 
4433     glEnable(GL_STENCIL_TEST);
4434     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4435     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4436     glStencilMask(0xFF);
4437 
4438     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4439     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
4440     ASSERT_GL_NO_ERROR();
4441 
4442     GLTexture colorCopy;
4443     glBindTexture(GL_TEXTURE_2D, colorCopy);
4444     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4445 
4446     GLFramebuffer copyFbo;
4447     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
4448     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorCopy, 0);
4449     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
4450     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
4451     ASSERT_GL_NO_ERROR();
4452 
4453     glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo);
4454     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4455 
4456     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4457 
4458     // Setup image for compute call
4459     GLTexture computeOut;
4460     glBindTexture(GL_TEXTURE_2D, computeOut);
4461     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4462     glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4463     ASSERT_GL_NO_ERROR();
4464 
4465     // Issue a dispatch call.
4466     glUseProgram(programCS);
4467     GLint uniformLoc = glGetUniformLocation(programCS, "data");
4468     ASSERT_NE(uniformLoc, -1);
4469 
4470     glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4471     glDispatchCompute(1, 1, 1);
4472     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4473     ASSERT_GL_NO_ERROR();
4474 
4475     // Blit the stencil texture.  This may use a compute shader internally.
4476     GLTexture depthStencilCopy;
4477     glBindTexture(GL_TEXTURE_2D, depthStencilCopy);
4478     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
4479     ASSERT_GL_NO_ERROR();
4480 
4481     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
4482     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
4483                            depthStencilCopy, 0);
4484     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
4485     ASSERT_GL_NO_ERROR();
4486 
4487     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
4488     ASSERT_GL_NO_ERROR();
4489 
4490     // Issue another dispatch call.
4491     glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
4492     glDispatchCompute(1, 1, 1);
4493     ASSERT_GL_NO_ERROR();
4494 
4495     // Verify the results.
4496     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4497     glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);
4498     glBindTexture(GL_TEXTURE_2D, computeOut);
4499     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
4500     ASSERT_GL_NO_ERROR();
4501 
4502     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4503 
4504     // Verify the blit copy results.
4505     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
4506     ASSERT_GL_NO_ERROR();
4507 
4508     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4509 }
4510 
4511 // Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
4512 // made.  Generate mipmap may issue a dispatch call.
TEST_P(ComputeShaderTest,DispatchGenerateMipmapDispatch)4513 TEST_P(ComputeShaderTest, DispatchGenerateMipmapDispatch)
4514 {
4515     constexpr GLsizei kSize = 8;
4516 
4517     constexpr char kCS[] = R"(#version 310 es
4518 layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4519 
4520 uniform vec4 data;
4521 
4522 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4523 
4524 void main()
4525 {
4526     imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4527 })";
4528 
4529     ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4530     EXPECT_GL_NO_ERROR();
4531 
4532     GLTexture color;
4533     glBindTexture(GL_TEXTURE_2D, color);
4534     glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, kSize, kSize);
4535 
4536     const std::vector<GLColor> kInitialColor(kSize * kSize, GLColor::green);
4537     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4538                     kInitialColor.data());
4539 
4540     // Setup image for compute call
4541     GLTexture computeOut;
4542     glBindTexture(GL_TEXTURE_2D, computeOut);
4543     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4544     glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4545     ASSERT_GL_NO_ERROR();
4546 
4547     // Issue a dispatch call.
4548     glUseProgram(programCS);
4549     GLint uniformLoc = glGetUniformLocation(programCS, "data");
4550     ASSERT_NE(uniformLoc, -1);
4551 
4552     glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4553     glDispatchCompute(1, 1, 1);
4554     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4555     ASSERT_GL_NO_ERROR();
4556 
4557     // Generate mipmap on the texture.  This may use a compute shader internally.
4558     glBindTexture(GL_TEXTURE_2D, color);
4559     glGenerateMipmap(GL_TEXTURE_2D);
4560 
4561     // Issue another dispatch call.
4562     glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
4563     glDispatchCompute(1, 1, 1);
4564     ASSERT_GL_NO_ERROR();
4565 
4566     // Verify the results.
4567     GLFramebuffer fbo;
4568     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4569     glBindTexture(GL_TEXTURE_2D, computeOut);
4570     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
4571     ASSERT_GL_NO_ERROR();
4572 
4573     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4574     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4575 }
4576 
4577 // Write to image array with an aliasing format.
TEST_P(ComputeShaderTest,AliasingFormatForImageArray)4578 TEST_P(ComputeShaderTest, AliasingFormatForImageArray)
4579 {
4580     // http://anglebug.com/42263894
4581     ANGLE_SKIP_TEST_IF(IsD3D11());
4582 
4583     constexpr char kCS[] = R"(#version 310 es
4584 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
4585 layout(r32ui, binding = 0) writeonly uniform highp uimage2DArray image;
4586 void main()
4587 {
4588     uint yellow = 0xFF00FFFFu;
4589     imageStore(image, ivec3(gl_LocalInvocationID.xyz), uvec4(yellow, 0, 0, 0));
4590 })";
4591 
4592     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
4593 
4594     const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);
4595 
4596     GLTexture texture;
4597     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
4598     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);
4599     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4600                     GL_UNSIGNED_BYTE, kInitData.data());
4601     EXPECT_GL_NO_ERROR();
4602 
4603     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4604     glUseProgram(program);
4605 
4606     // Output yellow to both layers.
4607     glBindImageTexture(0, texture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
4608     glDispatchCompute(1, 1, 1);
4609     EXPECT_GL_NO_ERROR();
4610 
4611     // Verify results.
4612     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4613     EXPECT_GL_NO_ERROR();
4614 
4615     GLFramebuffer framebuffer;
4616     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
4617     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);
4618     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);
4619     EXPECT_GL_NO_ERROR();
4620 
4621     glReadBuffer(GL_COLOR_ATTACHMENT0);
4622     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4623 
4624     glReadBuffer(GL_COLOR_ATTACHMENT1);
4625     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4626 }
4627 
4628 // Write to one layer of image array with an aliasing format.
TEST_P(ComputeShaderTest,AliasingFormatForOneLayerOfImageArray)4629 TEST_P(ComputeShaderTest, AliasingFormatForOneLayerOfImageArray)
4630 {
4631     // http://anglebug.com/42263894
4632     ANGLE_SKIP_TEST_IF(IsD3D11());
4633 
4634     constexpr char kCS[] = R"(#version 310 es
4635 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4636 layout(r32ui, binding = 0) writeonly uniform highp uimage2D image;
4637 void main()
4638 {
4639     uint yellow = 0xFF00FFFFu;
4640     imageStore(image, ivec2(gl_LocalInvocationID.xy), uvec4(yellow, 0, 0, 0));
4641 })";
4642 
4643     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
4644 
4645     const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);
4646 
4647     GLTexture texture;
4648     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
4649     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);
4650     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4651                     GL_UNSIGNED_BYTE, kInitData.data());
4652     EXPECT_GL_NO_ERROR();
4653 
4654     GLFramebuffer framebuffer;
4655     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
4656     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);
4657     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);
4658     EXPECT_GL_NO_ERROR();
4659 
4660     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4661     glUseProgram(program);
4662 
4663     // Output yellow to layer 0.
4664     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
4665     glDispatchCompute(1, 1, 1);
4666     EXPECT_GL_NO_ERROR();
4667 
4668     // Verify that only layer 0 was changed.
4669     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4670     EXPECT_GL_NO_ERROR();
4671 
4672     glReadBuffer(GL_COLOR_ATTACHMENT0);
4673     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4674 
4675     glReadBuffer(GL_COLOR_ATTACHMENT1);
4676     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4677 
4678     // Reset texture back to black.
4679     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4680                     GL_UNSIGNED_BYTE, kInitData.data());
4681 
4682     // Output yellow to layer 1.
4683     glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
4684     glDispatchCompute(1, 1, 1);
4685     EXPECT_GL_NO_ERROR();
4686 
4687     // Verify that only layer 1 was changed.
4688     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4689     EXPECT_GL_NO_ERROR();
4690 
4691     glReadBuffer(GL_COLOR_ATTACHMENT0);
4692     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4693 
4694     glReadBuffer(GL_COLOR_ATTACHMENT1);
4695     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4696 }
4697 
4698 // Test glMemoryBarrier(CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT) by writing to persistenly mapped
4699 // buffer from a compute shader.
TEST_P(ComputeShaderTest,WriteToPersistentBuffer)4700 TEST_P(ComputeShaderTest, WriteToPersistentBuffer)
4701 {
4702     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
4703 
4704     constexpr char kCS[] = R"(#version 310 es
4705 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4706 layout(std140, binding = 0) buffer block {
4707     uvec4 data;
4708 } outBlock;
4709 void main()
4710 {
4711     outBlock.data += uvec4(1);
4712 })";
4713 
4714     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4715     glUseProgram(program);
4716 
4717     constexpr std::array<uint32_t, 4> kInitData = {};
4718 
4719     GLBuffer coherentBuffer;
4720     glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4721     glBufferStorageEXT(
4722         GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),
4723         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
4724 
4725     GLBuffer nonCoherentBuffer;
4726     glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4727     glBufferStorageEXT(GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),
4728                        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4729 
4730     // Map the buffers for read and write.
4731     glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4732     uint32_t *coherentMapped = reinterpret_cast<uint32_t *>(glMapBufferRange(
4733         GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),
4734         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT));
4735     ASSERT_GL_NO_ERROR();
4736 
4737     glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4738     uint32_t *nonCoherentMapped = reinterpret_cast<uint32_t *>(
4739         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),
4740                          GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT));
4741     ASSERT_GL_NO_ERROR();
4742 
4743     constexpr std::array<uint32_t, 4> kCoherentExpectedData = {
4744         0x12354678u,
4745         0x2468ACE0u,
4746         0x13579BDFu,
4747         0x76543210u,
4748     };
4749 
4750     constexpr std::array<uint32_t, 4> kNonCoherentExpectedData = {
4751         0x9ABCDEF0u,
4752         0xFDB97531u,
4753         0x1F2E3D4Bu,
4754         0x5A697887u,
4755     };
4756 
4757     coherentMapped[0] = kCoherentExpectedData[0] - 1;
4758     coherentMapped[1] = kCoherentExpectedData[1] - 1;
4759     coherentMapped[2] = kCoherentExpectedData[2] - 1;
4760     coherentMapped[3] = kCoherentExpectedData[3] - 1;
4761 
4762     nonCoherentMapped[0] = kNonCoherentExpectedData[0] - 1;
4763     nonCoherentMapped[1] = kNonCoherentExpectedData[1] - 1;
4764     nonCoherentMapped[2] = kNonCoherentExpectedData[2] - 1;
4765     nonCoherentMapped[3] = kNonCoherentExpectedData[3] - 1;
4766 
4767     // Test coherent write
4768     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, coherentBuffer);
4769     glDispatchCompute(1, 1, 1);
4770     EXPECT_GL_NO_ERROR();
4771 
4772     glFinish();
4773     EXPECT_EQ(coherentMapped[0], kCoherentExpectedData[0]);
4774     EXPECT_EQ(coherentMapped[1], kCoherentExpectedData[1]);
4775     EXPECT_EQ(coherentMapped[2], kCoherentExpectedData[2]);
4776     EXPECT_EQ(coherentMapped[3], kCoherentExpectedData[3]);
4777 
4778     // Test non-coherent write
4779     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, nonCoherentBuffer);
4780     glDispatchCompute(1, 1, 1);
4781 
4782     glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT);
4783     EXPECT_GL_NO_ERROR();
4784 
4785     glFinish();
4786     EXPECT_EQ(nonCoherentMapped[0], kNonCoherentExpectedData[0]);
4787     EXPECT_EQ(nonCoherentMapped[1], kNonCoherentExpectedData[1]);
4788     EXPECT_EQ(nonCoherentMapped[2], kNonCoherentExpectedData[2]);
4789     EXPECT_EQ(nonCoherentMapped[3], kNonCoherentExpectedData[3]);
4790 
4791     glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4792     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4793     glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4794     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4795     EXPECT_GL_NO_ERROR();
4796 }
4797 
4798 // Verify the CS doesn't overwrite the mapped buffer data.
TEST_P(ComputeShaderTest,ImageBufferMapWrite)4799 TEST_P(ComputeShaderTest, ImageBufferMapWrite)
4800 {
4801     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
4802 
4803     // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
4804     // 'GL_OES_texture_buffer' is not supported".  http://anglebug.com/42264369
4805     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
4806 
4807     constexpr char kComputeImageBuffer[] = R"(#version 310 es
4808 #extension GL_OES_texture_buffer : require
4809 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4810 layout(rgba32f, binding = 0) uniform highp writeonly imageBuffer dst;
4811 uniform vec4 uniformData;
4812 void main()
4813 {
4814     imageStore(dst, int(gl_GlobalInvocationID.x), uniformData);
4815 })";
4816 
4817     GLProgram program;
4818     program.makeCompute(kComputeImageBuffer);
4819     glUseProgram(program);
4820 
4821     GLBuffer textureBufferStorage;
4822     GLTexture texture;
4823     constexpr std::array<float, 4> kInitData = {1.0, 0.0, 0.0, 1.0};
4824 
4825     glBindBuffer(GL_TEXTURE_BUFFER, textureBufferStorage);
4826     glBufferData(GL_TEXTURE_BUFFER, sizeof(kInitData), kInitData.data(), GL_STATIC_DRAW);
4827     EXPECT_GL_NO_ERROR();
4828 
4829     glBindTexture(GL_TEXTURE_BUFFER, texture);
4830     glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA32F, textureBufferStorage);
4831     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4832     EXPECT_GL_NO_ERROR();
4833 
4834     constexpr std::array<float, 4> kComputeShaderData = {0.0, 1.0, 0.0, 1.0};
4835     GLint uniformLocation = glGetUniformLocation(program, "uniformData");
4836     ASSERT_NE(uniformLocation, -1);
4837     glUniform4f(uniformLocation, kComputeShaderData[0], kComputeShaderData[1],
4838                 kComputeShaderData[2], kComputeShaderData[3]);
4839     EXPECT_GL_NO_ERROR();
4840 
4841     // Write to the buffer with the CS.
4842     glDispatchCompute(1, 1, 1);
4843 
4844     // Issue the appropriate memory barrier before mapping the buffer.
4845     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4846 
4847     // Map the buffer and write to it.
4848     constexpr std::array<float, 4> kMapData = {0.0, 0.0, 1.0, 1.0};
4849     void *mappedBuffer =
4850         glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_WRITE_BIT);
4851     memcpy(mappedBuffer, kMapData.data(), sizeof(kMapData));
4852     glUnmapBuffer(GL_TEXTURE_BUFFER);
4853 
4854     glFinish();
4855 
4856     // Read back and verify buffer data.
4857     std::array<float, 4> bufferData = {0};
4858     mappedBuffer = glMapBufferRange(GL_TEXTURE_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
4859     memcpy(bufferData.data(), mappedBuffer, sizeof(bufferData));
4860     glUnmapBuffer(GL_TEXTURE_BUFFER);
4861 
4862     EXPECT_EQ(bufferData[0], kMapData[0]);
4863     EXPECT_EQ(bufferData[1], kMapData[1]);
4864     EXPECT_EQ(bufferData[2], kMapData[2]);
4865     EXPECT_EQ(bufferData[3], kMapData[3]);
4866 }
4867 
4868 // Test compute shader write to texture buffer followed by texSubData and followed by compute shader
4869 // write to texture buffer again.
TEST_P(ComputeShaderTest,ImageBufferMapWriteAndBufferSubData)4870 TEST_P(ComputeShaderTest, ImageBufferMapWriteAndBufferSubData)
4871 {
4872     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_texture_buffer"));
4873 
4874     // Claims to support GL_OES_texture_buffer, but fails compilation of shader because "extension
4875     // 'GL_OES_texture_buffer' is not supported".  http://anglebug.com/42264369
4876     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
4877 
4878     // angleporject:6545. Known bug.
4879     ANGLE_SKIP_TEST_IF(IsVulkan());
4880 
4881     constexpr char kComputeImageBuffer[] = R"(#version 310 es
4882 #extension GL_OES_texture_buffer : require
4883 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4884 layout(rgba32f, binding = 0) uniform highp writeonly imageBuffer dst;
4885 uniform vec4 uniformData;
4886 uniform int uniformOffset;
4887 void main()
4888 {
4889     imageStore(dst, uniformOffset, uniformData);
4890 })";
4891 
4892     GLProgram program;
4893     program.makeCompute(kComputeImageBuffer);
4894     glUseProgram(program);
4895 
4896     for (int loop = 0; loop < 2; loop++)
4897     {
4898         GLBuffer textureBufferStorage;
4899         GLTexture texture;
4900         constexpr unsigned int kShaderUsedSize    = sizeof(float) * 4;
4901         constexpr unsigned int kMiddlePaddingSize = 1024;
4902         constexpr unsigned int kBufferSize = kShaderUsedSize + kMiddlePaddingSize + kShaderUsedSize;
4903         constexpr unsigned int kOffset0    = 0;
4904         constexpr unsigned int kOffset1    = kShaderUsedSize;
4905         constexpr unsigned int kOffset2    = kShaderUsedSize + kMiddlePaddingSize;
4906 
4907         glBindBuffer(GL_TEXTURE_BUFFER, textureBufferStorage);
4908         glBufferData(GL_TEXTURE_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW);
4909 
4910         glBindTexture(GL_TEXTURE_BUFFER, texture);
4911         glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA32F, textureBufferStorage);
4912         glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4913 
4914         // Write to the buffer with the CS.
4915         constexpr std::array<float, 4> kComputeShaderData1 = {0.0, 1.0, 0.0, 1.0};
4916         GLint uniformDataLocation = glGetUniformLocation(program, "uniformData");
4917         ASSERT_NE(uniformDataLocation, -1);
4918         glUniform4f(uniformDataLocation, kComputeShaderData1[0], kComputeShaderData1[1],
4919                     kComputeShaderData1[2], kComputeShaderData1[3]);
4920         GLint uniformOffsetLocation = glGetUniformLocation(program, "uniformOffset");
4921         ASSERT_NE(uniformOffsetLocation, -1);
4922         glUniform1i(uniformOffsetLocation, kOffset0 / (sizeof(float) * 4));
4923         glDispatchCompute(1, 1, 1);
4924         // Issue the appropriate memory barrier before mapping the buffer.
4925         glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4926 
4927         // Write to the buffer with the CS.
4928         constexpr std::array<float, 4> kComputeShaderData2 = {1.0, 0.0, 1.0, 1.0};
4929         glUniform4f(uniformDataLocation, kComputeShaderData2[0], kComputeShaderData2[1],
4930                     kComputeShaderData2[2], kComputeShaderData2[3]);
4931         glUniform1i(uniformOffsetLocation, kOffset2 / (sizeof(float) * 4));
4932         glDispatchCompute(1, 1, 1);
4933 
4934         if (loop == 1)
4935         {
4936             // Make write operation finished but read operation pending. We don't care actual
4937             // rendering result but just to have a unflushed rendering using the buffer so that it
4938             // will appears as pending.
4939             glFinish();
4940             constexpr char kVS[] = R"(attribute vec4 in_attrib;
4941                                     varying vec4 v_attrib;
4942                                     void main()
4943                                     {
4944                                         v_attrib = in_attrib;
4945                                         gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
4946                                         gl_PointSize = 100.0;
4947                                     })";
4948             constexpr char kFS[] = R"(precision mediump float;
4949                                     varying vec4 v_attrib;
4950                                     void main()
4951                                     {
4952                                         gl_FragColor = v_attrib;
4953                                     })";
4954             GLuint readProgram   = CompileProgram(kVS, kFS);
4955             ASSERT_NE(readProgram, 0U);
4956             GLint attribLocation = glGetAttribLocation(readProgram, "in_attrib");
4957             ASSERT_NE(attribLocation, -1);
4958             glUseProgram(readProgram);
4959             ASSERT_GL_NO_ERROR();
4960             glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
4961             glBindBuffer(GL_ARRAY_BUFFER, textureBufferStorage);
4962             glVertexAttribPointer(attribLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, 4, nullptr);
4963             glEnableVertexAttribArray(attribLocation);
4964             glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, textureBufferStorage);
4965             glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4966             glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
4967             ASSERT_GL_NO_ERROR();
4968         }
4969 
4970         // Use subData to update middle portion of data to trigger acquireAndUpdate code path in
4971         // ANGLE
4972         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4973         glBindBuffer(GL_TEXTURE_BUFFER, textureBufferStorage);
4974         constexpr unsigned int kMiddlePaddingValue = 0x55555555u;
4975         std::vector<unsigned int> kPaddingValues(kMiddlePaddingSize / sizeof(unsigned int),
4976                                                  kMiddlePaddingValue);
4977         glBufferSubData(GL_TEXTURE_BUFFER, kOffset1, kMiddlePaddingSize, kPaddingValues.data());
4978 
4979         // Read back and verify buffer data.
4980         const GLbyte *mappedBuffer = reinterpret_cast<const GLbyte *>(
4981             glMapBufferRange(GL_TEXTURE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
4982 
4983         const GLfloat *ptr0 = reinterpret_cast<const GLfloat *>(mappedBuffer);
4984         EXPECT_EQ(ptr0[0], kComputeShaderData1[0]);
4985         EXPECT_EQ(ptr0[1], kComputeShaderData1[1]);
4986         EXPECT_EQ(ptr0[2], kComputeShaderData1[2]);
4987         EXPECT_EQ(ptr0[3], kComputeShaderData1[3]);
4988 
4989         const GLuint *ptr1 = reinterpret_cast<const GLuint *>(mappedBuffer + kOffset1);
4990         for (unsigned int idx = 0; idx < kMiddlePaddingSize / sizeof(unsigned int); idx++)
4991         {
4992             EXPECT_EQ(ptr1[idx], kMiddlePaddingValue);
4993         }
4994 
4995         const GLfloat *ptr2 = reinterpret_cast<const GLfloat *>(mappedBuffer + kOffset2);
4996         EXPECT_EQ(ptr2[0], kComputeShaderData2[0]);
4997         EXPECT_EQ(ptr2[1], kComputeShaderData2[1]);
4998         EXPECT_EQ(ptr2[2], kComputeShaderData2[2]);
4999         EXPECT_EQ(ptr2[3], kComputeShaderData2[3]);
5000 
5001         glUnmapBuffer(GL_TEXTURE_BUFFER);
5002         EXPECT_GL_NO_ERROR();
5003     }
5004 }
5005 
5006 // Test one texture sampled by fragment shader, then bind it to image, followed by compute
5007 // shader load this image, and fragment shader read it again.
TEST_P(ComputeShaderTest,DrawDispatchImageReadDraw)5008 TEST_P(ComputeShaderTest, DrawDispatchImageReadDraw)
5009 {
5010 
5011     constexpr char kVSSource[] = R"(#version 310 es
5012 in vec4 a_position;
5013 out vec2 v_texCoord;
5014 
5015 void main()
5016 {
5017     gl_Position = vec4(a_position.xy, 0.0, 1.0);
5018     v_texCoord = a_position.xy * 0.5 + vec2(0.5);
5019 })";
5020 
5021     constexpr char kFSSource[] = R"(#version 310 es
5022 precision mediump float;
5023 uniform sampler2D u_tex2D;
5024 in vec2 v_texCoord;
5025 out vec4 out_FragColor;
5026 void main()
5027 {
5028     out_FragColor = texture(u_tex2D, v_texCoord);
5029 })";
5030 
5031     constexpr char kCSSource[] = R"(#version 310 es
5032 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
5033 layout(rgba32f, binding=0) readonly  uniform highp image2D uIn;
5034 layout(std140, binding=0) buffer buf {
5035     vec4 outData;
5036 };
5037 
5038 void main()
5039 {
5040     outData = imageLoad(uIn, ivec2(gl_LocalInvocationID.xy));
5041 })";
5042 
5043     GLfloat initValue[4] = {1.0, 1.0, 1.0, 1.0};
5044 
5045     // Step 1: Set up a simple 2D Texture rendering loop.
5046     GLTexture texture;
5047     glBindTexture(GL_TEXTURE_2D, texture);
5048     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
5049     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, initValue);
5050     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5051     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5052 
5053     GLBuffer vertexBuffer;
5054     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
5055     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
5056     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
5057 
5058     GLBuffer ssbo;
5059     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5060     glBufferData(GL_SHADER_STORAGE_BUFFER, 16, nullptr, GL_STREAM_DRAW);
5061     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
5062 
5063     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
5064     glUseProgram(program);
5065 
5066     GLint posLoc = glGetAttribLocation(program, "a_position");
5067     ASSERT_NE(-1, posLoc);
5068 
5069     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
5070     glEnableVertexAttribArray(posLoc);
5071     ASSERT_GL_NO_ERROR();
5072     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5073 
5074     glDrawArrays(GL_TRIANGLES, 0, 6);
5075     ASSERT_GL_NO_ERROR();
5076 
5077     // Step 2: load this image through compute
5078     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
5079     glUseProgram(csProgram);
5080 
5081     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5082     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
5083 
5084     glDispatchCompute(1, 1, 1);
5085     EXPECT_GL_NO_ERROR();
5086     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5087 
5088     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5089     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5090         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT));
5091 
5092     EXPECT_GL_NO_ERROR();
5093     for (unsigned int idx = 0; idx < 4; idx++)
5094     {
5095         EXPECT_EQ(1.0, *(ptr + idx));
5096     }
5097 
5098     // Step3: use the first program sample texture again
5099     glUseProgram(program);
5100     glDrawArrays(GL_TRIANGLES, 0, 6);
5101     ASSERT_GL_NO_ERROR();
5102 
5103     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::white);
5104 }
5105 
5106 // Test fragment shader read a image, followed by compute shader sample it.
TEST_P(ComputeShaderTest,FSReadImageThenCSSample)5107 TEST_P(ComputeShaderTest, FSReadImageThenCSSample)
5108 {
5109     GLint maxFragmentImageUniforms = 0;
5110     glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &maxFragmentImageUniforms);
5111 
5112     // MAX_FRAGMENT_IMAGE_UNIFORMS can be 0 according to OpenGL ES 3.1 SPEC.
5113     ANGLE_SKIP_TEST_IF(maxFragmentImageUniforms == 0);
5114 
5115     constexpr char kVSSource[] = R"(#version 310 es
5116 in vec4 a_position;
5117 out vec2 v_texCoord;
5118 void main()
5119 {
5120     gl_Position = vec4(a_position.xy, 0.0, 1.0);
5121     v_texCoord = a_position.xy * 0.5 + vec2(0.5);;
5122 })";
5123 
5124     constexpr char kFSSource[] = R"(#version 310 es
5125 precision mediump float;
5126 layout(rgba32f, binding=0) readonly  uniform highp image2D uIn;
5127 in vec2 v_texCoord;
5128 out vec4 out_FragColor;
5129 
5130 void main()
5131 {
5132     out_FragColor = imageLoad(uIn, ivec2(v_texCoord));
5133 })";
5134 
5135     constexpr char kCSSource[] = R"(#version 310 es
5136 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
5137 layout(std140, binding=0) buffer buf {
5138     vec4 outData;
5139 };
5140 uniform sampler2D u_tex2D;
5141 void main()
5142 {
5143     outData = texture(u_tex2D, vec2(gl_LocalInvocationID.xy));
5144 })";
5145 
5146     GLfloat initValue[4] = {1.0, 1.0, 1.0, 1.0};
5147 
5148     // Step 1: Set up a simple 2D Texture rendering loop.
5149     GLTexture texture;
5150     glBindTexture(GL_TEXTURE_2D, texture);
5151     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
5152     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, initValue);
5153     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5154     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5155 
5156     GLBuffer vertexBuffer;
5157     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
5158     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
5159     glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
5160 
5161     GLBuffer ssbo;
5162     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5163     glBufferData(GL_SHADER_STORAGE_BUFFER, 16, nullptr, GL_STREAM_DRAW);
5164     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
5165 
5166     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
5167     glUseProgram(program);
5168 
5169     GLint posLoc = glGetAttribLocation(program, "a_position");
5170     ASSERT_NE(-1, posLoc);
5171 
5172     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
5173     glEnableVertexAttribArray(posLoc);
5174     ASSERT_GL_NO_ERROR();
5175     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5176 
5177     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5178     ASSERT_GL_NO_ERROR();
5179 
5180     // Step 2: load this image through compute
5181     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
5182     glUseProgram(csProgram);
5183 
5184     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5185     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
5186 
5187     glDispatchCompute(1, 1, 1);
5188 
5189     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5190     const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
5191         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT));
5192 
5193     EXPECT_GL_NO_ERROR();
5194     for (unsigned int idx = 0; idx < 4; idx++)
5195     {
5196         EXPECT_EQ(1.0, *(ptr + idx));
5197     }
5198 }
5199 
5200 // Replicate the dEQP test dEQP-GLES31.functional.synchronization.in_invocation.ssbo_alias_overwrite
TEST_P(ComputeShaderTest,SSBOAliasOverWrite)5201 TEST_P(ComputeShaderTest, SSBOAliasOverWrite)
5202 {
5203     constexpr char kCSSource[] = R"(#version 310 es
5204     layout (local_size_x=16, local_size_y=8) in;
5205     layout(binding=0, std430) buffer Output {
5206         highp int values[];
5207     } sb_result;
5208     layout(binding=1, std430) coherent buffer Storage0
5209     {
5210         highp int values[];
5211     } sb_store0;
5212     layout(binding=2, std430) coherent buffer Storage1
5213     {
5214         highp int values[];
5215     } sb_store1;
5216 
5217     highp int getIndex(in highp uvec2 localID, in highp int element)
5218     {
5219         highp uint groupNdx = gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;
5220         return int((localID.y * gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupSize.x) + (groupNdx * gl_WorkGroupSize.x) + localID.x) * 8 + element;
5221     }
5222 
5223     void main (void)
5224     {
5225         int resultNdx = int(gl_GlobalInvocationID.y * gl_NumWorkGroups.x * gl_WorkGroupSize.x + gl_GlobalInvocationID.x);
5226         int groupNdx = int(gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x);
5227         bool allOk = true;
5228 
5229         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 0)] = 456;
5230         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 1)] = 456;
5231         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 2)] = 456;
5232         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 3)] = 456;
5233         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 4)] = 456;
5234         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 5)] = 456;
5235         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 6)] = 456;
5236         sb_store0.values[getIndex(gl_LocalInvocationID.xy, 7)] = 456;
5237 
5238         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 0)] = groupNdx;
5239         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 1)] = groupNdx;
5240         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 2)] = groupNdx;
5241         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 3)] = groupNdx;
5242         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 4)] = groupNdx;
5243         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 5)] = groupNdx;
5244         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 6)] = groupNdx;
5245         sb_store1.values[getIndex(gl_LocalInvocationID.xy, 7)] = groupNdx;
5246 
5247         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 0)] == groupNdx);
5248         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 1)] == groupNdx);
5249         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 2)] == groupNdx);
5250         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 3)] == groupNdx);
5251         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 4)] == groupNdx);
5252         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 5)] == groupNdx);
5253         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 6)] == groupNdx);
5254         allOk = allOk && (sb_store0.values[getIndex(gl_LocalInvocationID.xy, 7)] == groupNdx);
5255 
5256         sb_result.values[resultNdx] = allOk ? (1) : (2);
5257 
5258     })";
5259 
5260     const int totalWorkWidth        = 256;
5261     const int totalWorkHeight       = 256;
5262     const int elementsPerInvocation = 8;
5263 
5264     // define compute shader input storage buffer
5265     const int inputSSBOBufferSizeInBytes =
5266         totalWorkWidth * totalWorkHeight * elementsPerInvocation * sizeof(uint32_t);
5267     const int inputSSBOBufferElementsCount =
5268         totalWorkWidth * totalWorkHeight * elementsPerInvocation;
5269     std::vector<uint32_t> zeros(inputSSBOBufferElementsCount, 0);
5270     GLBuffer ssbo;
5271     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
5272     glBufferData(GL_SHADER_STORAGE_BUFFER, inputSSBOBufferSizeInBytes, zeros.data(),
5273                  GL_STATIC_DRAW);
5274     ASSERT_GL_NO_ERROR();
5275 
5276     // define compute shader output buffer
5277     const int outputBufferSizeInBytes   = totalWorkWidth * totalWorkHeight * sizeof(int32_t);
5278     const int outputBufferElementsCount = totalWorkWidth * totalWorkHeight;
5279     std::vector<int32_t> minusOnes(outputBufferElementsCount, -1);
5280     GLBuffer resultBuffer;
5281     glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5282     glBufferData(GL_SHADER_STORAGE_BUFFER, outputBufferSizeInBytes, &minusOnes[0], GL_STATIC_DRAW);
5283     ASSERT_GL_NO_ERROR();
5284 
5285     // dispatch compute shader
5286     const int localWidth  = 16;
5287     const int localHeight = 8;
5288     ASSERT(totalWorkWidth % localWidth == 0);
5289     ASSERT(totalWorkHeight % localHeight == 0);
5290     const int numGroupDimX = totalWorkWidth / localWidth;
5291     const int numGroupDimY = totalWorkHeight / localHeight;
5292 
5293     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
5294     glUseProgram(csProgram);
5295     ASSERT_GL_NO_ERROR();
5296 
5297     // Bind storage buffer to compute shader binding locations
5298     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo);
5299     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo);
5300     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
5301 
5302     glDispatchCompute(numGroupDimX, numGroupDimY, 1);
5303     ASSERT_GL_NO_ERROR();
5304 
5305     // verify the result
5306     glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5307     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5308     void *mappedResults =
5309         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSizeInBytes, GL_MAP_READ_BIT);
5310     std::vector<int32_t> results(outputBufferElementsCount);
5311     memcpy(results.data(), mappedResults, outputBufferSizeInBytes);
5312     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5313     ASSERT_GL_NO_ERROR();
5314 
5315     bool error = false;
5316     for (int index = 0; index < static_cast<int>(results.size()); ++index)
5317     {
5318         if (results[index] != 1)
5319         {
5320             error = true;
5321         }
5322     }
5323     EXPECT_EQ(false, error);
5324 }
5325 
5326 // Performs an atomic operation and assigns the previous value to an SSBO.
TEST_P(ComputeShaderTest,AtomicOpPreviousValueAssignedToSSBO)5327 TEST_P(ComputeShaderTest, AtomicOpPreviousValueAssignedToSSBO)
5328 {
5329 
5330     constexpr char kCSSource[] = R"(#version 310 es
5331     shared int wg;
5332     layout(binding = 0, std430) buffer Storage0 {
5333       int inner[16];
5334     } buf;
5335 
5336     layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
5337     void main() {
5338       wg = 0;
5339       atomicExchange(wg, 0);
5340       barrier();
5341       buf.inner[gl_WorkGroupID.x] = atomicOr(wg, 1);
5342     })";
5343 
5344     const int dispatchSize = 16;
5345 
5346     // define compute shader output buffer
5347     const int outputBufferSizeInBytes   = dispatchSize * sizeof(int32_t);
5348     const int outputBufferElementsCount = dispatchSize;
5349     std::vector<int32_t> minusOnes(outputBufferElementsCount, -1);
5350     GLBuffer resultBuffer;
5351     glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5352     glBufferData(GL_SHADER_STORAGE_BUFFER, outputBufferSizeInBytes, &minusOnes[0], GL_STATIC_DRAW);
5353     ASSERT_GL_NO_ERROR();
5354 
5355     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
5356     glUseProgram(csProgram);
5357     ASSERT_GL_NO_ERROR();
5358 
5359     // Bind storage buffer to compute shader binding locations
5360     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, resultBuffer);
5361 
5362     glDispatchCompute(dispatchSize, 1, 1);
5363     ASSERT_GL_NO_ERROR();
5364 
5365     // verify the result
5366     glBindBuffer(GL_SHADER_STORAGE_BUFFER, resultBuffer);
5367     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5368     void *mappedResults =
5369         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSizeInBytes, GL_MAP_READ_BIT);
5370     std::vector<int32_t> results(outputBufferElementsCount);
5371     memcpy(results.data(), mappedResults, outputBufferSizeInBytes);
5372     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5373     ASSERT_GL_NO_ERROR();
5374 
5375     for (int index = 0; index < static_cast<int>(results.size()); ++index)
5376     {
5377         EXPECT_EQ(results[index], 0);
5378     }
5379 }
5380 
5381 class StorageImageRenderProgramTest : public ANGLETest<>
5382 {};
5383 
5384 // Test creating a program with a vertex shader using storage image.
TEST_P(StorageImageRenderProgramTest,StorageImageInVertexShader)5385 TEST_P(StorageImageRenderProgramTest, StorageImageInVertexShader)
5386 {
5387     GLint maxVertexShaderImage = 0;
5388     glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &maxVertexShaderImage);
5389 
5390     // MAX_VERTEX_IMAGE_UNIFORMS can be 0 according to OpenGL ES 3.1 SPEC.
5391     ANGLE_SKIP_TEST_IF(maxVertexShaderImage == 0);
5392 
5393     constexpr char kVSSource_readonly[] = R"(#version 310 es
5394 layout(rgba32f, binding = 0) readonly uniform highp image2D uIn;
5395 void main()
5396 {
5397     gl_Position = imageLoad(uIn, ivec2(0, 0));
5398 })";
5399 
5400     constexpr char kVSSource_writeonly[] = R"(#version 310 es
5401 layout(rgba32f, binding = 0) writeonly uniform highp image2D uOut;
5402 void main()
5403 {
5404     gl_Position = vec4(0, 0, 0, 1);
5405     imageStore(uOut, ivec2(0, 0), vec4(0, 0, 0, 1));
5406 })";
5407 
5408     constexpr char kVSSource_readwrite[] = R"(#version 310 es
5409 layout(r32f, binding = 0) uniform highp image2D uImage;
5410 void main()
5411 {
5412     gl_Position = imageLoad(uImage, ivec2(0, 0));
5413     imageStore(uImage, ivec2(0, 0), vec4(0, 0, 0, 1));
5414 })";
5415 
5416     constexpr char kFSSource[] = R"(#version 310 es
5417 precision mediump float;
5418 out vec4 out_FragColor;
5419 void main()
5420 {
5421     out_FragColor = vec4(0, 1, 0, 1);
5422 })";
5423     ANGLE_GL_PROGRAM(program1, kVSSource_readonly, kFSSource);
5424     EXPECT_GL_NO_ERROR();
5425 
5426     ANGLE_GL_PROGRAM(program2, kVSSource_writeonly, kFSSource);
5427     EXPECT_GL_NO_ERROR();
5428 
5429     ANGLE_GL_PROGRAM(program3, kVSSource_readwrite, kFSSource);
5430     EXPECT_GL_NO_ERROR();
5431 }
5432 
5433 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest);
5434 ANGLE_INSTANTIATE_TEST_ES31(ComputeShaderTest);
5435 
5436 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTestES3);
5437 ANGLE_INSTANTIATE_TEST_ES3(ComputeShaderTestES3);
5438 
5439 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ComputeTest);
5440 ANGLE_INSTANTIATE_TEST_ES31(WebGL2ComputeTest);
5441 
5442 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StorageImageRenderProgramTest);
5443 ANGLE_INSTANTIATE_TEST_ES31(StorageImageRenderProgramTest);
5444 }  // namespace
5445