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