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