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