blob: bade1f5e39bf15e428f46152fef7710e586f19f5 [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
23 template <GLint kWidth, GLint kHeight>
24 void runSharedMemoryTest(const char *csSource,
25 const std::array<GLuint, kWidth * kHeight> &inputData,
26 const std::array<GLuint, kWidth * kHeight> &expectedValues)
27 {
28 GLTexture texture[2];
29 GLFramebuffer framebuffer;
30
31 glBindTexture(GL_TEXTURE_2D, texture[0]);
32 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
33 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
34 inputData.data());
35 EXPECT_GL_NO_ERROR();
36
37 constexpr GLuint initData[kWidth * kHeight] = {};
38 glBindTexture(GL_TEXTURE_2D, texture[1]);
39 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
40 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
41 initData);
42 EXPECT_GL_NO_ERROR();
43
44 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
45 glUseProgram(program.get());
46
47 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
48 EXPECT_GL_NO_ERROR();
49
50 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
51 EXPECT_GL_NO_ERROR();
52
53 glDispatchCompute(1, 1, 1);
54 EXPECT_GL_NO_ERROR();
55
56 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
57
58 GLuint outputValues[kWidth * kHeight];
59 glUseProgram(0);
60 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
61
62 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1],
63 0);
64 EXPECT_GL_NO_ERROR();
65 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
66 EXPECT_GL_NO_ERROR();
67
68 for (int i = 0; i < kWidth * kHeight; i++)
69 {
70 EXPECT_EQ(expectedValues[i], outputValues[i]);
71 }
72 }
Martin Radev4c4c8e72016-08-04 12:25:34 +030073};
74
75class ComputeShaderTestES3 : public ANGLETest
76{
77 protected:
78 ComputeShaderTestES3() {}
79};
80
81// link a simple compute program. It should be successful.
82TEST_P(ComputeShaderTest, LinkComputeProgram)
83{
84 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +080085 R"(#version 310 es
86 layout(local_size_x=1) in;
87 void main()
88 {\
89 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +030090
91 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
92
93 EXPECT_GL_NO_ERROR();
94}
95
Yunchao He85072e82017-11-14 15:43:28 +080096// Link a simple compute program. Then detach the shader and dispatch compute.
97// It should be successful.
98TEST_P(ComputeShaderTest, DetachShaderAfterLinkSuccess)
99{
100 const std::string csSource =
101 R"(#version 310 es
102 layout(local_size_x=1) in;
103 void main()
104 {
105 })";
106
107 GLuint program = glCreateProgram();
108
109 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
110 EXPECT_NE(0u, cs);
111
112 glAttachShader(program, cs);
113 glDeleteShader(cs);
114
115 glLinkProgram(program);
116 GLint linkStatus;
117 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
Yunchao He1f679cc2017-11-29 18:06:00 +0800118 EXPECT_GL_TRUE(linkStatus);
Yunchao He85072e82017-11-14 15:43:28 +0800119
120 glDetachShader(program, cs);
121 EXPECT_GL_NO_ERROR();
122
123 glUseProgram(program);
124 glDispatchCompute(8, 4, 2);
125 EXPECT_GL_NO_ERROR();
126}
127
Martin Radev4c4c8e72016-08-04 12:25:34 +0300128// link a simple compute program. There is no local size and linking should fail.
129TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)
130{
131 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800132 R"(#version 310 es
133 void main()
134 {
135 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300136
137 GLuint program = CompileComputeProgram(csSource, false);
138 EXPECT_EQ(0u, program);
139
140 glDeleteProgram(program);
141
142 EXPECT_GL_NO_ERROR();
143}
144
145// link a simple compute program.
146// make sure that uniforms and uniform samplers get recorded
147TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)
148{
149 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200150 R"(#version 310 es
151 precision mediump sampler2D;
152 layout(local_size_x=1) in;
153 uniform int myUniformInt;
154 uniform sampler2D myUniformSampler;
155 layout(rgba32i) uniform highp writeonly iimage2D imageOut;
156 void main()
157 {
158 int q = myUniformInt;
159 vec4 v = textureLod(myUniformSampler, vec2(0.0), 0.0);
160 imageStore(imageOut, ivec2(0), ivec4(v) * q);
161 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300162
163 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
164
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200165 GLint uniformLoc = glGetUniformLocation(program.get(), "myUniformInt");
166 EXPECT_NE(-1, uniformLoc);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300167
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200168 uniformLoc = glGetUniformLocation(program.get(), "myUniformSampler");
169 EXPECT_NE(-1, uniformLoc);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300170
171 EXPECT_GL_NO_ERROR();
172}
173
174// Attach both compute and non-compute shaders. A link time error should occur.
175// OpenGL ES 3.10, 7.3 Program Objects
176TEST_P(ComputeShaderTest, AttachMultipleShaders)
177{
178 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800179 R"(#version 310 es
180 layout(local_size_x=1) in;
181 void main()
182 {
183 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300184
185 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800186 R"(#version 310 es
187 void main()
188 {
189 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300190
191 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800192 R"(#version 310 es
193 void main()
194 {
195 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300196
197 GLuint program = glCreateProgram();
198
199 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
200 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
201 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
202
203 EXPECT_NE(0u, vs);
204 EXPECT_NE(0u, fs);
205 EXPECT_NE(0u, cs);
206
207 glAttachShader(program, vs);
208 glDeleteShader(vs);
209
210 glAttachShader(program, fs);
211 glDeleteShader(fs);
212
213 glAttachShader(program, cs);
214 glDeleteShader(cs);
215
216 glLinkProgram(program);
217
218 GLint linkStatus;
219 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
220
Yunchao He1f679cc2017-11-29 18:06:00 +0800221 EXPECT_GL_FALSE(linkStatus);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300222
223 EXPECT_GL_NO_ERROR();
224}
225
226// Attach a vertex, fragment and compute shader.
227// Query for the number of attached shaders and check the count.
228TEST_P(ComputeShaderTest, AttachmentCount)
229{
Martin Radev4c4c8e72016-08-04 12:25:34 +0300230 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800231 R"(#version 310 es
232 layout(local_size_x=1) in;
233 void main()
234 {
235 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300236
237 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800238 R"(#version 310 es
239 void main()
240 {
241 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300242
243 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800244 R"(#version 310 es
245 void main()
246 {
247 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300248
249 GLuint program = glCreateProgram();
250
251 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
252 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
253 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
254
255 EXPECT_NE(0u, vs);
256 EXPECT_NE(0u, fs);
257 EXPECT_NE(0u, cs);
258
259 glAttachShader(program, vs);
260 glDeleteShader(vs);
261
262 glAttachShader(program, fs);
263 glDeleteShader(fs);
264
265 glAttachShader(program, cs);
266 glDeleteShader(cs);
267
268 GLint numAttachedShaders;
269 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
270
271 EXPECT_EQ(3, numAttachedShaders);
272
273 glDeleteProgram(program);
274
275 EXPECT_GL_NO_ERROR();
276}
277
Yunchao Hecddcb592017-11-13 15:27:35 +0800278// Attach a compute shader and link, but start rendering.
279TEST_P(ComputeShaderTest, StartRenderingWithComputeProgram)
280{
281 const std::string csSource =
282 R"(#version 310 es
283 layout(local_size_x=1) in;
284 void main()
285 {
286 })";
287
288 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
289 EXPECT_GL_NO_ERROR();
290
291 glUseProgram(program);
292 glDrawArrays(GL_POINTS, 0, 2);
293 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
294}
295
Yunchao He70b715c2017-11-07 14:59:15 +0800296// Attach a vertex and fragment shader and link, but dispatch compute.
297TEST_P(ComputeShaderTest, DispatchComputeWithRenderingProgram)
298{
299 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800300 R"(#version 310 es
301 void main()
302 {
303 })";
Yunchao He70b715c2017-11-07 14:59:15 +0800304
305 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800306 R"(#version 310 es
307 void main()
308 {
309 })";
Yunchao He70b715c2017-11-07 14:59:15 +0800310
311 GLuint program = glCreateProgram();
312
313 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
314 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
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);
Yunchao He1f679cc2017-11-29 18:06:00 +0800329 EXPECT_GL_TRUE(linkStatus);
Yunchao He70b715c2017-11-07 14:59:15 +0800330
331 EXPECT_GL_NO_ERROR();
332
333 glUseProgram(program);
334 glDispatchCompute(8, 4, 2);
335 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
336}
337
Xinghua Caob1239382016-12-13 15:07:05 +0800338// Access all compute shader special variables.
339TEST_P(ComputeShaderTest, AccessAllSpecialVariables)
340{
341 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200342 R"(#version 310 es
343 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
344 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
345 void main()
346 {
347 uvec3 temp1 = gl_NumWorkGroups;
348 uvec3 temp2 = gl_WorkGroupSize;
349 uvec3 temp3 = gl_WorkGroupID;
350 uvec3 temp4 = gl_LocalInvocationID;
351 uvec3 temp5 = gl_GlobalInvocationID;
352 uint temp6 = gl_LocalInvocationIndex;
353 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));
354 })";
Xinghua Caob1239382016-12-13 15:07:05 +0800355
356 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
357}
358
359// Access part compute shader special variables.
360TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
361{
362 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200363 R"(#version 310 es
364 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
365 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
366 void main()
367 {
368 uvec3 temp1 = gl_WorkGroupSize;
369 uvec3 temp2 = gl_WorkGroupID;
370 uint temp3 = gl_LocalInvocationIndex;
371 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2, temp3));
372 })";
Xinghua Caob1239382016-12-13 15:07:05 +0800373
374 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
375}
376
Xinghua Cao73badc02017-03-29 19:14:53 +0800377// Use glDispatchCompute to define work group count.
378TEST_P(ComputeShaderTest, DispatchCompute)
Xinghua Cao2b396592017-03-29 15:36:04 +0800379{
380 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200381 R"(#version 310 es
382 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
383 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
384 void main()
385 {
386 uvec3 temp = gl_NumWorkGroups;
387 imageStore(imageOut, ivec2(0), uvec4(temp, 0u));
388 })";
Xinghua Cao2b396592017-03-29 15:36:04 +0800389
390 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
391
392 glUseProgram(program.get());
393 glDispatchCompute(8, 4, 2);
394 EXPECT_GL_NO_ERROR();
395}
396
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800397// Use image uniform to write texture in compute shader, and verify the content is expected.
398TEST_P(ComputeShaderTest, BindImageTexture)
399{
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800400 GLTexture mTexture[2];
401 GLFramebuffer mFramebuffer;
402 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800403 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800404 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Yunchao Hecddcb592017-11-13 15:27:35 +0800405 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
406 void main()
407 {
408 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
409 0, 0));
410 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
411 0, 0));
412 })";
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800413
414 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
415 glUseProgram(program.get());
Xinghua Cao27f43212018-02-26 11:05:53 +0800416 int width = 1, height = 1;
417 GLuint inputValues[] = {200};
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800418
419 glBindTexture(GL_TEXTURE_2D, mTexture[0]);
420 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
421 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
422 inputValues);
423 EXPECT_GL_NO_ERROR();
424
425 glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
426 EXPECT_GL_NO_ERROR();
427
428 glBindTexture(GL_TEXTURE_2D, mTexture[1]);
429 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
430 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
431 inputValues);
432 EXPECT_GL_NO_ERROR();
433
434 glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
435 EXPECT_GL_NO_ERROR();
436
Xinghua Cao27f43212018-02-26 11:05:53 +0800437 glDispatchCompute(1, 1, 1);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800438 EXPECT_GL_NO_ERROR();
439
Xinghua Cao27f43212018-02-26 11:05:53 +0800440 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800441 glUseProgram(0);
Xinghua Cao27f43212018-02-26 11:05:53 +0800442 GLuint outputValues[2][1];
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800443 GLuint expectedValue = 100;
444 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
445
446 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
447 0);
448 EXPECT_GL_NO_ERROR();
449 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
450 EXPECT_GL_NO_ERROR();
451
452 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
453 0);
454 EXPECT_GL_NO_ERROR();
455 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
456 EXPECT_GL_NO_ERROR();
457
458 for (int i = 0; i < width * height; i++)
459 {
460 EXPECT_EQ(expectedValue, outputValues[0][i]);
461 EXPECT_EQ(expectedValue, outputValues[1][i]);
462 }
463}
464
Xinghua Cao0328b572017-06-26 15:51:36 +0800465// When declare a image array without a binding qualifier, all elements are bound to unit zero.
466TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
467{
468 ANGLE_SKIP_TEST_IF(IsD3D11());
469
470 // TODO(xinghua.cao@intel.com): On AMD desktop OpenGL, bind two image variables to unit 0,
471 // only one variable is valid.
Corentin Wallez2bde9192017-07-28 14:15:01 -0400472 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
Xinghua Cao0328b572017-06-26 15:51:36 +0800473
474 GLTexture mTexture;
475 GLFramebuffer mFramebuffer;
476 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800477 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800478 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Yunchao Hecddcb592017-11-13 15:27:35 +0800479 layout(r32ui) writeonly uniform highp uimage2D uImage[2];
480 void main()
481 {
482 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
483 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
484 })";
Xinghua Cao0328b572017-06-26 15:51:36 +0800485
486 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
487 glUseProgram(program.get());
Xinghua Cao27f43212018-02-26 11:05:53 +0800488 constexpr int kTextureWidth = 1, kTextureHeight = 2;
489 GLuint inputValues[] = {200, 200};
Xinghua Cao0328b572017-06-26 15:51:36 +0800490
491 glBindTexture(GL_TEXTURE_2D, mTexture);
492 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
493 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
494 GL_UNSIGNED_INT, inputValues);
495 EXPECT_GL_NO_ERROR();
496
497 glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
498 glDispatchCompute(1, 1, 1);
499 EXPECT_GL_NO_ERROR();
500
Xinghua Cao27f43212018-02-26 11:05:53 +0800501 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
Xinghua Cao0328b572017-06-26 15:51:36 +0800502 glUseProgram(0);
503 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
504
505 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
Xinghua Cao27f43212018-02-26 11:05:53 +0800506 GLuint outputValues[kTextureWidth * kTextureHeight];
Xinghua Cao0328b572017-06-26 15:51:36 +0800507 glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
508 outputValues);
509 EXPECT_GL_NO_ERROR();
510
511 GLuint expectedValue = 100;
512 for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
513 {
514 EXPECT_EQ(expectedValue, outputValues[i]);
515 }
516}
517
Xinghua Cao711b7a12017-10-09 13:38:12 +0800518// imageLoad functions
519TEST_P(ComputeShaderTest, ImageLoad)
520{
521 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200522 R"(#version 310 es
523 layout(local_size_x=8) in;
524 layout(rgba8) uniform highp readonly image2D mImage2DInput;
525 layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
526 layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
527 layout(r32i) uniform highp writeonly iimage2D imageOut;
528 void main()
529 {
530 vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
531 ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
532 uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
533 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
534 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800535
536 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
537 EXPECT_GL_NO_ERROR();
538}
539
540// imageStore functions
541TEST_P(ComputeShaderTest, ImageStore)
542{
543 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800544 R"(#version 310 es
545 layout(local_size_x=8) in;
546 layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
547 layout(r32f) uniform highp writeonly image3D mImage3DOutput;
548 layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
549 void main()
550 {
551 imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
552 imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
553 imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
554 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800555
556 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
557 EXPECT_GL_NO_ERROR();
558}
559
560// imageSize functions
561TEST_P(ComputeShaderTest, ImageSize)
562{
563 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200564 R"(#version 310 es
565 layout(local_size_x=8) in;
566 layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
567 layout(r32i) uniform highp readonly iimage2D mImage2DInput;
568 layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
569 layout(r32i) uniform highp writeonly iimage2D imageOut;
570 void main()
571 {
572 ivec2 sizeCube = imageSize(mImageCubeInput);
573 ivec2 size2D = imageSize(mImage2DInput);
574 ivec3 size2DArray = imageSize(mImage2DArrayInput);
575 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
576 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800577
578 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
579 EXPECT_GL_NO_ERROR();
580}
581
Jiajia Qin5ae6ee42018-03-06 17:39:42 +0800582// Test that sampling texture works well in compute shader.
583TEST_P(ComputeShaderTest, TextureSampling)
584{
585 ANGLE_SKIP_TEST_IF(IsD3D11());
586
587 const std::string &csSource =
588 R"(#version 310 es
589 layout(local_size_x=16, local_size_y=16) in;
590 precision highp usampler2D;
591 uniform usampler2D tex;
592 layout(std140, binding = 0) buffer buf {
593 uint outData[16][16];
594 };
595
596 void main()
597 {
598 uint x = gl_LocalInvocationID.x;
599 uint y = gl_LocalInvocationID.y;
600 outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;
601 })";
602
603 constexpr unsigned int kWidth = 16;
604 constexpr unsigned int kHeight = 16;
605 GLTexture tex;
606 glBindTexture(GL_TEXTURE_2D, tex);
607 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
609 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
610 GLuint texels[kHeight][kWidth] = {{0}};
611 for (unsigned int y = 0; y < kHeight; ++y)
612 {
613 for (unsigned int x = 0; x < kWidth; ++x)
614 {
615 texels[y][x] = x + y * kWidth;
616 }
617 }
618 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
619 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
620 texels);
621 glBindTexture(GL_TEXTURE_2D, 0);
622
623 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
624 constexpr unsigned int kArrayStride = 16;
625 GLBuffer ssbo;
626 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
627 glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
628 GL_STREAM_DRAW);
629 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
630 EXPECT_GL_NO_ERROR();
631
632 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
633 glUseProgram(program.get());
634
635 glActiveTexture(GL_TEXTURE0);
636 glBindTexture(GL_TEXTURE_2D, tex);
637 glUniform1i(glGetUniformLocation(program, "tex"), 0);
638 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
639 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
640
641 glDispatchCompute(1, 1, 1);
642
643 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
644 void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride,
645 GL_MAP_READ_BIT);
646 for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
647 {
648 EXPECT_EQ(idx, *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
649 idx * kArrayStride)));
650 }
651 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
652 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
653 EXPECT_GL_NO_ERROR();
654}
655
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800656// Use image uniform to read and write Texture2D in compute shader, and verify the contents.
Xinghua Cao26143fd2017-11-01 18:19:05 +0800657TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
658{
659 GLTexture texture[2];
660 GLFramebuffer framebuffer;
661 const std::string csSource =
662 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800663 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800664 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
665 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
666 void main()
667 {
668 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
669 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
670 })";
671
Xinghua Cao27f43212018-02-26 11:05:53 +0800672 constexpr int kWidth = 1, kHeight = 1;
673 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800674
675 glBindTexture(GL_TEXTURE_2D, texture[0]);
676 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
677 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
678 kInputValues[0]);
679 EXPECT_GL_NO_ERROR();
680
681 glBindTexture(GL_TEXTURE_2D, texture[1]);
682 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
683 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
684 kInputValues[1]);
685 EXPECT_GL_NO_ERROR();
686
Xinghua Cao26143fd2017-11-01 18:19:05 +0800687 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
688 glUseProgram(program.get());
689
690 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
691 EXPECT_GL_NO_ERROR();
692
693 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
694 EXPECT_GL_NO_ERROR();
695
696 glDispatchCompute(1, 1, 1);
697 EXPECT_GL_NO_ERROR();
698
Xinghua Cao27f43212018-02-26 11:05:53 +0800699 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
700 GLuint outputValues[kWidth * kHeight];
701 constexpr GLuint expectedValue = 200;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800702 glUseProgram(0);
703 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
704
705 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
706 EXPECT_GL_NO_ERROR();
707 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
708 EXPECT_GL_NO_ERROR();
709
710 for (int i = 0; i < kWidth * kHeight; i++)
711 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800712 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao26143fd2017-11-01 18:19:05 +0800713 }
714}
715
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800716// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
717TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
718{
719 GLTexture texture[2];
720 GLFramebuffer framebuffer;
721 const std::string csSource =
722 R"(#version 310 es
723 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
724 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
725 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
726 void main()
727 {
728 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
729 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
730 })";
731
Xinghua Cao27f43212018-02-26 11:05:53 +0800732 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
733 constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800734
735 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
736 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
737 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
738 GL_UNSIGNED_INT, kInputValues[0]);
739 EXPECT_GL_NO_ERROR();
740
741 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
742 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
743 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
744 GL_UNSIGNED_INT, kInputValues[1]);
745 EXPECT_GL_NO_ERROR();
746
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800747 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
748 glUseProgram(program.get());
749
750 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
751 EXPECT_GL_NO_ERROR();
752
753 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
754 EXPECT_GL_NO_ERROR();
755
756 glDispatchCompute(1, 1, 1);
757 EXPECT_GL_NO_ERROR();
758
Xinghua Cao27f43212018-02-26 11:05:53 +0800759 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
760 GLuint outputValues[kWidth * kHeight];
761 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800762 glUseProgram(0);
763 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
764
765 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
766 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
767 EXPECT_GL_NO_ERROR();
768 glReadBuffer(GL_COLOR_ATTACHMENT0);
769 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
770 EXPECT_GL_NO_ERROR();
771 for (int i = 0; i < kWidth * kHeight; i++)
772 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800773 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800774 }
775 glReadBuffer(GL_COLOR_ATTACHMENT1);
776 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
777 EXPECT_GL_NO_ERROR();
778 for (int i = 0; i < kWidth * kHeight; i++)
779 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800780 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800781 }
782}
783
784// Use image uniform to read and write Texture3D in compute shader, and verify the contents.
785TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
786{
787 GLTexture texture[2];
788 GLFramebuffer framebuffer;
789 const std::string csSource =
790 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800791 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800792 layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
793 layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
794 void main()
795 {
796 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
797 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
798 })";
799
Xinghua Cao27f43212018-02-26 11:05:53 +0800800 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
801 constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800802
803 glBindTexture(GL_TEXTURE_3D, texture[0]);
804 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
805 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
806 GL_UNSIGNED_INT, kInputValues[0]);
807 EXPECT_GL_NO_ERROR();
808
809 glBindTexture(GL_TEXTURE_3D, texture[1]);
810 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
811 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
812 GL_UNSIGNED_INT, kInputValues[1]);
813 EXPECT_GL_NO_ERROR();
814
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800815 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
816 glUseProgram(program.get());
817
818 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
819 EXPECT_GL_NO_ERROR();
820
821 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
822 EXPECT_GL_NO_ERROR();
823
824 glDispatchCompute(1, 1, 1);
825 EXPECT_GL_NO_ERROR();
826
Xinghua Cao27f43212018-02-26 11:05:53 +0800827 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
828 GLuint outputValues[kWidth * kHeight];
829 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800830 glUseProgram(0);
831 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
832
833 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
834 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
835 EXPECT_GL_NO_ERROR();
836 glReadBuffer(GL_COLOR_ATTACHMENT0);
837 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
838 EXPECT_GL_NO_ERROR();
839 for (int i = 0; i < kWidth * kHeight; i++)
840 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800841 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800842 }
843 glReadBuffer(GL_COLOR_ATTACHMENT1);
844 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
845 EXPECT_GL_NO_ERROR();
846 for (int i = 0; i < kWidth * kHeight; i++)
847 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800848 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800849 }
850}
851
852// Use image uniform to read and write TextureCube in compute shader, and verify the contents.
853TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
854{
855 GLTexture texture[2];
856 GLFramebuffer framebuffer;
857 const std::string csSource =
858 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800859 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800860 layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
861 layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
862 void main()
863 {
864 for (int i = 0; i < 6; i++)
865 {
866 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
867 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
868 }
869 })";
870
Xinghua Cao27f43212018-02-26 11:05:53 +0800871 constexpr int kWidth = 1, kHeight = 1;
872 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800873
874 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
875 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
876 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
877 face++)
878 {
879 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
880 kInputValues[0]);
881 }
882 EXPECT_GL_NO_ERROR();
883
884 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
885 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
886 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
887 face++)
888 {
889 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
890 kInputValues[1]);
891 }
892 EXPECT_GL_NO_ERROR();
893
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800894 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
895 glUseProgram(program.get());
896
897 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
898 EXPECT_GL_NO_ERROR();
899
900 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
901 EXPECT_GL_NO_ERROR();
902
903 glDispatchCompute(1, 1, 1);
904 EXPECT_GL_NO_ERROR();
905
Xinghua Cao27f43212018-02-26 11:05:53 +0800906 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
907 GLuint outputValues[kWidth * kHeight];
908 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800909 glUseProgram(0);
910 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
911
912 for (GLenum face = 0; face < 6; face++)
913 {
914 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
915 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
916 EXPECT_GL_NO_ERROR();
917 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
918 EXPECT_GL_NO_ERROR();
919
920 for (int i = 0; i < kWidth * kHeight; i++)
921 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800922 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800923 }
924 }
925}
926
Xinghua Caob745f172018-01-09 16:10:02 +0800927// Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
928// contents.
929TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
930{
931 ANGLE_SKIP_TEST_IF(IsD3D11());
932
933 GLTexture texture[2];
934 GLFramebuffer framebuffer;
935 const std::string csSource =
936 R"(#version 310 es
937 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
938 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
939 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
940 void main()
941 {
942 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
943 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
944 })";
945
946 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
947 constexpr int kResultSize = kWidth * kHeight;
948 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
949 constexpr GLuint expectedValue_1 = 200;
950 constexpr GLuint expectedValue_2 = 100;
951 GLuint outputValues[kResultSize];
952
953 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
954 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
955 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
956 GL_UNSIGNED_INT, kInputValues[0]);
957 EXPECT_GL_NO_ERROR();
958
959 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
960 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
961 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
962 GL_UNSIGNED_INT, kInputValues[1]);
963 EXPECT_GL_NO_ERROR();
964
965 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
966 glUseProgram(program.get());
967
968 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
969 EXPECT_GL_NO_ERROR();
970 glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
971 EXPECT_GL_NO_ERROR();
972 glDispatchCompute(1, 1, 1);
973 EXPECT_GL_NO_ERROR();
974
975 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
976 glUseProgram(0);
977 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
978 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
979 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
980 EXPECT_GL_NO_ERROR();
981 glReadBuffer(GL_COLOR_ATTACHMENT0);
982 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
983 EXPECT_GL_NO_ERROR();
984 for (int i = 0; i < kResultSize; i++)
985 {
986 EXPECT_EQ(expectedValue_2, outputValues[i]);
987 }
988 glReadBuffer(GL_COLOR_ATTACHMENT1);
989 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
990 EXPECT_GL_NO_ERROR();
991 for (int i = 0; i < kResultSize; i++)
992 {
993 EXPECT_EQ(expectedValue_1, outputValues[i]);
994 }
995}
996
997// Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
998// contents.
999TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
1000{
1001 ANGLE_SKIP_TEST_IF(IsD3D11());
1002 GLTexture texture[2];
1003 GLFramebuffer framebuffer;
1004 const std::string csSource =
1005 R"(#version 310 es
1006 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1007 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1008 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1009 void main()
1010 {
1011 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1012 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1013 })";
1014
1015 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1016 constexpr int kResultSize = kWidth * kHeight;
1017 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1018 constexpr GLuint expectedValue_1 = 150;
1019 constexpr GLuint expectedValue_2 = 50;
1020 GLuint outputValues[kResultSize];
1021
1022 glBindTexture(GL_TEXTURE_3D, texture[0]);
1023 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1024 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1025 GL_UNSIGNED_INT, kInputValues[0]);
1026 EXPECT_GL_NO_ERROR();
1027
1028 glBindTexture(GL_TEXTURE_3D, texture[1]);
1029 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1030 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1031 GL_UNSIGNED_INT, kInputValues[1]);
1032 EXPECT_GL_NO_ERROR();
1033
1034 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1035 glUseProgram(program.get());
1036
1037 glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1038 EXPECT_GL_NO_ERROR();
1039 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1040 EXPECT_GL_NO_ERROR();
1041 glDispatchCompute(1, 1, 1);
1042 EXPECT_GL_NO_ERROR();
1043
1044 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1045 glUseProgram(0);
1046 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1047 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1048 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1049 EXPECT_GL_NO_ERROR();
1050 glReadBuffer(GL_COLOR_ATTACHMENT0);
1051 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1052 EXPECT_GL_NO_ERROR();
1053 for (int i = 0; i < kResultSize; i++)
1054 {
1055 EXPECT_EQ(expectedValue_1, outputValues[i]);
1056 }
1057 glReadBuffer(GL_COLOR_ATTACHMENT1);
1058 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1059 EXPECT_GL_NO_ERROR();
1060 for (int i = 0; i < kResultSize; i++)
1061 {
1062 EXPECT_EQ(expectedValue_2, outputValues[i]);
1063 }
1064}
1065
1066// Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1067// contents.
1068TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1069{
1070 ANGLE_SKIP_TEST_IF(IsD3D11());
1071
1072 GLTexture texture[2];
1073 GLFramebuffer framebuffer;
1074 const std::string csSource =
1075 R"(#version 310 es
1076 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1077 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1078 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1079 void main()
1080 {
1081 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1082 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1083 })";
1084
1085 constexpr int kWidth = 1, kHeight = 1;
1086 constexpr int kResultSize = kWidth * kHeight;
1087 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1088 constexpr GLuint expectedValue_1 = 200;
1089 constexpr GLuint expectedValue_2 = 100;
1090 GLuint outputValues[kResultSize];
1091
1092 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1093 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1094 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1095 face++)
1096 {
1097 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1098 kInputValues[0]);
1099 }
1100 EXPECT_GL_NO_ERROR();
1101
1102 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1103 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1104 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1105 face++)
1106 {
1107 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1108 kInputValues[1]);
1109 }
1110 EXPECT_GL_NO_ERROR();
1111
1112 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1113 glUseProgram(program.get());
1114
1115 glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1116 EXPECT_GL_NO_ERROR();
1117 glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1118 EXPECT_GL_NO_ERROR();
1119 glDispatchCompute(1, 1, 1);
1120 EXPECT_GL_NO_ERROR();
1121
1122 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1123 glUseProgram(0);
1124 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1125
1126 for (GLenum face = 0; face < 6; face++)
1127 {
1128 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1129 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1130 EXPECT_GL_NO_ERROR();
1131 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1132 EXPECT_GL_NO_ERROR();
1133
1134 if (face == 4)
1135 {
1136 for (int i = 0; i < kResultSize; i++)
1137 {
1138 EXPECT_EQ(expectedValue_1, outputValues[i]);
1139 }
1140 }
1141 else
1142 {
1143 for (int i = 0; i < kResultSize; i++)
1144 {
1145 EXPECT_EQ(expectedValue_2, outputValues[i]);
1146 }
1147 }
1148 }
1149}
1150
Jiawei Shao6ae51612018-02-23 14:03:25 +08001151// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
1152// program which has not been linked successfully or which does not contain objects to form a
1153// compute shader.
1154TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
1155{
1156 const std::string vsSource =
1157 R"(#version 310 es
1158 void main()
1159 {
1160 })";
1161
1162 const std::string fsSource =
1163 R"(#version 310 es
1164 void main()
1165 {
1166 })";
1167
1168 GLint workGroupSize[3];
1169
1170 ANGLE_GL_PROGRAM(graphicsProgram, vsSource, fsSource);
1171 glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1172 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1173
1174 GLuint computeProgram = glCreateProgram();
1175 GLShader computeShader(GL_COMPUTE_SHADER);
1176 glAttachShader(computeProgram, computeShader);
1177 glLinkProgram(computeProgram);
1178 glDetachShader(computeProgram, computeShader);
1179
1180 GLint linkStatus;
1181 glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
1182 ASSERT_GL_FALSE(linkStatus);
1183
1184 glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1185 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1186
1187 glDeleteProgram(computeProgram);
1188
1189 ASSERT_GL_NO_ERROR();
1190}
1191
Xinghua Cao47335852018-02-12 15:41:55 +08001192// Use groupMemoryBarrier and barrier to sync reads/writes order and the execution
1193// order of multiple shader invocations in compute shader.
1194TEST_P(ComputeShaderTest, groupMemoryBarrierAndBarrierTest)
1195{
1196 // TODO(xinghua.cao@intel.com): Figure out why we get this error message
1197 // that shader uses features not recognized by this D3D version.
Yuly Novikovbeafe1a2018-03-29 18:23:50 -04001198 ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());
Xinghua Cao47335852018-02-12 15:41:55 +08001199
1200 GLTexture texture;
1201 GLFramebuffer framebuffer;
1202
1203 // Each invocation first stores a single value in an image, then each invocation sums up
1204 // all the values in the image and stores the sum in the image. groupMemoryBarrier is
1205 // used to order reads/writes to variables stored in memory accessible to other shader
1206 // invocations, and barrier is used to control the relative execution order of multiple
1207 // shader invocations used to process a local work group.
1208 const std::string csSource =
1209 R"(#version 310 es
1210 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
1211 layout(r32i, binding = 0) uniform highp iimage2D image;
1212 void main()
1213 {
1214 uint x = gl_LocalInvocationID.x;
1215 uint y = gl_LocalInvocationID.y;
1216 imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));
1217 groupMemoryBarrier();
1218 barrier();
1219 int sum = 0;
1220 for (int i = 0; i < 2; i++)
1221 {
1222 for(int j = 0; j < 2; j++)
1223 {
1224 sum += imageLoad(image, ivec2(i, j)).x;
1225 }
1226 }
1227 groupMemoryBarrier();
1228 barrier();
1229 imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));
1230 })";
1231
1232 constexpr int kWidth = 2, kHeight = 2;
1233 glBindTexture(GL_TEXTURE_2D, texture);
1234 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);
1235 EXPECT_GL_NO_ERROR();
1236
1237 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1238 glUseProgram(program.get());
1239
1240 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
1241 EXPECT_GL_NO_ERROR();
1242
1243 glDispatchCompute(1, 1, 1);
1244 EXPECT_GL_NO_ERROR();
1245
1246 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1247 GLuint outputValues[kWidth * kHeight];
1248 constexpr GLuint kExpectedValue = 4;
1249 glUseProgram(0);
1250 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1251
1252 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1253 EXPECT_GL_NO_ERROR();
1254 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);
1255 EXPECT_GL_NO_ERROR();
1256
1257 for (int i = 0; i < kWidth * kHeight; i++)
1258 {
1259 EXPECT_EQ(kExpectedValue, outputValues[i]);
1260 }
1261}
1262
Jiawei Shao7a8fe152018-04-28 12:59:58 +08001263// Verify that a link error is generated when the sum of the number of active image uniforms and
1264// active shader storage blocks in a compute shader exceeds GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1265TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS)
1266{
1267 // TODO(jiawei.shao@intel.com): enable this test when shader storage buffer is supported on
1268 // D3D11 back-ends.
1269 ANGLE_SKIP_TEST_IF(IsD3D11());
1270
1271 GLint maxCombinedShaderOutputResources;
1272 GLint maxComputeShaderStorageBlocks;
1273 GLint maxComputeImageUniforms;
1274
1275 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
1276 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
1277 glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
1278
1279 ANGLE_SKIP_TEST_IF(maxCombinedShaderOutputResources >=
1280 maxComputeShaderStorageBlocks + maxComputeImageUniforms);
1281
1282 std::ostringstream computeShaderStream;
1283 computeShaderStream << "#version 310 es\n"
1284 "layout(local_size_x = 3, local_size_y = 1, local_size_z = 1) in;\n"
1285 "layout(shared, binding = 0) buffer blockName"
1286 "{\n"
1287 " uint data;\n"
1288 "} instance["
1289 << maxComputeShaderStorageBlocks << "];\n";
1290
1291 ASSERT_GE(maxComputeImageUniforms, 4);
1292 int numImagesInArray = maxComputeImageUniforms / 2;
1293 int numImagesNonArray = maxComputeImageUniforms - numImagesInArray;
1294 for (int i = 0; i < numImagesNonArray; ++i)
1295 {
1296 computeShaderStream << "layout(r32f, binding = " << i << ") uniform highp image2D image"
1297 << i << ";\n";
1298 }
1299
1300 computeShaderStream << "layout(r32f, binding = " << numImagesNonArray
1301 << ") uniform highp image2D imageArray[" << numImagesInArray << "];\n";
1302
1303 computeShaderStream << "void main()\n"
1304 "{\n"
1305 " uint val = 0u;\n"
1306 " vec4 val2 = vec4(0.0);\n";
1307
1308 for (int i = 0; i < maxComputeShaderStorageBlocks; ++i)
1309 {
1310 computeShaderStream << " val += instance[" << i << "].data; \n";
1311 }
1312
1313 for (int i = 0; i < numImagesNonArray; ++i)
1314 {
1315 computeShaderStream << " val2 += imageLoad(image" << i
1316 << ", ivec2(gl_LocalInvocationID.xy)); \n";
1317 }
1318
1319 for (int i = 0; i < numImagesInArray; ++i)
1320 {
1321 computeShaderStream << " val2 += imageLoad(imageArray[" << i << "]"
1322 << ", ivec2(gl_LocalInvocationID.xy)); \n";
1323 }
1324
1325 computeShaderStream << " instance[0].data = val + uint(val2.x);\n"
1326 "}\n";
1327
1328 GLuint computeProgram = CompileComputeProgram(computeShaderStream.str());
1329 EXPECT_EQ(0u, computeProgram);
1330}
1331
Qin Jiajia2a12b3d2018-05-23 13:42:13 +08001332// Test that uniform block with struct member in compute shader is supported.
1333TEST_P(ComputeShaderTest, UniformBlockWithStructMember)
1334{
1335 const std::string csSource =
1336 R"(#version 310 es
1337 layout(local_size_x=8) in;
1338 layout(rgba8) uniform highp readonly image2D mImage2DInput;
1339 layout(rgba8) uniform highp writeonly image2D mImage2DOutput;
1340 struct S {
1341 ivec3 a;
1342 ivec2 b;
1343 };
1344
1345 layout(std140, binding=0) uniform blockName {
1346 S bd;
1347 } instanceName;
1348 void main()
1349 {
1350 ivec2 t1 = instanceName.bd.b;
1351 vec4 result2d = imageLoad(mImage2DInput, t1);
1352 imageStore(mImage2DOutput, ivec2(gl_LocalInvocationID.xy), result2d);
1353 })";
1354
1355 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1356 EXPECT_GL_NO_ERROR();
1357}
1358
Jiawei Shaoa75aa3b2018-06-21 10:38:28 +08001359// Verify shared non-array variables can work correctly.
1360TEST_P(ComputeShaderTest, NonArraySharedVariable)
1361{
1362 const char kCSShader[] =
1363 R"(#version 310 es
1364 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
1365 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1366 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1367 shared uint temp;
1368 void main()
1369 {
1370 if (gl_LocalInvocationID == uvec3(0, 0, 0))
1371 {
1372 temp = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1373 }
1374 groupMemoryBarrier();
1375 barrier();
1376 if (gl_LocalInvocationID == uvec3(1, 1, 0))
1377 {
1378 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(temp));
1379 }
1380 else
1381 {
1382 uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1383 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(inputValue));
1384 }
1385 })";
1386
1387 const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
1388 const std::array<GLuint, 4> expectedValues = {{250, 200, 150, 250}};
1389 runSharedMemoryTest<2, 2>(kCSShader, inputData, expectedValues);
1390}
1391
1392// Verify shared non-struct array variables can work correctly.
1393TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)
1394{
1395 const char kCSShader[] =
1396 R"(#version 310 es
1397 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
1398 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1399 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1400 shared uint sharedData[2][2];
1401 void main()
1402 {
1403 uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1404 sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = inputData;
1405 groupMemoryBarrier();
1406 barrier();
1407 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1408 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x]));
1409 })";
1410
1411 const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
1412 const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
1413 runSharedMemoryTest<2, 2>(kCSShader, inputData, expectedValues);
1414}
1415
1416// Verify shared struct array variables work correctly.
1417TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)
1418{
1419 const char kCSShader[] =
1420 R"(#version 310 es
1421 layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
1422 layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
1423 layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
1424 struct SharedStruct
1425 {
1426 uint data;
1427 };
1428 shared SharedStruct sharedData[2][2];
1429 void main()
1430 {
1431 uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
1432 sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y].data = inputData;
1433 groupMemoryBarrier();
1434 barrier();
1435 imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
1436 uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x].data));
1437 })";
1438
1439 const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
1440 const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
1441 runSharedMemoryTest<2, 2>(kCSShader, inputData, expectedValues);
1442}
1443
Martin Radev4c4c8e72016-08-04 12:25:34 +03001444// Check that it is not possible to create a compute shader when the context does not support ES
1445// 3.10
1446TEST_P(ComputeShaderTestES3, NotSupported)
1447{
1448 GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
1449 EXPECT_EQ(0u, computeShaderHandle);
1450 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1451}
1452
Xinghua Caob1239382016-12-13 15:07:05 +08001453ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
Martin Radev4c4c8e72016-08-04 12:25:34 +03001454ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
1455
1456} // namespace