blob: f1c129e535fba41bf20c6891a091d933b90b7170 [file] [log] [blame]
Martin Radev4c4c8e72016-08-04 12:25:34 +03001//
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
Xinghua Cao08a8ec82017-12-27 13:31:11 +08009#include <vector>
Martin Radev4c4c8e72016-08-04 12:25:34 +030010#include "test_utils/ANGLETest.h"
11#include "test_utils/gl_raii.h"
Martin Radev4c4c8e72016-08-04 12:25:34 +030012
13using namespace angle;
14
15namespace
16{
17
18class ComputeShaderTest : public ANGLETest
19{
20 protected:
21 ComputeShaderTest() {}
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080022
Jiawei Shaoa6a78422018-06-28 08:32:54 +080023 template <class T, GLint kWidth, GLint kHeight>
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080024 void runSharedMemoryTest(const char *csSource,
Jiawei Shaoa6a78422018-06-28 08:32:54 +080025 GLenum internalFormat,
26 GLenum format,
27 const std::array<T, kWidth * kHeight> &inputData,
28 const std::array<T, kWidth * kHeight> &expectedValues)
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080029 {
30 GLTexture texture[2];
31 GLFramebuffer framebuffer;
32
33 glBindTexture(GL_TEXTURE_2D, texture[0]);
Jiawei Shaoa6a78422018-06-28 08:32:54 +080034 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);
35 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format,
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080036 inputData.data());
37 EXPECT_GL_NO_ERROR();
38
Jiawei Shaoa6a78422018-06-28 08:32:54 +080039 constexpr T initData[kWidth * kHeight] = {};
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080040 glBindTexture(GL_TEXTURE_2D, texture[1]);
Jiawei Shaoa6a78422018-06-28 08:32:54 +080041 glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);
42 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format, initData);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080043 EXPECT_GL_NO_ERROR();
44
45 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
46 glUseProgram(program.get());
47
Jiawei Shaoa6a78422018-06-28 08:32:54 +080048 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalFormat);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080049 EXPECT_GL_NO_ERROR();
50
Jiawei Shaoa6a78422018-06-28 08:32:54 +080051 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080052 EXPECT_GL_NO_ERROR();
53
54 glDispatchCompute(1, 1, 1);
55 EXPECT_GL_NO_ERROR();
56
57 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
58
Jiawei Shaoa6a78422018-06-28 08:32:54 +080059 T outputValues[kWidth * kHeight] = {};
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080060 glUseProgram(0);
61 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
62
63 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1],
64 0);
65 EXPECT_GL_NO_ERROR();
Jiawei Shaoa6a78422018-06-28 08:32:54 +080066 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, format, outputValues);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +080067 EXPECT_GL_NO_ERROR();
68
69 for (int i = 0; i < kWidth * kHeight; i++)
70 {
71 EXPECT_EQ(expectedValues[i], outputValues[i]);
72 }
73 }
Martin Radev4c4c8e72016-08-04 12:25:34 +030074};
75
76class ComputeShaderTestES3 : public ANGLETest
77{
78 protected:
79 ComputeShaderTestES3() {}
80};
81
82// link a simple compute program. It should be successful.
83TEST_P(ComputeShaderTest, LinkComputeProgram)
84{
85 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +080086 R"(#version 310 es
87 layout(local_size_x=1) in;
88 void main()
89 {\
90 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +030091
92 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
93
94 EXPECT_GL_NO_ERROR();
95}
96
Yunchao He85072e82017-11-14 15:43:28 +080097// Link a simple compute program. Then detach the shader and dispatch compute.
98// It should be successful.
99TEST_P(ComputeShaderTest, DetachShaderAfterLinkSuccess)
100{
101 const std::string csSource =
102 R"(#version 310 es
103 layout(local_size_x=1) in;
104 void main()
105 {
106 })";
107
108 GLuint program = glCreateProgram();
109
110 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
111 EXPECT_NE(0u, cs);
112
113 glAttachShader(program, cs);
114 glDeleteShader(cs);
115
116 glLinkProgram(program);
117 GLint linkStatus;
118 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
Yunchao He1f679cc2017-11-29 18:06:00 +0800119 EXPECT_GL_TRUE(linkStatus);
Yunchao He85072e82017-11-14 15:43:28 +0800120
121 glDetachShader(program, cs);
122 EXPECT_GL_NO_ERROR();
123
124 glUseProgram(program);
125 glDispatchCompute(8, 4, 2);
126 EXPECT_GL_NO_ERROR();
127}
128
Martin Radev4c4c8e72016-08-04 12:25:34 +0300129// link a simple compute program. There is no local size and linking should fail.
130TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)
131{
132 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800133 R"(#version 310 es
134 void main()
135 {
136 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300137
138 GLuint program = CompileComputeProgram(csSource, false);
139 EXPECT_EQ(0u, program);
140
141 glDeleteProgram(program);
142
143 EXPECT_GL_NO_ERROR();
144}
145
146// link a simple compute program.
147// make sure that uniforms and uniform samplers get recorded
148TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)
149{
150 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200151 R"(#version 310 es
152 precision mediump sampler2D;
153 layout(local_size_x=1) in;
154 uniform int myUniformInt;
155 uniform sampler2D myUniformSampler;
156 layout(rgba32i) uniform highp writeonly iimage2D imageOut;
157 void main()
158 {
159 int q = myUniformInt;
160 vec4 v = textureLod(myUniformSampler, vec2(0.0), 0.0);
161 imageStore(imageOut, ivec2(0), ivec4(v) * q);
162 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300163
164 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
165
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200166 GLint uniformLoc = glGetUniformLocation(program.get(), "myUniformInt");
167 EXPECT_NE(-1, uniformLoc);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300168
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200169 uniformLoc = glGetUniformLocation(program.get(), "myUniformSampler");
170 EXPECT_NE(-1, uniformLoc);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300171
172 EXPECT_GL_NO_ERROR();
173}
174
175// Attach both compute and non-compute shaders. A link time error should occur.
176// OpenGL ES 3.10, 7.3 Program Objects
177TEST_P(ComputeShaderTest, AttachMultipleShaders)
178{
179 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800180 R"(#version 310 es
181 layout(local_size_x=1) in;
182 void main()
183 {
184 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300185
186 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800187 R"(#version 310 es
188 void main()
189 {
190 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300191
192 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800193 R"(#version 310 es
194 void main()
195 {
196 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300197
198 GLuint program = glCreateProgram();
199
200 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
201 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
202 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
203
204 EXPECT_NE(0u, vs);
205 EXPECT_NE(0u, fs);
206 EXPECT_NE(0u, cs);
207
208 glAttachShader(program, vs);
209 glDeleteShader(vs);
210
211 glAttachShader(program, fs);
212 glDeleteShader(fs);
213
214 glAttachShader(program, cs);
215 glDeleteShader(cs);
216
217 glLinkProgram(program);
218
219 GLint linkStatus;
220 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
221
Yunchao He1f679cc2017-11-29 18:06:00 +0800222 EXPECT_GL_FALSE(linkStatus);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300223
224 EXPECT_GL_NO_ERROR();
225}
226
227// Attach a vertex, fragment and compute shader.
228// Query for the number of attached shaders and check the count.
229TEST_P(ComputeShaderTest, AttachmentCount)
230{
Martin Radev4c4c8e72016-08-04 12:25:34 +0300231 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800232 R"(#version 310 es
233 layout(local_size_x=1) in;
234 void main()
235 {
236 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300237
238 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800239 R"(#version 310 es
240 void main()
241 {
242 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300243
244 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800245 R"(#version 310 es
246 void main()
247 {
248 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300249
250 GLuint program = glCreateProgram();
251
252 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
253 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
254 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
255
256 EXPECT_NE(0u, vs);
257 EXPECT_NE(0u, fs);
258 EXPECT_NE(0u, cs);
259
260 glAttachShader(program, vs);
261 glDeleteShader(vs);
262
263 glAttachShader(program, fs);
264 glDeleteShader(fs);
265
266 glAttachShader(program, cs);
267 glDeleteShader(cs);
268
269 GLint numAttachedShaders;
270 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
271
272 EXPECT_EQ(3, numAttachedShaders);
273
274 glDeleteProgram(program);
275
276 EXPECT_GL_NO_ERROR();
277}
278
Yunchao Hecddcb592017-11-13 15:27:35 +0800279// Attach a compute shader and link, but start rendering.
280TEST_P(ComputeShaderTest, StartRenderingWithComputeProgram)
281{
282 const std::string csSource =
283 R"(#version 310 es
284 layout(local_size_x=1) in;
285 void main()
286 {
287 })";
288
289 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
290 EXPECT_GL_NO_ERROR();
291
292 glUseProgram(program);
293 glDrawArrays(GL_POINTS, 0, 2);
294 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
295}
296
Yunchao He70b715c2017-11-07 14:59:15 +0800297// Attach a vertex and fragment shader and link, but dispatch compute.
298TEST_P(ComputeShaderTest, DispatchComputeWithRenderingProgram)
299{
300 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800301 R"(#version 310 es
302 void main()
303 {
304 })";
Yunchao He70b715c2017-11-07 14:59:15 +0800305
306 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800307 R"(#version 310 es
308 void main()
309 {
310 })";
Yunchao He70b715c2017-11-07 14:59:15 +0800311
312 GLuint program = glCreateProgram();
313
314 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
315 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
316
317 EXPECT_NE(0u, vs);
318 EXPECT_NE(0u, fs);
319
320 glAttachShader(program, vs);
321 glDeleteShader(vs);
322
323 glAttachShader(program, fs);
324 glDeleteShader(fs);
325
326 glLinkProgram(program);
327
328 GLint linkStatus;
329 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
Yunchao He1f679cc2017-11-29 18:06:00 +0800330 EXPECT_GL_TRUE(linkStatus);
Yunchao He70b715c2017-11-07 14:59:15 +0800331
332 EXPECT_GL_NO_ERROR();
333
334 glUseProgram(program);
335 glDispatchCompute(8, 4, 2);
336 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
337}
338
Xinghua Caob1239382016-12-13 15:07:05 +0800339// Access all compute shader special variables.
340TEST_P(ComputeShaderTest, AccessAllSpecialVariables)
341{
342 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200343 R"(#version 310 es
344 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
345 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
346 void main()
347 {
348 uvec3 temp1 = gl_NumWorkGroups;
349 uvec3 temp2 = gl_WorkGroupSize;
350 uvec3 temp3 = gl_WorkGroupID;
351 uvec3 temp4 = gl_LocalInvocationID;
352 uvec3 temp5 = gl_GlobalInvocationID;
353 uint temp6 = gl_LocalInvocationIndex;
354 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));
355 })";
Xinghua Caob1239382016-12-13 15:07:05 +0800356
357 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
358}
359
360// Access part compute shader special variables.
361TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
362{
363 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200364 R"(#version 310 es
365 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
366 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
367 void main()
368 {
369 uvec3 temp1 = gl_WorkGroupSize;
370 uvec3 temp2 = gl_WorkGroupID;
371 uint temp3 = gl_LocalInvocationIndex;
372 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2, temp3));
373 })";
Xinghua Caob1239382016-12-13 15:07:05 +0800374
375 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
376}
377
Xinghua Cao73badc02017-03-29 19:14:53 +0800378// Use glDispatchCompute to define work group count.
379TEST_P(ComputeShaderTest, DispatchCompute)
Xinghua Cao2b396592017-03-29 15:36:04 +0800380{
381 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200382 R"(#version 310 es
383 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
384 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
385 void main()
386 {
387 uvec3 temp = gl_NumWorkGroups;
388 imageStore(imageOut, ivec2(0), uvec4(temp, 0u));
389 })";
Xinghua Cao2b396592017-03-29 15:36:04 +0800390
391 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
392
393 glUseProgram(program.get());
394 glDispatchCompute(8, 4, 2);
395 EXPECT_GL_NO_ERROR();
396}
397
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800398// Use image uniform to write texture in compute shader, and verify the content is expected.
399TEST_P(ComputeShaderTest, BindImageTexture)
400{
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800401 GLTexture mTexture[2];
402 GLFramebuffer mFramebuffer;
403 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800404 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800405 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Yunchao Hecddcb592017-11-13 15:27:35 +0800406 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
407 void main()
408 {
409 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
410 0, 0));
411 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
412 0, 0));
413 })";
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800414
415 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
416 glUseProgram(program.get());
Xinghua Cao27f43212018-02-26 11:05:53 +0800417 int width = 1, height = 1;
418 GLuint inputValues[] = {200};
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800419
420 glBindTexture(GL_TEXTURE_2D, mTexture[0]);
421 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
422 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
423 inputValues);
424 EXPECT_GL_NO_ERROR();
425
426 glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
427 EXPECT_GL_NO_ERROR();
428
429 glBindTexture(GL_TEXTURE_2D, mTexture[1]);
430 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
431 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
432 inputValues);
433 EXPECT_GL_NO_ERROR();
434
435 glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
436 EXPECT_GL_NO_ERROR();
437
Xinghua Cao27f43212018-02-26 11:05:53 +0800438 glDispatchCompute(1, 1, 1);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800439 EXPECT_GL_NO_ERROR();
440
Xinghua Cao27f43212018-02-26 11:05:53 +0800441 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800442 glUseProgram(0);
Xinghua Cao27f43212018-02-26 11:05:53 +0800443 GLuint outputValues[2][1];
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800444 GLuint expectedValue = 100;
445 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
446
447 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
448 0);
449 EXPECT_GL_NO_ERROR();
450 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
451 EXPECT_GL_NO_ERROR();
452
453 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
454 0);
455 EXPECT_GL_NO_ERROR();
456 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
457 EXPECT_GL_NO_ERROR();
458
459 for (int i = 0; i < width * height; i++)
460 {
461 EXPECT_EQ(expectedValue, outputValues[0][i]);
462 EXPECT_EQ(expectedValue, outputValues[1][i]);
463 }
464}
465
Xinghua Cao0328b572017-06-26 15:51:36 +0800466// When declare a image array without a binding qualifier, all elements are bound to unit zero.
467TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
468{
469 ANGLE_SKIP_TEST_IF(IsD3D11());
470
471 // TODO(xinghua.cao@intel.com): On AMD desktop OpenGL, bind two image variables to unit 0,
472 // only one variable is valid.
Corentin Wallez2bde9192017-07-28 14:15:01 -0400473 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
Xinghua Cao0328b572017-06-26 15:51:36 +0800474
475 GLTexture mTexture;
476 GLFramebuffer mFramebuffer;
477 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800478 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800479 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Yunchao Hecddcb592017-11-13 15:27:35 +0800480 layout(r32ui) writeonly uniform highp uimage2D uImage[2];
481 void main()
482 {
483 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
484 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
485 })";
Xinghua Cao0328b572017-06-26 15:51:36 +0800486
487 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
488 glUseProgram(program.get());
Xinghua Cao27f43212018-02-26 11:05:53 +0800489 constexpr int kTextureWidth = 1, kTextureHeight = 2;
490 GLuint inputValues[] = {200, 200};
Xinghua Cao0328b572017-06-26 15:51:36 +0800491
492 glBindTexture(GL_TEXTURE_2D, mTexture);
493 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
494 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
495 GL_UNSIGNED_INT, inputValues);
496 EXPECT_GL_NO_ERROR();
497
498 glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
499 glDispatchCompute(1, 1, 1);
500 EXPECT_GL_NO_ERROR();
501
Xinghua Cao27f43212018-02-26 11:05:53 +0800502 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
Xinghua Cao0328b572017-06-26 15:51:36 +0800503 glUseProgram(0);
504 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
505
506 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
Xinghua Cao27f43212018-02-26 11:05:53 +0800507 GLuint outputValues[kTextureWidth * kTextureHeight];
Xinghua Cao0328b572017-06-26 15:51:36 +0800508 glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
509 outputValues);
510 EXPECT_GL_NO_ERROR();
511
512 GLuint expectedValue = 100;
513 for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
514 {
515 EXPECT_EQ(expectedValue, outputValues[i]);
516 }
517}
518
Xinghua Cao711b7a12017-10-09 13:38:12 +0800519// imageLoad functions
520TEST_P(ComputeShaderTest, ImageLoad)
521{
522 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200523 R"(#version 310 es
524 layout(local_size_x=8) in;
525 layout(rgba8) uniform highp readonly image2D mImage2DInput;
526 layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
527 layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
528 layout(r32i) uniform highp writeonly iimage2D imageOut;
529 void main()
530 {
531 vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
532 ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
533 uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
534 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
535 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800536
537 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
538 EXPECT_GL_NO_ERROR();
539}
540
541// imageStore functions
542TEST_P(ComputeShaderTest, ImageStore)
543{
544 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800545 R"(#version 310 es
546 layout(local_size_x=8) in;
547 layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
548 layout(r32f) uniform highp writeonly image3D mImage3DOutput;
549 layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
550 void main()
551 {
552 imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
553 imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
554 imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
555 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800556
557 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
558 EXPECT_GL_NO_ERROR();
559}
560
561// imageSize functions
562TEST_P(ComputeShaderTest, ImageSize)
563{
564 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200565 R"(#version 310 es
566 layout(local_size_x=8) in;
567 layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
568 layout(r32i) uniform highp readonly iimage2D mImage2DInput;
569 layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
570 layout(r32i) uniform highp writeonly iimage2D imageOut;
571 void main()
572 {
573 ivec2 sizeCube = imageSize(mImageCubeInput);
574 ivec2 size2D = imageSize(mImage2DInput);
575 ivec3 size2DArray = imageSize(mImage2DArrayInput);
576 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
577 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800578
579 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
580 EXPECT_GL_NO_ERROR();
581}
582
Jiajia Qin5ae6ee42018-03-06 17:39:42 +0800583// Test that sampling texture works well in compute shader.
584TEST_P(ComputeShaderTest, TextureSampling)
585{
586 ANGLE_SKIP_TEST_IF(IsD3D11());
587
588 const std::string &csSource =
589 R"(#version 310 es
590 layout(local_size_x=16, local_size_y=16) in;
591 precision highp usampler2D;
592 uniform usampler2D tex;
593 layout(std140, binding = 0) buffer buf {
594 uint outData[16][16];
595 };
596
597 void main()
598 {
599 uint x = gl_LocalInvocationID.x;
600 uint y = gl_LocalInvocationID.y;
601 outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;
602 })";
603
604 constexpr unsigned int kWidth = 16;
605 constexpr unsigned int kHeight = 16;
606 GLTexture tex;
607 glBindTexture(GL_TEXTURE_2D, tex);
608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
610 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
611 GLuint texels[kHeight][kWidth] = {{0}};
612 for (unsigned int y = 0; y < kHeight; ++y)
613 {
614 for (unsigned int x = 0; x < kWidth; ++x)
615 {
616 texels[y][x] = x + y * kWidth;
617 }
618 }
619 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
620 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
621 texels);
622 glBindTexture(GL_TEXTURE_2D, 0);
623
624 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
625 constexpr unsigned int kArrayStride = 16;
626 GLBuffer ssbo;
627 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
628 glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
629 GL_STREAM_DRAW);
630 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
631 EXPECT_GL_NO_ERROR();
632
633 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
634 glUseProgram(program.get());
635
636 glActiveTexture(GL_TEXTURE0);
637 glBindTexture(GL_TEXTURE_2D, tex);
638 glUniform1i(glGetUniformLocation(program, "tex"), 0);
639 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
640 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
641
642 glDispatchCompute(1, 1, 1);
643
644 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
645 void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride,
646 GL_MAP_READ_BIT);
647 for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
648 {
649 EXPECT_EQ(idx, *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
650 idx * kArrayStride)));
651 }
652 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
653 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
654 EXPECT_GL_NO_ERROR();
655}
656
Xinghua Cao6dfdca82018-08-03 17:10:55 +0800657// Test mixed use of sampler and image.
658TEST_P(ComputeShaderTest, SamplingAndImageReadWrite)
659{
660 GLTexture texture[3];
661 GLFramebuffer framebuffer;
662 const std::string csSource =
663 R"(#version 310 es
664 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
665 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
666 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
667 precision highp usampler2D;
668 uniform usampler2D tex;
669 void main()
670 {
671 uvec4 value_1 = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
672 uvec4 value_2 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
673 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value_1 + value_2);
674 })";
675
676 constexpr int kWidth = 1, kHeight = 1;
677 constexpr GLuint kInputValues[3][1] = {{50}, {100}, {20}};
678
679 glBindTexture(GL_TEXTURE_2D, texture[0]);
680 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
681 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
682 kInputValues[0]);
683 glBindTexture(GL_TEXTURE_2D, texture[2]);
684 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
685 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
686 kInputValues[2]);
687 EXPECT_GL_NO_ERROR();
688 glBindTexture(GL_TEXTURE_2D, 0);
689
690 glBindTexture(GL_TEXTURE_2D, texture[1]);
691 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
692 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
693 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
694 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
695 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
696 kInputValues[1]);
697
698 EXPECT_GL_NO_ERROR();
699
700 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
701 glUseProgram(program.get());
702
703 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
704 glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
705 EXPECT_GL_NO_ERROR();
706
707 glDispatchCompute(1, 1, 1);
708 EXPECT_GL_NO_ERROR();
709
710 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
711 GLuint outputValues[kWidth * kHeight];
712 constexpr GLuint expectedValue = 150;
713 glUseProgram(0);
714 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
715
716 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
717 EXPECT_GL_NO_ERROR();
718 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
719 EXPECT_GL_NO_ERROR();
720
721 for (int i = 0; i < kWidth * kHeight; i++)
722 {
723 EXPECT_EQ(expectedValue, outputValues[i]);
724 }
725}
726
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800727// Use image uniform to read and write Texture2D in compute shader, and verify the contents.
Xinghua Cao26143fd2017-11-01 18:19:05 +0800728TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
729{
730 GLTexture texture[2];
731 GLFramebuffer framebuffer;
732 const std::string csSource =
733 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800734 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800735 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
736 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
737 void main()
738 {
739 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
740 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
741 })";
742
Xinghua Cao27f43212018-02-26 11:05:53 +0800743 constexpr int kWidth = 1, kHeight = 1;
744 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800745
746 glBindTexture(GL_TEXTURE_2D, texture[0]);
747 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
748 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
749 kInputValues[0]);
750 EXPECT_GL_NO_ERROR();
751
752 glBindTexture(GL_TEXTURE_2D, texture[1]);
753 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
754 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
755 kInputValues[1]);
756 EXPECT_GL_NO_ERROR();
757
Xinghua Cao26143fd2017-11-01 18:19:05 +0800758 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
759 glUseProgram(program.get());
760
761 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
762 EXPECT_GL_NO_ERROR();
763
764 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
765 EXPECT_GL_NO_ERROR();
766
767 glDispatchCompute(1, 1, 1);
768 EXPECT_GL_NO_ERROR();
769
Xinghua Cao27f43212018-02-26 11:05:53 +0800770 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
771 GLuint outputValues[kWidth * kHeight];
772 constexpr GLuint expectedValue = 200;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800773 glUseProgram(0);
774 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
775
776 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
777 EXPECT_GL_NO_ERROR();
778 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
779 EXPECT_GL_NO_ERROR();
780
781 for (int i = 0; i < kWidth * kHeight; i++)
782 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800783 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao26143fd2017-11-01 18:19:05 +0800784 }
785}
786
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800787// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
788TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
789{
790 GLTexture texture[2];
791 GLFramebuffer framebuffer;
792 const std::string csSource =
793 R"(#version 310 es
794 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
795 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
796 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
797 void main()
798 {
799 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
800 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
801 })";
802
Xinghua Cao27f43212018-02-26 11:05:53 +0800803 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
804 constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800805
806 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
807 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
808 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
809 GL_UNSIGNED_INT, kInputValues[0]);
810 EXPECT_GL_NO_ERROR();
811
812 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
813 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
814 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
815 GL_UNSIGNED_INT, kInputValues[1]);
816 EXPECT_GL_NO_ERROR();
817
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800818 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
819 glUseProgram(program.get());
820
821 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
822 EXPECT_GL_NO_ERROR();
823
824 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
825 EXPECT_GL_NO_ERROR();
826
827 glDispatchCompute(1, 1, 1);
828 EXPECT_GL_NO_ERROR();
829
Xinghua Cao27f43212018-02-26 11:05:53 +0800830 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
831 GLuint outputValues[kWidth * kHeight];
832 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800833 glUseProgram(0);
834 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
835
836 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
837 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
838 EXPECT_GL_NO_ERROR();
839 glReadBuffer(GL_COLOR_ATTACHMENT0);
840 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
841 EXPECT_GL_NO_ERROR();
842 for (int i = 0; i < kWidth * kHeight; i++)
843 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800844 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800845 }
846 glReadBuffer(GL_COLOR_ATTACHMENT1);
847 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
848 EXPECT_GL_NO_ERROR();
849 for (int i = 0; i < kWidth * kHeight; i++)
850 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800851 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800852 }
853}
854
855// Use image uniform to read and write Texture3D in compute shader, and verify the contents.
856TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
857{
858 GLTexture texture[2];
859 GLFramebuffer framebuffer;
860 const std::string csSource =
861 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800862 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800863 layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
864 layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
865 void main()
866 {
867 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
868 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
869 })";
870
Xinghua Cao27f43212018-02-26 11:05:53 +0800871 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
872 constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800873
874 glBindTexture(GL_TEXTURE_3D, texture[0]);
875 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
876 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
877 GL_UNSIGNED_INT, kInputValues[0]);
878 EXPECT_GL_NO_ERROR();
879
880 glBindTexture(GL_TEXTURE_3D, texture[1]);
881 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
882 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
883 GL_UNSIGNED_INT, kInputValues[1]);
884 EXPECT_GL_NO_ERROR();
885
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800886 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
887 glUseProgram(program.get());
888
889 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
890 EXPECT_GL_NO_ERROR();
891
892 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
893 EXPECT_GL_NO_ERROR();
894
895 glDispatchCompute(1, 1, 1);
896 EXPECT_GL_NO_ERROR();
897
Xinghua Cao27f43212018-02-26 11:05:53 +0800898 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
899 GLuint outputValues[kWidth * kHeight];
900 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800901 glUseProgram(0);
902 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
903
904 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
905 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
906 EXPECT_GL_NO_ERROR();
907 glReadBuffer(GL_COLOR_ATTACHMENT0);
908 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
909 EXPECT_GL_NO_ERROR();
910 for (int i = 0; i < kWidth * kHeight; i++)
911 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800912 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800913 }
914 glReadBuffer(GL_COLOR_ATTACHMENT1);
915 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
916 EXPECT_GL_NO_ERROR();
917 for (int i = 0; i < kWidth * kHeight; i++)
918 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800919 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800920 }
921}
922
923// Use image uniform to read and write TextureCube in compute shader, and verify the contents.
924TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
925{
926 GLTexture texture[2];
927 GLFramebuffer framebuffer;
928 const std::string csSource =
929 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800930 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800931 layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
932 layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
933 void main()
934 {
935 for (int i = 0; i < 6; i++)
936 {
937 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
938 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
939 }
940 })";
941
Xinghua Cao27f43212018-02-26 11:05:53 +0800942 constexpr int kWidth = 1, kHeight = 1;
943 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800944
945 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
946 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
947 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
948 face++)
949 {
950 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
951 kInputValues[0]);
952 }
953 EXPECT_GL_NO_ERROR();
954
955 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
956 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
957 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
958 face++)
959 {
960 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
961 kInputValues[1]);
962 }
963 EXPECT_GL_NO_ERROR();
964
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800965 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
966 glUseProgram(program.get());
967
968 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
969 EXPECT_GL_NO_ERROR();
970
971 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
972 EXPECT_GL_NO_ERROR();
973
974 glDispatchCompute(1, 1, 1);
975 EXPECT_GL_NO_ERROR();
976
Xinghua Cao27f43212018-02-26 11:05:53 +0800977 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
978 GLuint outputValues[kWidth * kHeight];
979 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800980 glUseProgram(0);
981 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
982
983 for (GLenum face = 0; face < 6; face++)
984 {
985 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
986 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
987 EXPECT_GL_NO_ERROR();
988 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
989 EXPECT_GL_NO_ERROR();
990
991 for (int i = 0; i < kWidth * kHeight; i++)
992 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800993 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800994 }
995 }
996}
997
Xinghua Caob745f172018-01-09 16:10:02 +0800998// Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
999// contents.
1000TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
1001{
1002 ANGLE_SKIP_TEST_IF(IsD3D11());
1003
1004 GLTexture texture[2];
1005 GLFramebuffer framebuffer;
1006 const std::string csSource =
1007 R"(#version 310 es
1008 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1009 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1010 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1011 void main()
1012 {
1013 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1014 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1015 })";
1016
1017 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1018 constexpr int kResultSize = kWidth * kHeight;
1019 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1020 constexpr GLuint expectedValue_1 = 200;
1021 constexpr GLuint expectedValue_2 = 100;
1022 GLuint outputValues[kResultSize];
1023
1024 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1025 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1026 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1027 GL_UNSIGNED_INT, kInputValues[0]);
1028 EXPECT_GL_NO_ERROR();
1029
1030 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1031 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1032 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1033 GL_UNSIGNED_INT, kInputValues[1]);
1034 EXPECT_GL_NO_ERROR();
1035
1036 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1037 glUseProgram(program.get());
1038
1039 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1040 EXPECT_GL_NO_ERROR();
1041 glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
1042 EXPECT_GL_NO_ERROR();
1043 glDispatchCompute(1, 1, 1);
1044 EXPECT_GL_NO_ERROR();
1045
1046 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1047 glUseProgram(0);
1048 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1049 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1050 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1051 EXPECT_GL_NO_ERROR();
1052 glReadBuffer(GL_COLOR_ATTACHMENT0);
1053 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1054 EXPECT_GL_NO_ERROR();
1055 for (int i = 0; i < kResultSize; i++)
1056 {
1057 EXPECT_EQ(expectedValue_2, outputValues[i]);
1058 }
1059 glReadBuffer(GL_COLOR_ATTACHMENT1);
1060 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1061 EXPECT_GL_NO_ERROR();
1062 for (int i = 0; i < kResultSize; i++)
1063 {
1064 EXPECT_EQ(expectedValue_1, outputValues[i]);
1065 }
1066}
1067
1068// Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
1069// contents.
1070TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
1071{
1072 ANGLE_SKIP_TEST_IF(IsD3D11());
1073 GLTexture texture[2];
1074 GLFramebuffer framebuffer;
1075 const std::string csSource =
1076 R"(#version 310 es
1077 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1078 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1079 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1080 void main()
1081 {
1082 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1083 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1084 })";
1085
1086 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1087 constexpr int kResultSize = kWidth * kHeight;
1088 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1089 constexpr GLuint expectedValue_1 = 150;
1090 constexpr GLuint expectedValue_2 = 50;
1091 GLuint outputValues[kResultSize];
1092
1093 glBindTexture(GL_TEXTURE_3D, texture[0]);
1094 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1095 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1096 GL_UNSIGNED_INT, kInputValues[0]);
1097 EXPECT_GL_NO_ERROR();
1098
1099 glBindTexture(GL_TEXTURE_3D, texture[1]);
1100 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1101 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1102 GL_UNSIGNED_INT, kInputValues[1]);
1103 EXPECT_GL_NO_ERROR();
1104
1105 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1106 glUseProgram(program.get());
1107
1108 glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1109 EXPECT_GL_NO_ERROR();
1110 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1111 EXPECT_GL_NO_ERROR();
1112 glDispatchCompute(1, 1, 1);
1113 EXPECT_GL_NO_ERROR();
1114
1115 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1116 glUseProgram(0);
1117 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1118 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1119 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1120 EXPECT_GL_NO_ERROR();
1121 glReadBuffer(GL_COLOR_ATTACHMENT0);
1122 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1123 EXPECT_GL_NO_ERROR();
1124 for (int i = 0; i < kResultSize; i++)
1125 {
1126 EXPECT_EQ(expectedValue_1, outputValues[i]);
1127 }
1128 glReadBuffer(GL_COLOR_ATTACHMENT1);
1129 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1130 EXPECT_GL_NO_ERROR();
1131 for (int i = 0; i < kResultSize; i++)
1132 {
1133 EXPECT_EQ(expectedValue_2, outputValues[i]);
1134 }
1135}
1136
1137// Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1138// contents.
1139TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1140{
1141 ANGLE_SKIP_TEST_IF(IsD3D11());
1142
1143 GLTexture texture[2];
1144 GLFramebuffer framebuffer;
1145 const std::string csSource =
1146 R"(#version 310 es
1147 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1148 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1149 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1150 void main()
1151 {
1152 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1153 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1154 })";
1155
1156 constexpr int kWidth = 1, kHeight = 1;
1157 constexpr int kResultSize = kWidth * kHeight;
1158 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1159 constexpr GLuint expectedValue_1 = 200;
1160 constexpr GLuint expectedValue_2 = 100;
1161 GLuint outputValues[kResultSize];
1162
1163 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1164 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1165 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1166 face++)
1167 {
1168 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1169 kInputValues[0]);
1170 }
1171 EXPECT_GL_NO_ERROR();
1172
1173 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1174 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1175 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1176 face++)
1177 {
1178 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1179 kInputValues[1]);
1180 }
1181 EXPECT_GL_NO_ERROR();
1182
1183 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1184 glUseProgram(program.get());
1185
1186 glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1187 EXPECT_GL_NO_ERROR();
1188 glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1189 EXPECT_GL_NO_ERROR();
1190 glDispatchCompute(1, 1, 1);
1191 EXPECT_GL_NO_ERROR();
1192
1193 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1194 glUseProgram(0);
1195 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1196
1197 for (GLenum face = 0; face < 6; face++)
1198 {
1199 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1200 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1201 EXPECT_GL_NO_ERROR();
1202 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1203 EXPECT_GL_NO_ERROR();
1204
1205 if (face == 4)
1206 {
1207 for (int i = 0; i < kResultSize; i++)
1208 {
1209 EXPECT_EQ(expectedValue_1, outputValues[i]);
1210 }
1211 }
1212 else
1213 {
1214 for (int i = 0; i < kResultSize; i++)
1215 {
1216 EXPECT_EQ(expectedValue_2, outputValues[i]);
1217 }
1218 }
1219 }
1220}
1221
Jiawei Shao6ae51612018-02-23 14:03:25 +08001222// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
1223// program which has not been linked successfully or which does not contain objects to form a
1224// compute shader.
1225TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
1226{
1227 const std::string vsSource =
1228 R"(#version 310 es
1229 void main()
1230 {
1231 })";
1232
1233 const std::string fsSource =
1234 R"(#version 310 es
1235 void main()
1236 {
1237 })";
1238
1239 GLint workGroupSize[3];
1240
1241 ANGLE_GL_PROGRAM(graphicsProgram, vsSource, fsSource);
1242 glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1243 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1244
1245 GLuint computeProgram = glCreateProgram();
1246 GLShader computeShader(GL_COMPUTE_SHADER);
1247 glAttachShader(computeProgram, computeShader);
1248 glLinkProgram(computeProgram);
1249 glDetachShader(computeProgram, computeShader);
1250
1251 GLint linkStatus;
1252 glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
1253 ASSERT_GL_FALSE(linkStatus);
1254
1255 glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1256 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1257
1258 glDeleteProgram(computeProgram);
1259
1260 ASSERT_GL_NO_ERROR();
1261}
1262
Xinghua Cao47335852018-02-12 15:41:55 +08001263// Use groupMemoryBarrier and barrier to sync reads/writes order and the execution
1264// order of multiple shader invocations in compute shader.
1265TEST_P(ComputeShaderTest, groupMemoryBarrierAndBarrierTest)
1266{
1267 // TODO(xinghua.cao@intel.com): Figure out why we get this error message
1268 // that shader uses features not recognized by this D3D version.
Yuly Novikovbeafe1a2018-03-29 18:23:50 -04001269 ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());
Xinghua Cao47335852018-02-12 15:41:55 +08001270
1271 GLTexture texture;
1272 GLFramebuffer framebuffer;
1273
1274 // Each invocation first stores a single value in an image, then each invocation sums up
1275 // all the values in the image and stores the sum in the image. groupMemoryBarrier is
1276 // used to order reads/writes to variables stored in memory accessible to other shader
1277 // invocations, and barrier is used to control the relative execution order of multiple
1278 // shader invocations used to process a local work group.
1279 const std::string csSource =
1280 R"(#version 310 es
1281 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
1282 layout(r32i, binding = 0) uniform highp iimage2D image;
1283 void main()
1284 {
1285 uint x = gl_LocalInvocationID.x;
1286 uint y = gl_LocalInvocationID.y;
1287 imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));
1288 groupMemoryBarrier();
1289 barrier();
1290 int sum = 0;
1291 for (int i = 0; i < 2; i++)
1292 {
1293 for(int j = 0; j < 2; j++)
1294 {
1295 sum += imageLoad(image, ivec2(i, j)).x;
1296 }
1297 }
1298 groupMemoryBarrier();
1299 barrier();
1300 imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));
1301 })";
1302
1303 constexpr int kWidth = 2, kHeight = 2;
1304 glBindTexture(GL_TEXTURE_2D, texture);
1305 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);
1306 EXPECT_GL_NO_ERROR();
1307
1308 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1309 glUseProgram(program.get());
1310
1311 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
1312 EXPECT_GL_NO_ERROR();
1313
1314 glDispatchCompute(1, 1, 1);
1315 EXPECT_GL_NO_ERROR();
1316
1317 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1318 GLuint outputValues[kWidth * kHeight];
1319 constexpr GLuint kExpectedValue = 4;
1320 glUseProgram(0);
1321 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1322
1323 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1324 EXPECT_GL_NO_ERROR();
1325 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);
1326 EXPECT_GL_NO_ERROR();
1327
1328 for (int i = 0; i < kWidth * kHeight; i++)
1329 {
1330 EXPECT_EQ(kExpectedValue, outputValues[i]);
1331 }
1332}
1333
Jiawei Shao7a8fe152018-04-28 12:59:58 +08001334// Verify that a link error is generated when the sum of the number of active image uniforms and
1335// active shader storage blocks in a compute shader exceeds GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1336TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS)
1337{
1338 // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
1339 // D3D11 back-ends.
1340 ANGLE_SKIP_TEST_IF(IsD3D11());
1341
1342 GLint maxCombinedShaderOutputResources;
1343 GLint maxComputeShaderStorageBlocks;
1344 GLint maxComputeImageUniforms;
1345
1346 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
1347 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
1348 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
1349
1350 ANGLE_SKIP_TEST_IF(maxCombinedShaderOutputResources >=
1351 maxComputeShaderStorageBlocks + maxComputeImageUniforms);
1352
1353 std::ostringstream computeShaderStream;
1354 computeShaderStream << "#version 310 es\n"
1355 "layout(local_size_x = 3, local_size_y = 1, local_size_z = 1) in;\n"
1356 "layout(shared, binding = 0) buffer blockName"
1357 "{\n"
1358 " uint data;\n"
1359 "} instance["
1360 << maxComputeShaderStorageBlocks << "];\n";
1361
1362 ASSERT_GE(maxComputeImageUniforms, 4);
1363 int numImagesInArray = maxComputeImageUniforms / 2;
1364 int numImagesNonArray = maxComputeImageUniforms - numImagesInArray;
1365 for (int i = 0; i < numImagesNonArray; ++i)
1366 {
1367 computeShaderStream << "layout(r32f, binding = " << i << ") uniform highp image2D image"
1368 << i << ";\n";
1369 }
1370
1371 computeShaderStream << "layout(r32f, binding = " << numImagesNonArray
1372 << ") uniform highp image2D imageArray[" << numImagesInArray << "];\n";
1373
1374 computeShaderStream << "void main()\n"
1375 "{\n"
1376 " uint val = 0u;\n"
1377 " vec4 val2 = vec4(0.0);\n";
1378
1379 for (int i = 0; i < maxComputeShaderStorageBlocks; ++i)
1380 {
1381 computeShaderStream << " val += instance[" << i << "].data; \n";
1382 }
1383
1384 for (int i = 0; i < numImagesNonArray; ++i)
1385 {
1386 computeShaderStream << " val2 += imageLoad(image" << i
1387 << ", ivec2(gl_LocalInvocationID.xy)); \n";
1388 }
1389
1390 for (int i = 0; i < numImagesInArray; ++i)
1391 {
1392 computeShaderStream << " val2 += imageLoad(imageArray[" << i << "]"
1393 << ", ivec2(gl_LocalInvocationID.xy)); \n";
1394 }
1395
1396 computeShaderStream << " instance[0].data = val + uint(val2.x);\n"
1397 "}\n";
1398
1399 GLuint computeProgram = CompileComputeProgram(computeShaderStream.str());
1400 EXPECT_EQ(0u, computeProgram);
1401}
1402
Qin Jiajia2a12b3d2018-05-23 13:42:13 +08001403// Test that uniform block with struct member in compute shader is supported.
1404TEST_P(ComputeShaderTest, UniformBlockWithStructMember)
1405{
1406 const std::string csSource =
1407 R"(#version 310 es
1408 layout(local_size_x=8) in;
1409 layout(rgba8) uniform highp readonly image2D mImage2DInput;
1410 layout(rgba8) uniform highp writeonly image2D mImage2DOutput;
1411 struct S {
1412 ivec3 a;
1413 ivec2 b;
1414 };
1415
1416 layout(std140, binding=0) uniform blockName {
1417 S bd;
1418 } instanceName;
1419 void main()
1420 {
1421 ivec2 t1 = instanceName.bd.b;
1422 vec4 result2d = imageLoad(mImage2DInput, t1);
1423 imageStore(mImage2DOutput, ivec2(gl_LocalInvocationID.xy), result2d);
1424 })";
1425
1426 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1427 EXPECT_GL_NO_ERROR();
1428}
1429
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +08001430// Verify shared non-array variables can work correctly.
1431TEST_P(ComputeShaderTest, NonArraySharedVariable)
1432{
1433 const char kCSShader[] =
1434 R"(#version 310 es
1435 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
1436 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1437 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1438 shared uint temp;
1439 void main()
1440 {
1441 if (gl_LocalInvocationID == uvec3(0, 0, 0))
1442 {
1443 temp = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1444 }
1445 groupMemoryBarrier();
1446 barrier();
1447 if (gl_LocalInvocationID == uvec3(1, 1, 0))
1448 {
1449 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(temp));
1450 }
1451 else
1452 {
1453 uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1454 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(inputValue));
1455 }
1456 })";
1457
1458 const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
1459 const std::array<GLuint, 4> expectedValues = {{250, 200, 150, 250}};
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001460 runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
1461 expectedValues);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +08001462}
1463
1464// Verify shared non-struct array variables can work correctly.
1465TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)
1466{
1467 const char kCSShader[] =
1468 R"(#version 310 es
1469 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
1470 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1471 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1472 shared uint sharedData[2][2];
1473 void main()
1474 {
1475 uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1476 sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = inputData;
1477 groupMemoryBarrier();
1478 barrier();
1479 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1480 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x]));
1481 })";
1482
1483 const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
1484 const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001485 runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
1486 expectedValues);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +08001487}
1488
1489// Verify shared struct array variables work correctly.
1490TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)
1491{
1492 const char kCSShader[] =
1493 R"(#version 310 es
1494 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
1495 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1496 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1497 struct SharedStruct
1498 {
1499 uint data;
1500 };
1501 shared SharedStruct sharedData[2][2];
1502 void main()
1503 {
1504 uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1505 sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y].data = inputData;
1506 groupMemoryBarrier();
1507 barrier();
1508 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1509 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x].data));
1510 })";
1511
1512 const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
1513 const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001514 runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
1515 expectedValues);
1516}
1517
1518// Verify using atomic functions without return value can work correctly.
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001519TEST_P(ComputeShaderTest, AtomicFunctionsNoReturnValue)
1520{
1521 // TODO(jiawei.shao@intel.com): find out why this shader causes a link error on Android Nexus 5
1522 // bot.
1523 ANGLE_SKIP_TEST_IF(IsAndroid());
1524
1525 const char kCSShader[] =
1526 R"(#version 310 es
Jiawei Shao35bc74d2018-08-03 14:07:59 +08001527 layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in;
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001528 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1529 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1530
1531 const uint kSumIndex = 0u;
1532 const uint kMinIndex = 1u;
1533 const uint kMaxIndex = 2u;
1534 const uint kOrIndex = 3u;
1535 const uint kAndIndex = 4u;
1536 const uint kXorIndex = 5u;
Jiawei Shao35bc74d2018-08-03 14:07:59 +08001537 const uint kExchangeIndex = 6u;
1538 const uint kCompSwapIndex = 7u;
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001539
Jiawei Shao35bc74d2018-08-03 14:07:59 +08001540 shared highp uint results[8];
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001541
1542 void main()
1543 {
1544 if (gl_LocalInvocationID.x == kMinIndex || gl_LocalInvocationID.x == kAndIndex)
1545 {
1546 results[gl_LocalInvocationID.x] = 0xFFFFu;
1547 }
Jiawei Shao35bc74d2018-08-03 14:07:59 +08001548 else if (gl_LocalInvocationID.x == kCompSwapIndex)
1549 {
1550 results[gl_LocalInvocationID.x] = 1u;
1551 }
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001552 else
1553 {
1554 results[gl_LocalInvocationID.x] = 0u;
1555 }
1556 memoryBarrierShared();
1557 barrier();
1558
1559 uint value = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1560 atomicAdd(results[kSumIndex], value);
1561 atomicMin(results[kMinIndex], value);
1562 atomicMax(results[kMaxIndex], value);
1563 atomicOr(results[kOrIndex], value);
1564 atomicAnd(results[kAndIndex], value);
1565 atomicXor(results[kXorIndex], value);
Jiawei Shao35bc74d2018-08-03 14:07:59 +08001566 atomicExchange(results[kExchangeIndex], value);
1567 atomicCompSwap(results[kCompSwapIndex], value, 256u);
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001568 memoryBarrierShared();
1569 barrier();
1570
1571 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1572 uvec4(results[gl_LocalInvocationID.x]));
1573 })";
1574
Jiawei Shao35bc74d2018-08-03 14:07:59 +08001575 const std::array<GLuint, 8> inputData = {{1, 2, 4, 8, 16, 32, 64, 128}};
1576 const std::array<GLuint, 8> expectedValues = {{255, 1, 128, 255, 0, 255, 128, 256}};
1577 runSharedMemoryTest<GLuint, 8, 1>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
Jiawei Shaoa6a78422018-06-28 08:32:54 +08001578 expectedValues);
1579}
1580
1581// Verify using atomic functions in a non-initializer single assignment can work correctly.
1582TEST_P(ComputeShaderTest, AtomicFunctionsInNonInitializerSingleAssignment)
1583{
1584 const char kCSShader[] =
1585 R"(#version 310 es
1586 layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
1587 layout (r32i, binding = 0) readonly uniform highp iimage2D srcImage;
1588 layout (r32i, binding = 1) writeonly uniform highp iimage2D dstImage;
1589
1590 shared highp int sharedVariable;
1591
1592 shared highp int inputData[9];
1593 shared highp int outputData[9];
1594
1595 void main()
1596 {
1597 int inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1598 inputData[gl_LocalInvocationID.x] = inputValue;
1599 memoryBarrierShared();
1600 barrier();
1601
1602 if (gl_LocalInvocationID.x == 0u)
1603 {
1604 sharedVariable = 0;
1605
1606 outputData[0] = atomicAdd(sharedVariable, inputData[0]);
1607 outputData[1] = atomicMin(sharedVariable, inputData[1]);
1608 outputData[2] = atomicMax(sharedVariable, inputData[2]);
1609 outputData[3] = atomicAnd(sharedVariable, inputData[3]);
1610 outputData[4] = atomicOr(sharedVariable, inputData[4]);
1611 outputData[5] = atomicXor(sharedVariable, inputData[5]);
1612 outputData[6] = atomicExchange(sharedVariable, inputData[6]);
1613 outputData[7] = atomicCompSwap(sharedVariable, 64, inputData[7]);
1614 outputData[8] = atomicAdd(sharedVariable, inputData[8]);
1615 }
1616 memoryBarrierShared();
1617 barrier();
1618
1619 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1620 ivec4(outputData[gl_LocalInvocationID.x]));
1621 })";
1622
1623 const std::array<GLint, 9> inputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
1624 const std::array<GLint, 9> expectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
1625 runSharedMemoryTest<GLint, 9, 1>(kCSShader, GL_R32I, GL_INT, inputData, expectedValues);
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +08001626}
1627
Xinghua Cao913ff542018-08-07 15:14:05 +08001628// Basic uniform buffer functionality.
1629TEST_P(ComputeShaderTest, UniformBuffer)
1630{
1631 GLTexture texture;
1632 GLBuffer buffer;
1633 GLFramebuffer framebuffer;
1634 const std::string csSource =
1635 R"(#version 310 es
1636 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1637 uniform uni
1638 {
1639 uvec4 value;
1640 };
1641 layout(rgba32ui, binding = 0) writeonly uniform highp uimage2D uImage;
1642 void main()
1643 {
1644 imageStore(uImage, ivec2(gl_LocalInvocationID.xy), value);
1645 })";
1646
1647 constexpr int kWidth = 1, kHeight = 1;
1648 constexpr GLuint kInputValues[4] = {56, 57, 58, 59};
1649
1650 glBindTexture(GL_TEXTURE_2D, texture);
1651 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth, kHeight);
1652 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
1653 kInputValues);
1654 EXPECT_GL_NO_ERROR();
1655
1656 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1657 glUseProgram(program.get());
1658
1659 GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
1660 EXPECT_NE(uniformBufferIndex, -1);
1661 GLuint data[4] = {201, 202, 203, 204};
1662 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
1663 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint) * 4, data, GL_STATIC_DRAW);
1664 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
1665 glUniformBlockBinding(program, uniformBufferIndex, 0);
1666 EXPECT_GL_NO_ERROR();
1667
1668 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
1669 EXPECT_GL_NO_ERROR();
1670
1671 glDispatchCompute(1, 1, 1);
1672 EXPECT_GL_NO_ERROR();
1673
1674 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1675 GLuint outputValues[kWidth * kHeight * 4];
1676 glUseProgram(0);
1677 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1678
1679 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1680 EXPECT_GL_NO_ERROR();
1681 glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
1682 EXPECT_GL_NO_ERROR();
1683
1684 for (int i = 0; i < kWidth * kHeight * 4; i++)
1685 {
1686 EXPECT_EQ(data[i], outputValues[i]);
1687 }
1688}
1689
Qin Jiajia155bfd12018-08-31 17:27:10 +08001690// Test that storing data to image and then loading the same image data works correctly.
1691TEST_P(ComputeShaderTest, StoreImageThenLoad)
1692{
1693 const char kCSSource[] =
1694 R"(#version 310 es
1695 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1696 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1697 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1698 void main()
1699 {
1700 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1701 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1702 })";
1703
1704 constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
1705 GLTexture texture[3];
1706 glBindTexture(GL_TEXTURE_2D, texture[0]);
1707 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1708 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
1709 EXPECT_GL_NO_ERROR();
1710
1711 glBindTexture(GL_TEXTURE_2D, texture[1]);
1712 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1713 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
1714 EXPECT_GL_NO_ERROR();
1715
1716 glBindTexture(GL_TEXTURE_2D, texture[2]);
1717 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1718 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
1719 EXPECT_GL_NO_ERROR();
1720
1721 ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
1722 glUseProgram(program.get());
1723
1724 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1725 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1726
1727 glDispatchCompute(1, 1, 1);
1728 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1729 EXPECT_GL_NO_ERROR();
1730
1731 glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1732 glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1733
1734 glDispatchCompute(1, 1, 1);
1735 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1736 EXPECT_GL_NO_ERROR();
1737
1738 GLuint outputValue;
1739 GLFramebuffer framebuffer;
1740 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1741 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
1742 glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
1743 EXPECT_GL_NO_ERROR();
1744
1745 EXPECT_EQ(300u, outputValue);
1746}
1747
1748// Test that loading image data and then storing data to the same image works correctly.
1749TEST_P(ComputeShaderTest, LoadImageThenStore)
1750{
1751 const char kCSSource[] =
1752 R"(#version 310 es
1753 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1754 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1755 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1756 void main()
1757 {
1758 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1759 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1760 })";
1761
1762 constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
1763 GLTexture texture[3];
1764 glBindTexture(GL_TEXTURE_2D, texture[0]);
1765 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1766 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
1767 EXPECT_GL_NO_ERROR();
1768
1769 glBindTexture(GL_TEXTURE_2D, texture[1]);
1770 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1771 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
1772 EXPECT_GL_NO_ERROR();
1773
1774 glBindTexture(GL_TEXTURE_2D, texture[2]);
1775 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
1776 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
1777 EXPECT_GL_NO_ERROR();
1778
1779 ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
1780 glUseProgram(program.get());
1781
1782 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1783 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1784
1785 glDispatchCompute(1, 1, 1);
1786 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1787 EXPECT_GL_NO_ERROR();
1788
1789 glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1790 glBindImageTexture(1, texture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1791
1792 glDispatchCompute(1, 1, 1);
1793 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1794 EXPECT_GL_NO_ERROR();
1795
1796 GLuint outputValue;
1797 GLFramebuffer framebuffer;
1798 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1799 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
1800 glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
1801 EXPECT_GL_NO_ERROR();
1802
1803 EXPECT_EQ(100u, outputValue);
1804}
1805
Martin Radev4c4c8e72016-08-04 12:25:34 +03001806// Check that it is not possible to create a compute shader when the context does not support ES
1807// 3.10
1808TEST_P(ComputeShaderTestES3, NotSupported)
1809{
1810 GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
1811 EXPECT_EQ(0u, computeShaderHandle);
1812 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1813}
1814
Xinghua Caob1239382016-12-13 15:07:05 +08001815ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
Martin Radev4c4c8e72016-08-04 12:25:34 +03001816ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
1817
1818} // namespace