blob: d86fff18c8c80fb7167c90c55eb1f70a112f3c78 [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
353 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
354 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());
365 int width = 4, height = 2;
366 GLuint inputValues[] = {200, 200, 200, 200, 200, 200, 200, 200};
367
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
386 glDispatchCompute(2, 1, 1);
387 EXPECT_GL_NO_ERROR();
388
389 glUseProgram(0);
390 GLuint outputValues[2][8];
391 GLuint expectedValue = 100;
392 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
393
394 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
395 0);
396 EXPECT_GL_NO_ERROR();
397 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
398 EXPECT_GL_NO_ERROR();
399
400 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
401 0);
402 EXPECT_GL_NO_ERROR();
403 glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
404 EXPECT_GL_NO_ERROR();
405
406 for (int i = 0; i < width * height; i++)
407 {
408 EXPECT_EQ(expectedValue, outputValues[0][i]);
409 EXPECT_EQ(expectedValue, outputValues[1][i]);
410 }
411}
412
Xinghua Cao0328b572017-06-26 15:51:36 +0800413// When declare a image array without a binding qualifier, all elements are bound to unit zero.
414TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
415{
416 ANGLE_SKIP_TEST_IF(IsD3D11());
417
418 // TODO(xinghua.cao@intel.com): On AMD desktop OpenGL, bind two image variables to unit 0,
419 // only one variable is valid.
Corentin Wallez2bde9192017-07-28 14:15:01 -0400420 ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
Xinghua Cao0328b572017-06-26 15:51:36 +0800421
422 GLTexture mTexture;
423 GLFramebuffer mFramebuffer;
424 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800425 R"(#version 310 es
426 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
427 layout(r32ui) writeonly uniform highp uimage2D uImage[2];
428 void main()
429 {
430 imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
431 imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
432 })";
Xinghua Cao0328b572017-06-26 15:51:36 +0800433
434 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
435 glUseProgram(program.get());
436 constexpr int kTextureWidth = 4, kTextureHeight = 2;
437 GLuint inputValues[] = {200, 200, 200, 200, 200, 200, 200, 200};
438
439 glBindTexture(GL_TEXTURE_2D, mTexture);
440 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
441 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
442 GL_UNSIGNED_INT, inputValues);
443 EXPECT_GL_NO_ERROR();
444
445 glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
446 glDispatchCompute(1, 1, 1);
447 EXPECT_GL_NO_ERROR();
448
449 glUseProgram(0);
450 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
451
452 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
453 GLuint outputValues[8];
454 glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
455 outputValues);
456 EXPECT_GL_NO_ERROR();
457
458 GLuint expectedValue = 100;
459 for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
460 {
461 EXPECT_EQ(expectedValue, outputValues[i]);
462 }
463}
464
Xinghua Cao711b7a12017-10-09 13:38:12 +0800465// imageLoad functions
466TEST_P(ComputeShaderTest, ImageLoad)
467{
468 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200469 R"(#version 310 es
470 layout(local_size_x=8) in;
471 layout(rgba8) uniform highp readonly image2D mImage2DInput;
472 layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
473 layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
474 layout(r32i) uniform highp writeonly iimage2D imageOut;
475 void main()
476 {
477 vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
478 ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
479 uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
480 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
481 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800482
483 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
484 EXPECT_GL_NO_ERROR();
485}
486
487// imageStore functions
488TEST_P(ComputeShaderTest, ImageStore)
489{
490 const std::string csSource =
Yunchao Hecddcb592017-11-13 15:27:35 +0800491 R"(#version 310 es
492 layout(local_size_x=8) in;
493 layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
494 layout(r32f) uniform highp writeonly image3D mImage3DOutput;
495 layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
496 void main()
497 {
498 imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
499 imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
500 imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
501 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800502
503 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
504 EXPECT_GL_NO_ERROR();
505}
506
507// imageSize functions
508TEST_P(ComputeShaderTest, ImageSize)
509{
510 const std::string csSource =
Olli Etuaho7caa80e2017-11-14 15:03:14 +0200511 R"(#version 310 es
512 layout(local_size_x=8) in;
513 layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
514 layout(r32i) uniform highp readonly iimage2D mImage2DInput;
515 layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
516 layout(r32i) uniform highp writeonly iimage2D imageOut;
517 void main()
518 {
519 ivec2 sizeCube = imageSize(mImageCubeInput);
520 ivec2 size2D = imageSize(mImage2DInput);
521 ivec3 size2DArray = imageSize(mImage2DArrayInput);
522 imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
523 })";
Xinghua Cao711b7a12017-10-09 13:38:12 +0800524
525 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
526 EXPECT_GL_NO_ERROR();
527}
528
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800529// Use image uniform to read and write Texture2D in compute shader, and verify the contents.
Xinghua Cao26143fd2017-11-01 18:19:05 +0800530TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
531{
532 GLTexture texture[2];
533 GLFramebuffer framebuffer;
534 const std::string csSource =
535 R"(#version 310 es
536 layout(local_size_x=4, local_size_y=2, local_size_z=1) in;
537 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
538 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
539 void main()
540 {
541 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
542 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
543 })";
544
545 constexpr int kWidth = 4, kHeight = 2;
546 constexpr GLuint kInputValues[2][8] = {{200, 200, 200, 200, 200, 200, 200, 200},
547 {100, 100, 100, 100, 100, 100, 100, 100}};
548
549 glBindTexture(GL_TEXTURE_2D, texture[0]);
550 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
551 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
552 kInputValues[0]);
553 EXPECT_GL_NO_ERROR();
554
555 glBindTexture(GL_TEXTURE_2D, texture[1]);
556 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
557 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
558 kInputValues[1]);
559 EXPECT_GL_NO_ERROR();
560
561 glUseProgram(0);
562 GLuint outputValues[8];
563 constexpr GLuint expectedValue_1 = 200;
564 constexpr GLuint expectedValue_2 = 100;
565 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
566
567 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
568 EXPECT_GL_NO_ERROR();
569 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
570
571 for (int i = 0; i < kWidth * kHeight; i++)
572 {
573 EXPECT_EQ(expectedValue_1, outputValues[i]);
574 }
575
576 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
577 EXPECT_GL_NO_ERROR();
578 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
579
580 for (int i = 0; i < kWidth * kHeight; i++)
581 {
582 EXPECT_EQ(expectedValue_2, outputValues[i]);
583 }
584
585 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
586 glUseProgram(program.get());
587
588 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
589 EXPECT_GL_NO_ERROR();
590
591 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
592 EXPECT_GL_NO_ERROR();
593
594 glDispatchCompute(1, 1, 1);
595 EXPECT_GL_NO_ERROR();
596
597 glUseProgram(0);
598 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
599
600 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
601 EXPECT_GL_NO_ERROR();
602 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
603 EXPECT_GL_NO_ERROR();
604
605 for (int i = 0; i < kWidth * kHeight; i++)
606 {
607 EXPECT_EQ(expectedValue_1, outputValues[i]);
608 }
609}
610
Xinghua Cao08a8ec82017-12-27 13:31:11 +0800611// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
612TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
613{
614 GLTexture texture[2];
615 GLFramebuffer framebuffer;
616 const std::string csSource =
617 R"(#version 310 es
618 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
619 layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
620 layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
621 void main()
622 {
623 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
624 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
625 })";
626
627 constexpr int kWidth = 2, kHeight = 2, kDepth = 2;
628 constexpr GLuint kInputValues[2][8] = {{200, 200, 200, 200, 200, 200, 200, 200},
629 {100, 100, 100, 100, 100, 100, 100, 100}};
630
631 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
632 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
633 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
634 GL_UNSIGNED_INT, kInputValues[0]);
635 EXPECT_GL_NO_ERROR();
636
637 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
638 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
639 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
640 GL_UNSIGNED_INT, kInputValues[1]);
641 EXPECT_GL_NO_ERROR();
642
643 glUseProgram(0);
644 GLuint outputValues[4];
645 constexpr GLuint expectedValue_1 = 200;
646 constexpr GLuint expectedValue_2 = 100;
647 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
648
649 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[0], 0, 0);
650 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[0], 0, 1);
651 EXPECT_GL_NO_ERROR();
652
653 glReadBuffer(GL_COLOR_ATTACHMENT0);
654 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
655 for (int i = 0; i < kWidth * kHeight; i++)
656 {
657 EXPECT_EQ(expectedValue_1, outputValues[i]);
658 }
659
660 glReadBuffer(GL_COLOR_ATTACHMENT1);
661 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
662
663 for (int i = 0; i < kWidth * kHeight; i++)
664 {
665 EXPECT_EQ(expectedValue_1, outputValues[i]);
666 }
667
668 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
669 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
670 EXPECT_GL_NO_ERROR();
671
672 glReadBuffer(GL_COLOR_ATTACHMENT0);
673 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
674 for (int i = 0; i < kWidth * kHeight; i++)
675 {
676 EXPECT_EQ(expectedValue_2, outputValues[i]);
677 }
678
679 glReadBuffer(GL_COLOR_ATTACHMENT1);
680 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
681 for (int i = 0; i < kWidth * kHeight; i++)
682 {
683 EXPECT_EQ(expectedValue_2, outputValues[i]);
684 }
685
686 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
687 glUseProgram(program.get());
688
689 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
690 EXPECT_GL_NO_ERROR();
691
692 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
693 EXPECT_GL_NO_ERROR();
694
695 glDispatchCompute(1, 1, 1);
696 EXPECT_GL_NO_ERROR();
697
698 glUseProgram(0);
699 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
700
701 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
702 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
703 EXPECT_GL_NO_ERROR();
704 glReadBuffer(GL_COLOR_ATTACHMENT0);
705 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
706 EXPECT_GL_NO_ERROR();
707 for (int i = 0; i < kWidth * kHeight; i++)
708 {
709 EXPECT_EQ(expectedValue_1, outputValues[i]);
710 }
711 glReadBuffer(GL_COLOR_ATTACHMENT1);
712 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
713 EXPECT_GL_NO_ERROR();
714 for (int i = 0; i < kWidth * kHeight; i++)
715 {
716 EXPECT_EQ(expectedValue_1, outputValues[i]);
717 }
718}
719
720// Use image uniform to read and write Texture3D in compute shader, and verify the contents.
721TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
722{
723 GLTexture texture[2];
724 GLFramebuffer framebuffer;
725 const std::string csSource =
726 R"(#version 310 es
727 layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
728 layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
729 layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
730 void main()
731 {
732 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
733 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
734 })";
735
736 constexpr int kWidth = 2, kHeight = 2, kDepth = 2;
737 constexpr GLuint kInputValues[2][8] = {{200, 200, 200, 200, 200, 200, 200, 200},
738 {100, 100, 100, 100, 100, 100, 100, 100}};
739
740 glBindTexture(GL_TEXTURE_3D, texture[0]);
741 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
742 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
743 GL_UNSIGNED_INT, kInputValues[0]);
744 EXPECT_GL_NO_ERROR();
745
746 glBindTexture(GL_TEXTURE_3D, texture[1]);
747 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
748 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
749 GL_UNSIGNED_INT, kInputValues[1]);
750 EXPECT_GL_NO_ERROR();
751
752 glUseProgram(0);
753 GLuint outputValues[4];
754 constexpr GLuint expectedValue_1 = 200;
755 constexpr GLuint expectedValue_2 = 100;
756 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
757
758 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[0], 0, 0);
759 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[0], 0, 1);
760 EXPECT_GL_NO_ERROR();
761
762 glReadBuffer(GL_COLOR_ATTACHMENT0);
763 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
764 for (int i = 0; i < kWidth * kHeight; i++)
765 {
766 EXPECT_EQ(expectedValue_1, outputValues[i]);
767 }
768
769 glReadBuffer(GL_COLOR_ATTACHMENT1);
770 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
771
772 for (int i = 0; i < kWidth * kHeight; i++)
773 {
774 EXPECT_EQ(expectedValue_1, outputValues[i]);
775 }
776
777 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
778 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
779 EXPECT_GL_NO_ERROR();
780
781 glReadBuffer(GL_COLOR_ATTACHMENT0);
782 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
783 for (int i = 0; i < kWidth * kHeight; i++)
784 {
785 EXPECT_EQ(expectedValue_2, outputValues[i]);
786 }
787
788 glReadBuffer(GL_COLOR_ATTACHMENT1);
789 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
790 for (int i = 0; i < kWidth * kHeight; i++)
791 {
792 EXPECT_EQ(expectedValue_2, outputValues[i]);
793 }
794
795 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
796 glUseProgram(program.get());
797
798 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
799 EXPECT_GL_NO_ERROR();
800
801 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
802 EXPECT_GL_NO_ERROR();
803
804 glDispatchCompute(1, 1, 1);
805 EXPECT_GL_NO_ERROR();
806
807 glUseProgram(0);
808 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
809
810 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
811 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
812 EXPECT_GL_NO_ERROR();
813 glReadBuffer(GL_COLOR_ATTACHMENT0);
814 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
815 EXPECT_GL_NO_ERROR();
816 for (int i = 0; i < kWidth * kHeight; i++)
817 {
818 EXPECT_EQ(expectedValue_1, outputValues[i]);
819 }
820 glReadBuffer(GL_COLOR_ATTACHMENT1);
821 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
822 EXPECT_GL_NO_ERROR();
823 for (int i = 0; i < kWidth * kHeight; i++)
824 {
825 EXPECT_EQ(expectedValue_1, outputValues[i]);
826 }
827}
828
829// Use image uniform to read and write TextureCube in compute shader, and verify the contents.
830TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
831{
832 GLTexture texture[2];
833 GLFramebuffer framebuffer;
834 const std::string csSource =
835 R"(#version 310 es
836 layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
837 layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
838 layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
839 void main()
840 {
841 for (int i = 0; i < 6; i++)
842 {
843 uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
844 imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
845 }
846 })";
847
848 constexpr int kWidth = 2, kHeight = 2;
849 constexpr GLuint kInputValues[2][4] = {{200, 200, 200, 200}, {100, 100, 100, 100}};
850
851 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
852 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
853 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
854 face++)
855 {
856 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
857 kInputValues[0]);
858 }
859 EXPECT_GL_NO_ERROR();
860
861 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
862 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
863 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
864 face++)
865 {
866 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
867 kInputValues[1]);
868 }
869 EXPECT_GL_NO_ERROR();
870
871 glUseProgram(0);
872 GLuint outputValues[4];
873 constexpr GLuint expectedValue_1 = 200;
874 constexpr GLuint expectedValue_2 = 100;
875 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
876 for (GLenum face = 0; face < 6; face++)
877 {
878 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
879 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[0], 0);
880 EXPECT_GL_NO_ERROR();
881 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
882 EXPECT_GL_NO_ERROR();
883
884 for (int i = 0; i < kWidth * kHeight; i++)
885 {
886 EXPECT_EQ(expectedValue_1, outputValues[i]);
887 }
888
889 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
890 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
891 EXPECT_GL_NO_ERROR();
892 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
893 EXPECT_GL_NO_ERROR();
894
895 for (int i = 0; i < kWidth * kHeight; i++)
896 {
897 EXPECT_EQ(expectedValue_2, outputValues[i]);
898 }
899 }
900
901 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
902 glUseProgram(program.get());
903
904 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
905 EXPECT_GL_NO_ERROR();
906
907 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
908 EXPECT_GL_NO_ERROR();
909
910 glDispatchCompute(1, 1, 1);
911 EXPECT_GL_NO_ERROR();
912
913 glUseProgram(0);
914 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
915
916 for (GLenum face = 0; face < 6; face++)
917 {
918 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
919 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
920 EXPECT_GL_NO_ERROR();
921 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
922 EXPECT_GL_NO_ERROR();
923
924 for (int i = 0; i < kWidth * kHeight; i++)
925 {
926 EXPECT_EQ(expectedValue_1, outputValues[i]);
927 }
928 }
929}
930
Xinghua Caob745f172018-01-09 16:10:02 +0800931// Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
932// contents.
933TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
934{
935 ANGLE_SKIP_TEST_IF(IsD3D11());
936
937 GLTexture texture[2];
938 GLFramebuffer framebuffer;
939 const std::string csSource =
940 R"(#version 310 es
941 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
942 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
943 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
944 void main()
945 {
946 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
947 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
948 })";
949
950 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
951 constexpr int kResultSize = kWidth * kHeight;
952 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
953 constexpr GLuint expectedValue_1 = 200;
954 constexpr GLuint expectedValue_2 = 100;
955 GLuint outputValues[kResultSize];
956
957 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
958 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
959 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
960 GL_UNSIGNED_INT, kInputValues[0]);
961 EXPECT_GL_NO_ERROR();
962
963 glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
964 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
965 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
966 GL_UNSIGNED_INT, kInputValues[1]);
967 EXPECT_GL_NO_ERROR();
968
969 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
970 glUseProgram(program.get());
971
972 glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
973 EXPECT_GL_NO_ERROR();
974 glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
975 EXPECT_GL_NO_ERROR();
976 glDispatchCompute(1, 1, 1);
977 EXPECT_GL_NO_ERROR();
978
979 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
980 glUseProgram(0);
981 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
982 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
983 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
984 EXPECT_GL_NO_ERROR();
985 glReadBuffer(GL_COLOR_ATTACHMENT0);
986 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
987 EXPECT_GL_NO_ERROR();
988 for (int i = 0; i < kResultSize; i++)
989 {
990 EXPECT_EQ(expectedValue_2, outputValues[i]);
991 }
992 glReadBuffer(GL_COLOR_ATTACHMENT1);
993 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
994 EXPECT_GL_NO_ERROR();
995 for (int i = 0; i < kResultSize; i++)
996 {
997 EXPECT_EQ(expectedValue_1, outputValues[i]);
998 }
999}
1000
1001// Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
1002// contents.
1003TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
1004{
1005 ANGLE_SKIP_TEST_IF(IsD3D11());
1006 GLTexture texture[2];
1007 GLFramebuffer framebuffer;
1008 const std::string csSource =
1009 R"(#version 310 es
1010 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1011 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1012 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1013 void main()
1014 {
1015 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1016 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1017 })";
1018
1019 constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1020 constexpr int kResultSize = kWidth * kHeight;
1021 constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1022 constexpr GLuint expectedValue_1 = 150;
1023 constexpr GLuint expectedValue_2 = 50;
1024 GLuint outputValues[kResultSize];
1025
1026 glBindTexture(GL_TEXTURE_3D, texture[0]);
1027 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1028 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1029 GL_UNSIGNED_INT, kInputValues[0]);
1030 EXPECT_GL_NO_ERROR();
1031
1032 glBindTexture(GL_TEXTURE_3D, texture[1]);
1033 glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1034 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1035 GL_UNSIGNED_INT, kInputValues[1]);
1036 EXPECT_GL_NO_ERROR();
1037
1038 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1039 glUseProgram(program.get());
1040
1041 glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1042 EXPECT_GL_NO_ERROR();
1043 glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1044 EXPECT_GL_NO_ERROR();
1045 glDispatchCompute(1, 1, 1);
1046 EXPECT_GL_NO_ERROR();
1047
1048 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1049 glUseProgram(0);
1050 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1051 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1052 glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1053 EXPECT_GL_NO_ERROR();
1054 glReadBuffer(GL_COLOR_ATTACHMENT0);
1055 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1056 EXPECT_GL_NO_ERROR();
1057 for (int i = 0; i < kResultSize; i++)
1058 {
1059 EXPECT_EQ(expectedValue_1, outputValues[i]);
1060 }
1061 glReadBuffer(GL_COLOR_ATTACHMENT1);
1062 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1063 EXPECT_GL_NO_ERROR();
1064 for (int i = 0; i < kResultSize; i++)
1065 {
1066 EXPECT_EQ(expectedValue_2, outputValues[i]);
1067 }
1068}
1069
1070// Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1071// contents.
1072TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1073{
1074 ANGLE_SKIP_TEST_IF(IsD3D11());
1075
1076 GLTexture texture[2];
1077 GLFramebuffer framebuffer;
1078 const std::string csSource =
1079 R"(#version 310 es
1080 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1081 layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1082 layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1083 void main()
1084 {
1085 uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1086 imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1087 })";
1088
1089 constexpr int kWidth = 1, kHeight = 1;
1090 constexpr int kResultSize = kWidth * kHeight;
1091 constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1092 constexpr GLuint expectedValue_1 = 200;
1093 constexpr GLuint expectedValue_2 = 100;
1094 GLuint outputValues[kResultSize];
1095
1096 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1097 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1098 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1099 face++)
1100 {
1101 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1102 kInputValues[0]);
1103 }
1104 EXPECT_GL_NO_ERROR();
1105
1106 glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1107 glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1108 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1109 face++)
1110 {
1111 glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1112 kInputValues[1]);
1113 }
1114 EXPECT_GL_NO_ERROR();
1115
1116 ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1117 glUseProgram(program.get());
1118
1119 glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1120 EXPECT_GL_NO_ERROR();
1121 glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1122 EXPECT_GL_NO_ERROR();
1123 glDispatchCompute(1, 1, 1);
1124 EXPECT_GL_NO_ERROR();
1125
1126 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1127 glUseProgram(0);
1128 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1129
1130 for (GLenum face = 0; face < 6; face++)
1131 {
1132 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1133 GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1134 EXPECT_GL_NO_ERROR();
1135 glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1136 EXPECT_GL_NO_ERROR();
1137
1138 if (face == 4)
1139 {
1140 for (int i = 0; i < kResultSize; i++)
1141 {
1142 EXPECT_EQ(expectedValue_1, outputValues[i]);
1143 }
1144 }
1145 else
1146 {
1147 for (int i = 0; i < kResultSize; i++)
1148 {
1149 EXPECT_EQ(expectedValue_2, outputValues[i]);
1150 }
1151 }
1152 }
1153}
1154
Jiawei Shao6ae51612018-02-23 14:03:25 +08001155// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
1156// program which has not been linked successfully or which does not contain objects to form a
1157// compute shader.
1158TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
1159{
1160 const std::string vsSource =
1161 R"(#version 310 es
1162 void main()
1163 {
1164 })";
1165
1166 const std::string fsSource =
1167 R"(#version 310 es
1168 void main()
1169 {
1170 })";
1171
1172 GLint workGroupSize[3];
1173
1174 ANGLE_GL_PROGRAM(graphicsProgram, vsSource, fsSource);
1175 glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1176 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1177
1178 GLuint computeProgram = glCreateProgram();
1179 GLShader computeShader(GL_COMPUTE_SHADER);
1180 glAttachShader(computeProgram, computeShader);
1181 glLinkProgram(computeProgram);
1182 glDetachShader(computeProgram, computeShader);
1183
1184 GLint linkStatus;
1185 glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
1186 ASSERT_GL_FALSE(linkStatus);
1187
1188 glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1189 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1190
1191 glDeleteProgram(computeProgram);
1192
1193 ASSERT_GL_NO_ERROR();
1194}
1195
Martin Radev4c4c8e72016-08-04 12:25:34 +03001196// Check that it is not possible to create a compute shader when the context does not support ES
1197// 3.10
1198TEST_P(ComputeShaderTestES3, NotSupported)
1199{
1200 GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
1201 EXPECT_EQ(0u, computeShaderHandle);
1202 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1203}
1204
Xinghua Caob1239382016-12-13 15:07:05 +08001205ANGLE_INSTANTIATE_TEST(ComputeShaderTest, ES31_OPENGL(), ES31_OPENGLES(), ES31_D3D11());
Martin Radev4c4c8e72016-08-04 12:25:34 +03001206ANGLE_INSTANTIATE_TEST(ComputeShaderTestES3, ES3_OPENGL(), ES3_OPENGLES());
1207
1208} // namespace