• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.get());
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.get(), "myUniformInt");
179     EXPECT_NE(-1, uniformLoc);
180 
181     uniformLoc = glGetUniformLocation(program.get(), "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.get());
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     // See http://anglebug.com/3536
401     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
402 
403     constexpr char kCS0[] = R"(#version 310 es
404 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
405 layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
406 void main()
407 {
408     atomicCounterIncrement(ac[0]);
409     atomicCounterDecrement(ac[1]);
410 })";
411 
412     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
413     glUseProgram(program0);
414 
415     unsigned int bufferData[3] = {11u, 4u, 4u};
416     GLBuffer atomicCounterBuffer;
417     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
418     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
419 
420     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
421 
422     glDispatchCompute(1, 1, 1);
423     EXPECT_GL_NO_ERROR();
424 
425     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
426     void *mappedBuffer =
427         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
428     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
429     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
430 
431     EXPECT_EQ(11u, bufferData[0]);
432     EXPECT_EQ(5u, bufferData[1]);
433     EXPECT_EQ(3u, bufferData[2]);
434 
435     constexpr char kCS1[] = R"(#version 310 es
436 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
437 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
438 void main()
439 {
440     uvec3 temp = gl_NumWorkGroups;
441     imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));
442 })";
443 
444     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
445 
446     GLTexture texture;
447     createMockOutputImage(texture, GL_RGBA32UI, 4, 3);
448 
449     glUseProgram(program1);
450     glDispatchCompute(8, 4, 2);
451 
452     glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
453     glUseProgram(program0);
454     glDispatchCompute(1, 1, 1);
455     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
456     mappedBuffer =
457         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
458     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
459     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
460 
461     EXPECT_EQ(11u, bufferData[0]);
462     EXPECT_EQ(6u, bufferData[1]);
463     EXPECT_EQ(2u, bufferData[2]);
464 
465     EXPECT_GL_NO_ERROR();
466 }
467 
468 // Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.
TEST_P(ComputeShaderTest,ImageAtomicCounterBuffer)469 TEST_P(ComputeShaderTest, ImageAtomicCounterBuffer)
470 {
471     // Flaky hang. http://anglebug.com/3636
472     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsDesktopOpenGL());
473 
474     constexpr char kCS0[] = R"(#version 310 es
475 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
476 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
477 void main()
478 {
479     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
480 0, 0));
481     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
482 0, 0));
483 })";
484 
485     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
486     glUseProgram(program0);
487     int width = 1, height = 1;
488     GLuint inputValues[] = {200};
489     GLTexture mTexture[2];
490     glBindTexture(GL_TEXTURE_2D, mTexture[0]);
491     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
492     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
493                     inputValues);
494 
495     glBindTexture(GL_TEXTURE_2D, mTexture[1]);
496     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
497     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
498                     inputValues);
499 
500     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
501     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
502 
503     glDispatchCompute(1, 1, 1);
504     EXPECT_GL_NO_ERROR();
505 
506     constexpr char kCS1[] = R"(#version 310 es
507 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
508 layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
509 void main()
510 {
511     atomicCounterIncrement(ac[0]);
512     atomicCounterDecrement(ac[1]);
513 })";
514 
515     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
516 
517     unsigned int bufferData[3] = {11u, 4u, 4u};
518     GLBuffer atomicCounterBuffer;
519     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
520     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
521 
522     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
523 
524     glUseProgram(program1);
525     glDispatchCompute(1, 1, 1);
526     EXPECT_GL_NO_ERROR();
527 
528     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
529     void *mappedBuffer =
530         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
531     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
532     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
533 
534     EXPECT_EQ(11u, bufferData[0]);
535     EXPECT_EQ(5u, bufferData[1]);
536     EXPECT_EQ(3u, bufferData[2]);
537 
538     EXPECT_GL_NO_ERROR();
539 }
540 
541 // Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.
TEST_P(ComputeShaderTest,ImageShaderStorageBuffer)542 TEST_P(ComputeShaderTest, ImageShaderStorageBuffer)
543 {
544     constexpr char kCS0[] = R"(#version 310 es
545 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
546 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
547 void main()
548 {
549     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
550 0, 0));
551     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
552 0, 0));
553 })";
554 
555     ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
556     glUseProgram(program0);
557     int width = 1, height = 1;
558     GLuint inputValues[] = {200};
559     GLTexture mTexture[2];
560     glBindTexture(GL_TEXTURE_2D, mTexture[0]);
561     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
562     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
563                     inputValues);
564 
565     glBindTexture(GL_TEXTURE_2D, mTexture[1]);
566     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
567     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
568                     inputValues);
569 
570     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
571     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
572 
573     glDispatchCompute(1, 1, 1);
574     EXPECT_GL_NO_ERROR();
575 
576     constexpr char kCS1[] =
577         R"(#version 310 es
578  layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
579  layout(std140, binding = 0) buffer blockOut {
580      uvec2 data;
581  } instanceOut;
582  layout(std140, binding = 1) buffer blockIn {
583      uvec2 data;
584  } instanceIn;
585  void main()
586  {
587      instanceOut.data = instanceIn.data;
588  }
589  )";
590 
591     ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
592 
593     constexpr unsigned int kBufferSize              = 2;
594     constexpr unsigned int kBufferData[kBufferSize] = {10, 20};
595 
596     GLBuffer blockIn;
597     glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockIn);
598     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
599     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, blockIn);
600 
601     GLBuffer blockOut;
602     glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);
603     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), nullptr, GL_STATIC_DRAW);
604     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, blockOut);
605 
606     glUseProgram(program1);
607     glDispatchCompute(1, 1, 1);
608     EXPECT_GL_NO_ERROR();
609 
610     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
611 
612     glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);
613     unsigned int bufferDataOut[kBufferSize] = {};
614     const GLColor *ptr                      = reinterpret_cast<GLColor *>(
615         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferData), GL_MAP_READ_BIT));
616     memcpy(bufferDataOut, ptr, sizeof(kBufferData));
617     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
618 
619     for (unsigned int index = 0; index < kBufferSize; ++index)
620     {
621         EXPECT_EQ(bufferDataOut[index], kBufferData[index]) << " index " << index;
622     }
623 }
624 
625 // Basic test for DispatchComputeIndirect.
TEST_P(ComputeShaderTest,DispatchComputeIndirect)626 TEST_P(ComputeShaderTest, DispatchComputeIndirect)
627 {
628     // Flaky crash on teardown, see http://anglebug.com/3349
629     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
630 
631     const char kCSSource[] = R"(#version 310 es
632 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
633 layout(r32ui, binding = 0) uniform highp uimage2D uImage;
634 void main()
635 {
636     imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
637 })";
638 
639     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
640     glUseProgram(program.get());
641     const int kWidth = 4, kHeight = 6;
642     GLuint inputValues[kWidth][kHeight] = {};
643 
644     GLBuffer buffer;
645     glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
646     GLuint params[] = {kWidth, kHeight, 1};
647     glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(params), params, GL_STATIC_DRAW);
648 
649     GLTexture texture;
650     glBindTexture(GL_TEXTURE_2D, texture);
651     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
652     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
653                     inputValues);
654     EXPECT_GL_NO_ERROR();
655 
656     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
657     EXPECT_GL_NO_ERROR();
658 
659     glDispatchComputeIndirect(0);
660     EXPECT_GL_NO_ERROR();
661 
662     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
663 
664     GLuint outputValues[kWidth][kHeight];
665 
666     GLFramebuffer framebuffer;
667     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
668     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
669     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
670     EXPECT_GL_NO_ERROR();
671 
672     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
673     EXPECT_GL_NO_ERROR();
674 
675     constexpr GLuint kExpectedValue = 100u;
676     for (int x = 0; x < kWidth; x++)
677     {
678         for (int y = 0; y < kHeight; y++)
679         {
680             EXPECT_EQ(kExpectedValue, outputValues[x][y]);
681         }
682     }
683 }
684 
685 // Test that uploading data to buffer that's in use then using it as indirect buffer works.
TEST_P(ComputeShaderTest,UseAsUBOThenUpdateThenDispatchComputeIndirect)686 TEST_P(ComputeShaderTest, UseAsUBOThenUpdateThenDispatchComputeIndirect)
687 {
688     // Flaky crash on teardown, see http://anglebug.com/3349
689     ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
690 
691     constexpr GLsizei kWidth = 4, kHeight = 6;
692 
693     const std::array<uint32_t, 4> kInitialData = {1, 2, 3, 4};
694     const std::array<uint32_t, 4> kUpdateData  = {kWidth, kHeight, 1, 0};
695 
696     GLBuffer buffer;
697     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
698     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
699     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
700     EXPECT_GL_NO_ERROR();
701 
702     constexpr char kVerifyUBO[] = R"(#version 310 es
703 precision mediump float;
704 layout(binding = 0) uniform block {
705     uvec4 data;
706 } ubo;
707 out vec4 colorOut;
708 void main()
709 {
710     if (all(equal(ubo.data, uvec4(1, 2, 3, 4))))
711         colorOut = vec4(0, 1.0, 0, 1.0);
712     else
713         colorOut = vec4(1.0, 0, 0, 1.0);
714 })";
715 
716     ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
717     drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
718     EXPECT_GL_NO_ERROR();
719 
720     // Update buffer data
721     glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
722     EXPECT_GL_NO_ERROR();
723 
724     const char kCS[] = R"(#version 310 es
725 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
726 layout(r32ui, binding = 0) uniform highp uimage2D uImage;
727 void main()
728 {
729     imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
730 })";
731 
732     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
733     glUseProgram(program.get());
734 
735     glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
736 
737     const std::vector<GLuint> inputValues(kWidth * kHeight, 0);
738 
739     GLTexture texture;
740     glBindTexture(GL_TEXTURE_2D, texture);
741     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
742     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
743                     inputValues.data());
744     EXPECT_GL_NO_ERROR();
745 
746     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
747     EXPECT_GL_NO_ERROR();
748 
749     glDispatchComputeIndirect(0);
750     EXPECT_GL_NO_ERROR();
751 
752     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
753 
754     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
755 
756     GLuint outputValues[kWidth][kHeight];
757 
758     GLFramebuffer framebuffer;
759     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
760     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
761     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
762     EXPECT_GL_NO_ERROR();
763 
764     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
765     EXPECT_GL_NO_ERROR();
766 
767     constexpr GLuint kExpectedValue = 100u;
768     for (int x = 0; x < kWidth; x++)
769     {
770         for (int y = 0; y < kHeight; y++)
771         {
772             EXPECT_EQ(kExpectedValue, outputValues[x][y]);
773         }
774     }
775 }
776 
777 // Use image uniform to write texture in compute shader, and verify the content is expected.
TEST_P(ComputeShaderTest,BindImageTexture)778 TEST_P(ComputeShaderTest, BindImageTexture)
779 {
780     GLTexture mTexture[2];
781     GLFramebuffer mFramebuffer;
782     constexpr char kCS[] = R"(#version 310 es
783 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
784 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
785 void main()
786 {
787     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
788 0, 0));
789     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
790 0, 0));
791 })";
792 
793     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
794     glUseProgram(program.get());
795     int width = 1, height = 1;
796     GLuint inputValues[] = {200};
797 
798     glBindTexture(GL_TEXTURE_2D, mTexture[0]);
799     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
800     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
801                     inputValues);
802     EXPECT_GL_NO_ERROR();
803 
804     glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
805     EXPECT_GL_NO_ERROR();
806 
807     glBindTexture(GL_TEXTURE_2D, mTexture[1]);
808     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
809     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
810                     inputValues);
811     EXPECT_GL_NO_ERROR();
812 
813     glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
814     EXPECT_GL_NO_ERROR();
815 
816     glDispatchCompute(1, 1, 1);
817     EXPECT_GL_NO_ERROR();
818 
819     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
820     glUseProgram(0);
821     GLuint outputValues[2][1];
822     GLuint expectedValue = 100;
823     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
824 
825     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
826                            0);
827     EXPECT_GL_NO_ERROR();
828     glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
829     EXPECT_GL_NO_ERROR();
830 
831     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
832                            0);
833     EXPECT_GL_NO_ERROR();
834     glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
835     EXPECT_GL_NO_ERROR();
836 
837     for (int i = 0; i < width * height; i++)
838     {
839         EXPECT_EQ(expectedValue, outputValues[0][i]);
840         EXPECT_EQ(expectedValue, outputValues[1][i]);
841     }
842 }
843 
844 // When declare a image array without a binding qualifier, all elements are bound to unit zero.
TEST_P(ComputeShaderTest,ImageArrayWithoutBindingQualifier)845 TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
846 {
847     ANGLE_SKIP_TEST_IF(IsD3D11());
848 
849     // TODO(xinghua.cao@intel.com): On AMD desktop OpenGL, bind two image variables to unit 0,
850     // only one variable is valid.
851     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
852 
853     GLTexture mTexture;
854     GLFramebuffer mFramebuffer;
855     constexpr char kCS[] = R"(#version 310 es
856 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
857 layout(r32ui) writeonly uniform highp uimage2D uImage[2];
858 void main()
859 {
860     imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
861     imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
862 })";
863 
864     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
865     glUseProgram(program.get());
866     constexpr int kTextureWidth = 1, kTextureHeight = 2;
867     GLuint inputValues[] = {200, 200};
868 
869     glBindTexture(GL_TEXTURE_2D, mTexture);
870     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
871     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
872                     GL_UNSIGNED_INT, inputValues);
873     EXPECT_GL_NO_ERROR();
874 
875     glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
876     glDispatchCompute(1, 1, 1);
877     EXPECT_GL_NO_ERROR();
878 
879     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
880     glUseProgram(0);
881     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
882 
883     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
884     GLuint outputValues[kTextureWidth * kTextureHeight];
885     glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
886                  outputValues);
887     EXPECT_GL_NO_ERROR();
888 
889     GLuint expectedValue = 100;
890     for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
891     {
892         EXPECT_EQ(expectedValue, outputValues[i]);
893     }
894 }
895 
896 // When an image array is declared without a binding qualifier, all elements are bound to unit zero.
897 // Check that the unused uniform image array element does not cause any corruption. Checks for a bug
898 // where unused element could make the whole array seem as unused.
TEST_P(ComputeShaderTest,ImageArrayUnusedElement)899 TEST_P(ComputeShaderTest, ImageArrayUnusedElement)
900 {
901     ANGLE_SKIP_TEST_IF(IsD3D11());
902 
903     // TODO(xinghua.cao@intel.com): On AMD desktop OpenGL, bind two image variables to unit 0,
904     // only one variable is valid.
905     ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
906 
907     // Vulkan is currently unable to handle unbound image units in compute shaders.
908     // http://anglebug.com/5026
909     ANGLE_SKIP_TEST_IF(IsVulkan());
910 
911     GLFramebuffer framebuffer;
912     constexpr char kCS[] = R"(#version 310 es
913 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
914 layout(r32ui, binding=0) writeonly uniform highp uimage2D uOut;
915 layout(r32ui, binding=1) readonly uniform highp uimage2D uIn[2];
916 
917 void main()
918 {
919     uvec4 inValue = imageLoad(uIn[0], ivec2(gl_LocalInvocationID.xy));
920     imageStore(uOut, ivec2(gl_LocalInvocationIndex, 0), inValue);
921     imageStore(uOut, ivec2(gl_LocalInvocationIndex, 1), inValue);
922 })";
923 
924     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
925     glUseProgram(program.get());
926     constexpr int kTextureWidth = 1, kTextureHeight = 2;
927     GLuint inputValues[] = {100, 100};
928     GLTexture in;
929     glBindTexture(GL_TEXTURE_2D, in);
930     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
931     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
932                     GL_UNSIGNED_INT, inputValues);
933     EXPECT_GL_NO_ERROR();
934     glBindImageTexture(1, in, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
935 
936     GLuint initValues[] = {111, 111};
937     GLTexture out;
938     glBindTexture(GL_TEXTURE_2D, out);
939     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
940     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
941                     GL_UNSIGNED_INT, initValues);
942     EXPECT_GL_NO_ERROR();
943 
944     glBindImageTexture(0, out, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
945     glDispatchCompute(1, 1, 1);
946     EXPECT_GL_NO_ERROR();
947 
948     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
949     glUseProgram(0);
950     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
951 
952     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, out, 0);
953     GLuint outputValues[kTextureWidth * kTextureHeight];
954     glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
955                  outputValues);
956     EXPECT_GL_NO_ERROR();
957 
958     GLuint expectedValue = 100;
959     for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
960     {
961         EXPECT_EQ(expectedValue, outputValues[i]);
962     }
963 }
964 // imageLoad functions
TEST_P(ComputeShaderTest,ImageLoad)965 TEST_P(ComputeShaderTest, ImageLoad)
966 {
967     constexpr char kCS[] = R"(#version 310 es
968 layout(local_size_x=8) in;
969 layout(rgba8) uniform highp readonly image2D mImage2DInput;
970 layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
971 layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
972 layout(r32i) uniform highp writeonly iimage2D imageOut;
973 void main()
974 {
975     vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
976     ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
977     uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
978     imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
979 })";
980 
981     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
982     EXPECT_GL_NO_ERROR();
983 }
984 
985 // imageStore functions
TEST_P(ComputeShaderTest,ImageStore)986 TEST_P(ComputeShaderTest, ImageStore)
987 {
988     constexpr char kCS[] = R"(#version 310 es
989 layout(local_size_x=8) in;
990 layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
991 layout(r32f) uniform highp writeonly image3D mImage3DOutput;
992 layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
993 void main()
994 {
995     imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
996     imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
997     imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
998 })";
999 
1000     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1001     EXPECT_GL_NO_ERROR();
1002 }
1003 
1004 // imageSize functions
TEST_P(ComputeShaderTest,ImageSize)1005 TEST_P(ComputeShaderTest, ImageSize)
1006 {
1007     constexpr char kCS[] = R"(#version 310 es
1008 layout(local_size_x=8) in;
1009 layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
1010 layout(r32i) uniform highp readonly iimage2D mImage2DInput;
1011 layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
1012 layout(r32i) uniform highp writeonly iimage2D imageOut;
1013 void main()
1014 {
1015     ivec2 sizeCube = imageSize(mImageCubeInput);
1016     ivec2 size2D = imageSize(mImage2DInput);
1017     ivec3 size2DArray = imageSize(mImage2DArrayInput);
1018     imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
1019 })";
1020 
1021     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1022     EXPECT_GL_NO_ERROR();
1023 }
1024 
1025 // Test that texelFetch works well in compute shader.
TEST_P(ComputeShaderTest,TexelFetchFunction)1026 TEST_P(ComputeShaderTest, TexelFetchFunction)
1027 {
1028     // http://anglebug.com/4092
1029     ANGLE_SKIP_TEST_IF(isSwiftshader());
1030     constexpr char kCS[] = R"(#version 310 es
1031 layout(local_size_x=16, local_size_y=12) in;
1032 precision highp usampler2D;
1033 uniform usampler2D tex;
1034 layout(std140, binding = 0) buffer buf {
1035     uint outData[12][16];
1036 };
1037 
1038 void main()
1039 {
1040     uint x = gl_LocalInvocationID.x;
1041     uint y = gl_LocalInvocationID.y;
1042     outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;
1043 })";
1044 
1045     constexpr unsigned int kWidth  = 16;
1046     constexpr unsigned int kHeight = 12;
1047     GLTexture tex;
1048     glBindTexture(GL_TEXTURE_2D, tex);
1049     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1050     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1051     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1052     GLuint texels[kHeight][kWidth] = {{0}};
1053     for (unsigned int y = 0; y < kHeight; ++y)
1054     {
1055         for (unsigned int x = 0; x < kWidth; ++x)
1056         {
1057             texels[y][x] = x + y * kWidth;
1058         }
1059     }
1060     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1061     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1062                     texels);
1063     glBindTexture(GL_TEXTURE_2D, 0);
1064 
1065     // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1066     constexpr unsigned int kArrayStride = 16;
1067     GLBuffer ssbo;
1068     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1069     glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
1070                  GL_STREAM_DRAW);
1071     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1072     EXPECT_GL_NO_ERROR();
1073 
1074     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1075     glUseProgram(program);
1076 
1077     glActiveTexture(GL_TEXTURE0);
1078     glBindTexture(GL_TEXTURE_2D, tex);
1079     glUniform1i(glGetUniformLocation(program, "tex"), 0);
1080     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1081     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
1082 
1083     glDispatchCompute(1, 1, 1);
1084 
1085     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1086     const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1087         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
1088     EXPECT_GL_NO_ERROR();
1089     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
1090     {
1091         EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));
1092     }
1093 }
1094 
1095 // Test that texture function works well in compute shader.
TEST_P(ComputeShaderTest,TextureFunction)1096 TEST_P(ComputeShaderTest, TextureFunction)
1097 {
1098     // http://anglebug.com/4092
1099     ANGLE_SKIP_TEST_IF(isSwiftshader());
1100     constexpr char kCS[] = R"(#version 310 es
1101 layout(local_size_x=16, local_size_y=16) in;
1102 precision highp usampler2D;
1103 uniform usampler2D tex;
1104 layout(std140, binding = 0) buffer buf {
1105     uint outData[16][16];
1106 };
1107 
1108 void main()
1109 {
1110     uint x = gl_LocalInvocationID.x;
1111     uint y = gl_LocalInvocationID.y;
1112     float xCoord = float(x) / float(16);
1113     float yCoord = float(y) / float(16);
1114     outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x;
1115 })";
1116 
1117     constexpr unsigned int kWidth  = 16;
1118     constexpr unsigned int kHeight = 16;
1119     GLTexture tex;
1120     glBindTexture(GL_TEXTURE_2D, tex);
1121     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1122     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1123     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1124     GLuint texels[kHeight][kWidth] = {{0}};
1125     for (unsigned int y = 0; y < kHeight; ++y)
1126     {
1127         for (unsigned int x = 0; x < kWidth; ++x)
1128         {
1129             texels[y][x] = x + y * kWidth;
1130         }
1131     }
1132     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1133     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1134                     texels);
1135     glBindTexture(GL_TEXTURE_2D, 0);
1136 
1137     // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1138     constexpr unsigned int kArrayStride = 16;
1139     GLBuffer ssbo;
1140     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1141     glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
1142                  GL_STREAM_DRAW);
1143     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1144     EXPECT_GL_NO_ERROR();
1145 
1146     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1147     glUseProgram(program);
1148 
1149     glActiveTexture(GL_TEXTURE0);
1150     glBindTexture(GL_TEXTURE_2D, tex);
1151     glUniform1i(glGetUniformLocation(program, "tex"), 0);
1152     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1153     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
1154 
1155     glDispatchCompute(1, 1, 1);
1156 
1157     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1158     const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1159         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
1160     EXPECT_GL_NO_ERROR();
1161     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
1162     {
1163         EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));
1164     }
1165 }
1166 
1167 // Test mixed use of sampler and image.
TEST_P(ComputeShaderTest,SamplingAndImageReadWrite)1168 TEST_P(ComputeShaderTest, SamplingAndImageReadWrite)
1169 {
1170     GLTexture texture[3];
1171     GLFramebuffer framebuffer;
1172     constexpr char kCS[] = R"(#version 310 es
1173 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1174 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1175 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1176 precision highp usampler2D;
1177 uniform usampler2D tex;
1178 void main()
1179 {
1180     uvec4 value_1 = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
1181     uvec4 value_2 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1182     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value_1 + value_2);
1183 })";
1184 
1185     constexpr int kWidth = 1, kHeight = 1;
1186     constexpr GLuint kInputValues[3][1] = {{50}, {100}, {20}};
1187 
1188     glBindTexture(GL_TEXTURE_2D, texture[0]);
1189     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1190     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1191                     kInputValues[0]);
1192     glBindTexture(GL_TEXTURE_2D, texture[2]);
1193     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1194     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1195                     kInputValues[2]);
1196     EXPECT_GL_NO_ERROR();
1197     glBindTexture(GL_TEXTURE_2D, 0);
1198 
1199     glBindTexture(GL_TEXTURE_2D, texture[1]);
1200     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1201     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1202     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1203     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1204     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1205                     kInputValues[1]);
1206 
1207     EXPECT_GL_NO_ERROR();
1208 
1209     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1210     glUseProgram(program.get());
1211 
1212     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1213     glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1214     EXPECT_GL_NO_ERROR();
1215 
1216     glDispatchCompute(1, 1, 1);
1217     EXPECT_GL_NO_ERROR();
1218 
1219     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1220     GLuint outputValues[kWidth * kHeight];
1221     constexpr GLuint expectedValue = 150;
1222     glUseProgram(0);
1223     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1224 
1225     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
1226     EXPECT_GL_NO_ERROR();
1227     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1228     EXPECT_GL_NO_ERROR();
1229 
1230     for (int i = 0; i < kWidth * kHeight; i++)
1231     {
1232         EXPECT_EQ(expectedValue, outputValues[i]);
1233     }
1234 }
1235 
1236 // Use image uniform to read and write Texture2D in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTexture2D)1237 TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
1238 {
1239     GLTexture texture[2];
1240     GLFramebuffer framebuffer;
1241     constexpr char kCS[] = R"(#version 310 es
1242 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1243 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1244 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1245 void main()
1246 {
1247     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1248     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1249 })";
1250 
1251     constexpr int kWidth = 1, kHeight = 1;
1252     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1253 
1254     glBindTexture(GL_TEXTURE_2D, texture[0]);
1255     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1256     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1257                     kInputValues[0]);
1258     EXPECT_GL_NO_ERROR();
1259 
1260     glBindTexture(GL_TEXTURE_2D, texture[1]);
1261     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1262     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1263                     kInputValues[1]);
1264     EXPECT_GL_NO_ERROR();
1265 
1266     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1267     glUseProgram(program.get());
1268 
1269     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1270     EXPECT_GL_NO_ERROR();
1271 
1272     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1273     EXPECT_GL_NO_ERROR();
1274 
1275     glDispatchCompute(1, 1, 1);
1276     EXPECT_GL_NO_ERROR();
1277 
1278     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1279     GLuint outputValues[kWidth * kHeight];
1280     constexpr GLuint expectedValue = 200;
1281     glUseProgram(0);
1282     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1283 
1284     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
1285     EXPECT_GL_NO_ERROR();
1286     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1287     EXPECT_GL_NO_ERROR();
1288 
1289     for (int i = 0; i < kWidth * kHeight; i++)
1290     {
1291         EXPECT_EQ(expectedValue, outputValues[i]);
1292     }
1293 }
1294 
1295 // Use image uniform to read and write Texture2D with non-zero base in compute shader, and verify
1296 // the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithNonZeroBaseTexture2D)1297 TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2D)
1298 {
1299     GLTexture texture[2];
1300     GLFramebuffer framebuffer;
1301     constexpr char kCS[] = R"(#version 310 es
1302 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1303 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1304 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1305 void main()
1306 {
1307     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1308     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1309 })";
1310 
1311     constexpr int kWidth = 1, kHeight = 1;
1312     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1313 
1314     glBindTexture(GL_TEXTURE_2D, texture[0]);
1315     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
1316     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1317                     kInputValues[0]);
1318     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1319     EXPECT_GL_NO_ERROR();
1320 
1321     glBindTexture(GL_TEXTURE_2D, texture[1]);
1322     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
1323     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1324                     kInputValues[1]);
1325     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1326     EXPECT_GL_NO_ERROR();
1327 
1328     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1329     glUseProgram(program.get());
1330 
1331     glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1332     EXPECT_GL_NO_ERROR();
1333 
1334     glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1335     EXPECT_GL_NO_ERROR();
1336 
1337     glDispatchCompute(1, 1, 1);
1338     EXPECT_GL_NO_ERROR();
1339 
1340     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1341     GLuint outputValues[kWidth * kHeight];
1342     constexpr GLuint expectedValue = 200;
1343     glUseProgram(0);
1344     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1345 
1346     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
1347     EXPECT_GL_NO_ERROR();
1348     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1349     EXPECT_GL_NO_ERROR();
1350 
1351     for (int i = 0; i < kWidth * kHeight; i++)
1352     {
1353         EXPECT_EQ(expectedValue, outputValues[i]) << "  at index: " << i;
1354     }
1355 }
1356 
1357 // Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTexture2DArray)1358 TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
1359 {
1360     GLTexture texture[2];
1361     GLFramebuffer framebuffer;
1362     constexpr char kCS[] = R"(#version 310 es
1363 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
1364 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
1365 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
1366 void main()
1367 {
1368     uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1369     imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1370 })";
1371 
1372     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1373     constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1374 
1375     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1376     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1377     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1378                     GL_UNSIGNED_INT, kInputValues[0]);
1379     EXPECT_GL_NO_ERROR();
1380 
1381     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1382     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1383     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1384                     GL_UNSIGNED_INT, kInputValues[1]);
1385     EXPECT_GL_NO_ERROR();
1386 
1387     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1388     glUseProgram(program.get());
1389 
1390     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1391     EXPECT_GL_NO_ERROR();
1392 
1393     glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1394     EXPECT_GL_NO_ERROR();
1395 
1396     glDispatchCompute(1, 1, 1);
1397     EXPECT_GL_NO_ERROR();
1398 
1399     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1400     GLuint outputValues[kWidth * kHeight];
1401     constexpr GLuint expectedValue = 200;
1402     glUseProgram(0);
1403     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1404 
1405     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1406     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1407     EXPECT_GL_NO_ERROR();
1408     glReadBuffer(GL_COLOR_ATTACHMENT0);
1409     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1410     EXPECT_GL_NO_ERROR();
1411     for (int i = 0; i < kWidth * kHeight; i++)
1412     {
1413         EXPECT_EQ(expectedValue, outputValues[i]);
1414     }
1415     glReadBuffer(GL_COLOR_ATTACHMENT1);
1416     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1417     EXPECT_GL_NO_ERROR();
1418     for (int i = 0; i < kWidth * kHeight; i++)
1419     {
1420         EXPECT_EQ(expectedValue, outputValues[i]);
1421     }
1422 }
1423 
1424 // Use image uniform to read and write Texture2DArray with non-zero base in compute shader, and
1425 // verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithNonZeroBaseTexture2DArray)1426 TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2DArray)
1427 {
1428     GLTexture texture[2];
1429     GLFramebuffer framebuffer;
1430     constexpr char kCS[] = R"(#version 310 es
1431 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
1432 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
1433 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
1434 void main()
1435 {
1436     uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1437     imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1438 })";
1439 
1440     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1441     constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1442 
1443     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1444     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
1445     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1446                     GL_UNSIGNED_INT, kInputValues[0]);
1447     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
1448     EXPECT_GL_NO_ERROR();
1449 
1450     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1451     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
1452     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1453                     GL_UNSIGNED_INT, kInputValues[1]);
1454     glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
1455     EXPECT_GL_NO_ERROR();
1456 
1457     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1458     glUseProgram(program.get());
1459 
1460     glBindImageTexture(0, texture[0], 1, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1461     EXPECT_GL_NO_ERROR();
1462 
1463     glBindImageTexture(1, texture[1], 1, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1464     EXPECT_GL_NO_ERROR();
1465 
1466     glDispatchCompute(1, 1, 1);
1467     EXPECT_GL_NO_ERROR();
1468 
1469     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1470     GLuint outputValues[kWidth * kHeight];
1471     constexpr GLuint expectedValue = 200;
1472     glUseProgram(0);
1473     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1474 
1475     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 1, 0);
1476     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 1, 1);
1477     EXPECT_GL_NO_ERROR();
1478     glReadBuffer(GL_COLOR_ATTACHMENT0);
1479     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1480     EXPECT_GL_NO_ERROR();
1481     for (int i = 0; i < kWidth * kHeight; i++)
1482     {
1483         EXPECT_EQ(expectedValue, outputValues[i]);
1484     }
1485     glReadBuffer(GL_COLOR_ATTACHMENT1);
1486     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1487     EXPECT_GL_NO_ERROR();
1488     for (int i = 0; i < kWidth * kHeight; i++)
1489     {
1490         EXPECT_EQ(expectedValue, outputValues[i]);
1491     }
1492 }
1493 
1494 // Use image uniform to read and write Texture3D in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTexture3D)1495 TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
1496 {
1497     GLTexture texture[2];
1498     GLFramebuffer framebuffer;
1499     constexpr char kCS[] = R"(#version 310 es
1500 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
1501 layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
1502 layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
1503 void main()
1504 {
1505     uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1506     imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1507 })";
1508 
1509     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1510     constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1511 
1512     glBindTexture(GL_TEXTURE_3D, texture[0]);
1513     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1514     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1515                     GL_UNSIGNED_INT, kInputValues[0]);
1516     EXPECT_GL_NO_ERROR();
1517 
1518     glBindTexture(GL_TEXTURE_3D, texture[1]);
1519     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1520     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1521                     GL_UNSIGNED_INT, kInputValues[1]);
1522     EXPECT_GL_NO_ERROR();
1523 
1524     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1525     glUseProgram(program.get());
1526 
1527     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1528     EXPECT_GL_NO_ERROR();
1529 
1530     glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1531     EXPECT_GL_NO_ERROR();
1532 
1533     glDispatchCompute(1, 1, 1);
1534     EXPECT_GL_NO_ERROR();
1535 
1536     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1537     GLuint outputValues[kWidth * kHeight];
1538     constexpr GLuint expectedValue = 200;
1539     glUseProgram(0);
1540     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1541 
1542     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1543     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1544     EXPECT_GL_NO_ERROR();
1545     glReadBuffer(GL_COLOR_ATTACHMENT0);
1546     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1547     EXPECT_GL_NO_ERROR();
1548     for (int i = 0; i < kWidth * kHeight; i++)
1549     {
1550         EXPECT_EQ(expectedValue, outputValues[i]);
1551     }
1552     glReadBuffer(GL_COLOR_ATTACHMENT1);
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 }
1560 
1561 // Use image uniform to read and write TextureCube in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,BindImageTextureWithTextureCube)1562 TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
1563 {
1564     GLTexture texture[2];
1565     GLFramebuffer framebuffer;
1566     constexpr char kCS[] = R"(#version 310 es
1567 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1568 layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
1569 layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
1570 void main()
1571 {
1572     for (int i = 0; i < 6; i++)
1573     {
1574         uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
1575         imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
1576     }
1577 })";
1578 
1579     constexpr int kWidth = 1, kHeight = 1;
1580     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1581 
1582     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1583     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1584     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1585          face++)
1586     {
1587         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1588                         kInputValues[0]);
1589     }
1590     EXPECT_GL_NO_ERROR();
1591 
1592     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1593     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1594     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1595          face++)
1596     {
1597         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1598                         kInputValues[1]);
1599     }
1600     EXPECT_GL_NO_ERROR();
1601 
1602     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1603     glUseProgram(program.get());
1604 
1605     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1606     EXPECT_GL_NO_ERROR();
1607 
1608     glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1609     EXPECT_GL_NO_ERROR();
1610 
1611     glDispatchCompute(1, 1, 1);
1612     EXPECT_GL_NO_ERROR();
1613 
1614     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1615     GLuint outputValues[kWidth * kHeight];
1616     constexpr GLuint expectedValue = 200;
1617     glUseProgram(0);
1618     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1619 
1620     for (GLenum face = 0; face < 6; face++)
1621     {
1622         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1623                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1624         EXPECT_GL_NO_ERROR();
1625         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1626         EXPECT_GL_NO_ERROR();
1627 
1628         for (int i = 0; i < kWidth * kHeight; i++)
1629         {
1630             EXPECT_EQ(expectedValue, outputValues[i]);
1631         }
1632     }
1633 }
1634 
1635 // Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
1636 // contents.
TEST_P(ComputeShaderTest,BindImageTextureWithOneLayerTexture2DArray)1637 TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
1638 {
1639     GLTexture texture[2];
1640     GLFramebuffer framebuffer;
1641     constexpr char kCS[] = R"(#version 310 es
1642 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1643 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1644 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1645 void main()
1646 {
1647     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1648     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1649 })";
1650 
1651     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1652     constexpr int kResultSize           = kWidth * kHeight;
1653     constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1654     constexpr GLuint expectedValue_1    = 200;
1655     constexpr GLuint expectedValue_2    = 100;
1656     GLuint outputValues[kResultSize];
1657 
1658     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1659     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1660     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1661                     GL_UNSIGNED_INT, kInputValues[0]);
1662     EXPECT_GL_NO_ERROR();
1663 
1664     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1665     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1666     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1667                     GL_UNSIGNED_INT, kInputValues[1]);
1668     EXPECT_GL_NO_ERROR();
1669 
1670     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1671     glUseProgram(program.get());
1672 
1673     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1674     EXPECT_GL_NO_ERROR();
1675     glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
1676     EXPECT_GL_NO_ERROR();
1677     glDispatchCompute(1, 1, 1);
1678     EXPECT_GL_NO_ERROR();
1679 
1680     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1681     glUseProgram(0);
1682     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1683     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1684     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1685     EXPECT_GL_NO_ERROR();
1686     glReadBuffer(GL_COLOR_ATTACHMENT0);
1687     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1688     EXPECT_GL_NO_ERROR();
1689     for (int i = 0; i < kResultSize; i++)
1690     {
1691         EXPECT_EQ(expectedValue_2, outputValues[i]);
1692     }
1693     glReadBuffer(GL_COLOR_ATTACHMENT1);
1694     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1695     EXPECT_GL_NO_ERROR();
1696     for (int i = 0; i < kResultSize; i++)
1697     {
1698         EXPECT_EQ(expectedValue_1, outputValues[i]);
1699     }
1700 }
1701 
1702 // Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
1703 // contents.
TEST_P(ComputeShaderTest,BindImageTextureWithOneLayerTexture3D)1704 TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
1705 {
1706     // Vulkan validation error creating a 2D image view of a 3D image layer.
1707     // http://anglebug.com/3886
1708     ANGLE_SKIP_TEST_IF(IsVulkan());
1709 
1710     GLTexture texture[2];
1711     GLFramebuffer framebuffer;
1712     constexpr char kCS[] = R"(#version 310 es
1713 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1714 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1715 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1716 void main()
1717 {
1718     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1719     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1720 })";
1721 
1722     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1723     constexpr int kResultSize           = kWidth * kHeight;
1724     constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1725     constexpr GLuint expectedValue_1    = 150;
1726     constexpr GLuint expectedValue_2    = 50;
1727     GLuint outputValues[kResultSize];
1728 
1729     glBindTexture(GL_TEXTURE_3D, texture[0]);
1730     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1731     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1732                     GL_UNSIGNED_INT, kInputValues[0]);
1733     EXPECT_GL_NO_ERROR();
1734 
1735     glBindTexture(GL_TEXTURE_3D, texture[1]);
1736     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1737     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1738                     GL_UNSIGNED_INT, kInputValues[1]);
1739     EXPECT_GL_NO_ERROR();
1740 
1741     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1742     glUseProgram(program.get());
1743 
1744     glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1745     EXPECT_GL_NO_ERROR();
1746     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1747     EXPECT_GL_NO_ERROR();
1748     glDispatchCompute(1, 1, 1);
1749     EXPECT_GL_NO_ERROR();
1750 
1751     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1752     glUseProgram(0);
1753     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1754     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1755     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1756     EXPECT_GL_NO_ERROR();
1757     glReadBuffer(GL_COLOR_ATTACHMENT0);
1758     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1759     EXPECT_GL_NO_ERROR();
1760     for (int i = 0; i < kResultSize; i++)
1761     {
1762         EXPECT_EQ(expectedValue_1, outputValues[i]);
1763     }
1764     glReadBuffer(GL_COLOR_ATTACHMENT1);
1765     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1766     EXPECT_GL_NO_ERROR();
1767     for (int i = 0; i < kResultSize; i++)
1768     {
1769         EXPECT_EQ(expectedValue_2, outputValues[i]);
1770     }
1771 }
1772 
1773 // Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1774 // contents.
TEST_P(ComputeShaderTest,BindImageTextureWithOneLayerTextureCube)1775 TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1776 {
1777     // GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.
1778     // http://anglebug.com/3736
1779     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());
1780 
1781     GLTexture texture[2];
1782     GLFramebuffer framebuffer;
1783     constexpr char kCS[] = R"(#version 310 es
1784 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1785 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1786 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1787 void main()
1788 {
1789     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1790     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1791 })";
1792 
1793     constexpr int kWidth = 1, kHeight = 1;
1794     constexpr int kResultSize           = kWidth * kHeight;
1795     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1796     constexpr GLuint expectedValue_1    = 200;
1797     constexpr GLuint expectedValue_2    = 100;
1798     GLuint outputValues[kResultSize];
1799 
1800     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1801     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1802     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1803          face++)
1804     {
1805         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1806                         kInputValues[0]);
1807     }
1808     EXPECT_GL_NO_ERROR();
1809 
1810     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1811     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1812     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1813          face++)
1814     {
1815         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1816                         kInputValues[1]);
1817     }
1818     EXPECT_GL_NO_ERROR();
1819 
1820     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1821     glUseProgram(program.get());
1822 
1823     glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1824     EXPECT_GL_NO_ERROR();
1825     glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1826     EXPECT_GL_NO_ERROR();
1827     glDispatchCompute(1, 1, 1);
1828     EXPECT_GL_NO_ERROR();
1829 
1830     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1831     glUseProgram(0);
1832     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1833 
1834     for (GLenum face = 0; face < 6; face++)
1835     {
1836         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1837                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1838         EXPECT_GL_NO_ERROR();
1839         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1840         EXPECT_GL_NO_ERROR();
1841 
1842         if (face == 4)
1843         {
1844             for (int i = 0; i < kResultSize; i++)
1845             {
1846                 EXPECT_EQ(expectedValue_1, outputValues[i]);
1847             }
1848         }
1849         else
1850         {
1851             for (int i = 0; i < kResultSize; i++)
1852             {
1853                 EXPECT_EQ(expectedValue_2, outputValues[i]);
1854             }
1855         }
1856     }
1857 }
1858 
1859 // Test to bind kinds of texture types, bind either the entire texture
1860 // level or a single layer or face of the face level.
TEST_P(ComputeShaderTest,BindImageTextureWithMixTextureTypes)1861 TEST_P(ComputeShaderTest, BindImageTextureWithMixTextureTypes)
1862 {
1863     // GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.
1864     // http://anglebug.com/3736
1865     ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());
1866 
1867     // http://anglebug.com/5072
1868     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
1869 
1870     GLTexture texture[4];
1871     GLFramebuffer framebuffer;
1872     const char csSource[] =
1873         R"(#version 310 es
1874         layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1875         layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1876         layout(r32ui, binding = 1) readonly uniform highp uimage2D uImage_2;
1877         layout(r32ui, binding = 2) readonly uniform highp uimage3D uImage_3;
1878         layout(r32ui, binding = 3) writeonly uniform highp uimage2D uImage_4;
1879         void main()
1880         {
1881             uvec4 value_1 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1882             uvec4 value_2 = imageLoad(uImage_2, ivec2(gl_LocalInvocationID.xy));
1883             uvec4 value_3 = imageLoad(uImage_3, ivec3(gl_LocalInvocationID.xyz));
1884             imageStore(uImage_4, ivec2(gl_LocalInvocationID.xy), value_1 + value_2 + value_3);
1885         })";
1886 
1887     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1888     constexpr int kResultSize               = kWidth * kHeight;
1889     constexpr GLuint kInputValues2D[1]      = {11};
1890     constexpr GLuint KInputValues2DArray[2] = {23, 35};
1891     constexpr GLuint KInputValues3D[2]      = {102, 67};
1892     constexpr GLuint KInputValuesCube[1]    = {232};
1893 
1894     constexpr GLuint expectedValue_1 = 148;
1895     constexpr GLuint expectedValue_2 = 232;
1896     GLuint outputValues[kResultSize];
1897 
1898     glBindTexture(GL_TEXTURE_2D, texture[0]);
1899     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1900     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1901                     kInputValues2D);
1902     EXPECT_GL_NO_ERROR();
1903 
1904     glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1905     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1906     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1907                     GL_UNSIGNED_INT, KInputValues2DArray);
1908     EXPECT_GL_NO_ERROR();
1909 
1910     glBindTexture(GL_TEXTURE_3D, texture[2]);
1911     glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1912     glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1913                     GL_UNSIGNED_INT, KInputValues3D);
1914     EXPECT_GL_NO_ERROR();
1915 
1916     glBindTexture(GL_TEXTURE_CUBE_MAP, texture[3]);
1917     glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1918     for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1919          face++)
1920     {
1921         glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1922                         KInputValuesCube);
1923     }
1924     EXPECT_GL_NO_ERROR();
1925 
1926     ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1927     glUseProgram(program.get());
1928 
1929     glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1930     EXPECT_GL_NO_ERROR();
1931     glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1932     EXPECT_GL_NO_ERROR();
1933     glBindImageTexture(2, texture[2], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1934     EXPECT_GL_NO_ERROR();
1935     glBindImageTexture(3, texture[3], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1936     EXPECT_GL_NO_ERROR();
1937     glDispatchCompute(1, 1, 1);
1938     EXPECT_GL_NO_ERROR();
1939 
1940     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1941     glUseProgram(0);
1942     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1943 
1944     for (GLenum face = 0; face < 6; face++)
1945     {
1946         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1947                                GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[3], 0);
1948         EXPECT_GL_NO_ERROR();
1949         glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1950         EXPECT_GL_NO_ERROR();
1951 
1952         if (face == 4)
1953         {
1954             for (int i = 0; i < kResultSize; i++)
1955             {
1956                 EXPECT_EQ(expectedValue_1, outputValues[i]);
1957             }
1958         }
1959         else
1960         {
1961             for (int i = 0; i < kResultSize; i++)
1962             {
1963                 EXPECT_EQ(expectedValue_2, outputValues[i]);
1964             }
1965         }
1966     }
1967 }
1968 
1969 // Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
1970 // program which has not been linked successfully or which does not contain objects to form a
1971 // compute shader.
TEST_P(ComputeShaderTest,QueryComputeWorkGroupSize)1972 TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
1973 {
1974     constexpr char kVS[] = R"(#version 310 es
1975 void main()
1976 {
1977 })";
1978 
1979     constexpr char kFS[] = R"(#version 310 es
1980 void main()
1981 {
1982 })";
1983 
1984     GLint workGroupSize[3];
1985 
1986     ANGLE_GL_PROGRAM(graphicsProgram, kVS, kFS);
1987     glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1988     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1989 
1990     GLuint computeProgram = glCreateProgram();
1991     GLShader computeShader(GL_COMPUTE_SHADER);
1992     glAttachShader(computeProgram, computeShader);
1993     glLinkProgram(computeProgram);
1994     glDetachShader(computeProgram, computeShader);
1995 
1996     GLint linkStatus;
1997     glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
1998     ASSERT_GL_FALSE(linkStatus);
1999 
2000     glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
2001     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2002 
2003     glDeleteProgram(computeProgram);
2004 
2005     ASSERT_GL_NO_ERROR();
2006 }
2007 
2008 // Use groupMemoryBarrier and barrier to sync reads/writes order and the execution
2009 // order of multiple shader invocations in compute shader.
TEST_P(ComputeShaderTest,GroupMemoryBarrierAndBarrierTest)2010 TEST_P(ComputeShaderTest, GroupMemoryBarrierAndBarrierTest)
2011 {
2012     // TODO(xinghua.cao@intel.com): Figure out why we get this error message
2013     // that shader uses features not recognized by this D3D version.
2014     ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());
2015     ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
2016 
2017     // http://anglebug.com/5072
2018     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2019 
2020     GLTexture texture;
2021     GLFramebuffer framebuffer;
2022 
2023     // Each invocation first stores a single value in an image, then each invocation sums up
2024     // all the values in the image and stores the sum in the image. groupMemoryBarrier is
2025     // used to order reads/writes to variables stored in memory accessible to other shader
2026     // invocations, and barrier is used to control the relative execution order of multiple
2027     // shader invocations used to process a local work group.
2028     constexpr char kCS[] = R"(#version 310 es
2029 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
2030 layout(r32i, binding = 0) uniform highp iimage2D image;
2031 void main()
2032 {
2033     uint x = gl_LocalInvocationID.x;
2034     uint y = gl_LocalInvocationID.y;
2035     imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));
2036     groupMemoryBarrier();
2037     barrier();
2038     int sum = 0;
2039     for (int i = 0; i < 2; i++)
2040     {
2041         for(int j = 0; j < 2; j++)
2042         {
2043             sum += imageLoad(image, ivec2(i, j)).x;
2044         }
2045     }
2046     groupMemoryBarrier();
2047     barrier();
2048     imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));
2049 })";
2050 
2051     constexpr int kWidth = 2, kHeight = 2;
2052     glBindTexture(GL_TEXTURE_2D, texture);
2053     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);
2054     EXPECT_GL_NO_ERROR();
2055 
2056     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2057     glUseProgram(program.get());
2058 
2059     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
2060     EXPECT_GL_NO_ERROR();
2061 
2062     glDispatchCompute(1, 1, 1);
2063     EXPECT_GL_NO_ERROR();
2064 
2065     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2066     GLuint outputValues[kWidth * kHeight];
2067     constexpr GLuint kExpectedValue = 4;
2068     glUseProgram(0);
2069     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2070 
2071     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2072     EXPECT_GL_NO_ERROR();
2073     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);
2074     EXPECT_GL_NO_ERROR();
2075 
2076     for (int i = 0; i < kWidth * kHeight; i++)
2077     {
2078         EXPECT_EQ(kExpectedValue, outputValues[i]);
2079     }
2080 }
2081 
2082 // Verify that a link error is generated when the sum of the number of active image uniforms and
2083 // active shader storage blocks in a compute shader exceeds GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
TEST_P(ComputeShaderTest,ExceedCombinedShaderOutputResourcesInCS)2084 TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS)
2085 {
2086     GLint maxCombinedShaderOutputResources;
2087     GLint maxComputeShaderStorageBlocks;
2088     GLint maxComputeImageUniforms;
2089 
2090     glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
2091     glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
2092     glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
2093 
2094     ANGLE_SKIP_TEST_IF(maxCombinedShaderOutputResources >=
2095                        maxComputeShaderStorageBlocks + maxComputeImageUniforms);
2096 
2097     std::ostringstream computeShaderStream;
2098     computeShaderStream << "#version 310 es\n"
2099                            "layout(local_size_x = 3, local_size_y = 1, local_size_z = 1) in;\n"
2100                            "layout(shared, binding = 0) buffer blockName"
2101                            "{\n"
2102                            "    uint data;\n"
2103                            "} instance["
2104                         << maxComputeShaderStorageBlocks << "];\n";
2105 
2106     ASSERT_GE(maxComputeImageUniforms, 4);
2107     int numImagesInArray  = maxComputeImageUniforms / 2;
2108     int numImagesNonArray = maxComputeImageUniforms - numImagesInArray;
2109     for (int i = 0; i < numImagesNonArray; ++i)
2110     {
2111         computeShaderStream << "layout(r32f, binding = " << i << ") uniform highp image2D image"
2112                             << i << ";\n";
2113     }
2114 
2115     computeShaderStream << "layout(r32f, binding = " << numImagesNonArray
2116                         << ") uniform highp image2D imageArray[" << numImagesInArray << "];\n";
2117 
2118     computeShaderStream << "void main()\n"
2119                            "{\n"
2120                            "    uint val = 0u;\n"
2121                            "    vec4 val2 = vec4(0.0);\n";
2122 
2123     for (int i = 0; i < maxComputeShaderStorageBlocks; ++i)
2124     {
2125         computeShaderStream << "    val += instance[" << i << "].data; \n";
2126     }
2127 
2128     for (int i = 0; i < numImagesNonArray; ++i)
2129     {
2130         computeShaderStream << "    val2 += imageLoad(image" << i
2131                             << ", ivec2(gl_LocalInvocationID.xy)); \n";
2132     }
2133 
2134     for (int i = 0; i < numImagesInArray; ++i)
2135     {
2136         computeShaderStream << "    val2 += imageLoad(imageArray[" << i << "]"
2137                             << ", ivec2(gl_LocalInvocationID.xy)); \n";
2138     }
2139 
2140     computeShaderStream << "    instance[0].data = val + uint(val2.x);\n"
2141                            "}\n";
2142 
2143     GLuint computeProgram = CompileComputeProgram(computeShaderStream.str().c_str());
2144     EXPECT_EQ(0u, computeProgram);
2145 }
2146 
2147 // Test that uniform block with struct member in compute shader is supported.
TEST_P(ComputeShaderTest,UniformBlockWithStructMember)2148 TEST_P(ComputeShaderTest, UniformBlockWithStructMember)
2149 {
2150     constexpr char kCS[] = R"(#version 310 es
2151 layout(local_size_x=8) in;
2152 layout(rgba8) uniform highp readonly image2D mImage2DInput;
2153 layout(rgba8) uniform highp writeonly image2D mImage2DOutput;
2154 struct S {
2155     ivec3 a;
2156     ivec2 b;
2157 };
2158 
2159 layout(std140, binding=0) uniform blockName {
2160     S bd;
2161 } instanceName;
2162 void main()
2163 {
2164     ivec2 t1 = instanceName.bd.b;
2165     vec4 result2d = imageLoad(mImage2DInput, t1);
2166     imageStore(mImage2DOutput, ivec2(gl_LocalInvocationID.xy), result2d);
2167 })";
2168 
2169     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2170     EXPECT_GL_NO_ERROR();
2171 }
2172 
2173 // Verify shared non-array variables can work correctly.
TEST_P(ComputeShaderTest,NonArraySharedVariable)2174 TEST_P(ComputeShaderTest, NonArraySharedVariable)
2175 {
2176     // http://anglebug.com/5072
2177     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2178 
2179     const char kCSShader[] = R"(#version 310 es
2180 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2181 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2182 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2183 shared uint temp;
2184 void main()
2185 {
2186     if (gl_LocalInvocationID == uvec3(0, 0, 0))
2187     {
2188         temp = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2189     }
2190     groupMemoryBarrier();
2191     barrier();
2192     if (gl_LocalInvocationID == uvec3(1, 1, 0))
2193     {
2194         imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(temp));
2195     }
2196     else
2197     {
2198         uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2199         imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(inputValue));
2200     }
2201 })";
2202 
2203     const std::array<GLuint, 4> inputData      = {{250, 200, 150, 100}};
2204     const std::array<GLuint, 4> expectedValues = {{250, 200, 150, 250}};
2205     runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2206                                       expectedValues);
2207 }
2208 
2209 // Verify shared non-struct array variables can work correctly.
TEST_P(ComputeShaderTest,NonStructArrayAsSharedVariable)2210 TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)
2211 {
2212     // http://anglebug.com/5072
2213     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2214 
2215     const char kCSShader[] = R"(#version 310 es
2216 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2217 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2218 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2219 shared uint sharedData[2][2];
2220 void main()
2221 {
2222     uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2223     sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = inputData;
2224     groupMemoryBarrier();
2225     barrier();
2226     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2227                 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x]));
2228 })";
2229 
2230     const std::array<GLuint, 4> inputData      = {{250, 200, 150, 100}};
2231     const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
2232     runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2233                                       expectedValues);
2234 }
2235 
2236 // Verify shared struct array variables work correctly.
TEST_P(ComputeShaderTest,StructArrayAsSharedVariable)2237 TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)
2238 {
2239     // http://anglebug.com/5072
2240     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2241 
2242     const char kCSShader[] = R"(#version 310 es
2243 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2244 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2245 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2246 struct SharedStruct
2247 {
2248     uint data;
2249 };
2250 shared SharedStruct sharedData[2][2];
2251 void main()
2252 {
2253     uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2254     sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y].data = inputData;
2255     groupMemoryBarrier();
2256     barrier();
2257     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2258                 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x].data));
2259 })";
2260 
2261     const std::array<GLuint, 4> inputData      = {{250, 200, 150, 100}};
2262     const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
2263     runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2264                                       expectedValues);
2265 }
2266 
2267 // Verify using atomic functions without return value can work correctly.
TEST_P(ComputeShaderTest,AtomicFunctionsNoReturnValue)2268 TEST_P(ComputeShaderTest, AtomicFunctionsNoReturnValue)
2269 {
2270     // http://anglebug.com/5072
2271     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2272 
2273     // Fails on AMD windows drivers.  http://anglebug.com/3872
2274     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2275 
2276     // Fails to link on Android.  http://anglebug.com/3874
2277     ANGLE_SKIP_TEST_IF(IsAndroid());
2278 
2279     ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
2280 
2281     const char kCSShader[] = R"(#version 310 es
2282 layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in;
2283 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2284 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2285 
2286 const uint kSumIndex = 0u;
2287 const uint kMinIndex = 1u;
2288 const uint kMaxIndex = 2u;
2289 const uint kOrIndex = 3u;
2290 const uint kAndIndex = 4u;
2291 const uint kXorIndex = 5u;
2292 const uint kExchangeIndex = 6u;
2293 const uint kCompSwapIndex = 7u;
2294 
2295 shared highp uint results[8];
2296 
2297 void main()
2298 {
2299     if (gl_LocalInvocationID.x == kMinIndex || gl_LocalInvocationID.x == kAndIndex)
2300     {
2301         results[gl_LocalInvocationID.x] = 0xFFFFu;
2302     }
2303     else if (gl_LocalInvocationID.x == kCompSwapIndex)
2304     {
2305         results[gl_LocalInvocationID.x] = 1u;
2306     }
2307     else
2308     {
2309         results[gl_LocalInvocationID.x] = 0u;
2310     }
2311     memoryBarrierShared();
2312     barrier();
2313 
2314     uint value = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2315     atomicAdd(results[kSumIndex], value);
2316     atomicMin(results[kMinIndex], value);
2317     atomicMax(results[kMaxIndex], value);
2318     atomicOr(results[kOrIndex], value);
2319     atomicAnd(results[kAndIndex], value);
2320     atomicXor(results[kXorIndex], value);
2321     atomicExchange(results[kExchangeIndex], value);
2322     atomicCompSwap(results[kCompSwapIndex], value, 256u);
2323     memoryBarrierShared();
2324     barrier();
2325 
2326     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2327                 uvec4(results[gl_LocalInvocationID.x]));
2328 })";
2329 
2330     const std::array<GLuint, 8> inputData      = {{1, 2, 4, 8, 16, 32, 64, 128}};
2331     const std::array<GLuint, 8> expectedValues = {{255, 1, 128, 255, 0, 255, 128, 256}};
2332     runSharedMemoryTest<GLuint, 8, 1>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2333                                       expectedValues);
2334 }
2335 
2336 // Verify using atomic functions in a non-initializer single assignment can work correctly.
TEST_P(ComputeShaderTest,AtomicFunctionsInNonInitializerSingleAssignment)2337 TEST_P(ComputeShaderTest, AtomicFunctionsInNonInitializerSingleAssignment)
2338 {
2339     // http://anglebug.com/5072
2340     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2341 
2342     // Fails on AMD windows drivers.  http://anglebug.com/3872
2343     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2344 
2345     const char kCSShader[] = R"(#version 310 es
2346 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2347 layout (r32i, binding = 0) readonly uniform highp iimage2D srcImage;
2348 layout (r32i, binding = 1) writeonly uniform highp iimage2D dstImage;
2349 
2350 shared highp int sharedVariable;
2351 
2352 shared highp int inputData[9];
2353 shared highp int outputData[9];
2354 
2355 void main()
2356 {
2357     int inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2358     inputData[gl_LocalInvocationID.x] = inputValue;
2359     memoryBarrierShared();
2360     barrier();
2361 
2362     if (gl_LocalInvocationID.x == 0u)
2363     {
2364         sharedVariable = 0;
2365 
2366         outputData[0] = atomicAdd(sharedVariable, inputData[0]);
2367         outputData[1] = atomicMin(sharedVariable, inputData[1]);
2368         outputData[2] = atomicMax(sharedVariable, inputData[2]);
2369         outputData[3] = atomicAnd(sharedVariable, inputData[3]);
2370         outputData[4] = atomicOr(sharedVariable, inputData[4]);
2371         outputData[5] = atomicXor(sharedVariable, inputData[5]);
2372         outputData[6] = atomicExchange(sharedVariable, inputData[6]);
2373         outputData[7] = atomicCompSwap(sharedVariable, 64, inputData[7]);
2374         outputData[8] = atomicAdd(sharedVariable, inputData[8]);
2375     }
2376     memoryBarrierShared();
2377     barrier();
2378 
2379     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2380                 ivec4(outputData[gl_LocalInvocationID.x]));
2381 })";
2382 
2383     const std::array<GLint, 9> inputData      = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2384     const std::array<GLint, 9> expectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
2385     runSharedMemoryTest<GLint, 9, 1>(kCSShader, GL_R32I, GL_INT, inputData, expectedValues);
2386 }
2387 
2388 // Verify using atomic functions in an initializers and using unsigned int works correctly.
TEST_P(ComputeShaderTest,AtomicFunctionsInitializerWithUnsigned)2389 TEST_P(ComputeShaderTest, AtomicFunctionsInitializerWithUnsigned)
2390 {
2391     // http://anglebug.com/5072
2392     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2393 
2394     // Fails on AMD windows drivers.  http://anglebug.com/3872
2395     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2396 
2397     constexpr char kCShader[] = R"(#version 310 es
2398 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2399 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2400 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2401 
2402 shared highp uint sharedVariable;
2403 
2404 shared highp uint inputData[9];
2405 shared highp uint outputData[9];
2406 
2407 void main()
2408 {
2409     uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2410     inputData[gl_LocalInvocationID.x] = inputValue;
2411     memoryBarrierShared();
2412     barrier();
2413 
2414     if (gl_LocalInvocationID.x == 0u)
2415     {
2416         sharedVariable = 0u;
2417 
2418         uint addValue = atomicAdd(sharedVariable, inputData[0]);
2419         outputData[0] = addValue;
2420         uint minValue = atomicMin(sharedVariable, inputData[1]);
2421         outputData[1] = minValue;
2422         uint maxValue = atomicMax(sharedVariable, inputData[2]);
2423         outputData[2] = maxValue;
2424         uint andValue = atomicAnd(sharedVariable, inputData[3]);
2425         outputData[3] = andValue;
2426         uint orValue = atomicOr(sharedVariable, inputData[4]);
2427         outputData[4] = orValue;
2428         uint xorValue = atomicXor(sharedVariable, inputData[5]);
2429         outputData[5] = xorValue;
2430         uint exchangeValue = atomicExchange(sharedVariable, inputData[6]);
2431         outputData[6] = exchangeValue;
2432         uint compSwapValue = atomicCompSwap(sharedVariable, 64u, inputData[7]);
2433         outputData[7] = compSwapValue;
2434         uint sharedVariable = atomicAdd(sharedVariable, inputData[8]);
2435         outputData[8] = sharedVariable;
2436 
2437     }
2438     memoryBarrierShared();
2439     barrier();
2440 
2441     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2442                 uvec4(outputData[gl_LocalInvocationID.x]));
2443 })";
2444 
2445     constexpr std::array<GLuint, 9> kInputData      = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2446     constexpr std::array<GLuint, 9> kExpectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
2447     runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2448                                       kExpectedValues);
2449 }
2450 
2451 // Verify using atomic functions inside expressions as unsigned int.
TEST_P(ComputeShaderTest,AtomicFunctionsReturnWithUnsigned)2452 TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithUnsigned)
2453 {
2454     // http://anglebug.com/5072
2455     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2456 
2457     // Fails on AMD windows drivers.  http://anglebug.com/3872
2458     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2459 
2460     constexpr char kCShader[] = R"(#version 310 es
2461 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2462 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2463 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2464 
2465 shared highp uint sharedVariable;
2466 
2467 shared highp uint inputData[9];
2468 shared highp uint outputData[9];
2469 
2470 void main()
2471 {
2472     uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2473     inputData[gl_LocalInvocationID.x] = inputValue;
2474     memoryBarrierShared();
2475     barrier();
2476 
2477     if (gl_LocalInvocationID.x == 0u)
2478     {
2479         sharedVariable = 0u;
2480 
2481         outputData[0] = 1u + atomicAdd(sharedVariable, inputData[0]);
2482         outputData[1] = 1u + atomicMin(sharedVariable, inputData[1]);
2483         outputData[2] = 1u + atomicMax(sharedVariable, inputData[2]);
2484         outputData[3] = 1u + atomicAnd(sharedVariable, inputData[3]);
2485         outputData[4] = 1u + atomicOr(sharedVariable, inputData[4]);
2486         outputData[5] = 1u + atomicXor(sharedVariable, inputData[5]);
2487         outputData[6] = 1u + atomicExchange(sharedVariable, inputData[6]);
2488         outputData[7] = 1u + atomicCompSwap(sharedVariable, 64u, inputData[7]);
2489         outputData[8] = 1u + atomicAdd(sharedVariable, inputData[8]);
2490     }
2491     memoryBarrierShared();
2492     barrier();
2493 
2494     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2495                 uvec4(outputData[gl_LocalInvocationID.x]));
2496 })";
2497 
2498     constexpr std::array<GLuint, 9> kInputData      = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2499     constexpr std::array<GLuint, 9> kExpectedValues = {{1, 2, 2, 5, 1, 17, 49, 65, 129}};
2500     runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2501                                       kExpectedValues);
2502 }
2503 
2504 // Verify using nested atomic functions in expressions.
TEST_P(ComputeShaderTest,AtomicFunctionsReturnWithMultipleTypes)2505 TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithMultipleTypes)
2506 {
2507     // http://anglebug.com/5072
2508     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2509 
2510     constexpr char kCShader[] = R"(#version 310 es
2511 layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
2512 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2513 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2514 
2515 shared highp uint sharedVariable;
2516 shared highp int  indexVariable;
2517 
2518 shared highp uint inputData[4];
2519 shared highp uint outputData[4];
2520 
2521 void main()
2522 {
2523     uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2524     inputData[gl_LocalInvocationID.x] = inputValue;
2525     memoryBarrierShared();
2526     barrier();
2527 
2528     if (gl_LocalInvocationID.x == 0u)
2529     {
2530         sharedVariable = 0u;
2531         indexVariable = 2;
2532 
2533         outputData[0] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2534         outputData[1] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2535         outputData[2] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2536         outputData[3] = atomicAdd(sharedVariable, 0u);
2537 
2538     }
2539     memoryBarrierShared();
2540     barrier();
2541 
2542     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2543                 uvec4(outputData[gl_LocalInvocationID.x]));
2544 })";
2545 
2546     constexpr std::array<GLuint, 4> kInputData      = {{1, 2, 3, 0}};
2547     constexpr std::array<GLuint, 4> kExpectedValues = {{1, 4, 6, 6}};
2548     runSharedMemoryTest<GLuint, 4, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2549                                       kExpectedValues);
2550 }
2551 
2552 // Basic uniform buffer functionality.
TEST_P(ComputeShaderTest,UniformBuffer)2553 TEST_P(ComputeShaderTest, UniformBuffer)
2554 {
2555     // http://anglebug.com/5072
2556     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2557 
2558     GLTexture texture;
2559     GLBuffer buffer;
2560     GLFramebuffer framebuffer;
2561     constexpr char kCS[] = R"(#version 310 es
2562 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2563 uniform uni
2564 {
2565     uvec4 value;
2566 };
2567 layout(rgba32ui, binding = 0) writeonly uniform highp uimage2D uImage;
2568 void main()
2569 {
2570     imageStore(uImage, ivec2(gl_LocalInvocationID.xy), value);
2571 })";
2572 
2573     constexpr int kWidth = 1, kHeight = 1;
2574     constexpr GLuint kInputValues[4] = {56, 57, 58, 59};
2575 
2576     glBindTexture(GL_TEXTURE_2D, texture);
2577     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth, kHeight);
2578     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
2579                     kInputValues);
2580     EXPECT_GL_NO_ERROR();
2581 
2582     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2583     glUseProgram(program.get());
2584 
2585     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
2586     EXPECT_NE(uniformBufferIndex, -1);
2587     GLuint data[4] = {201, 202, 203, 204};
2588     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
2589     glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint) * 4, data, GL_STATIC_DRAW);
2590     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
2591     glUniformBlockBinding(program, uniformBufferIndex, 0);
2592     EXPECT_GL_NO_ERROR();
2593 
2594     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
2595     EXPECT_GL_NO_ERROR();
2596 
2597     glDispatchCompute(1, 1, 1);
2598     EXPECT_GL_NO_ERROR();
2599 
2600     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2601     GLuint outputValues[kWidth * kHeight * 4];
2602     glUseProgram(0);
2603     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2604 
2605     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2606     EXPECT_GL_NO_ERROR();
2607     glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
2608     EXPECT_GL_NO_ERROR();
2609 
2610     for (int i = 0; i < kWidth * kHeight * 4; i++)
2611     {
2612         EXPECT_EQ(data[i], outputValues[i]);
2613     }
2614 }
2615 
2616 // Test that storing data to image and then loading the same image data works correctly.
TEST_P(ComputeShaderTest,StoreImageThenLoad)2617 TEST_P(ComputeShaderTest, StoreImageThenLoad)
2618 {
2619     // http://anglebug.com/5072
2620     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2621 
2622     const char kCSSource[] = R"(#version 310 es
2623 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2624 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2625 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
2626 void main()
2627 {
2628     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2629     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
2630 })";
2631 
2632     constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
2633     GLTexture texture[3];
2634     glBindTexture(GL_TEXTURE_2D, texture[0]);
2635     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2636     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
2637     EXPECT_GL_NO_ERROR();
2638 
2639     glBindTexture(GL_TEXTURE_2D, texture[1]);
2640     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2641     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
2642     EXPECT_GL_NO_ERROR();
2643 
2644     glBindTexture(GL_TEXTURE_2D, texture[2]);
2645     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2646     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
2647     EXPECT_GL_NO_ERROR();
2648 
2649     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2650     glUseProgram(program.get());
2651 
2652     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2653     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2654 
2655     glDispatchCompute(1, 1, 1);
2656     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2657     EXPECT_GL_NO_ERROR();
2658 
2659     glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2660     glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2661 
2662     glDispatchCompute(1, 1, 1);
2663     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2664     EXPECT_GL_NO_ERROR();
2665 
2666     GLuint outputValue;
2667     GLFramebuffer framebuffer;
2668     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2669     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
2670     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
2671     EXPECT_GL_NO_ERROR();
2672 
2673     EXPECT_EQ(300u, outputValue);
2674 }
2675 
2676 // Test that loading image data and then storing data to the same image works correctly.
TEST_P(ComputeShaderTest,LoadImageThenStore)2677 TEST_P(ComputeShaderTest, LoadImageThenStore)
2678 {
2679     // http://anglebug.com/5072
2680     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2681 
2682     const char kCSSource[] = R"(#version 310 es
2683 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2684 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2685 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
2686 void main()
2687 {
2688     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2689     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
2690 })";
2691 
2692     constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
2693     GLTexture texture[3];
2694     glBindTexture(GL_TEXTURE_2D, texture[0]);
2695     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2696     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
2697     EXPECT_GL_NO_ERROR();
2698 
2699     glBindTexture(GL_TEXTURE_2D, texture[1]);
2700     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2701     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
2702     EXPECT_GL_NO_ERROR();
2703 
2704     glBindTexture(GL_TEXTURE_2D, texture[2]);
2705     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2706     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
2707     EXPECT_GL_NO_ERROR();
2708 
2709     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2710     glUseProgram(program.get());
2711 
2712     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2713     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2714 
2715     glDispatchCompute(1, 1, 1);
2716     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2717     EXPECT_GL_NO_ERROR();
2718 
2719     glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2720     glBindImageTexture(1, texture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2721 
2722     glDispatchCompute(1, 1, 1);
2723     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2724     EXPECT_GL_NO_ERROR();
2725 
2726     GLuint outputValue;
2727     GLFramebuffer framebuffer;
2728     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2729     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
2730     glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
2731     EXPECT_GL_NO_ERROR();
2732 
2733     EXPECT_EQ(100u, outputValue);
2734 }
2735 
2736 // Test that the length of a struct buffer variable is supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksStructLength)2737 TEST_P(ComputeShaderTest, ShaderStorageBlocksStructLength)
2738 {
2739     const char kCSSource[] = R"(#version 310 es
2740 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
2741 
2742 struct Particle
2743 {
2744     int len;
2745 };
2746 
2747 layout(binding = 0, std430) readonly buffer Buf1
2748 {
2749     Particle particlesRead[];
2750 };
2751 
2752 layout(binding = 1, std430) buffer Buf2
2753 {
2754     Particle particlesWrite[];
2755 };
2756 
2757 void main()
2758 {
2759     int index = int(gl_GlobalInvocationID.x);
2760     particlesWrite[index].len = particlesRead.length();
2761 })";
2762 
2763     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2764     EXPECT_GL_NO_ERROR();
2765 }
2766 
2767 // Test that scalar buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksScalar)2768 TEST_P(ComputeShaderTest, ShaderStorageBlocksScalar)
2769 {
2770     const char kCSSource[] = R"(#version 310 es
2771 layout(local_size_x=1) in;
2772 layout(std140, binding = 0) buffer blockA {
2773     uvec3 uv;
2774     float f;
2775 } instanceA;
2776 layout(std140, binding = 1) buffer blockB {
2777     vec2 v;
2778     uint u[3];
2779     float f;
2780 };
2781 void main()
2782 {
2783     f = instanceA.f;
2784 })";
2785 
2786     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2787     EXPECT_GL_NO_ERROR();
2788 }
2789 
2790 // Test that vector buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksVector)2791 TEST_P(ComputeShaderTest, ShaderStorageBlocksVector)
2792 {
2793     const char kCSSource[] = R"(#version 310 es
2794 layout(local_size_x=1) in;
2795 layout(std140, binding = 0) buffer blockA {
2796     vec2 f;
2797 } instanceA;
2798 layout(std140, binding = 1) buffer blockB {
2799     vec3 f;
2800 };
2801 void main()
2802 {
2803     f[1] = instanceA.f[0];
2804 })";
2805 
2806     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2807     EXPECT_GL_NO_ERROR();
2808 }
2809 
2810 // Test that matrix buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksMatrix)2811 TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrix)
2812 {
2813     const char kCSSource[] = R"(#version 310 es
2814 layout(local_size_x=1) in;
2815 layout(std140, binding = 0) buffer blockA {
2816     mat3x4 m;
2817 } instanceA;
2818 layout(std140, binding = 1) buffer blockB {
2819     mat3x4 m;
2820 };
2821 void main()
2822 {
2823     m[0][1] = instanceA.m[0][1];
2824 })";
2825 
2826     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2827     EXPECT_GL_NO_ERROR();
2828 }
2829 
2830 // Test that scalar array buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksScalarArray)2831 TEST_P(ComputeShaderTest, ShaderStorageBlocksScalarArray)
2832 {
2833     const char kCSSource[] = R"(#version 310 es
2834 layout(local_size_x=8) in;
2835 layout(std140, binding = 0) buffer blockA {
2836     float f[8];
2837 } instanceA;
2838 layout(std140, binding = 1) buffer blockB {
2839     float f[8];
2840 };
2841 void main()
2842 {
2843     f[gl_LocalInvocationIndex] = instanceA.f[gl_LocalInvocationIndex];
2844 })";
2845 
2846     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2847     EXPECT_GL_NO_ERROR();
2848 }
2849 
2850 // Test that vector array buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksVectorArray)2851 TEST_P(ComputeShaderTest, ShaderStorageBlocksVectorArray)
2852 {
2853     const char kCSSource[] = R"(#version 310 es
2854 layout(local_size_x=4) in;
2855 layout(std140, binding = 0) buffer blockA {
2856     vec2 v[4];
2857 } instanceA;
2858 layout(std140, binding = 1) buffer blockB {
2859     vec4 v[4];
2860 };
2861 void main()
2862 {
2863     v[0][gl_LocalInvocationIndex] = instanceA.v[gl_LocalInvocationIndex][1];
2864 })";
2865 
2866     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2867     EXPECT_GL_NO_ERROR();
2868 }
2869 
2870 // Test that matrix array buffer variables are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksMatrixArray)2871 TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrixArray)
2872 {
2873     const char kCSSource[] = R"(#version 310 es
2874 layout(local_size_x=8) in;
2875 layout(std140, binding = 0) buffer blockA {
2876     float v1[5];
2877     mat4 m[8];
2878 } instanceA;
2879 layout(std140, binding = 1) buffer blockB {
2880     vec2 v1[3];
2881     mat4 m[8];
2882 };
2883 void main()
2884 {
2885     float data = instanceA.m[gl_LocalInvocationIndex][0][0];
2886     m[gl_LocalInvocationIndex][gl_LocalInvocationIndex][gl_LocalInvocationIndex] = data;
2887 })";
2888 
2889     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2890     EXPECT_GL_NO_ERROR();
2891 }
2892 
2893 // Test that shader storage blocks only in assignment right is supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksInAssignmentRight)2894 TEST_P(ComputeShaderTest, ShaderStorageBlocksInAssignmentRight)
2895 {
2896     const char kCSSource[] = R"(#version 310 es
2897 layout(local_size_x=8) in;
2898 layout(std140, binding = 0) buffer blockA {
2899     float data[8];
2900 } instanceA;
2901 layout(r32f, binding = 0) writeonly uniform highp image2D imageOut;
2902 
2903 void main()
2904 {
2905     float data = 1.0;
2906     data = instanceA.data[gl_LocalInvocationIndex];
2907     imageStore(imageOut, ivec2(gl_LocalInvocationID.xy), vec4(data));
2908 })";
2909 
2910     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2911     EXPECT_GL_NO_ERROR();
2912 }
2913 
2914 // Test that shader storage blocks with unsized array are supported.
TEST_P(ComputeShaderTest,ShaderStorageBlocksWithUnsizedArray)2915 TEST_P(ComputeShaderTest, ShaderStorageBlocksWithUnsizedArray)
2916 {
2917     const char kCSSource[] = R"(#version 310 es
2918 layout(local_size_x=8) in;
2919 layout(std140, binding = 0) buffer blockA {
2920     float v[];
2921 } instanceA;
2922 layout(std140, binding = 0) buffer blockB {
2923     float v[];
2924 } instanceB[1];
2925 
2926 void main()
2927 {
2928     float data = instanceA.v[gl_LocalInvocationIndex];
2929     instanceB[0].v[gl_LocalInvocationIndex * 2u + 1u] = data;
2930 }
2931 )";
2932 
2933     ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2934     EXPECT_GL_NO_ERROR();
2935 }
2936 
2937 // Test that EOpIndexDirect/EOpIndexIndirect/EOpIndexDirectStruct nodes in ssbo EOpIndexInDirect
2938 // don't need to calculate the offset and should be translated by OutputHLSL directly.
TEST_P(ComputeShaderTest,IndexAndDotOperatorsInSSBOIndexIndirectOperator)2939 TEST_P(ComputeShaderTest, IndexAndDotOperatorsInSSBOIndexIndirectOperator)
2940 {
2941     constexpr char kComputeShaderSource[] = R"(#version 310 es
2942 layout(local_size_x=1) in;
2943 layout(std140, binding = 0) buffer blockA {
2944     float v[4];
2945 };
2946 layout(std140, binding = 1) buffer blockB {
2947     float v[4];
2948 } instanceB[1];
2949 struct S
2950 {
2951     uvec4 index[2];
2952 } s;
2953 void main()
2954 {
2955         s.index[0] = uvec4(0u, 1u, 2u, 3u);
2956     float data = v[s.index[0].y];
2957     instanceB[0].v[s.index[0].x] = data;
2958 })";
2959 
2960     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2961     EXPECT_GL_NO_ERROR();
2962 }
2963 
2964 // Test that swizzle node in non-SSBO symbol works well.
TEST_P(ComputeShaderTest,ShaderStorageBlocksWithNonSSBOSwizzle)2965 TEST_P(ComputeShaderTest, ShaderStorageBlocksWithNonSSBOSwizzle)
2966 {
2967     constexpr char kComputeShaderSource[] = R"(#version 310 es
2968 layout(local_size_x=8) in;
2969 layout(std140, binding = 0) buffer blockA {
2970     float v[8];
2971 };
2972 layout(std140, binding = 1) buffer blockB {
2973     float v[8];
2974 } instanceB[1];
2975 
2976 void main()
2977 {
2978     float data = v[gl_GlobalInvocationID.x];
2979     instanceB[0].v[gl_GlobalInvocationID.x] = data;
2980 })";
2981 
2982     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2983     EXPECT_GL_NO_ERROR();
2984 }
2985 
2986 // Test that swizzle node in SSBO symbol works well.
TEST_P(ComputeShaderTest,ShaderStorageBlocksWithSSBOSwizzle)2987 TEST_P(ComputeShaderTest, ShaderStorageBlocksWithSSBOSwizzle)
2988 {
2989     constexpr char kComputeShaderSource[] = R"(#version 310 es
2990 layout(local_size_x=1) in;
2991 layout(std140, binding = 0) buffer blockA {
2992     vec2 v;
2993 };
2994 layout(std140, binding = 1) buffer blockB {
2995     float v;
2996 } instanceB[1];
2997 
2998 void main()
2999 {
3000     instanceB[0].v = v.x;
3001 })";
3002 
3003     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3004     EXPECT_GL_NO_ERROR();
3005 }
3006 
3007 // Test that a large struct array in std140 uniform block won't consume too much time.
TEST_P(ComputeShaderTest,LargeStructArraySize)3008 TEST_P(ComputeShaderTest, LargeStructArraySize)
3009 {
3010     constexpr char kComputeShaderSource[] = R"(#version 310 es
3011 layout(local_size_x=8) in;
3012 precision mediump float;
3013 
3014 struct InstancingData
3015 {
3016     mat4 transformation;
3017 };
3018 
3019 #define MAX_INSTANCE_COUNT 800
3020 
3021 layout(std140) uniform InstanceBlock
3022 {
3023     InstancingData instances[MAX_INSTANCE_COUNT];
3024 };
3025 
3026 layout(std140, binding = 1) buffer blockB {
3027     mat4 v[];
3028 } instanceB;
3029 
3030 void main()
3031 {
3032     instanceB.v[gl_GlobalInvocationID.x] = instances[gl_GlobalInvocationID.x].transformation;
3033 })";
3034 
3035     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3036     EXPECT_GL_NO_ERROR();
3037 }
3038 
3039 // Check that it is not possible to create a compute shader when the context does not support ES
3040 // 3.10
TEST_P(ComputeShaderTestES3,NotSupported)3041 TEST_P(ComputeShaderTestES3, NotSupported)
3042 {
3043     GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
3044     EXPECT_EQ(0u, computeShaderHandle);
3045     EXPECT_GL_ERROR(GL_INVALID_ENUM);
3046 }
3047 
3048 // The contents of shared variables should be cleared to zero at the beginning of shader execution.
TEST_P(WebGL2ComputeTest,sharedVariablesShouldBeZero)3049 TEST_P(WebGL2ComputeTest, sharedVariablesShouldBeZero)
3050 {
3051     // http://anglebug.com/3226
3052     ANGLE_SKIP_TEST_IF(IsD3D11());
3053 
3054     // Fails on Android, AMD/windows and Intel/windows.  Probably works by chance on other
3055     // platforms, so suppressing on all platforms to avoid possible flakiness.
3056     // http://anglebug.com/3869
3057     ANGLE_SKIP_TEST_IF(IsVulkan());
3058 
3059     // http://anglebug.com/4092
3060     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3061     ANGLE_SKIP_TEST_IF(IsOpenGL() &&
3062                        ((getClientMajorVersion() == 3) && (getClientMinorVersion() >= 1)));
3063 
3064     const char kCSShader[] = R"(#version 310 es
3065 layout (local_size_x = 4, local_size_y = 4, local_size_z = 1) in;
3066 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
3067 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
3068 struct S {
3069     float f;
3070     int i;
3071     uint u;
3072     bool b;
3073     vec4 v[64];
3074 };
3075 
3076 shared S vars[16];
3077 void main()
3078 {
3079     S zeroS;
3080     zeroS.f = 0.0f;
3081     zeroS.i = 0;
3082     zeroS.u = 0u;
3083     zeroS.b = false;
3084     for (int i = 0; i < 64; i++)
3085     {
3086         zeroS.v[i] = vec4(0.0f);
3087     }
3088 
3089     uint tid = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4u;
3090     uint value = (zeroS == vars[tid] ? 127u : 0u);
3091     imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(value));
3092 })";
3093 
3094     const std::array<GLuint, 16> inputData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
3095     const std::array<GLuint, 16> expectedValues = {
3096         {127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127}};
3097     runSharedMemoryTest<GLuint, 4, 4>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
3098                                       expectedValues);
3099 }
3100 
3101 // Test uniform dirty in compute shader, and verify the contents.
TEST_P(ComputeShaderTest,UniformDirty)3102 TEST_P(ComputeShaderTest, UniformDirty)
3103 {
3104     // http://anglebug.com/5072
3105     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3106 
3107     // glReadPixels is getting the result of the first dispatch call.  http://anglebug.com/3879
3108     ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && (IsAMD() || IsNVIDIA()));
3109 
3110     GLTexture texture[2];
3111     GLFramebuffer framebuffer;
3112     constexpr char kCS[] = R"(#version 310 es
3113 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3114 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3115 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3116 uniform uint factor;
3117 void main()
3118 {
3119     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3120     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value * factor);
3121 })";
3122 
3123     constexpr int kWidth = 1, kHeight = 1;
3124     constexpr GLuint kInputValues[2][1] = {{200}, {100}};
3125 
3126     glBindTexture(GL_TEXTURE_2D, texture[0]);
3127     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3128     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3129                     kInputValues[0]);
3130     EXPECT_GL_NO_ERROR();
3131 
3132     glBindTexture(GL_TEXTURE_2D, texture[1]);
3133     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3134     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3135                     kInputValues[1]);
3136     EXPECT_GL_NO_ERROR();
3137 
3138     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3139     glUseProgram(program);
3140 
3141     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3142     EXPECT_GL_NO_ERROR();
3143 
3144     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3145     EXPECT_GL_NO_ERROR();
3146 
3147     glUniform1ui(glGetUniformLocation(program, "factor"), 2);
3148     EXPECT_GL_NO_ERROR();
3149 
3150     glDispatchCompute(1, 1, 1);
3151     EXPECT_GL_NO_ERROR();
3152 
3153     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3154 
3155     glUniform1ui(glGetUniformLocation(program, "factor"), 3);
3156     EXPECT_GL_NO_ERROR();
3157 
3158     glDispatchCompute(1, 1, 1);
3159     EXPECT_GL_NO_ERROR();
3160 
3161     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3162     GLuint outputValues[kWidth * kHeight];
3163     GLuint expectedValue = 600;
3164     glUseProgram(0);
3165     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3166 
3167     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3168     EXPECT_GL_NO_ERROR();
3169     glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
3170     EXPECT_GL_NO_ERROR();
3171 
3172     for (int i = 0; i < kWidth * kHeight; i++)
3173     {
3174         EXPECT_EQ(expectedValue, outputValues[i]) << " index " << i;
3175     }
3176 }
3177 
3178 // Test storage buffer bound is unchanged, shader writes it, buffer content should be updated.
TEST_P(ComputeShaderTest,StorageBufferBoundUnchanged)3179 TEST_P(ComputeShaderTest, StorageBufferBoundUnchanged)
3180 {
3181     // http://anglebug.com/4092
3182     ANGLE_SKIP_TEST_IF(isSwiftshader());
3183     constexpr char kCS[] = R"(#version 310 es
3184 layout(local_size_x=16, local_size_y=16) in;
3185 precision highp usampler2D;
3186 uniform usampler2D tex;
3187 uniform uint factor;
3188 layout(std140, binding = 0) buffer buf {
3189     uint outData[16][16];
3190 };
3191 
3192 void main()
3193 {
3194     uint x = gl_LocalInvocationID.x;
3195     uint y = gl_LocalInvocationID.y;
3196     float xCoord = float(x) / float(16);
3197     float yCoord = float(y) / float(16);
3198     outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x + factor;
3199 })";
3200 
3201     constexpr unsigned int kWidth  = 16;
3202     constexpr unsigned int kHeight = 16;
3203     GLTexture tex;
3204     glBindTexture(GL_TEXTURE_2D, tex);
3205     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3206     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3207     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3208     GLuint texels[kHeight][kWidth] = {{0}};
3209     for (unsigned int y = 0; y < kHeight; ++y)
3210     {
3211         for (unsigned int x = 0; x < kWidth; ++x)
3212         {
3213             texels[y][x] = x + y * kWidth;
3214         }
3215     }
3216     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3217     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3218                     texels);
3219     glBindTexture(GL_TEXTURE_2D, 0);
3220 
3221     // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
3222     constexpr unsigned int kArrayStride = 16;
3223     GLBuffer ssbo;
3224     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3225     glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
3226                  GL_STREAM_DRAW);
3227     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3228     EXPECT_GL_NO_ERROR();
3229 
3230     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3231     glUseProgram(program);
3232 
3233     glActiveTexture(GL_TEXTURE0);
3234     glBindTexture(GL_TEXTURE_2D, tex);
3235     glUniform1i(glGetUniformLocation(program, "tex"), 0);
3236     glUniform1ui(glGetUniformLocation(program, "factor"), 2);
3237     glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3238     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
3239 
3240     glDispatchCompute(1, 1, 1);
3241 
3242     const GLuint *ptr1 = reinterpret_cast<const GLuint *>(glMapBufferRange(
3243         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
3244     EXPECT_GL_NO_ERROR();
3245     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
3246     {
3247         EXPECT_EQ(idx + 2, *(ptr1 + idx * kArrayStride / 4));
3248     }
3249     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3250     glUniform1ui(glGetUniformLocation(program, "factor"), 3);
3251     glDispatchCompute(1, 1, 1);
3252 
3253     const GLuint *ptr2 = reinterpret_cast<const GLuint *>(glMapBufferRange(
3254         GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
3255     EXPECT_GL_NO_ERROR();
3256     for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
3257     {
3258         EXPECT_EQ(idx + 3, *(ptr2 + idx * kArrayStride / 4));
3259     }
3260 }
3261 
3262 // Test imageSize to access mipmap slice.
TEST_P(ComputeShaderTest,ImageSizeMipmapSlice)3263 TEST_P(ComputeShaderTest, ImageSizeMipmapSlice)
3264 {
3265     // TODO(xinghua.cao@intel.com): http://anglebug.com/3101
3266     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
3267 
3268     // http://anglebug.com/4392
3269     ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsD3D11());
3270 
3271     GLTexture texture[2];
3272     GLFramebuffer framebuffer;
3273     const char kCS[] = R"(#version 310 es
3274 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3275 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3276 layout(rgba32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3277 void main()
3278 {
3279     ivec2 size = imageSize(uImage_1);
3280     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), uvec4(size, 0, 0));
3281 })";
3282 
3283     constexpr int kWidth1 = 8, kHeight1 = 4, kWidth2 = 1, kHeight2 = 1;
3284     constexpr GLuint kInputValues[] = {0, 0, 0, 0};
3285 
3286     glBindTexture(GL_TEXTURE_2D, texture[0]);
3287     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);
3288     EXPECT_GL_NO_ERROR();
3289 
3290     glBindTexture(GL_TEXTURE_2D, texture[1]);
3291     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth2, kHeight2);
3292     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
3293                     kInputValues);
3294     EXPECT_GL_NO_ERROR();
3295 
3296     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3297     glUseProgram(program);
3298 
3299     glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3300     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
3301 
3302     glDispatchCompute(1, 1, 1);
3303     EXPECT_GL_NO_ERROR();
3304 
3305     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3306     GLuint outputValues[kWidth2 * kHeight2 * 4];
3307     constexpr GLuint expectedValue[] = {4, 2};
3308     glUseProgram(0);
3309     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3310 
3311     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3312     EXPECT_GL_NO_ERROR();
3313     glReadPixels(0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
3314     EXPECT_GL_NO_ERROR();
3315 
3316     for (int i = 0; i < kWidth2 * kHeight2; i++)
3317     {
3318         EXPECT_EQ(expectedValue[i], outputValues[i]);
3319         EXPECT_EQ(expectedValue[i + 1], outputValues[i + 1]);
3320     }
3321 }
3322 
3323 // Test imageLoad to access mipmap slice.
TEST_P(ComputeShaderTest,ImageLoadMipmapSlice)3324 TEST_P(ComputeShaderTest, ImageLoadMipmapSlice)
3325 {
3326     // TODO(xinghua.cao@intel.com): http://anglebug.com/3101
3327     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
3328 
3329     GLTexture texture[2];
3330     GLFramebuffer framebuffer;
3331     constexpr char kCS[] = R"(#version 310 es
3332 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3333 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3334 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3335 void main()
3336 {
3337     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3338     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
3339 })";
3340 
3341     constexpr int kWidth1 = 2, kHeight1 = 2, kWidth2 = 1, kHeight2 = 1;
3342     constexpr GLuint kInputValues11[] = {3, 3, 3, 3};
3343     constexpr GLuint kInputValues12[] = {2};
3344     constexpr GLuint kInputValues2[]  = {1};
3345 
3346     glBindTexture(GL_TEXTURE_2D, texture[0]);
3347     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);
3348     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3349                     kInputValues11);
3350     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3351                     kInputValues12);
3352     EXPECT_GL_NO_ERROR();
3353 
3354     glBindTexture(GL_TEXTURE_2D, texture[1]);
3355     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth2, kHeight2);
3356     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3357                     kInputValues2);
3358     EXPECT_GL_NO_ERROR();
3359 
3360     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3361     glUseProgram(program);
3362 
3363     glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3364     glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3365 
3366     glDispatchCompute(1, 1, 1);
3367     EXPECT_GL_NO_ERROR();
3368 
3369     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3370     GLuint outputValues;
3371     constexpr GLuint expectedValue = 2;
3372     glUseProgram(0);
3373     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3374 
3375     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3376     EXPECT_GL_NO_ERROR();
3377     glReadPixels(0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);
3378     EXPECT_GL_NO_ERROR();
3379     EXPECT_EQ(expectedValue, outputValues);
3380 }
3381 
3382 // Test imageStore to access mipmap slice.
TEST_P(ComputeShaderTest,ImageStoreMipmapSlice)3383 TEST_P(ComputeShaderTest, ImageStoreMipmapSlice)
3384 {
3385     // TODO(xinghua.cao@intel.com): http://anglebug.com/3101
3386     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3387 
3388     GLTexture texture[2];
3389     GLFramebuffer framebuffer;
3390     constexpr char kCS[] = R"(#version 310 es
3391 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3392 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3393 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3394 void main()
3395 {
3396     uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3397     imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
3398 })";
3399 
3400     constexpr int kWidth1 = 1, kHeight1 = 1, kWidth2 = 2, kHeight2 = 2;
3401     constexpr GLuint kInputValues1[]  = {3};
3402     constexpr GLuint kInputValues21[] = {2, 2, 2, 2};
3403     constexpr GLuint kInputValues22[] = {1};
3404 
3405     glBindTexture(GL_TEXTURE_2D, texture[0]);
3406     glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth1, kHeight1);
3407     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3408                     kInputValues1);
3409     EXPECT_GL_NO_ERROR();
3410 
3411     glBindTexture(GL_TEXTURE_2D, texture[1]);
3412     glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth2, kHeight2);
3413     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3414                     kInputValues21);
3415     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3416                     kInputValues22);
3417     EXPECT_GL_NO_ERROR();
3418 
3419     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3420     glUseProgram(program);
3421 
3422     glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3423     glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3424 
3425     glDispatchCompute(1, 1, 1);
3426     EXPECT_GL_NO_ERROR();
3427 
3428     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3429     GLuint outputValues;
3430     constexpr GLuint expectedValue = 3;
3431     glUseProgram(0);
3432     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3433 
3434     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
3435     EXPECT_GL_NO_ERROR();
3436     glReadPixels(0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);
3437     EXPECT_GL_NO_ERROR();
3438     EXPECT_EQ(expectedValue, outputValues);
3439 }
3440 
3441 // Test that a resource is bound on render pipeline output, and then it's bound as the compute
3442 // pipeline input. It works well. See http://anglebug.com/3658
TEST_P(ComputeShaderTest,DrawTexture1DispatchTexture2)3443 TEST_P(ComputeShaderTest, DrawTexture1DispatchTexture2)
3444 {
3445     // http://anglebug.com/5072
3446     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3447 
3448     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"));
3449 
3450     const char kCSSource[] = R"(#version 310 es
3451 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3452 precision highp sampler2D;
3453 uniform sampler2D tex;
3454 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3455 void main()
3456 {
3457     vec4 value = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
3458     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(value.x - 1.0, 1.0, 0.0, value.w - 1.0));
3459 })";
3460 
3461     const char kVSSource[] = R"(#version 310 es
3462 layout (location = 0) in vec2 pos;
3463 out vec2 texCoord;
3464 void main(void) {
3465     texCoord = 0.5*pos + 0.5;
3466     gl_Position = vec4(pos, 0.0, 1.0);
3467 })";
3468 
3469     const char kFSSource[] = R"(#version 310 es
3470 precision highp float;
3471 uniform sampler2D tex;
3472 in vec2 texCoord;
3473 out vec4 fragColor;
3474 void main(void) {
3475     fragColor = texture(tex, texCoord);
3476 })";
3477 
3478     GLuint aPosLoc = 0;
3479     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3480     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3481     glBindAttribLocation(program, aPosLoc, "pos");
3482     GLuint buffer;
3483     glGenBuffers(1, &buffer);
3484     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3485     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3486     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3487     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3488     glEnableVertexAttribArray(aPosLoc);
3489 
3490     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3491     constexpr GLfloat kZero[4]        = {0.0, 0.0, 0.0, 0.0};
3492     GLFramebuffer framebuffer;
3493     GLTexture texture[3];
3494     glBindTexture(GL_TEXTURE_2D, texture[0]);
3495     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3496     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3497     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3498     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3499 
3500     glBindTexture(GL_TEXTURE_2D, texture[1]);
3501     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3502     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);
3503     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3504     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3505 
3506     glBindTexture(GL_TEXTURE_2D, texture[2]);
3507     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3508     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);
3509     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3510     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3511 
3512     glUseProgram(program);
3513     glActiveTexture(GL_TEXTURE0);
3514     glBindTexture(GL_TEXTURE_2D, texture[0]);
3515     glUniform1i(glGetUniformLocation(program, "tex"), 0);
3516     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3517     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3518     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3519     EXPECT_GL_NO_ERROR();
3520     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3521     GLfloat actual[4];
3522     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);
3523     EXPECT_GL_NO_ERROR();
3524     EXPECT_EQ(1.0, actual[0]);
3525     EXPECT_EQ(0.0, actual[1]);
3526     EXPECT_EQ(0.0, actual[2]);
3527     EXPECT_EQ(1.0, actual[3]);
3528 
3529     glUseProgram(csProgram);
3530     glActiveTexture(GL_TEXTURE0);
3531     glBindTexture(GL_TEXTURE_2D, texture[1]);
3532     glUniform1i(glGetUniformLocation(program, "tex"), 0);
3533     glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3534     glDispatchCompute(1, 1, 1);
3535     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3536 
3537     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3538     glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
3539     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);
3540     EXPECT_GL_NO_ERROR();
3541     EXPECT_EQ(0.0, actual[0]);
3542     EXPECT_EQ(1.0, actual[1]);
3543     EXPECT_EQ(0.0, actual[2]);
3544     EXPECT_EQ(0.0, actual[3]);
3545 }
3546 
3547 // Test that render pipeline and compute pipeline access to the same texture.
3548 // Steps:
3549 //   1. DispatchCompute.
3550 //   2. DrawArrays.
TEST_P(ComputeShaderTest,DispatchDraw)3551 TEST_P(ComputeShaderTest, DispatchDraw)
3552 {
3553     // http://anglebug.com/5072
3554     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3555 
3556     const char kCSSource[] = R"(#version 310 es
3557 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3558 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3559 void main()
3560 {
3561     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));
3562 })";
3563 
3564     const char kVSSource[] = R"(#version 310 es
3565 layout (location = 0) in vec2 pos;
3566 out vec2 texCoord;
3567 void main(void) {
3568     texCoord = 0.5*pos + 0.5;
3569     gl_Position = vec4(pos, 0.0, 1.0);
3570 })";
3571 
3572     const char kFSSource[] = R"(#version 310 es
3573 precision highp float;
3574 uniform sampler2D tex;
3575 in vec2 texCoord;
3576 out vec4 fragColor;
3577 void main(void) {
3578     fragColor = texture(tex, texCoord);
3579 })";
3580 
3581     GLuint aPosLoc = 0;
3582     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3583     glBindAttribLocation(program, aPosLoc, "pos");
3584     GLuint buffer;
3585     glGenBuffers(1, &buffer);
3586     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3587     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3588     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3589     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3590     glEnableVertexAttribArray(aPosLoc);
3591 
3592     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3593     GLTexture texture;
3594     glBindTexture(GL_TEXTURE_2D, texture);
3595     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3596     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3597     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3598     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3599     EXPECT_GL_NO_ERROR();
3600 
3601     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3602     glUseProgram(csProgram);
3603 
3604     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3605 
3606     glDispatchCompute(1, 1, 1);
3607     EXPECT_GL_NO_ERROR();
3608 
3609     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3610     glUseProgram(program);
3611     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3612     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
3613 }
3614 
3615 // Test that render pipeline and compute pipeline access to the same texture.
3616 // Steps:
3617 //   1. DrawArrays.
3618 //   2. DispatchCompute.
3619 //   3. DispatchCompute.
3620 //   4. DrawArrays.
TEST_P(ComputeShaderTest,DrawDispatchDispatchDraw)3621 TEST_P(ComputeShaderTest, DrawDispatchDispatchDraw)
3622 {
3623     // http://anglebug.com/5072
3624     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3625 
3626     // Fails on AMD windows drivers.  http://anglebug.com/3871
3627     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
3628 
3629     const char kCSSource[] = R"(#version 310 es
3630 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3631 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3632 uniform float factor;
3633 void main()
3634 {
3635     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(factor, 0.0, 1.0, 1.0));
3636 })";
3637 
3638     const char kVSSource[] = R"(#version 310 es
3639 layout (location = 0) in vec2 pos;
3640 out vec2 texCoord;
3641 void main(void) {
3642     texCoord = 0.5*pos + 0.5;
3643     gl_Position = vec4(pos, 0.0, 1.0);
3644 })";
3645 
3646     const char kFSSource[] = R"(#version 310 es
3647 precision highp float;
3648 uniform sampler2D tex;
3649 in vec2 texCoord;
3650 out vec4 fragColor;
3651 void main(void) {
3652     fragColor = texture(tex, texCoord);
3653 })";
3654 
3655     GLuint aPosLoc = 0;
3656     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3657     glBindAttribLocation(program, aPosLoc, "pos");
3658     GLuint buffer;
3659     glGenBuffers(1, &buffer);
3660     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3661     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3662     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3663     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3664     glEnableVertexAttribArray(aPosLoc);
3665 
3666     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3667     GLTexture texture;
3668     glBindTexture(GL_TEXTURE_2D, texture);
3669     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3670     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3671     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3672     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3673     glUseProgram(program);
3674     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3675     EXPECT_GL_NO_ERROR();
3676 
3677     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3678     glUseProgram(csProgram);
3679     glUniform1f(glGetUniformLocation(csProgram, "factor"), 0.0);
3680     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3681     EXPECT_GL_NO_ERROR();
3682 
3683     glDispatchCompute(1, 1, 1);
3684     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3685     EXPECT_GL_NO_ERROR();
3686 
3687     glUniform1f(glGetUniformLocation(csProgram, "factor"), 1.0);
3688     glDispatchCompute(1, 1, 1);
3689     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3690     EXPECT_GL_NO_ERROR();
3691 
3692     glUseProgram(program);
3693     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3694     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::magenta);
3695 }
3696 
3697 // Test that render pipeline and compute pipeline access to the same texture.
3698 // Steps:
3699 //   1. DispatchCompute.
3700 //   2. DrawArrays.
3701 //   3. DrawArrays.
3702 //   4. DispatchCompute.
TEST_P(ComputeShaderTest,DispatchDrawDrawDispatch)3703 TEST_P(ComputeShaderTest, DispatchDrawDrawDispatch)
3704 {
3705     // http://anglebug.com/5072
3706     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3707 
3708     const char kCSSource[] = R"(#version 310 es
3709 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3710 layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3711 
3712 void main()
3713 {
3714     imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));
3715 })";
3716 
3717     const char kVSSource[] = R"(#version 310 es
3718 layout (location = 0) in vec2 pos;
3719 out vec2 texCoord;
3720 void main(void) {
3721     texCoord = 0.5*pos + 0.5;
3722     gl_Position = vec4(pos, 0.0, 1.0);
3723 })";
3724 
3725     const char kFSSource[] = R"(#version 310 es
3726 precision highp float;
3727 uniform sampler2D tex;
3728 in vec2 texCoord;
3729 uniform float factor;
3730 out vec4 fragColor;
3731 void main(void) {
3732     fragColor = texture(tex, texCoord) + vec4(factor, 0.0, 0.0, 0.0);
3733 })";
3734 
3735     GLuint aPosLoc = 0;
3736     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3737     glBindAttribLocation(program, aPosLoc, "pos");
3738     GLuint buffer;
3739     glGenBuffers(1, &buffer);
3740     glBindBuffer(GL_ARRAY_BUFFER, buffer);
3741     GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3742     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3743     glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3744     glEnableVertexAttribArray(aPosLoc);
3745 
3746     constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3747     GLTexture texture;
3748     glBindTexture(GL_TEXTURE_2D, texture);
3749     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3750     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3751     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3752     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3753 
3754     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3755     glUseProgram(csProgram);
3756     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3757 
3758     glDispatchCompute(1, 1, 1);
3759     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3760     EXPECT_GL_NO_ERROR();
3761 
3762     glUseProgram(program);
3763     glUniform1f(glGetUniformLocation(program, "factor"), 0.0);
3764     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3765     EXPECT_GL_NO_ERROR();
3766 
3767     glUniform1f(glGetUniformLocation(program, "factor"), 1.0);
3768     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3769     EXPECT_GL_NO_ERROR();
3770 
3771     glUseProgram(csProgram);
3772     glDispatchCompute(1, 1, 1);
3773     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3774     EXPECT_GL_NO_ERROR();
3775 
3776     glUseProgram(program);
3777     glUniform1f(glGetUniformLocation(program, "factor"), 0.0);
3778     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3779     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
3780 }
3781 
3782 // Test that invalid memory barrier will produce an error.
TEST_P(ComputeShaderTest,InvalidMemoryBarrier)3783 TEST_P(ComputeShaderTest, InvalidMemoryBarrier)
3784 {
3785     GLbitfield barriers = 0;
3786     glMemoryBarrier(barriers);
3787     EXPECT_GL_ERROR(GL_INVALID_VALUE);
3788 }
3789 
3790 // test atomic counter increment
3791 // http://anglebug.com/3246
TEST_P(ComputeShaderTest,AtomicCounterIncrement)3792 TEST_P(ComputeShaderTest, AtomicCounterIncrement)
3793 {
3794     constexpr char kComputeShader[] = R"(#version 310 es
3795 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3796 layout(binding = 1, std430) buffer Output {
3797   uint preGet[1];
3798   uint increment[1];
3799   uint postGet[1];
3800 } sb_in;
3801 layout(binding=0) uniform atomic_uint counter0;
3802 
3803 void main(void)
3804 {
3805   uint id = (gl_GlobalInvocationID.x);
3806   sb_in.preGet[0u]    = atomicCounter(counter0);
3807   sb_in.increment[0u] = atomicCounterIncrement(counter0);
3808   sb_in.postGet[0u]   = atomicCounter(counter0);
3809 }
3810 )";
3811     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
3812     EXPECT_GL_NO_ERROR();
3813 
3814     glUseProgram(program);
3815 
3816     constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
3817 
3818     GLBuffer shaderStorageBuffer;
3819     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3820     glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
3821     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
3822     EXPECT_GL_NO_ERROR();
3823 
3824     constexpr GLuint atomicBufferInitialData[] = {2u};
3825     GLuint atomicBuffer;
3826     glGenBuffers(1, &atomicBuffer);
3827     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicBuffer);
3828     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomicBufferInitialData), atomicBufferInitialData,
3829                  GL_DYNAMIC_DRAW);
3830     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicBuffer);
3831     EXPECT_GL_NO_ERROR();
3832 
3833     glDispatchCompute(1, 1, 1);
3834     glFinish();
3835     EXPECT_GL_NO_ERROR();
3836 
3837     // read back
3838     const GLuint *ptr = reinterpret_cast<const GLuint *>(
3839         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
3840     EXPECT_EQ(2u, ptr[0]);
3841     EXPECT_EQ(2u, ptr[1]);
3842     EXPECT_EQ(3u, ptr[2]);
3843 
3844     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3845 }
3846 
3847 // Create a 'very large' array inside of a function in a compute shader.
TEST_P(ComputeShaderTest,VeryLargeArrayInsideFunction)3848 TEST_P(ComputeShaderTest, VeryLargeArrayInsideFunction)
3849 {
3850     constexpr char kComputeShader[] = R"(#version 310 es
3851 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3852 layout(binding = 0, std430) buffer Output {
3853   int value[1];
3854 } output_data;
3855 
3856 void main()
3857 {
3858     int values[1000];
3859     for (int i = 0; i < values.length(); i++)
3860     {
3861         values[i] = 0;
3862     }
3863 
3864     int total = 0;
3865     for (int i = 0; i < values.length(); i++)
3866     {
3867         total += i;
3868         values[i] = total;
3869     }
3870     output_data.value[0u] = values[1000-1];
3871 })";
3872 
3873     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
3874     EXPECT_GL_NO_ERROR();
3875 
3876     glUseProgram(program);
3877 
3878     constexpr unsigned int kBytesPerComponent = sizeof(GLint);
3879 
3880     GLBuffer shaderStorageBuffer;
3881     glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3882     glBufferData(GL_SHADER_STORAGE_BUFFER, 1 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
3883     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
3884     EXPECT_GL_NO_ERROR();
3885 
3886     glDispatchCompute(1, 1, 1);
3887     glFinish();
3888     EXPECT_GL_NO_ERROR();
3889 
3890     // read back
3891     const GLint *ptr = reinterpret_cast<const GLint *>(
3892         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 1 * kBytesPerComponent, GL_MAP_READ_BIT));
3893     EXPECT_EQ(499500, ptr[0]);
3894 
3895     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3896 }
3897 
3898 // Test that render pipeline and compute pipeline access to the same texture.
3899 // Steps:
3900 //   1. Clear the texture and DrawArrays.
3901 //   2. DispatchCompute to set the image's first pixel to a specific color.
3902 //   3. DrawArrays and check data.
TEST_P(ComputeShaderTest,DrawDispatchDrawPreserve)3903 TEST_P(ComputeShaderTest, DrawDispatchDrawPreserve)
3904 {
3905     // http://anglebug.com/5072
3906     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3907 
3908     const char kCSSource[] = R"(#version 310 es
3909 layout(local_size_x=1, local_size_y=1) in;
3910 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
3911 void main()
3912 {
3913     imageStore(image, ivec2(0, 0), vec4(0.0, 0.0, 1.0, 1.0));
3914 })";
3915 
3916     const char kVSSource[] = R"(#version 310 es
3917 layout (location = 0) in vec2 pos;
3918 in vec4 inTex;
3919 out vec4 texCoord;
3920 void main(void) {
3921     texCoord = inTex;
3922     gl_Position = vec4(pos, 0.0, 1.0);
3923 })";
3924 
3925     const char kFSSource[] = R"(#version 310 es
3926 precision highp float;
3927 uniform sampler2D tex;
3928 in vec4 texCoord;
3929 out vec4 fragColor;
3930 void main(void) {
3931     fragColor = texture(tex, texCoord.xy);
3932 })";
3933     GLuint aPosLoc         = 0;
3934     ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3935     glBindAttribLocation(program, aPosLoc, "pos");
3936 
3937     unsigned char *data = new unsigned char[4 * getWindowWidth() * getWindowHeight()];
3938     for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
3939     {
3940         data[i * 4]     = 0xff;
3941         data[i * 4 + 1] = 0;
3942         data[i * 4 + 2] = 0;
3943         data[i * 4 + 3] = 0xff;
3944     }
3945     GLTexture texture;
3946     glBindTexture(GL_TEXTURE_2D, texture);
3947     glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth(), getWindowHeight());
3948     // Clear the texture level 0 to Red.
3949     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA,
3950                     GL_UNSIGNED_BYTE, data);
3951     for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
3952     {
3953         data[i * 4]     = 0;
3954         data[i * 4 + 1] = 0xff;
3955         data[i * 4 + 2] = 0;
3956         data[i * 4 + 3] = 0xff;
3957     }
3958     // Clear the texture level 1 to Green.
3959     glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
3960                     GL_UNSIGNED_BYTE, data);
3961     delete[] data;
3962     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3963     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3964     glUseProgram(program);
3965     GLfloat vertices[]  = {-1, -1, 1, -1, -1, 1, 1, 1};
3966     GLfloat texCoords[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
3967     GLint pos           = glGetAttribLocation(program, "pos");
3968     glEnableVertexAttribArray(pos);
3969     glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
3970     GLint posTex = glGetAttribLocation(program, "inTex");
3971     glEnableVertexAttribArray(posTex);
3972     glVertexAttribPointer(posTex, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
3973 
3974     // Draw with level 0, the whole framebuffer should be Red.
3975     glViewport(0, 0, getWindowWidth(), getWindowHeight());
3976     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3977     EXPECT_GL_NO_ERROR();
3978     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3979     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
3980     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
3981     // Draw with level 1, a quarter of the framebuffer should be Green.
3982     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
3983     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3984     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3985     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3986     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
3987 
3988     // Clear the texture level 0's (0, 0) position to Blue.
3989     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
3990     ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3991     glUseProgram(csProgram);
3992     glDispatchCompute(1, 1, 1);
3993     glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3994     EXPECT_GL_NO_ERROR();
3995     glFinish();
3996 
3997     glUseProgram(program);
3998     // Draw with level 0, the first position should be Blue.
3999     glViewport(0, 0, getWindowWidth(), getWindowHeight());
4000     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4001     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4002     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4003     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
4004     // Draw with level 1, a quarter of the framebuffer should be Green.
4005     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
4006     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4007     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4008     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
4009     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
4010 }
4011 
4012 // Test that maxComputeWorkGroupCount is valid number.
TEST_P(ComputeShaderTest,ValidateMaxComputeWorkGroupCount)4013 TEST_P(ComputeShaderTest, ValidateMaxComputeWorkGroupCount)
4014 {
4015     constexpr char kCS[] = R"(#version 310 es
4016 layout(local_size_x=1) in;
4017 void main()
4018 {
4019 })";
4020 
4021     GLuint program = glCreateProgram();
4022     GLuint cs      = CompileShader(GL_COMPUTE_SHADER, kCS);
4023     EXPECT_NE(0u, cs);
4024 
4025     glAttachShader(program, cs);
4026     glDeleteShader(cs);
4027 
4028     GLint x, y, z;
4029     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &x);
4030     EXPECT_LE(65535, x);
4031     EXPECT_GE(std::numeric_limits<GLint>::max(), x);
4032 
4033     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &y);
4034     EXPECT_LE(65535, y);
4035     EXPECT_GE(std::numeric_limits<GLint>::max(), y);
4036 
4037     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &z);
4038     EXPECT_LE(65535, z);
4039     EXPECT_GE(std::numeric_limits<GLint>::max(), z);
4040 
4041     glDeleteProgram(program);
4042     EXPECT_GL_NO_ERROR();
4043 }
4044 
4045 // Validate that on Vulkan, compute pipeline driver uniforms descriptor set is updated after an
4046 // internal compute-based UtilsVk function is used.  The latter is achieved through a draw with a
4047 // vertex buffer whose format is not natively supported.  Atomic counters are used to make sure the
4048 // compute pipeline uses the driver uniforms descriptor set.
TEST_P(ComputeShaderTest,DispatchConvertVertexDispatch)4049 TEST_P(ComputeShaderTest, DispatchConvertVertexDispatch)
4050 {
4051     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_vertex_type_10_10_10_2"));
4052 
4053     constexpr uint32_t kVertexCount = 6;
4054 
4055     constexpr char kCS[] = R"(#version 310 es
4056 layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4057 
4058 layout(binding = 0) uniform atomic_uint ac;
4059 
4060 layout(binding=0, std140) buffer VertexData
4061 {
4062     uint data[];
4063 };
4064 
4065 void main()
4066 {
4067     atomicCounterIncrement(ac);
4068     data[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;
4069 })";
4070 
4071     constexpr char kVS[] = R"(#version 310 es
4072 precision mediump float;
4073 
4074 layout(location = 0) in vec4 position;
4075 layout(location = 1) in uvec4 data;
4076 
4077 out vec4 color;
4078 
4079 void main() {
4080     color = data.x < 6u && data.y == 0u && data.z == 0u && data.w == 0u
4081         ? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
4082     gl_Position = position;
4083 })";
4084 
4085     constexpr char kFS[] = R"(#version 310 es
4086 precision mediump float;
4087 in vec4 color;
4088 out vec4 colorOut;
4089 void main() {
4090     colorOut = color;
4091 })";
4092 
4093     ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4094     ANGLE_GL_PROGRAM(programVSFS, kVS, kFS);
4095     EXPECT_GL_NO_ERROR();
4096 
4097     // Create atomic counter buffer
4098     GLBuffer atomicCounterBuffer;
4099     constexpr GLuint kInitialAcbData = 0;
4100     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4101     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kInitialAcbData), &kInitialAcbData,
4102                  GL_STATIC_DRAW);
4103     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4104     EXPECT_GL_NO_ERROR();
4105 
4106     // Create vertex buffer
4107     constexpr unsigned kVertexBufferInitData[kVertexCount] = {};
4108     GLBuffer vertexBuffer;
4109     glBindBuffer(GL_SHADER_STORAGE_BUFFER, vertexBuffer);
4110     glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kVertexBufferInitData), kVertexBufferInitData,
4111                  GL_STATIC_DRAW);
4112     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vertexBuffer);
4113     EXPECT_GL_NO_ERROR();
4114 
4115     // Create position buffer
4116     constexpr GLfloat positions[kVertexCount * 2] = {1.0, 1.0, -1.0, 1.0,  -1.0, -1.0,
4117                                                      1.0, 1.0, -1.0, -1.0, 1.0,  -1.0};
4118     GLBuffer positionBuffer;
4119     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4120     glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
4121     EXPECT_GL_NO_ERROR();
4122 
4123     // Create vertex array
4124     GLVertexArray vao;
4125     glBindVertexArray(vao);
4126 
4127     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4128     glEnableVertexAttribArray(0);
4129     glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
4130 
4131     glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4132     glEnableVertexAttribArray(1);
4133     glVertexAttribPointer(1, 4, GL_UNSIGNED_INT_10_10_10_2_OES, false, 0, 0);
4134     EXPECT_GL_NO_ERROR();
4135 
4136     // Fill the vertex buffer with a dispatch call
4137     glUseProgram(programCS);
4138     glDispatchCompute(1, 1, 1);
4139     EXPECT_GL_NO_ERROR();
4140 
4141     glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
4142 
4143     // Draw using the vertex buffer, causing vertex format conversion in compute (in the Vulkan
4144     // backend)
4145     glUseProgram(programVSFS);
4146     glBindVertexArray(vao);
4147     glDrawArrays(GL_TRIANGLES, 0, kVertexCount);
4148     EXPECT_GL_NO_ERROR();
4149 
4150     // Issue another dispatch call. The driver uniforms descriptor set must be rebound.
4151     glUseProgram(programCS);
4152     glDispatchCompute(1, 1, 1);
4153     EXPECT_GL_NO_ERROR();
4154 
4155     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4156 
4157     // Verify that the atomic counter has the expected value.
4158     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4159     GLuint *mappedBuffer = static_cast<GLuint *>(
4160         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4161     EXPECT_EQ(kVertexCount * 2, mappedBuffer[0]);
4162     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4163 }
4164 
4165 // Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
4166 // made.  Blit stencil may issue a dispatch call.
TEST_P(ComputeShaderTest,DispatchBlitStencilDispatch)4167 TEST_P(ComputeShaderTest, DispatchBlitStencilDispatch)
4168 {
4169     // http://anglebug.com/5533
4170     ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
4171 
4172     // http://anglebug.com/5072
4173     ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4174 
4175     constexpr GLsizei kSize = 1;
4176 
4177     constexpr char kCS[] = R"(#version 310 es
4178 layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4179 
4180 uniform vec4 data;
4181 
4182 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4183 
4184 void main()
4185 {
4186     imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4187 })";
4188 
4189     ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4190     EXPECT_GL_NO_ERROR();
4191 
4192     // Create a framebuffer with stencil buffer.  Use multisampled textures so the future blit
4193     // cannot use vkCmdBlitImage.
4194     GLTexture color;
4195     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color);
4196     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);
4197 
4198     GLTexture depthStencil;
4199     glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depthStencil);
4200     glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_DEPTH24_STENCIL8, kSize, kSize,
4201                               true);
4202 
4203     GLFramebuffer fbo;
4204     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4205     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color,
4206                            0);
4207     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
4208                            depthStencil, 0);
4209     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4210     ASSERT_GL_NO_ERROR();
4211 
4212     // Clear the stencil and make sure it's done.
4213     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
4214     glClearStencil(0x55);
4215     glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4216 
4217     glEnable(GL_STENCIL_TEST);
4218     glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4219     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4220     glStencilMask(0xFF);
4221 
4222     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4223     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
4224     ASSERT_GL_NO_ERROR();
4225 
4226     GLTexture colorCopy;
4227     glBindTexture(GL_TEXTURE_2D, colorCopy);
4228     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4229 
4230     GLFramebuffer copyFbo;
4231     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
4232     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorCopy, 0);
4233     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
4234     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
4235     ASSERT_GL_NO_ERROR();
4236 
4237     glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo);
4238     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4239 
4240     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4241 
4242     // Setup image for compute call
4243     GLTexture computeOut;
4244     glBindTexture(GL_TEXTURE_2D, computeOut);
4245     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4246     glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4247     ASSERT_GL_NO_ERROR();
4248 
4249     // Issue a dispatch call.
4250     glUseProgram(programCS);
4251     GLint uniformLoc = glGetUniformLocation(programCS, "data");
4252     ASSERT_NE(uniformLoc, -1);
4253 
4254     glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4255     glDispatchCompute(1, 1, 1);
4256     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4257     ASSERT_GL_NO_ERROR();
4258 
4259     // Blit the stencil texture.  This may use a compute shader internally.
4260     GLTexture depthStencilCopy;
4261     glBindTexture(GL_TEXTURE_2D, depthStencilCopy);
4262     glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
4263     ASSERT_GL_NO_ERROR();
4264 
4265     glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
4266     glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
4267                            depthStencilCopy, 0);
4268     ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
4269     ASSERT_GL_NO_ERROR();
4270 
4271     glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
4272     ASSERT_GL_NO_ERROR();
4273 
4274     // Issue another dispatch call.
4275     glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
4276     glDispatchCompute(1, 1, 1);
4277     ASSERT_GL_NO_ERROR();
4278 
4279     // Verify the results.
4280     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4281     glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);
4282     glBindTexture(GL_TEXTURE_2D, computeOut);
4283     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
4284     ASSERT_GL_NO_ERROR();
4285 
4286     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4287 
4288     // Verify the blit copy results.
4289     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
4290     ASSERT_GL_NO_ERROR();
4291 
4292     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4293 }
4294 
4295 // Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
4296 // made.  Generate mipmap may issue a dispatch call.
TEST_P(ComputeShaderTest,DispatchGenerateMipmapDispatch)4297 TEST_P(ComputeShaderTest, DispatchGenerateMipmapDispatch)
4298 {
4299     constexpr GLsizei kSize = 8;
4300 
4301     constexpr char kCS[] = R"(#version 310 es
4302 layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4303 
4304 uniform vec4 data;
4305 
4306 layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4307 
4308 void main()
4309 {
4310     imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4311 })";
4312 
4313     ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4314     EXPECT_GL_NO_ERROR();
4315 
4316     GLTexture color;
4317     glBindTexture(GL_TEXTURE_2D, color);
4318     glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, kSize, kSize);
4319 
4320     const std::vector<GLColor> kInitialColor(kSize * kSize, GLColor::green);
4321     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4322                     kInitialColor.data());
4323 
4324     // Setup image for compute call
4325     GLTexture computeOut;
4326     glBindTexture(GL_TEXTURE_2D, computeOut);
4327     glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4328     glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4329     ASSERT_GL_NO_ERROR();
4330 
4331     // Issue a dispatch call.
4332     glUseProgram(programCS);
4333     GLint uniformLoc = glGetUniformLocation(programCS, "data");
4334     ASSERT_NE(uniformLoc, -1);
4335 
4336     glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4337     glDispatchCompute(1, 1, 1);
4338     glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4339     ASSERT_GL_NO_ERROR();
4340 
4341     // Generate mipmap on the texture.  This may use a compute shader internally.
4342     glBindTexture(GL_TEXTURE_2D, color);
4343     glGenerateMipmap(GL_TEXTURE_2D);
4344 
4345     // Issue another dispatch call.
4346     glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
4347     glDispatchCompute(1, 1, 1);
4348     ASSERT_GL_NO_ERROR();
4349 
4350     // Verify the results.
4351     GLFramebuffer fbo;
4352     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4353     glBindTexture(GL_TEXTURE_2D, computeOut);
4354     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
4355     ASSERT_GL_NO_ERROR();
4356 
4357     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4358     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4359 }
4360 
4361 // Write to image array with an aliasing format.
TEST_P(ComputeShaderTest,AliasingFormatForImageArray)4362 TEST_P(ComputeShaderTest, AliasingFormatForImageArray)
4363 {
4364     // http://anglebug.com/5352
4365     ANGLE_SKIP_TEST_IF(IsD3D11());
4366 
4367     constexpr char kCS[] = R"(#version 310 es
4368 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
4369 layout(r32ui, binding = 0) writeonly uniform highp uimage2DArray image;
4370 void main()
4371 {
4372     uint yellow = 0xFF00FFFFu;
4373     imageStore(image, ivec3(gl_LocalInvocationID.xyz), uvec4(yellow, 0, 0, 0));
4374 })";
4375 
4376     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
4377 
4378     const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);
4379 
4380     GLTexture texture;
4381     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
4382     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);
4383     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4384                     GL_UNSIGNED_BYTE, kInitData.data());
4385     EXPECT_GL_NO_ERROR();
4386 
4387     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4388     glUseProgram(program);
4389 
4390     // Output yellow to both layers.
4391     glBindImageTexture(0, texture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
4392     glDispatchCompute(1, 1, 1);
4393     EXPECT_GL_NO_ERROR();
4394 
4395     // Verify results.
4396     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4397     EXPECT_GL_NO_ERROR();
4398 
4399     GLFramebuffer framebuffer;
4400     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
4401     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);
4402     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);
4403     EXPECT_GL_NO_ERROR();
4404 
4405     glReadBuffer(GL_COLOR_ATTACHMENT0);
4406     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4407 
4408     glReadBuffer(GL_COLOR_ATTACHMENT1);
4409     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4410 }
4411 
4412 // Write to one layer of image array with an aliasing format.
TEST_P(ComputeShaderTest,AliasingFormatForOneLayerOfImageArray)4413 TEST_P(ComputeShaderTest, AliasingFormatForOneLayerOfImageArray)
4414 {
4415     // http://anglebug.com/5352
4416     ANGLE_SKIP_TEST_IF(IsD3D11());
4417 
4418     constexpr char kCS[] = R"(#version 310 es
4419 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4420 layout(r32ui, binding = 0) writeonly uniform highp uimage2D image;
4421 void main()
4422 {
4423     uint yellow = 0xFF00FFFFu;
4424     imageStore(image, ivec2(gl_LocalInvocationID.xy), uvec4(yellow, 0, 0, 0));
4425 })";
4426 
4427     constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
4428 
4429     const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);
4430 
4431     GLTexture texture;
4432     glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
4433     glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);
4434     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4435                     GL_UNSIGNED_BYTE, kInitData.data());
4436     EXPECT_GL_NO_ERROR();
4437 
4438     GLFramebuffer framebuffer;
4439     glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
4440     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);
4441     glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);
4442     EXPECT_GL_NO_ERROR();
4443 
4444     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4445     glUseProgram(program);
4446 
4447     // Output yellow to layer 0.
4448     glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
4449     glDispatchCompute(1, 1, 1);
4450     EXPECT_GL_NO_ERROR();
4451 
4452     // Verify that only layer 0 was changed.
4453     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4454     EXPECT_GL_NO_ERROR();
4455 
4456     glReadBuffer(GL_COLOR_ATTACHMENT0);
4457     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4458 
4459     glReadBuffer(GL_COLOR_ATTACHMENT1);
4460     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4461 
4462     // Reset texture back to black.
4463     glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4464                     GL_UNSIGNED_BYTE, kInitData.data());
4465 
4466     // Output yellow to layer 1.
4467     glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
4468     glDispatchCompute(1, 1, 1);
4469     EXPECT_GL_NO_ERROR();
4470 
4471     // Verify that only layer 1 was changed.
4472     glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4473     EXPECT_GL_NO_ERROR();
4474 
4475     glReadBuffer(GL_COLOR_ATTACHMENT0);
4476     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4477 
4478     glReadBuffer(GL_COLOR_ATTACHMENT1);
4479     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4480 }
4481 
4482 // Test glMemoryBarrier(CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT) by writing to persistenly mapped
4483 // buffer from a compute shader.
TEST_P(ComputeShaderTest,WriteToPersistentBuffer)4484 TEST_P(ComputeShaderTest, WriteToPersistentBuffer)
4485 {
4486     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
4487 
4488     constexpr char kCS[] = R"(#version 310 es
4489 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4490 layout(std140, binding = 0) buffer block {
4491     uvec4 data;
4492 } outBlock;
4493 void main()
4494 {
4495     outBlock.data += uvec4(1);
4496 })";
4497 
4498     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4499     glUseProgram(program);
4500 
4501     constexpr std::array<uint32_t, 4> kInitData = {};
4502 
4503     GLBuffer coherentBuffer;
4504     glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4505     glBufferStorageEXT(
4506         GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),
4507         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
4508 
4509     GLBuffer nonCoherentBuffer;
4510     glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4511     glBufferStorageEXT(GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),
4512                        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4513 
4514     // Map the buffers for read and write.
4515     glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4516     uint32_t *coherentMapped = reinterpret_cast<uint32_t *>(glMapBufferRange(
4517         GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),
4518         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT));
4519     ASSERT_GL_NO_ERROR();
4520 
4521     glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4522     uint32_t *nonCoherentMapped = reinterpret_cast<uint32_t *>(
4523         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),
4524                          GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT));
4525     ASSERT_GL_NO_ERROR();
4526 
4527     constexpr std::array<uint32_t, 4> kCoherentExpectedData = {
4528         0x12354678u,
4529         0x2468ACE0u,
4530         0x13579BDFu,
4531         0x76543210u,
4532     };
4533 
4534     constexpr std::array<uint32_t, 4> kNonCoherentExpectedData = {
4535         0x9ABCDEF0u,
4536         0xFDB97531u,
4537         0x1F2E3D4Bu,
4538         0x5A697887u,
4539     };
4540 
4541     coherentMapped[0] = kCoherentExpectedData[0] - 1;
4542     coherentMapped[1] = kCoherentExpectedData[1] - 1;
4543     coherentMapped[2] = kCoherentExpectedData[2] - 1;
4544     coherentMapped[3] = kCoherentExpectedData[3] - 1;
4545 
4546     nonCoherentMapped[0] = kNonCoherentExpectedData[0] - 1;
4547     nonCoherentMapped[1] = kNonCoherentExpectedData[1] - 1;
4548     nonCoherentMapped[2] = kNonCoherentExpectedData[2] - 1;
4549     nonCoherentMapped[3] = kNonCoherentExpectedData[3] - 1;
4550 
4551     // Test coherent write
4552     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, coherentBuffer);
4553     glDispatchCompute(1, 1, 1);
4554     EXPECT_GL_NO_ERROR();
4555 
4556     glFinish();
4557     EXPECT_EQ(coherentMapped[0], kCoherentExpectedData[0]);
4558     EXPECT_EQ(coherentMapped[1], kCoherentExpectedData[1]);
4559     EXPECT_EQ(coherentMapped[2], kCoherentExpectedData[2]);
4560     EXPECT_EQ(coherentMapped[3], kCoherentExpectedData[3]);
4561 
4562     // Test non-coherent write
4563     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, nonCoherentBuffer);
4564     glDispatchCompute(1, 1, 1);
4565 
4566     glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT);
4567     EXPECT_GL_NO_ERROR();
4568 
4569     glFinish();
4570     EXPECT_EQ(nonCoherentMapped[0], kNonCoherentExpectedData[0]);
4571     EXPECT_EQ(nonCoherentMapped[1], kNonCoherentExpectedData[1]);
4572     EXPECT_EQ(nonCoherentMapped[2], kNonCoherentExpectedData[2]);
4573     EXPECT_EQ(nonCoherentMapped[3], kNonCoherentExpectedData[3]);
4574 
4575     glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4576     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4577     glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4578     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4579     EXPECT_GL_NO_ERROR();
4580 }
4581 
4582 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest);
4583 ANGLE_INSTANTIATE_TEST_ES31_AND(ComputeShaderTest, WithDirectSPIRVGeneration(ES31_VULKAN()));
4584 
4585 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTestES3);
4586 ANGLE_INSTANTIATE_TEST_ES3(ComputeShaderTestES3);
4587 
4588 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ComputeTest);
4589 ANGLE_INSTANTIATE_TEST_ES31(WebGL2ComputeTest);
4590 }  // namespace
4591