blob: 6bf34e12ed54e424e42f04de4668367f6c5853f4 [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() {}
22};
23
24class ComputeShaderTestES3 : public ANGLETest
25{
26 protected:
27 ComputeShaderTestES3() {}
28};
29
30// link a simple compute program. It should be successful.
31TEST_P(ComputeShaderTest, LinkComputeProgram)
32{
33 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +080034 R"(#version 310 es
35 layout(local_size_x=1) in;
36 void main()
37 {\
38 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +030039
40 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
41
42 EXPECT_GL_NO_ERROR();
43}
44
Yunchao He85072e82017-11-14 15:43:28 +080045// Link a simple compute program. Then detach the shader and dispatch compute.
46// It should be successful.
47TEST_P(ComputeShaderTest, DetachShaderAfterLinkSuccess)
48{
49 const std::string csSource =
50 R"(#version 310 es
51 layout(local_size_x=1) in;
52 void main()
53 {
54 })";
55
56 GLuint program = glCreateProgram();
57
58 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
59 EXPECT_NE(0u, cs);
60
61 glAttachShader(program, cs);
62 glDeleteShader(cs);
63
64 glLinkProgram(program);
65 GLint linkStatus;
66 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
Yunchao He1f679cc2017-11-29 18:06:00 +080067 EXPECT_GL_TRUE(linkStatus);
Yunchao He85072e82017-11-14 15:43:28 +080068
69 glDetachShader(program, cs);
70 EXPECT_GL_NO_ERROR();
71
72 glUseProgram(program);
73 glDispatchCompute(8, 4, 2);
74 EXPECT_GL_NO_ERROR();
75}
76
Martin Radev4c4c8e72016-08-04 12:25:34 +030077// link a simple compute program. There is no local size and linking should fail.
78TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)
79{
80 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +080081 R"(#version 310 es
82 void main()
83 {
84 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +030085
86 GLuint program = CompileComputeProgram(csSource, false);
87 EXPECT_EQ(0u, program);
88
89 glDeleteProgram(program);
90
91 EXPECT_GL_NO_ERROR();
92}
93
94// link a simple compute program.
95// make sure that uniforms and uniform samplers get recorded
96TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)
97{
98 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +020099 R"(#version 310 es
100 precision mediump sampler2D;
101 layout(local_size_x=1) in;
102 uniform int myUniformInt;
103 uniform sampler2D myUniformSampler;
104 layout(rgba32i) uniform highp writeonly iimage2D imageOut;
105 void main()
106 {
107 int q = myUniformInt;
108 vec4 v = textureLod(myUniformSampler, vec2(0.0), 0.0);
109 imageStore(imageOut, ivec2(0), ivec4(v) * q);
110 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300111
112 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
113
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200114 GLint uniformLoc = glGetUniformLocation(program.get(), "myUniformInt");
115 EXPECT_NE(-1, uniformLoc);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300116
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200117 uniformLoc = glGetUniformLocation(program.get(), "myUniformSampler");
118 EXPECT_NE(-1, uniformLoc);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300119
120 EXPECT_GL_NO_ERROR();
121}
122
123// Attach both compute and non-compute shaders. A link time error should occur.
124// OpenGL ES 3.10, 7.3 Program Objects
125TEST_P(ComputeShaderTest, AttachMultipleShaders)
126{
127 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800128 R"(#version 310 es
129 layout(local_size_x=1) in;
130 void main()
131 {
132 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300133
134 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800135 R"(#version 310 es
136 void main()
137 {
138 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300139
140 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800141 R"(#version 310 es
142 void main()
143 {
144 })";
Martin Radev4c4c8e72016-08-04 12:25:34 +0300145
146 GLuint program = glCreateProgram();
147
148 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
149 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
150 GLuint cs = CompileShader(GL_COMPUTE_SHADER, csSource);
151
152 EXPECT_NE(0u, vs);
153 EXPECT_NE(0u, fs);
154 EXPECT_NE(0u, cs);
155
156 glAttachShader(program, vs);
157 glDeleteShader(vs);
158
159 glAttachShader(program, fs);
160 glDeleteShader(fs);
161
162 glAttachShader(program, cs);
163 glDeleteShader(cs);
164
165 glLinkProgram(program);
166
167 GLint linkStatus;
168 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
169
Yunchao He1f679cc2017-11-29 18:06:00 +0800170 EXPECT_GL_FALSE(linkStatus);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300171
172 EXPECT_GL_NO_ERROR();
173}
174
175// Attach a vertex, fragment and compute shader.
176// Query for the number of attached shaders and check the count.
177TEST_P(ComputeShaderTest, AttachmentCount)
178{
Martin Radev4c4c8e72016-08-04 12:25:34 +0300179 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 GLint numAttachedShaders;
218 glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
219
220 EXPECT_EQ(3, numAttachedShaders);
221
222 glDeleteProgram(program);
223
224 EXPECT_GL_NO_ERROR();
225}
226
Yunchao Hecddcb592017-11-13 15:27:35 +0800227// Attach a compute shader and link, but start rendering.
228TEST_P(ComputeShaderTest, StartRenderingWithComputeProgram)
229{
230 const std::string csSource =
231 R"(#version 310 es
232 layout(local_size_x=1) in;
233 void main()
234 {
235 })";
236
237 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
238 EXPECT_GL_NO_ERROR();
239
240 glUseProgram(program);
241 glDrawArrays(GL_POINTS, 0, 2);
242 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
243}
244
Yunchao He70b715c2017-11-07 14:59:15 +0800245// Attach a vertex and fragment shader and link, but dispatch compute.
246TEST_P(ComputeShaderTest, DispatchComputeWithRenderingProgram)
247{
248 const std::string vsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800249 R"(#version 310 es
250 void main()
251 {
252 })";
Yunchao He70b715c2017-11-07 14:59:15 +0800253
254 const std::string fsSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800255 R"(#version 310 es
256 void main()
257 {
258 })";
Yunchao He70b715c2017-11-07 14:59:15 +0800259
260 GLuint program = glCreateProgram();
261
262 GLuint vs = CompileShader(GL_VERTEX_SHADER, vsSource);
263 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, fsSource);
264
265 EXPECT_NE(0u, vs);
266 EXPECT_NE(0u, fs);
267
268 glAttachShader(program, vs);
269 glDeleteShader(vs);
270
271 glAttachShader(program, fs);
272 glDeleteShader(fs);
273
274 glLinkProgram(program);
275
276 GLint linkStatus;
277 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
Yunchao He1f679cc2017-11-29 18:06:00 +0800278 EXPECT_GL_TRUE(linkStatus);
Yunchao He70b715c2017-11-07 14:59:15 +0800279
280 EXPECT_GL_NO_ERROR();
281
282 glUseProgram(program);
283 glDispatchCompute(8, 4, 2);
284 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
285}
286
Xinghua Caob1239382016-12-13 15:07:05 +0800287// Access all compute shader special variables.
288TEST_P(ComputeShaderTest, AccessAllSpecialVariables)
289{
290 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200291 R"(#version 310 es
292 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
293 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
294 void main()
295 {
296 uvec3 temp1 = gl_NumWorkGroups;
297 uvec3 temp2 = gl_WorkGroupSize;
298 uvec3 temp3 = gl_WorkGroupID;
299 uvec3 temp4 = gl_LocalInvocationID;
300 uvec3 temp5 = gl_GlobalInvocationID;
301 uint temp6 = gl_LocalInvocationIndex;
302 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));
303 })";
Xinghua Caob1239382016-12-13 15:07:05 +0800304
305 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
306}
307
308// Access part compute shader special variables.
309TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
310{
311 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200312 R"(#version 310 es
313 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
314 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
315 void main()
316 {
317 uvec3 temp1 = gl_WorkGroupSize;
318 uvec3 temp2 = gl_WorkGroupID;
319 uint temp3 = gl_LocalInvocationIndex;
320 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2, temp3));
321 })";
Xinghua Caob1239382016-12-13 15:07:05 +0800322
323 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
324}
325
Xinghua Cao73badc02017-03-29 19:14:53 +0800326// Use glDispatchCompute to define work group count.
327TEST_P(ComputeShaderTest, DispatchCompute)
Xinghua Cao2b396592017-03-29 15:36:04 +0800328{
329 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200330 R"(#version 310 es
331 layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
332 layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
333 void main()
334 {
335 uvec3 temp = gl_NumWorkGroups;
336 imageStore(imageOut, ivec2(0), uvec4(temp, 0u));
337 })";
Xinghua Cao2b396592017-03-29 15:36:04 +0800338
339 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
340
341 glUseProgram(program.get());
342 glDispatchCompute(8, 4, 2);
343 EXPECT_GL_NO_ERROR();
344}
345
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800346// Use image uniform to write texture in compute shader, and verify the content is expected.
347TEST_P(ComputeShaderTest, BindImageTexture)
348{
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800349 GLTexture mTexture[2];
350 GLFramebuffer mFramebuffer;
351 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800352 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800353 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Yunchao Hecddcb592017-11-13 15:27:35 +0800354 layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
355 void main()
356 {
357 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
358 0, 0));
359 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
360 0, 0));
361 })";
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800362
363 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
364 glUseProgram(program.get());
Xinghua Cao27f43212018-02-26 11:05:53 +0800365 int width = 1, height = 1;
366 GLuint inputValues[] = {200};
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800367
368 glBindTexture(GL_TEXTURE_2D, mTexture[0]);
369 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
370 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
371 inputValues);
372 EXPECT_GL_NO_ERROR();
373
374 glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
375 EXPECT_GL_NO_ERROR();
376
377 glBindTexture(GL_TEXTURE_2D, mTexture[1]);
378 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
379 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
380 inputValues);
381 EXPECT_GL_NO_ERROR();
382
383 glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
384 EXPECT_GL_NO_ERROR();
385
Xinghua Cao27f43212018-02-26 11:05:53 +0800386 glDispatchCompute(1, 1, 1);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800387 EXPECT_GL_NO_ERROR();
388
Xinghua Cao27f43212018-02-26 11:05:53 +0800389 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800390 glUseProgram(0);
Xinghua Cao27f43212018-02-26 11:05:53 +0800391 GLuint outputValues[2][1];
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800392 GLuint expectedValue = 100;
393 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
394
395 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
396 0);
397 EXPECT_GL_NO_ERROR();
398 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
399 EXPECT_GL_NO_ERROR();
400
401 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
402 0);
403 EXPECT_GL_NO_ERROR();
404 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
405 EXPECT_GL_NO_ERROR();
406
407 for (int i = 0; i < width * height; i++)
408 {
409 EXPECT_EQ(expectedValue, outputValues[0][i]);
410 EXPECT_EQ(expectedValue, outputValues[1][i]);
411 }
412}
413
Xinghua Cao0328b572017-06-26 15:51:36 +0800414// When declare a image array without a binding qualifier, all elements are bound to unit zero.
415TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
416{
417 ANGLE_SKIP_TEST_IF(IsD3D11());
418
419 // TODO(xinghua.cao@intel.com): On AMD desktop OpenGL, bind two image variables to unit 0,
420 // only one variable is valid.
Corentin Wallez2bde9192017-07-28 14:15:01 -0400421 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
Xinghua Cao0328b572017-06-26 15:51:36 +0800422
423 GLTexture mTexture;
424 GLFramebuffer mFramebuffer;
425 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800426 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800427 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Yunchao Hecddcb592017-11-13 15:27:35 +0800428 layout(r32ui) writeonly uniform highp uimage2D uImage[2];
429 void main()
430 {
431 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
432 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
433 })";
Xinghua Cao0328b572017-06-26 15:51:36 +0800434
435 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
436 glUseProgram(program.get());
Xinghua Cao27f43212018-02-26 11:05:53 +0800437 constexpr int kTextureWidth = 1, kTextureHeight = 2;
438 GLuint inputValues[] = {200, 200};
Xinghua Cao0328b572017-06-26 15:51:36 +0800439
440 glBindTexture(GL_TEXTURE_2D, mTexture);
441 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
442 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
443 GL_UNSIGNED_INT, inputValues);
444 EXPECT_GL_NO_ERROR();
445
446 glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
447 glDispatchCompute(1, 1, 1);
448 EXPECT_GL_NO_ERROR();
449
Xinghua Cao27f43212018-02-26 11:05:53 +0800450 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
Xinghua Cao0328b572017-06-26 15:51:36 +0800451 glUseProgram(0);
452 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
453
454 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
Xinghua Cao27f43212018-02-26 11:05:53 +0800455 GLuint outputValues[kTextureWidth * kTextureHeight];
Xinghua Cao0328b572017-06-26 15:51:36 +0800456 glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
457 outputValues);
458 EXPECT_GL_NO_ERROR();
459
460 GLuint expectedValue = 100;
461 for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
462 {
463 EXPECT_EQ(expectedValue, outputValues[i]);
464 }
465}
466
Xinghua Cao711b7a12017-10-09 13:38:12 +0800467// imageLoad functions
468TEST_P(ComputeShaderTest, ImageLoad)
469{
470 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200471 R"(#version 310 es
472 layout(local_size_x=8) in;
473 layout(rgba8) uniform highp readonly image2D mImage2DInput;
474 layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
475 layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
476 layout(r32i) uniform highp writeonly iimage2D imageOut;
477 void main()
478 {
479 vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
480 ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
481 uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
482 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
483 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800484
485 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
486 EXPECT_GL_NO_ERROR();
487}
488
489// imageStore functions
490TEST_P(ComputeShaderTest, ImageStore)
491{
492 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800493 R"(#version 310 es
494 layout(local_size_x=8) in;
495 layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
496 layout(r32f) uniform highp writeonly image3D mImage3DOutput;
497 layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
498 void main()
499 {
500 imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
501 imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
502 imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
503 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800504
505 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
506 EXPECT_GL_NO_ERROR();
507}
508
509// imageSize functions
510TEST_P(ComputeShaderTest, ImageSize)
511{
512 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200513 R"(#version 310 es
514 layout(local_size_x=8) in;
515 layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
516 layout(r32i) uniform highp readonly iimage2D mImage2DInput;
517 layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
518 layout(r32i) uniform highp writeonly iimage2D imageOut;
519 void main()
520 {
521 ivec2 sizeCube = imageSize(mImageCubeInput);
522 ivec2 size2D = imageSize(mImage2DInput);
523 ivec3 size2DArray = imageSize(mImage2DArrayInput);
524 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
525 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800526
527 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
528 EXPECT_GL_NO_ERROR();
529}
530
Jiajia Qin5ae6ee42018-03-06 17:39:42 +0800531// Test that sampling texture works well in compute shader.
532TEST_P(ComputeShaderTest, TextureSampling)
533{
534 ANGLE_SKIP_TEST_IF(IsD3D11());
535
536 const std::string &csSource =
537 R"(#version 310 es
538 layout(local_size_x=16, local_size_y=16) in;
539 precision highp usampler2D;
540 uniform usampler2D tex;
541 layout(std140, binding = 0) buffer buf {
542 uint outData[16][16];
543 };
544
545 void main()
546 {
547 uint x = gl_LocalInvocationID.x;
548 uint y = gl_LocalInvocationID.y;
549 outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;
550 })";
551
552 constexpr unsigned int kWidth = 16;
553 constexpr unsigned int kHeight = 16;
554 GLTexture tex;
555 glBindTexture(GL_TEXTURE_2D, tex);
556 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
558 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
559 GLuint texels[kHeight][kWidth] = {{0}};
560 for (unsigned int y = 0; y < kHeight; ++y)
561 {
562 for (unsigned int x = 0; x < kWidth; ++x)
563 {
564 texels[y][x] = x + y * kWidth;
565 }
566 }
567 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
568 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
569 texels);
570 glBindTexture(GL_TEXTURE_2D, 0);
571
572 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
573 constexpr unsigned int kArrayStride = 16;
574 GLBuffer ssbo;
575 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
576 glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
577 GL_STREAM_DRAW);
578 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
579 EXPECT_GL_NO_ERROR();
580
581 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
582 glUseProgram(program.get());
583
584 glActiveTexture(GL_TEXTURE0);
585 glBindTexture(GL_TEXTURE_2D, tex);
586 glUniform1i(glGetUniformLocation(program, "tex"), 0);
587 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
588 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
589
590 glDispatchCompute(1, 1, 1);
591
592 glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
593 void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride,
594 GL_MAP_READ_BIT);
595 for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
596 {
597 EXPECT_EQ(idx, *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
598 idx * kArrayStride)));
599 }
600 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
601 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
602 EXPECT_GL_NO_ERROR();
603}
604
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800605// Use image uniform to read and write Texture2D in compute shader, and verify the contents.
Xinghua Cao26143fd2017-11-01 18:19:05 +0800606TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
607{
608 GLTexture texture[2];
609 GLFramebuffer framebuffer;
610 const std::string csSource =
611 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800612 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800613 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
614 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
615 void main()
616 {
617 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
618 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
619 })";
620
Xinghua Cao27f43212018-02-26 11:05:53 +0800621 constexpr int kWidth = 1, kHeight = 1;
622 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
Xinghua Cao26143fd2017-11-01 18:19:05 +0800623
624 glBindTexture(GL_TEXTURE_2D, texture[0]);
625 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
626 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
627 kInputValues[0]);
628 EXPECT_GL_NO_ERROR();
629
630 glBindTexture(GL_TEXTURE_2D, texture[1]);
631 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
632 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
633 kInputValues[1]);
634 EXPECT_GL_NO_ERROR();
635
Xinghua Cao26143fd2017-11-01 18:19:05 +0800636 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
637 glUseProgram(program.get());
638
639 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
640 EXPECT_GL_NO_ERROR();
641
642 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
643 EXPECT_GL_NO_ERROR();
644
645 glDispatchCompute(1, 1, 1);
646 EXPECT_GL_NO_ERROR();
647
Xinghua Cao27f43212018-02-26 11:05:53 +0800648 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
649 GLuint outputValues[kWidth * kHeight];
650 constexpr GLuint expectedValue = 200;
Xinghua Cao26143fd2017-11-01 18:19:05 +0800651 glUseProgram(0);
652 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
653
654 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
655 EXPECT_GL_NO_ERROR();
656 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
657 EXPECT_GL_NO_ERROR();
658
659 for (int i = 0; i < kWidth * kHeight; i++)
660 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800661 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao26143fd2017-11-01 18:19:05 +0800662 }
663}
664
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800665// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
666TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
667{
668 GLTexture texture[2];
669 GLFramebuffer framebuffer;
670 const std::string csSource =
671 R"(#version 310 es
672 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
673 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
674 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
675 void main()
676 {
677 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
678 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
679 })";
680
Xinghua Cao27f43212018-02-26 11:05:53 +0800681 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
682 constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800683
684 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
685 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
686 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
687 GL_UNSIGNED_INT, kInputValues[0]);
688 EXPECT_GL_NO_ERROR();
689
690 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
691 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
692 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
693 GL_UNSIGNED_INT, kInputValues[1]);
694 EXPECT_GL_NO_ERROR();
695
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800696 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
697 glUseProgram(program.get());
698
699 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
700 EXPECT_GL_NO_ERROR();
701
702 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
703 EXPECT_GL_NO_ERROR();
704
705 glDispatchCompute(1, 1, 1);
706 EXPECT_GL_NO_ERROR();
707
Xinghua Cao27f43212018-02-26 11:05:53 +0800708 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
709 GLuint outputValues[kWidth * kHeight];
710 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800711 glUseProgram(0);
712 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
713
714 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
715 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
716 EXPECT_GL_NO_ERROR();
717 glReadBuffer(GL_COLOR_ATTACHMENT0);
718 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
719 EXPECT_GL_NO_ERROR();
720 for (int i = 0; i < kWidth * kHeight; i++)
721 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800722 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800723 }
724 glReadBuffer(GL_COLOR_ATTACHMENT1);
725 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
726 EXPECT_GL_NO_ERROR();
727 for (int i = 0; i < kWidth * kHeight; i++)
728 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800729 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800730 }
731}
732
733// Use image uniform to read and write Texture3D in compute shader, and verify the contents.
734TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
735{
736 GLTexture texture[2];
737 GLFramebuffer framebuffer;
738 const std::string csSource =
739 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800740 layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800741 layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
742 layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
743 void main()
744 {
745 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
746 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
747 })";
748
Xinghua Cao27f43212018-02-26 11:05:53 +0800749 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
750 constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800751
752 glBindTexture(GL_TEXTURE_3D, texture[0]);
753 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
754 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
755 GL_UNSIGNED_INT, kInputValues[0]);
756 EXPECT_GL_NO_ERROR();
757
758 glBindTexture(GL_TEXTURE_3D, texture[1]);
759 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
760 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
761 GL_UNSIGNED_INT, kInputValues[1]);
762 EXPECT_GL_NO_ERROR();
763
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800764 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
765 glUseProgram(program.get());
766
767 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
768 EXPECT_GL_NO_ERROR();
769
770 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
771 EXPECT_GL_NO_ERROR();
772
773 glDispatchCompute(1, 1, 1);
774 EXPECT_GL_NO_ERROR();
775
Xinghua Cao27f43212018-02-26 11:05:53 +0800776 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
777 GLuint outputValues[kWidth * kHeight];
778 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800779 glUseProgram(0);
780 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
781
782 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
783 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
784 EXPECT_GL_NO_ERROR();
785 glReadBuffer(GL_COLOR_ATTACHMENT0);
786 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
787 EXPECT_GL_NO_ERROR();
788 for (int i = 0; i < kWidth * kHeight; i++)
789 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800790 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800791 }
792 glReadBuffer(GL_COLOR_ATTACHMENT1);
793 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
794 EXPECT_GL_NO_ERROR();
795 for (int i = 0; i < kWidth * kHeight; i++)
796 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800797 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800798 }
799}
800
801// Use image uniform to read and write TextureCube in compute shader, and verify the contents.
802TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
803{
804 GLTexture texture[2];
805 GLFramebuffer framebuffer;
806 const std::string csSource =
807 R"(#version 310 es
Xinghua Cao27f43212018-02-26 11:05:53 +0800808 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800809 layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
810 layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
811 void main()
812 {
813 for (int i = 0; i < 6; i++)
814 {
815 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
816 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
817 }
818 })";
819
Xinghua Cao27f43212018-02-26 11:05:53 +0800820 constexpr int kWidth = 1, kHeight = 1;
821 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800822
823 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
824 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
825 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
826 face++)
827 {
828 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
829 kInputValues[0]);
830 }
831 EXPECT_GL_NO_ERROR();
832
833 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
834 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
835 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
836 face++)
837 {
838 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
839 kInputValues[1]);
840 }
841 EXPECT_GL_NO_ERROR();
842
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800843 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
844 glUseProgram(program.get());
845
846 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
847 EXPECT_GL_NO_ERROR();
848
849 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
850 EXPECT_GL_NO_ERROR();
851
852 glDispatchCompute(1, 1, 1);
853 EXPECT_GL_NO_ERROR();
854
Xinghua Cao27f43212018-02-26 11:05:53 +0800855 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
856 GLuint outputValues[kWidth * kHeight];
857 constexpr GLuint expectedValue = 200;
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800858 glUseProgram(0);
859 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
860
861 for (GLenum face = 0; face < 6; face++)
862 {
863 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
864 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
865 EXPECT_GL_NO_ERROR();
866 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
867 EXPECT_GL_NO_ERROR();
868
869 for (int i = 0; i < kWidth * kHeight; i++)
870 {
Xinghua Cao27f43212018-02-26 11:05:53 +0800871 EXPECT_EQ(expectedValue, outputValues[i]);
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800872 }
873 }
874}
875
Xinghua Caob745f172018-01-09 16:10:02 +0800876// Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
877// contents.
878TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
879{
880 ANGLE_SKIP_TEST_IF(IsD3D11());
881
882 GLTexture texture[2];
883 GLFramebuffer framebuffer;
884 const std::string csSource =
885 R"(#version 310 es
886 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
887 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
888 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
889 void main()
890 {
891 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
892 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
893 })";
894
895 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
896 constexpr int kResultSize = kWidth * kHeight;
897 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
898 constexpr GLuint expectedValue_1 = 200;
899 constexpr GLuint expectedValue_2 = 100;
900 GLuint outputValues[kResultSize];
901
902 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
903 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
904 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
905 GL_UNSIGNED_INT, kInputValues[0]);
906 EXPECT_GL_NO_ERROR();
907
908 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
909 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
910 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
911 GL_UNSIGNED_INT, kInputValues[1]);
912 EXPECT_GL_NO_ERROR();
913
914 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
915 glUseProgram(program.get());
916
917 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
918 EXPECT_GL_NO_ERROR();
919 glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
920 EXPECT_GL_NO_ERROR();
921 glDispatchCompute(1, 1, 1);
922 EXPECT_GL_NO_ERROR();
923
924 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
925 glUseProgram(0);
926 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
927 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
928 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
929 EXPECT_GL_NO_ERROR();
930 glReadBuffer(GL_COLOR_ATTACHMENT0);
931 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
932 EXPECT_GL_NO_ERROR();
933 for (int i = 0; i < kResultSize; i++)
934 {
935 EXPECT_EQ(expectedValue_2, outputValues[i]);
936 }
937 glReadBuffer(GL_COLOR_ATTACHMENT1);
938 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
939 EXPECT_GL_NO_ERROR();
940 for (int i = 0; i < kResultSize; i++)
941 {
942 EXPECT_EQ(expectedValue_1, outputValues[i]);
943 }
944}
945
946// Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
947// contents.
948TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
949{
950 ANGLE_SKIP_TEST_IF(IsD3D11());
951 GLTexture texture[2];
952 GLFramebuffer framebuffer;
953 const std::string csSource =
954 R"(#version 310 es
955 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
956 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
957 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
958 void main()
959 {
960 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
961 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
962 })";
963
964 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
965 constexpr int kResultSize = kWidth * kHeight;
966 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
967 constexpr GLuint expectedValue_1 = 150;
968 constexpr GLuint expectedValue_2 = 50;
969 GLuint outputValues[kResultSize];
970
971 glBindTexture(GL_TEXTURE_3D, texture[0]);
972 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
973 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
974 GL_UNSIGNED_INT, kInputValues[0]);
975 EXPECT_GL_NO_ERROR();
976
977 glBindTexture(GL_TEXTURE_3D, texture[1]);
978 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
979 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
980 GL_UNSIGNED_INT, kInputValues[1]);
981 EXPECT_GL_NO_ERROR();
982
983 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
984 glUseProgram(program.get());
985
986 glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
987 EXPECT_GL_NO_ERROR();
988 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
989 EXPECT_GL_NO_ERROR();
990 glDispatchCompute(1, 1, 1);
991 EXPECT_GL_NO_ERROR();
992
993 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
994 glUseProgram(0);
995 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
996 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
997 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
998 EXPECT_GL_NO_ERROR();
999 glReadBuffer(GL_COLOR_ATTACHMENT0);
1000 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1001 EXPECT_GL_NO_ERROR();
1002 for (int i = 0; i < kResultSize; i++)
1003 {
1004 EXPECT_EQ(expectedValue_1, outputValues[i]);
1005 }
1006 glReadBuffer(GL_COLOR_ATTACHMENT1);
1007 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1008 EXPECT_GL_NO_ERROR();
1009 for (int i = 0; i < kResultSize; i++)
1010 {
1011 EXPECT_EQ(expectedValue_2, outputValues[i]);
1012 }
1013}
1014
1015// Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1016// contents.
1017TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1018{
1019 ANGLE_SKIP_TEST_IF(IsD3D11());
1020
1021 GLTexture texture[2];
1022 GLFramebuffer framebuffer;
1023 const std::string csSource =
1024 R"(#version 310 es
1025 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1026 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1027 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1028 void main()
1029 {
1030 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1031 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1032 })";
1033
1034 constexpr int kWidth = 1, kHeight = 1;
1035 constexpr int kResultSize = kWidth * kHeight;
1036 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1037 constexpr GLuint expectedValue_1 = 200;
1038 constexpr GLuint expectedValue_2 = 100;
1039 GLuint outputValues[kResultSize];
1040
1041 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1042 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1043 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1044 face++)
1045 {
1046 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1047 kInputValues[0]);
1048 }
1049 EXPECT_GL_NO_ERROR();
1050
1051 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1052 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1053 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1054 face++)
1055 {
1056 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1057 kInputValues[1]);
1058 }
1059 EXPECT_GL_NO_ERROR();
1060
1061 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1062 glUseProgram(program.get());
1063
1064 glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1065 EXPECT_GL_NO_ERROR();
1066 glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1067 EXPECT_GL_NO_ERROR();
1068 glDispatchCompute(1, 1, 1);
1069 EXPECT_GL_NO_ERROR();
1070
1071 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1072 glUseProgram(0);
1073 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1074
1075 for (GLenum face = 0; face < 6; face++)
1076 {
1077 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1078 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1079 EXPECT_GL_NO_ERROR();
1080 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1081 EXPECT_GL_NO_ERROR();
1082
1083 if (face == 4)
1084 {
1085 for (int i = 0; i < kResultSize; i++)
1086 {
1087 EXPECT_EQ(expectedValue_1, outputValues[i]);
1088 }
1089 }
1090 else
1091 {
1092 for (int i = 0; i < kResultSize; i++)
1093 {
1094 EXPECT_EQ(expectedValue_2, outputValues[i]);
1095 }
1096 }
1097 }
1098}
1099
Jiawei Shao6ae51612018-02-23 14:03:25 +08001100// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
1101// program which has not been linked successfully or which does not contain objects to form a
1102// compute shader.
1103TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
1104{
1105 const std::string vsSource =
1106 R"(#version 310 es
1107 void main()
1108 {
1109 })";
1110
1111 const std::string fsSource =
1112 R"(#version 310 es
1113 void main()
1114 {
1115 })";
1116
1117 GLint workGroupSize[3];
1118
1119 ANGLE_GL_PROGRAM(graphicsProgram, vsSource, fsSource);
1120 glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1121 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1122
1123 GLuint computeProgram = glCreateProgram();
1124 GLShader computeShader(GL_COMPUTE_SHADER);
1125 glAttachShader(computeProgram, computeShader);
1126 glLinkProgram(computeProgram);
1127 glDetachShader(computeProgram, computeShader);
1128
1129 GLint linkStatus;
1130 glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
1131 ASSERT_GL_FALSE(linkStatus);
1132
1133 glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1134 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1135
1136 glDeleteProgram(computeProgram);
1137
1138 ASSERT_GL_NO_ERROR();
1139}
1140
Xinghua Cao47335852018-02-12 15:41:55 +08001141// Use groupMemoryBarrier and barrier to sync reads/writes order and the execution
1142// order of multiple shader invocations in compute shader.
1143TEST_P(ComputeShaderTest, groupMemoryBarrierAndBarrierTest)
1144{
1145 // TODO(xinghua.cao@intel.com): Figure out why we get this error message
1146 // that shader uses features not recognized by this D3D version.
1147 ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D11());
1148
1149 GLTexture texture;
1150 GLFramebuffer framebuffer;
1151
1152 // Each invocation first stores a single value in an image, then each invocation sums up
1153 // all the values in the image and stores the sum in the image. groupMemoryBarrier is
1154 // used to order reads/writes to variables stored in memory accessible to other shader
1155 // invocations, and barrier is used to control the relative execution order of multiple
1156 // shader invocations used to process a local work group.
1157 const std::string csSource =
1158 R"(#version 310 es
1159 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
1160 layout(r32i, binding = 0) uniform highp iimage2D image;
1161 void main()
1162 {
1163 uint x = gl_LocalInvocationID.x;
1164 uint y = gl_LocalInvocationID.y;
1165 imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));
1166 groupMemoryBarrier();
1167 barrier();
1168 int sum = 0;
1169 for (int i = 0; i < 2; i++)
1170 {
1171 for(int j = 0; j < 2; j++)
1172 {
1173 sum += imageLoad(image, ivec2(i, j)).x;
1174 }
1175 }
1176 groupMemoryBarrier();
1177 barrier();
1178 imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));
1179 })";
1180
1181 constexpr int kWidth = 2, kHeight = 2;
1182 glBindTexture(GL_TEXTURE_2D, texture);
1183 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);
1184 EXPECT_GL_NO_ERROR();
1185
1186 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1187 glUseProgram(program.get());
1188
1189 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
1190 EXPECT_GL_NO_ERROR();
1191
1192 glDispatchCompute(1, 1, 1);
1193 EXPECT_GL_NO_ERROR();
1194
1195 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1196 GLuint outputValues[kWidth * kHeight];
1197 constexpr GLuint kExpectedValue = 4;
1198 glUseProgram(0);
1199 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1200
1201 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1202 EXPECT_GL_NO_ERROR();
1203 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);
1204 EXPECT_GL_NO_ERROR();
1205
1206 for (int i = 0; i < kWidth * kHeight; i++)
1207 {
1208 EXPECT_EQ(kExpectedValue, outputValues[i]);
1209 }
1210}
1211
Martin Radev4c4c8e72016-08-04 12:25:34 +03001212// Check that it is not possible to create a compute shader when the context does not support ES
1213// 3.10
1214TEST_P(ComputeShaderTestES3, NotSupported)
1215{
1216 GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
1217 EXPECT_EQ(0u, computeShaderHandle);
1218 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1219}
1220
Xinghua Caob1239382016-12-13 15:07:05 +08001221ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
Martin Radev4c4c8e72016-08-04 12:25:34 +03001222ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
1223
1224} // namespace