Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/gl_tests/ComputeShaderTest.cpp
1693 views
1
//
2
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3
// Use of this source code is governed by a BSD-style license that can be
4
// found in the LICENSE file.
5
//
6
// ComputeShaderTest:
7
// Compute shader specific tests.
8
9
#include <vector>
10
#include "test_utils/ANGLETest.h"
11
#include "test_utils/gl_raii.h"
12
13
using namespace angle;
14
15
namespace
16
{
17
18
class ComputeShaderTest : public ANGLETest
19
{
20
protected:
21
ComputeShaderTest() {}
22
23
void createMockOutputImage(GLuint texture, GLenum internalFormat, GLint width, GLint height)
24
{
25
glBindTexture(GL_TEXTURE_2D, texture);
26
glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, width, height);
27
EXPECT_GL_NO_ERROR();
28
29
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);
30
EXPECT_GL_NO_ERROR();
31
}
32
33
template <class T, GLint kWidth, GLint kHeight>
34
void runSharedMemoryTest(const char *kCS,
35
GLenum internalFormat,
36
GLenum format,
37
const std::array<T, kWidth * kHeight> &inputData,
38
const std::array<T, kWidth * kHeight> &expectedValues)
39
{
40
GLTexture texture[2];
41
GLFramebuffer framebuffer;
42
43
glBindTexture(GL_TEXTURE_2D, texture[0]);
44
glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);
45
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format,
46
inputData.data());
47
EXPECT_GL_NO_ERROR();
48
49
constexpr T initData[kWidth * kHeight] = {};
50
glBindTexture(GL_TEXTURE_2D, texture[1]);
51
glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, kWidth, kHeight);
52
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, format, initData);
53
EXPECT_GL_NO_ERROR();
54
55
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
56
glUseProgram(program.get());
57
58
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalFormat);
59
EXPECT_GL_NO_ERROR();
60
61
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalFormat);
62
EXPECT_GL_NO_ERROR();
63
64
glDispatchCompute(1, 1, 1);
65
EXPECT_GL_NO_ERROR();
66
67
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
68
69
T outputValues[kWidth * kHeight] = {};
70
glUseProgram(0);
71
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
72
73
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1],
74
0);
75
EXPECT_GL_NO_ERROR();
76
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, format, outputValues);
77
EXPECT_GL_NO_ERROR();
78
79
for (int i = 0; i < kWidth * kHeight; i++)
80
{
81
EXPECT_EQ(expectedValues[i], outputValues[i]);
82
}
83
}
84
};
85
86
class ComputeShaderTestES3 : public ANGLETest
87
{
88
protected:
89
ComputeShaderTestES3() {}
90
};
91
92
class WebGL2ComputeTest : public ComputeShaderTest
93
{
94
protected:
95
WebGL2ComputeTest() { setWebGLCompatibilityEnabled(true); }
96
};
97
98
// link a simple compute program. It should be successful.
99
TEST_P(ComputeShaderTest, LinkComputeProgram)
100
{
101
constexpr char kCS[] = R"(#version 310 es
102
layout(local_size_x=1) in;
103
void main()
104
{
105
})";
106
107
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
108
109
EXPECT_GL_NO_ERROR();
110
}
111
112
// Link a simple compute program. Then detach the shader and dispatch compute.
113
// It should be successful.
114
TEST_P(ComputeShaderTest, DetachShaderAfterLinkSuccess)
115
{
116
constexpr char kCS[] = R"(#version 310 es
117
layout(local_size_x=1) in;
118
void main()
119
{
120
})";
121
122
GLuint program = glCreateProgram();
123
124
GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
125
EXPECT_NE(0u, cs);
126
127
glAttachShader(program, cs);
128
glDeleteShader(cs);
129
130
glLinkProgram(program);
131
GLint linkStatus;
132
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
133
EXPECT_GL_TRUE(linkStatus);
134
135
glDetachShader(program, cs);
136
EXPECT_GL_NO_ERROR();
137
138
glUseProgram(program);
139
glDispatchCompute(8, 4, 2);
140
EXPECT_GL_NO_ERROR();
141
}
142
143
// link a simple compute program. There is no local size and linking should fail.
144
TEST_P(ComputeShaderTest, LinkComputeProgramNoLocalSizeLinkError)
145
{
146
constexpr char kCS[] = R"(#version 310 es
147
void main()
148
{
149
})";
150
151
GLuint program = CompileComputeProgram(kCS, false);
152
EXPECT_EQ(0u, program);
153
154
glDeleteProgram(program);
155
156
EXPECT_GL_NO_ERROR();
157
}
158
159
// link a simple compute program.
160
// make sure that uniforms and uniform samplers get recorded
161
TEST_P(ComputeShaderTest, LinkComputeProgramWithUniforms)
162
{
163
constexpr char kCS[] = R"(#version 310 es
164
precision mediump sampler2D;
165
layout(local_size_x=1) in;
166
uniform int myUniformInt;
167
uniform sampler2D myUniformSampler;
168
layout(rgba32i) uniform highp writeonly iimage2D imageOut;
169
void main()
170
{
171
int q = myUniformInt;
172
vec4 v = textureLod(myUniformSampler, vec2(0.0), 0.0);
173
imageStore(imageOut, ivec2(0), ivec4(v) * q);
174
})";
175
176
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
177
178
GLint uniformLoc = glGetUniformLocation(program.get(), "myUniformInt");
179
EXPECT_NE(-1, uniformLoc);
180
181
uniformLoc = glGetUniformLocation(program.get(), "myUniformSampler");
182
EXPECT_NE(-1, uniformLoc);
183
184
EXPECT_GL_NO_ERROR();
185
}
186
187
// Attach both compute and non-compute shaders. A link time error should occur.
188
// OpenGL ES 3.10, 7.3 Program Objects
189
TEST_P(ComputeShaderTest, AttachMultipleShaders)
190
{
191
constexpr char kCS[] = R"(#version 310 es
192
layout(local_size_x=1) in;
193
void main()
194
{
195
})";
196
197
constexpr char kVS[] = R"(#version 310 es
198
void main()
199
{
200
})";
201
202
constexpr char kFS[] = R"(#version 310 es
203
void main()
204
{
205
})";
206
207
GLuint program = glCreateProgram();
208
209
GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
210
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
211
GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
212
213
EXPECT_NE(0u, vs);
214
EXPECT_NE(0u, fs);
215
EXPECT_NE(0u, cs);
216
217
glAttachShader(program, vs);
218
glDeleteShader(vs);
219
220
glAttachShader(program, fs);
221
glDeleteShader(fs);
222
223
glAttachShader(program, cs);
224
glDeleteShader(cs);
225
226
glLinkProgram(program);
227
228
GLint linkStatus;
229
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
230
231
EXPECT_GL_FALSE(linkStatus);
232
233
EXPECT_GL_NO_ERROR();
234
}
235
236
// Attach a vertex, fragment and compute shader.
237
// Query for the number of attached shaders and check the count.
238
TEST_P(ComputeShaderTest, AttachmentCount)
239
{
240
constexpr char kCS[] = R"(#version 310 es
241
layout(local_size_x=1) in;
242
void main()
243
{
244
})";
245
246
constexpr char kVS[] = R"(#version 310 es
247
void main()
248
{
249
})";
250
251
constexpr char kFS[] = R"(#version 310 es
252
void main()
253
{
254
})";
255
256
GLuint program = glCreateProgram();
257
258
GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
259
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
260
GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
261
262
EXPECT_NE(0u, vs);
263
EXPECT_NE(0u, fs);
264
EXPECT_NE(0u, cs);
265
266
glAttachShader(program, vs);
267
glDeleteShader(vs);
268
269
glAttachShader(program, fs);
270
glDeleteShader(fs);
271
272
glAttachShader(program, cs);
273
glDeleteShader(cs);
274
275
GLint numAttachedShaders;
276
glGetProgramiv(program, GL_ATTACHED_SHADERS, &numAttachedShaders);
277
278
EXPECT_EQ(3, numAttachedShaders);
279
280
glDeleteProgram(program);
281
282
EXPECT_GL_NO_ERROR();
283
}
284
285
// Attach a compute shader and link, but start rendering.
286
TEST_P(ComputeShaderTest, StartRenderingWithComputeProgram)
287
{
288
constexpr char kCS[] = R"(#version 310 es
289
layout(local_size_x=1) in;
290
void main()
291
{
292
})";
293
294
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
295
EXPECT_GL_NO_ERROR();
296
297
glUseProgram(program);
298
glDrawArrays(GL_POINTS, 0, 2);
299
EXPECT_GL_NO_ERROR();
300
}
301
302
// Attach a vertex and fragment shader and link, but dispatch compute.
303
TEST_P(ComputeShaderTest, DispatchComputeWithRenderingProgram)
304
{
305
constexpr char kVS[] = R"(#version 310 es
306
void main() {})";
307
308
constexpr char kFS[] = R"(#version 310 es
309
void main() {})";
310
311
GLuint program = glCreateProgram();
312
313
GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
314
GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
315
316
EXPECT_NE(0u, vs);
317
EXPECT_NE(0u, fs);
318
319
glAttachShader(program, vs);
320
glDeleteShader(vs);
321
322
glAttachShader(program, fs);
323
glDeleteShader(fs);
324
325
glLinkProgram(program);
326
327
GLint linkStatus;
328
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
329
EXPECT_GL_TRUE(linkStatus);
330
331
EXPECT_GL_NO_ERROR();
332
333
glUseProgram(program);
334
glDispatchCompute(8, 4, 2);
335
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
336
}
337
338
// Access all compute shader special variables.
339
TEST_P(ComputeShaderTest, AccessAllSpecialVariables)
340
{
341
constexpr char kCS[] = R"(#version 310 es
342
layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
343
layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
344
void main()
345
{
346
uvec3 temp1 = gl_NumWorkGroups;
347
uvec3 temp2 = gl_WorkGroupSize;
348
uvec3 temp3 = gl_WorkGroupID;
349
uvec3 temp4 = gl_LocalInvocationID;
350
uvec3 temp5 = gl_GlobalInvocationID;
351
uint temp6 = gl_LocalInvocationIndex;
352
imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2 + temp3 + temp4 + temp5, temp6));
353
})";
354
355
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
356
}
357
358
// Access part compute shader special variables.
359
TEST_P(ComputeShaderTest, AccessPartSpecialVariables)
360
{
361
constexpr char kCS[] = R"(#version 310 es
362
layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
363
layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
364
void main()
365
{
366
uvec3 temp1 = gl_WorkGroupSize;
367
uvec3 temp2 = gl_WorkGroupID;
368
uint temp3 = gl_LocalInvocationIndex;
369
imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), uvec4(temp1 + temp2, temp3));
370
})";
371
372
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
373
}
374
375
// Use glDispatchCompute to define work group count.
376
TEST_P(ComputeShaderTest, DispatchCompute)
377
{
378
constexpr char kCS[] = R"(#version 310 es
379
layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
380
layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
381
void main()
382
{
383
uvec3 temp = gl_NumWorkGroups;
384
imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));
385
})";
386
387
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
388
389
GLTexture texture;
390
createMockOutputImage(texture, GL_RGBA32UI, 4, 3);
391
392
glUseProgram(program.get());
393
glDispatchCompute(8, 4, 2);
394
EXPECT_GL_NO_ERROR();
395
}
396
397
// Binds a storage buffer to slot 0, then binds a storage image to slot 0, then buffer again.
398
TEST_P(ComputeShaderTest, BufferImageBuffer)
399
{
400
// See http://anglebug.com/3536
401
ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
402
403
constexpr char kCS0[] = R"(#version 310 es
404
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
405
layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
406
void main()
407
{
408
atomicCounterIncrement(ac[0]);
409
atomicCounterDecrement(ac[1]);
410
})";
411
412
ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
413
glUseProgram(program0);
414
415
unsigned int bufferData[3] = {11u, 4u, 4u};
416
GLBuffer atomicCounterBuffer;
417
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
418
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
419
420
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
421
422
glDispatchCompute(1, 1, 1);
423
EXPECT_GL_NO_ERROR();
424
425
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
426
void *mappedBuffer =
427
glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
428
memcpy(bufferData, mappedBuffer, sizeof(bufferData));
429
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
430
431
EXPECT_EQ(11u, bufferData[0]);
432
EXPECT_EQ(5u, bufferData[1]);
433
EXPECT_EQ(3u, bufferData[2]);
434
435
constexpr char kCS1[] = R"(#version 310 es
436
layout(local_size_x=4, local_size_y=3, local_size_z=2) in;
437
layout(rgba32ui) uniform highp writeonly uimage2D imageOut;
438
void main()
439
{
440
uvec3 temp = gl_NumWorkGroups;
441
imageStore(imageOut, ivec2(gl_GlobalInvocationID.xy), uvec4(temp, 0u));
442
})";
443
444
ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
445
446
GLTexture texture;
447
createMockOutputImage(texture, GL_RGBA32UI, 4, 3);
448
449
glUseProgram(program1);
450
glDispatchCompute(8, 4, 2);
451
452
glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
453
glUseProgram(program0);
454
glDispatchCompute(1, 1, 1);
455
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
456
mappedBuffer =
457
glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
458
memcpy(bufferData, mappedBuffer, sizeof(bufferData));
459
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
460
461
EXPECT_EQ(11u, bufferData[0]);
462
EXPECT_EQ(6u, bufferData[1]);
463
EXPECT_EQ(2u, bufferData[2]);
464
465
EXPECT_GL_NO_ERROR();
466
}
467
468
// Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.
469
TEST_P(ComputeShaderTest, ImageAtomicCounterBuffer)
470
{
471
// Flaky hang. http://anglebug.com/3636
472
ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsDesktopOpenGL());
473
474
constexpr char kCS0[] = R"(#version 310 es
475
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
476
layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
477
void main()
478
{
479
imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
480
0, 0));
481
imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
482
0, 0));
483
})";
484
485
ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
486
glUseProgram(program0);
487
int width = 1, height = 1;
488
GLuint inputValues[] = {200};
489
GLTexture mTexture[2];
490
glBindTexture(GL_TEXTURE_2D, mTexture[0]);
491
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
492
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
493
inputValues);
494
495
glBindTexture(GL_TEXTURE_2D, mTexture[1]);
496
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
497
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
498
inputValues);
499
500
glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
501
glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
502
503
glDispatchCompute(1, 1, 1);
504
EXPECT_GL_NO_ERROR();
505
506
constexpr char kCS1[] = R"(#version 310 es
507
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
508
layout(binding = 0, offset = 4) uniform atomic_uint ac[2];
509
void main()
510
{
511
atomicCounterIncrement(ac[0]);
512
atomicCounterDecrement(ac[1]);
513
})";
514
515
ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
516
517
unsigned int bufferData[3] = {11u, 4u, 4u};
518
GLBuffer atomicCounterBuffer;
519
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
520
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
521
522
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
523
524
glUseProgram(program1);
525
glDispatchCompute(1, 1, 1);
526
EXPECT_GL_NO_ERROR();
527
528
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
529
void *mappedBuffer =
530
glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
531
memcpy(bufferData, mappedBuffer, sizeof(bufferData));
532
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
533
534
EXPECT_EQ(11u, bufferData[0]);
535
EXPECT_EQ(5u, bufferData[1]);
536
EXPECT_EQ(3u, bufferData[2]);
537
538
EXPECT_GL_NO_ERROR();
539
}
540
541
// Test that binds UAV with type image to slot 0, then binds UAV with type buffer to slot 0.
542
TEST_P(ComputeShaderTest, ImageShaderStorageBuffer)
543
{
544
constexpr char kCS0[] = R"(#version 310 es
545
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
546
layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
547
void main()
548
{
549
imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
550
0, 0));
551
imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
552
0, 0));
553
})";
554
555
ANGLE_GL_COMPUTE_PROGRAM(program0, kCS0);
556
glUseProgram(program0);
557
int width = 1, height = 1;
558
GLuint inputValues[] = {200};
559
GLTexture mTexture[2];
560
glBindTexture(GL_TEXTURE_2D, mTexture[0]);
561
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
562
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
563
inputValues);
564
565
glBindTexture(GL_TEXTURE_2D, mTexture[1]);
566
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
567
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
568
inputValues);
569
570
glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
571
glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
572
573
glDispatchCompute(1, 1, 1);
574
EXPECT_GL_NO_ERROR();
575
576
constexpr char kCS1[] =
577
R"(#version 310 es
578
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
579
layout(std140, binding = 0) buffer blockOut {
580
uvec2 data;
581
} instanceOut;
582
layout(std140, binding = 1) buffer blockIn {
583
uvec2 data;
584
} instanceIn;
585
void main()
586
{
587
instanceOut.data = instanceIn.data;
588
}
589
)";
590
591
ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
592
593
constexpr unsigned int kBufferSize = 2;
594
constexpr unsigned int kBufferData[kBufferSize] = {10, 20};
595
596
GLBuffer blockIn;
597
glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockIn);
598
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), kBufferData, GL_STATIC_DRAW);
599
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, blockIn);
600
601
GLBuffer blockOut;
602
glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);
603
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferData), nullptr, GL_STATIC_DRAW);
604
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, blockOut);
605
606
glUseProgram(program1);
607
glDispatchCompute(1, 1, 1);
608
EXPECT_GL_NO_ERROR();
609
610
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
611
612
glBindBuffer(GL_SHADER_STORAGE_BUFFER, blockOut);
613
unsigned int bufferDataOut[kBufferSize] = {};
614
const GLColor *ptr = reinterpret_cast<GLColor *>(
615
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kBufferData), GL_MAP_READ_BIT));
616
memcpy(bufferDataOut, ptr, sizeof(kBufferData));
617
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
618
619
for (unsigned int index = 0; index < kBufferSize; ++index)
620
{
621
EXPECT_EQ(bufferDataOut[index], kBufferData[index]) << " index " << index;
622
}
623
}
624
625
// Basic test for DispatchComputeIndirect.
626
TEST_P(ComputeShaderTest, DispatchComputeIndirect)
627
{
628
// Flaky crash on teardown, see http://anglebug.com/3349
629
ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
630
631
const char kCSSource[] = R"(#version 310 es
632
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
633
layout(r32ui, binding = 0) uniform highp uimage2D uImage;
634
void main()
635
{
636
imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
637
})";
638
639
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
640
glUseProgram(program.get());
641
const int kWidth = 4, kHeight = 6;
642
GLuint inputValues[kWidth][kHeight] = {};
643
644
GLBuffer buffer;
645
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
646
GLuint params[] = {kWidth, kHeight, 1};
647
glBufferData(GL_DISPATCH_INDIRECT_BUFFER, sizeof(params), params, GL_STATIC_DRAW);
648
649
GLTexture texture;
650
glBindTexture(GL_TEXTURE_2D, texture);
651
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
652
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
653
inputValues);
654
EXPECT_GL_NO_ERROR();
655
656
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
657
EXPECT_GL_NO_ERROR();
658
659
glDispatchComputeIndirect(0);
660
EXPECT_GL_NO_ERROR();
661
662
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
663
664
GLuint outputValues[kWidth][kHeight];
665
666
GLFramebuffer framebuffer;
667
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
668
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
669
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
670
EXPECT_GL_NO_ERROR();
671
672
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
673
EXPECT_GL_NO_ERROR();
674
675
constexpr GLuint kExpectedValue = 100u;
676
for (int x = 0; x < kWidth; x++)
677
{
678
for (int y = 0; y < kHeight; y++)
679
{
680
EXPECT_EQ(kExpectedValue, outputValues[x][y]);
681
}
682
}
683
}
684
685
// Test that uploading data to buffer that's in use then using it as indirect buffer works.
686
TEST_P(ComputeShaderTest, UseAsUBOThenUpdateThenDispatchComputeIndirect)
687
{
688
// Flaky crash on teardown, see http://anglebug.com/3349
689
ANGLE_SKIP_TEST_IF(IsD3D11() && IsIntel() && IsWindows());
690
691
constexpr GLsizei kWidth = 4, kHeight = 6;
692
693
const std::array<uint32_t, 4> kInitialData = {1, 2, 3, 4};
694
const std::array<uint32_t, 4> kUpdateData = {kWidth, kHeight, 1, 0};
695
696
GLBuffer buffer;
697
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
698
glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
699
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
700
EXPECT_GL_NO_ERROR();
701
702
constexpr char kVerifyUBO[] = R"(#version 310 es
703
precision mediump float;
704
layout(binding = 0) uniform block {
705
uvec4 data;
706
} ubo;
707
out vec4 colorOut;
708
void main()
709
{
710
if (all(equal(ubo.data, uvec4(1, 2, 3, 4))))
711
colorOut = vec4(0, 1.0, 0, 1.0);
712
else
713
colorOut = vec4(1.0, 0, 0, 1.0);
714
})";
715
716
ANGLE_GL_PROGRAM(verifyUbo, essl31_shaders::vs::Simple(), kVerifyUBO);
717
drawQuad(verifyUbo, essl31_shaders::PositionAttrib(), 0.5);
718
EXPECT_GL_NO_ERROR();
719
720
// Update buffer data
721
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
722
EXPECT_GL_NO_ERROR();
723
724
const char kCS[] = R"(#version 310 es
725
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
726
layout(r32ui, binding = 0) uniform highp uimage2D uImage;
727
void main()
728
{
729
imageStore(uImage, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y), uvec4(100, 0, 0, 0));
730
})";
731
732
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
733
glUseProgram(program.get());
734
735
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer);
736
737
const std::vector<GLuint> inputValues(kWidth * kHeight, 0);
738
739
GLTexture texture;
740
glBindTexture(GL_TEXTURE_2D, texture);
741
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
742
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
743
inputValues.data());
744
EXPECT_GL_NO_ERROR();
745
746
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
747
EXPECT_GL_NO_ERROR();
748
749
glDispatchComputeIndirect(0);
750
EXPECT_GL_NO_ERROR();
751
752
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
753
754
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
755
756
GLuint outputValues[kWidth][kHeight];
757
758
GLFramebuffer framebuffer;
759
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
760
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
761
EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_READ_FRAMEBUFFER);
762
EXPECT_GL_NO_ERROR();
763
764
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
765
EXPECT_GL_NO_ERROR();
766
767
constexpr GLuint kExpectedValue = 100u;
768
for (int x = 0; x < kWidth; x++)
769
{
770
for (int y = 0; y < kHeight; y++)
771
{
772
EXPECT_EQ(kExpectedValue, outputValues[x][y]);
773
}
774
}
775
}
776
777
// Use image uniform to write texture in compute shader, and verify the content is expected.
778
TEST_P(ComputeShaderTest, BindImageTexture)
779
{
780
GLTexture mTexture[2];
781
GLFramebuffer mFramebuffer;
782
constexpr char kCS[] = R"(#version 310 es
783
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
784
layout(r32ui, binding = 0) writeonly uniform highp uimage2D uImage[2];
785
void main()
786
{
787
imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
788
0, 0));
789
imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, gl_WorkGroupID.x), uvec4(100, 0,
790
0, 0));
791
})";
792
793
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
794
glUseProgram(program.get());
795
int width = 1, height = 1;
796
GLuint inputValues[] = {200};
797
798
glBindTexture(GL_TEXTURE_2D, mTexture[0]);
799
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
800
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
801
inputValues);
802
EXPECT_GL_NO_ERROR();
803
804
glBindImageTexture(0, mTexture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
805
EXPECT_GL_NO_ERROR();
806
807
glBindTexture(GL_TEXTURE_2D, mTexture[1]);
808
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, width, height);
809
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT,
810
inputValues);
811
EXPECT_GL_NO_ERROR();
812
813
glBindImageTexture(1, mTexture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
814
EXPECT_GL_NO_ERROR();
815
816
glDispatchCompute(1, 1, 1);
817
EXPECT_GL_NO_ERROR();
818
819
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
820
glUseProgram(0);
821
GLuint outputValues[2][1];
822
GLuint expectedValue = 100;
823
glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
824
825
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[0],
826
0);
827
EXPECT_GL_NO_ERROR();
828
glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[0]);
829
EXPECT_GL_NO_ERROR();
830
831
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture[1],
832
0);
833
EXPECT_GL_NO_ERROR();
834
glReadPixels(0, 0, width, height, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues[1]);
835
EXPECT_GL_NO_ERROR();
836
837
for (int i = 0; i < width * height; i++)
838
{
839
EXPECT_EQ(expectedValue, outputValues[0][i]);
840
EXPECT_EQ(expectedValue, outputValues[1][i]);
841
}
842
}
843
844
// When declare a image array without a binding qualifier, all elements are bound to unit zero.
845
TEST_P(ComputeShaderTest, ImageArrayWithoutBindingQualifier)
846
{
847
ANGLE_SKIP_TEST_IF(IsD3D11());
848
849
// TODO([email protected]): On AMD desktop OpenGL, bind two image variables to unit 0,
850
// only one variable is valid.
851
ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
852
853
GLTexture mTexture;
854
GLFramebuffer mFramebuffer;
855
constexpr char kCS[] = R"(#version 310 es
856
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
857
layout(r32ui) writeonly uniform highp uimage2D uImage[2];
858
void main()
859
{
860
imageStore(uImage[0], ivec2(gl_LocalInvocationIndex, 0), uvec4(100, 0, 0, 0));
861
imageStore(uImage[1], ivec2(gl_LocalInvocationIndex, 1), uvec4(100, 0, 0, 0));
862
})";
863
864
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
865
glUseProgram(program.get());
866
constexpr int kTextureWidth = 1, kTextureHeight = 2;
867
GLuint inputValues[] = {200, 200};
868
869
glBindTexture(GL_TEXTURE_2D, mTexture);
870
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
871
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
872
GL_UNSIGNED_INT, inputValues);
873
EXPECT_GL_NO_ERROR();
874
875
glBindImageTexture(0, mTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
876
glDispatchCompute(1, 1, 1);
877
EXPECT_GL_NO_ERROR();
878
879
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
880
glUseProgram(0);
881
glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
882
883
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
884
GLuint outputValues[kTextureWidth * kTextureHeight];
885
glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
886
outputValues);
887
EXPECT_GL_NO_ERROR();
888
889
GLuint expectedValue = 100;
890
for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
891
{
892
EXPECT_EQ(expectedValue, outputValues[i]);
893
}
894
}
895
896
// When an image array is declared without a binding qualifier, all elements are bound to unit zero.
897
// Check that the unused uniform image array element does not cause any corruption. Checks for a bug
898
// where unused element could make the whole array seem as unused.
899
TEST_P(ComputeShaderTest, ImageArrayUnusedElement)
900
{
901
ANGLE_SKIP_TEST_IF(IsD3D11());
902
903
// TODO([email protected]): On AMD desktop OpenGL, bind two image variables to unit 0,
904
// only one variable is valid.
905
ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
906
907
// Vulkan is currently unable to handle unbound image units in compute shaders.
908
// http://anglebug.com/5026
909
ANGLE_SKIP_TEST_IF(IsVulkan());
910
911
GLFramebuffer framebuffer;
912
constexpr char kCS[] = R"(#version 310 es
913
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
914
layout(r32ui, binding=0) writeonly uniform highp uimage2D uOut;
915
layout(r32ui, binding=1) readonly uniform highp uimage2D uIn[2];
916
917
void main()
918
{
919
uvec4 inValue = imageLoad(uIn[0], ivec2(gl_LocalInvocationID.xy));
920
imageStore(uOut, ivec2(gl_LocalInvocationIndex, 0), inValue);
921
imageStore(uOut, ivec2(gl_LocalInvocationIndex, 1), inValue);
922
})";
923
924
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
925
glUseProgram(program.get());
926
constexpr int kTextureWidth = 1, kTextureHeight = 2;
927
GLuint inputValues[] = {100, 100};
928
GLTexture in;
929
glBindTexture(GL_TEXTURE_2D, in);
930
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
931
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
932
GL_UNSIGNED_INT, inputValues);
933
EXPECT_GL_NO_ERROR();
934
glBindImageTexture(1, in, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
935
936
GLuint initValues[] = {111, 111};
937
GLTexture out;
938
glBindTexture(GL_TEXTURE_2D, out);
939
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kTextureWidth, kTextureHeight);
940
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER,
941
GL_UNSIGNED_INT, initValues);
942
EXPECT_GL_NO_ERROR();
943
944
glBindImageTexture(0, out, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
945
glDispatchCompute(1, 1, 1);
946
EXPECT_GL_NO_ERROR();
947
948
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
949
glUseProgram(0);
950
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
951
952
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, out, 0);
953
GLuint outputValues[kTextureWidth * kTextureHeight];
954
glReadPixels(0, 0, kTextureWidth, kTextureHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
955
outputValues);
956
EXPECT_GL_NO_ERROR();
957
958
GLuint expectedValue = 100;
959
for (int i = 0; i < kTextureWidth * kTextureHeight; i++)
960
{
961
EXPECT_EQ(expectedValue, outputValues[i]);
962
}
963
}
964
// imageLoad functions
965
TEST_P(ComputeShaderTest, ImageLoad)
966
{
967
constexpr char kCS[] = R"(#version 310 es
968
layout(local_size_x=8) in;
969
layout(rgba8) uniform highp readonly image2D mImage2DInput;
970
layout(rgba16i) uniform highp readonly iimageCube mImageCubeInput;
971
layout(rgba32ui) uniform highp readonly uimage3D mImage3DInput;
972
layout(r32i) uniform highp writeonly iimage2D imageOut;
973
void main()
974
{
975
vec4 result2d = imageLoad(mImage2DInput, ivec2(gl_LocalInvocationID.xy));
976
ivec4 resultCube = imageLoad(mImageCubeInput, ivec3(gl_LocalInvocationID.xyz));
977
uvec4 result3d = imageLoad(mImage3DInput, ivec3(gl_LocalInvocationID.xyz));
978
imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(result2d) + resultCube + ivec4(result3d));
979
})";
980
981
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
982
EXPECT_GL_NO_ERROR();
983
}
984
985
// imageStore functions
986
TEST_P(ComputeShaderTest, ImageStore)
987
{
988
constexpr char kCS[] = R"(#version 310 es
989
layout(local_size_x=8) in;
990
layout(rgba16f) uniform highp writeonly imageCube mImageCubeOutput;
991
layout(r32f) uniform highp writeonly image3D mImage3DOutput;
992
layout(rgba8ui) uniform highp writeonly uimage2DArray mImage2DArrayOutput;
993
void main()
994
{
995
imageStore(mImageCubeOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
996
imageStore(mImage3DOutput, ivec3(gl_LocalInvocationID.xyz), vec4(0.0));
997
imageStore(mImage2DArrayOutput, ivec3(gl_LocalInvocationID.xyz), uvec4(0));
998
})";
999
1000
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1001
EXPECT_GL_NO_ERROR();
1002
}
1003
1004
// imageSize functions
1005
TEST_P(ComputeShaderTest, ImageSize)
1006
{
1007
constexpr char kCS[] = R"(#version 310 es
1008
layout(local_size_x=8) in;
1009
layout(rgba8) uniform highp readonly imageCube mImageCubeInput;
1010
layout(r32i) uniform highp readonly iimage2D mImage2DInput;
1011
layout(rgba16ui) uniform highp readonly uimage2DArray mImage2DArrayInput;
1012
layout(r32i) uniform highp writeonly iimage2D imageOut;
1013
void main()
1014
{
1015
ivec2 sizeCube = imageSize(mImageCubeInput);
1016
ivec2 size2D = imageSize(mImage2DInput);
1017
ivec3 size2DArray = imageSize(mImage2DArrayInput);
1018
imageStore(imageOut, ivec2(gl_LocalInvocationIndex, 0), ivec4(sizeCube, size2D.x, size2DArray.x));
1019
})";
1020
1021
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1022
EXPECT_GL_NO_ERROR();
1023
}
1024
1025
// Test that texelFetch works well in compute shader.
1026
TEST_P(ComputeShaderTest, TexelFetchFunction)
1027
{
1028
// http://anglebug.com/4092
1029
ANGLE_SKIP_TEST_IF(isSwiftshader());
1030
constexpr char kCS[] = R"(#version 310 es
1031
layout(local_size_x=16, local_size_y=12) in;
1032
precision highp usampler2D;
1033
uniform usampler2D tex;
1034
layout(std140, binding = 0) buffer buf {
1035
uint outData[12][16];
1036
};
1037
1038
void main()
1039
{
1040
uint x = gl_LocalInvocationID.x;
1041
uint y = gl_LocalInvocationID.y;
1042
outData[y][x] = texelFetch(tex, ivec2(x, y), 0).x;
1043
})";
1044
1045
constexpr unsigned int kWidth = 16;
1046
constexpr unsigned int kHeight = 12;
1047
GLTexture tex;
1048
glBindTexture(GL_TEXTURE_2D, tex);
1049
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1050
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1051
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1052
GLuint texels[kHeight][kWidth] = {{0}};
1053
for (unsigned int y = 0; y < kHeight; ++y)
1054
{
1055
for (unsigned int x = 0; x < kWidth; ++x)
1056
{
1057
texels[y][x] = x + y * kWidth;
1058
}
1059
}
1060
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1061
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1062
texels);
1063
glBindTexture(GL_TEXTURE_2D, 0);
1064
1065
// The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1066
constexpr unsigned int kArrayStride = 16;
1067
GLBuffer ssbo;
1068
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1069
glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
1070
GL_STREAM_DRAW);
1071
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1072
EXPECT_GL_NO_ERROR();
1073
1074
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1075
glUseProgram(program);
1076
1077
glActiveTexture(GL_TEXTURE0);
1078
glBindTexture(GL_TEXTURE_2D, tex);
1079
glUniform1i(glGetUniformLocation(program, "tex"), 0);
1080
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1081
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
1082
1083
glDispatchCompute(1, 1, 1);
1084
1085
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1086
const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1087
GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
1088
EXPECT_GL_NO_ERROR();
1089
for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
1090
{
1091
EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));
1092
}
1093
}
1094
1095
// Test that texture function works well in compute shader.
1096
TEST_P(ComputeShaderTest, TextureFunction)
1097
{
1098
// http://anglebug.com/4092
1099
ANGLE_SKIP_TEST_IF(isSwiftshader());
1100
constexpr char kCS[] = R"(#version 310 es
1101
layout(local_size_x=16, local_size_y=16) in;
1102
precision highp usampler2D;
1103
uniform usampler2D tex;
1104
layout(std140, binding = 0) buffer buf {
1105
uint outData[16][16];
1106
};
1107
1108
void main()
1109
{
1110
uint x = gl_LocalInvocationID.x;
1111
uint y = gl_LocalInvocationID.y;
1112
float xCoord = float(x) / float(16);
1113
float yCoord = float(y) / float(16);
1114
outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x;
1115
})";
1116
1117
constexpr unsigned int kWidth = 16;
1118
constexpr unsigned int kHeight = 16;
1119
GLTexture tex;
1120
glBindTexture(GL_TEXTURE_2D, tex);
1121
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1122
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1123
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1124
GLuint texels[kHeight][kWidth] = {{0}};
1125
for (unsigned int y = 0; y < kHeight; ++y)
1126
{
1127
for (unsigned int x = 0; x < kWidth; ++x)
1128
{
1129
texels[y][x] = x + y * kWidth;
1130
}
1131
}
1132
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1133
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1134
texels);
1135
glBindTexture(GL_TEXTURE_2D, 0);
1136
1137
// The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1138
constexpr unsigned int kArrayStride = 16;
1139
GLBuffer ssbo;
1140
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1141
glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
1142
GL_STREAM_DRAW);
1143
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1144
EXPECT_GL_NO_ERROR();
1145
1146
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1147
glUseProgram(program);
1148
1149
glActiveTexture(GL_TEXTURE0);
1150
glBindTexture(GL_TEXTURE_2D, tex);
1151
glUniform1i(glGetUniformLocation(program, "tex"), 0);
1152
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1153
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
1154
1155
glDispatchCompute(1, 1, 1);
1156
1157
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
1158
const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1159
GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
1160
EXPECT_GL_NO_ERROR();
1161
for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
1162
{
1163
EXPECT_EQ(idx, *(ptr + idx * kArrayStride / 4));
1164
}
1165
}
1166
1167
// Test mixed use of sampler and image.
1168
TEST_P(ComputeShaderTest, SamplingAndImageReadWrite)
1169
{
1170
GLTexture texture[3];
1171
GLFramebuffer framebuffer;
1172
constexpr char kCS[] = R"(#version 310 es
1173
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1174
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1175
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1176
precision highp usampler2D;
1177
uniform usampler2D tex;
1178
void main()
1179
{
1180
uvec4 value_1 = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
1181
uvec4 value_2 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1182
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value_1 + value_2);
1183
})";
1184
1185
constexpr int kWidth = 1, kHeight = 1;
1186
constexpr GLuint kInputValues[3][1] = {{50}, {100}, {20}};
1187
1188
glBindTexture(GL_TEXTURE_2D, texture[0]);
1189
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1190
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1191
kInputValues[0]);
1192
glBindTexture(GL_TEXTURE_2D, texture[2]);
1193
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1194
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1195
kInputValues[2]);
1196
EXPECT_GL_NO_ERROR();
1197
glBindTexture(GL_TEXTURE_2D, 0);
1198
1199
glBindTexture(GL_TEXTURE_2D, texture[1]);
1200
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1201
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1202
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1203
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1204
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1205
kInputValues[1]);
1206
1207
EXPECT_GL_NO_ERROR();
1208
1209
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1210
glUseProgram(program.get());
1211
1212
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1213
glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1214
EXPECT_GL_NO_ERROR();
1215
1216
glDispatchCompute(1, 1, 1);
1217
EXPECT_GL_NO_ERROR();
1218
1219
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1220
GLuint outputValues[kWidth * kHeight];
1221
constexpr GLuint expectedValue = 150;
1222
glUseProgram(0);
1223
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1224
1225
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
1226
EXPECT_GL_NO_ERROR();
1227
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1228
EXPECT_GL_NO_ERROR();
1229
1230
for (int i = 0; i < kWidth * kHeight; i++)
1231
{
1232
EXPECT_EQ(expectedValue, outputValues[i]);
1233
}
1234
}
1235
1236
// Use image uniform to read and write Texture2D in compute shader, and verify the contents.
1237
TEST_P(ComputeShaderTest, BindImageTextureWithTexture2D)
1238
{
1239
GLTexture texture[2];
1240
GLFramebuffer framebuffer;
1241
constexpr char kCS[] = R"(#version 310 es
1242
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1243
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1244
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1245
void main()
1246
{
1247
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1248
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1249
})";
1250
1251
constexpr int kWidth = 1, kHeight = 1;
1252
constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1253
1254
glBindTexture(GL_TEXTURE_2D, texture[0]);
1255
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1256
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1257
kInputValues[0]);
1258
EXPECT_GL_NO_ERROR();
1259
1260
glBindTexture(GL_TEXTURE_2D, texture[1]);
1261
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1262
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1263
kInputValues[1]);
1264
EXPECT_GL_NO_ERROR();
1265
1266
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1267
glUseProgram(program.get());
1268
1269
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1270
EXPECT_GL_NO_ERROR();
1271
1272
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1273
EXPECT_GL_NO_ERROR();
1274
1275
glDispatchCompute(1, 1, 1);
1276
EXPECT_GL_NO_ERROR();
1277
1278
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1279
GLuint outputValues[kWidth * kHeight];
1280
constexpr GLuint expectedValue = 200;
1281
glUseProgram(0);
1282
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1283
1284
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
1285
EXPECT_GL_NO_ERROR();
1286
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1287
EXPECT_GL_NO_ERROR();
1288
1289
for (int i = 0; i < kWidth * kHeight; i++)
1290
{
1291
EXPECT_EQ(expectedValue, outputValues[i]);
1292
}
1293
}
1294
1295
// Use image uniform to read and write Texture2D with non-zero base in compute shader, and verify
1296
// the contents.
1297
TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2D)
1298
{
1299
GLTexture texture[2];
1300
GLFramebuffer framebuffer;
1301
constexpr char kCS[] = R"(#version 310 es
1302
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1303
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1304
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1305
void main()
1306
{
1307
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1308
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1309
})";
1310
1311
constexpr int kWidth = 1, kHeight = 1;
1312
constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1313
1314
glBindTexture(GL_TEXTURE_2D, texture[0]);
1315
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
1316
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1317
kInputValues[0]);
1318
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1319
EXPECT_GL_NO_ERROR();
1320
1321
glBindTexture(GL_TEXTURE_2D, texture[1]);
1322
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth * 2, kHeight * 2);
1323
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1324
kInputValues[1]);
1325
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
1326
EXPECT_GL_NO_ERROR();
1327
1328
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1329
glUseProgram(program.get());
1330
1331
glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1332
EXPECT_GL_NO_ERROR();
1333
1334
glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1335
EXPECT_GL_NO_ERROR();
1336
1337
glDispatchCompute(1, 1, 1);
1338
EXPECT_GL_NO_ERROR();
1339
1340
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1341
GLuint outputValues[kWidth * kHeight];
1342
constexpr GLuint expectedValue = 200;
1343
glUseProgram(0);
1344
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1345
1346
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
1347
EXPECT_GL_NO_ERROR();
1348
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1349
EXPECT_GL_NO_ERROR();
1350
1351
for (int i = 0; i < kWidth * kHeight; i++)
1352
{
1353
EXPECT_EQ(expectedValue, outputValues[i]) << " at index: " << i;
1354
}
1355
}
1356
1357
// Use image uniform to read and write Texture2DArray in compute shader, and verify the contents.
1358
TEST_P(ComputeShaderTest, BindImageTextureWithTexture2DArray)
1359
{
1360
GLTexture texture[2];
1361
GLFramebuffer framebuffer;
1362
constexpr char kCS[] = R"(#version 310 es
1363
layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
1364
layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
1365
layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
1366
void main()
1367
{
1368
uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1369
imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1370
})";
1371
1372
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1373
constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1374
1375
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1376
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1377
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1378
GL_UNSIGNED_INT, kInputValues[0]);
1379
EXPECT_GL_NO_ERROR();
1380
1381
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1382
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1383
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1384
GL_UNSIGNED_INT, kInputValues[1]);
1385
EXPECT_GL_NO_ERROR();
1386
1387
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1388
glUseProgram(program.get());
1389
1390
glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1391
EXPECT_GL_NO_ERROR();
1392
1393
glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1394
EXPECT_GL_NO_ERROR();
1395
1396
glDispatchCompute(1, 1, 1);
1397
EXPECT_GL_NO_ERROR();
1398
1399
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1400
GLuint outputValues[kWidth * kHeight];
1401
constexpr GLuint expectedValue = 200;
1402
glUseProgram(0);
1403
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1404
1405
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1406
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1407
EXPECT_GL_NO_ERROR();
1408
glReadBuffer(GL_COLOR_ATTACHMENT0);
1409
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1410
EXPECT_GL_NO_ERROR();
1411
for (int i = 0; i < kWidth * kHeight; i++)
1412
{
1413
EXPECT_EQ(expectedValue, outputValues[i]);
1414
}
1415
glReadBuffer(GL_COLOR_ATTACHMENT1);
1416
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1417
EXPECT_GL_NO_ERROR();
1418
for (int i = 0; i < kWidth * kHeight; i++)
1419
{
1420
EXPECT_EQ(expectedValue, outputValues[i]);
1421
}
1422
}
1423
1424
// Use image uniform to read and write Texture2DArray with non-zero base in compute shader, and
1425
// verify the contents.
1426
TEST_P(ComputeShaderTest, BindImageTextureWithNonZeroBaseTexture2DArray)
1427
{
1428
GLTexture texture[2];
1429
GLFramebuffer framebuffer;
1430
constexpr char kCS[] = R"(#version 310 es
1431
layout(local_size_x=2, local_size_y=2, local_size_z=2) in;
1432
layout(r32ui, binding = 0) readonly uniform highp uimage2DArray uImage_1;
1433
layout(r32ui, binding = 1) writeonly uniform highp uimage2DArray uImage_2;
1434
void main()
1435
{
1436
uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1437
imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1438
})";
1439
1440
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1441
constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1442
1443
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1444
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
1445
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1446
GL_UNSIGNED_INT, kInputValues[0]);
1447
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
1448
EXPECT_GL_NO_ERROR();
1449
1450
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1451
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32UI, kWidth * 2, kHeight * 2, kDepth);
1452
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 1, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1453
GL_UNSIGNED_INT, kInputValues[1]);
1454
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 1);
1455
EXPECT_GL_NO_ERROR();
1456
1457
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1458
glUseProgram(program.get());
1459
1460
glBindImageTexture(0, texture[0], 1, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1461
EXPECT_GL_NO_ERROR();
1462
1463
glBindImageTexture(1, texture[1], 1, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1464
EXPECT_GL_NO_ERROR();
1465
1466
glDispatchCompute(1, 1, 1);
1467
EXPECT_GL_NO_ERROR();
1468
1469
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1470
GLuint outputValues[kWidth * kHeight];
1471
constexpr GLuint expectedValue = 200;
1472
glUseProgram(0);
1473
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1474
1475
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 1, 0);
1476
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 1, 1);
1477
EXPECT_GL_NO_ERROR();
1478
glReadBuffer(GL_COLOR_ATTACHMENT0);
1479
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1480
EXPECT_GL_NO_ERROR();
1481
for (int i = 0; i < kWidth * kHeight; i++)
1482
{
1483
EXPECT_EQ(expectedValue, outputValues[i]);
1484
}
1485
glReadBuffer(GL_COLOR_ATTACHMENT1);
1486
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1487
EXPECT_GL_NO_ERROR();
1488
for (int i = 0; i < kWidth * kHeight; i++)
1489
{
1490
EXPECT_EQ(expectedValue, outputValues[i]);
1491
}
1492
}
1493
1494
// Use image uniform to read and write Texture3D in compute shader, and verify the contents.
1495
TEST_P(ComputeShaderTest, BindImageTextureWithTexture3D)
1496
{
1497
GLTexture texture[2];
1498
GLFramebuffer framebuffer;
1499
constexpr char kCS[] = R"(#version 310 es
1500
layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
1501
layout(r32ui, binding = 0) readonly uniform highp uimage3D uImage_1;
1502
layout(r32ui, binding = 1) writeonly uniform highp uimage3D uImage_2;
1503
void main()
1504
{
1505
uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xyz));
1506
imageStore(uImage_2, ivec3(gl_LocalInvocationID.xyz), value);
1507
})";
1508
1509
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1510
constexpr GLuint kInputValues[2][2] = {{200, 200}, {100, 100}};
1511
1512
glBindTexture(GL_TEXTURE_3D, texture[0]);
1513
glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1514
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1515
GL_UNSIGNED_INT, kInputValues[0]);
1516
EXPECT_GL_NO_ERROR();
1517
1518
glBindTexture(GL_TEXTURE_3D, texture[1]);
1519
glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1520
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1521
GL_UNSIGNED_INT, kInputValues[1]);
1522
EXPECT_GL_NO_ERROR();
1523
1524
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1525
glUseProgram(program.get());
1526
1527
glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1528
EXPECT_GL_NO_ERROR();
1529
1530
glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1531
EXPECT_GL_NO_ERROR();
1532
1533
glDispatchCompute(1, 1, 1);
1534
EXPECT_GL_NO_ERROR();
1535
1536
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1537
GLuint outputValues[kWidth * kHeight];
1538
constexpr GLuint expectedValue = 200;
1539
glUseProgram(0);
1540
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1541
1542
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1543
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1544
EXPECT_GL_NO_ERROR();
1545
glReadBuffer(GL_COLOR_ATTACHMENT0);
1546
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1547
EXPECT_GL_NO_ERROR();
1548
for (int i = 0; i < kWidth * kHeight; i++)
1549
{
1550
EXPECT_EQ(expectedValue, outputValues[i]);
1551
}
1552
glReadBuffer(GL_COLOR_ATTACHMENT1);
1553
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1554
EXPECT_GL_NO_ERROR();
1555
for (int i = 0; i < kWidth * kHeight; i++)
1556
{
1557
EXPECT_EQ(expectedValue, outputValues[i]);
1558
}
1559
}
1560
1561
// Use image uniform to read and write TextureCube in compute shader, and verify the contents.
1562
TEST_P(ComputeShaderTest, BindImageTextureWithTextureCube)
1563
{
1564
GLTexture texture[2];
1565
GLFramebuffer framebuffer;
1566
constexpr char kCS[] = R"(#version 310 es
1567
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1568
layout(r32ui, binding = 0) readonly uniform highp uimageCube uImage_1;
1569
layout(r32ui, binding = 1) writeonly uniform highp uimageCube uImage_2;
1570
void main()
1571
{
1572
for (int i = 0; i < 6; i++)
1573
{
1574
uvec4 value = imageLoad(uImage_1, ivec3(gl_LocalInvocationID.xy, i));
1575
imageStore(uImage_2, ivec3(gl_LocalInvocationID.xy, i), value);
1576
}
1577
})";
1578
1579
constexpr int kWidth = 1, kHeight = 1;
1580
constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1581
1582
glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1583
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1584
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1585
face++)
1586
{
1587
glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1588
kInputValues[0]);
1589
}
1590
EXPECT_GL_NO_ERROR();
1591
1592
glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1593
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1594
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1595
face++)
1596
{
1597
glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1598
kInputValues[1]);
1599
}
1600
EXPECT_GL_NO_ERROR();
1601
1602
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1603
glUseProgram(program.get());
1604
1605
glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1606
EXPECT_GL_NO_ERROR();
1607
1608
glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
1609
EXPECT_GL_NO_ERROR();
1610
1611
glDispatchCompute(1, 1, 1);
1612
EXPECT_GL_NO_ERROR();
1613
1614
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1615
GLuint outputValues[kWidth * kHeight];
1616
constexpr GLuint expectedValue = 200;
1617
glUseProgram(0);
1618
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1619
1620
for (GLenum face = 0; face < 6; face++)
1621
{
1622
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1623
GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1624
EXPECT_GL_NO_ERROR();
1625
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1626
EXPECT_GL_NO_ERROR();
1627
1628
for (int i = 0; i < kWidth * kHeight; i++)
1629
{
1630
EXPECT_EQ(expectedValue, outputValues[i]);
1631
}
1632
}
1633
}
1634
1635
// Use image uniform to read and write one layer of Texture2DArray in compute shader, and verify the
1636
// contents.
1637
TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture2DArray)
1638
{
1639
GLTexture texture[2];
1640
GLFramebuffer framebuffer;
1641
constexpr char kCS[] = R"(#version 310 es
1642
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1643
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1644
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1645
void main()
1646
{
1647
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1648
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1649
})";
1650
1651
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1652
constexpr int kResultSize = kWidth * kHeight;
1653
constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1654
constexpr GLuint expectedValue_1 = 200;
1655
constexpr GLuint expectedValue_2 = 100;
1656
GLuint outputValues[kResultSize];
1657
1658
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[0]);
1659
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1660
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1661
GL_UNSIGNED_INT, kInputValues[0]);
1662
EXPECT_GL_NO_ERROR();
1663
1664
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1665
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1666
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1667
GL_UNSIGNED_INT, kInputValues[1]);
1668
EXPECT_GL_NO_ERROR();
1669
1670
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1671
glUseProgram(program.get());
1672
1673
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
1674
EXPECT_GL_NO_ERROR();
1675
glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
1676
EXPECT_GL_NO_ERROR();
1677
glDispatchCompute(1, 1, 1);
1678
EXPECT_GL_NO_ERROR();
1679
1680
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1681
glUseProgram(0);
1682
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1683
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1684
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1685
EXPECT_GL_NO_ERROR();
1686
glReadBuffer(GL_COLOR_ATTACHMENT0);
1687
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1688
EXPECT_GL_NO_ERROR();
1689
for (int i = 0; i < kResultSize; i++)
1690
{
1691
EXPECT_EQ(expectedValue_2, outputValues[i]);
1692
}
1693
glReadBuffer(GL_COLOR_ATTACHMENT1);
1694
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1695
EXPECT_GL_NO_ERROR();
1696
for (int i = 0; i < kResultSize; i++)
1697
{
1698
EXPECT_EQ(expectedValue_1, outputValues[i]);
1699
}
1700
}
1701
1702
// Use image uniform to read and write one layer of Texture3D in compute shader, and verify the
1703
// contents.
1704
TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTexture3D)
1705
{
1706
// Vulkan validation error creating a 2D image view of a 3D image layer.
1707
// http://anglebug.com/3886
1708
ANGLE_SKIP_TEST_IF(IsVulkan());
1709
1710
GLTexture texture[2];
1711
GLFramebuffer framebuffer;
1712
constexpr char kCS[] = R"(#version 310 es
1713
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1714
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1715
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1716
void main()
1717
{
1718
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1719
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1720
})";
1721
1722
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1723
constexpr int kResultSize = kWidth * kHeight;
1724
constexpr GLuint kInputValues[2][2] = {{200, 150}, {100, 50}};
1725
constexpr GLuint expectedValue_1 = 150;
1726
constexpr GLuint expectedValue_2 = 50;
1727
GLuint outputValues[kResultSize];
1728
1729
glBindTexture(GL_TEXTURE_3D, texture[0]);
1730
glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1731
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1732
GL_UNSIGNED_INT, kInputValues[0]);
1733
EXPECT_GL_NO_ERROR();
1734
1735
glBindTexture(GL_TEXTURE_3D, texture[1]);
1736
glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1737
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1738
GL_UNSIGNED_INT, kInputValues[1]);
1739
EXPECT_GL_NO_ERROR();
1740
1741
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1742
glUseProgram(program.get());
1743
1744
glBindImageTexture(0, texture[0], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1745
EXPECT_GL_NO_ERROR();
1746
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
1747
EXPECT_GL_NO_ERROR();
1748
glDispatchCompute(1, 1, 1);
1749
EXPECT_GL_NO_ERROR();
1750
1751
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1752
glUseProgram(0);
1753
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1754
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture[1], 0, 0);
1755
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture[1], 0, 1);
1756
EXPECT_GL_NO_ERROR();
1757
glReadBuffer(GL_COLOR_ATTACHMENT0);
1758
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1759
EXPECT_GL_NO_ERROR();
1760
for (int i = 0; i < kResultSize; i++)
1761
{
1762
EXPECT_EQ(expectedValue_1, outputValues[i]);
1763
}
1764
glReadBuffer(GL_COLOR_ATTACHMENT1);
1765
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1766
EXPECT_GL_NO_ERROR();
1767
for (int i = 0; i < kResultSize; i++)
1768
{
1769
EXPECT_EQ(expectedValue_2, outputValues[i]);
1770
}
1771
}
1772
1773
// Use image uniform to read and write one layer of TextureCube in compute shader, and verify the
1774
// contents.
1775
TEST_P(ComputeShaderTest, BindImageTextureWithOneLayerTextureCube)
1776
{
1777
// GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.
1778
// http://anglebug.com/3736
1779
ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());
1780
1781
GLTexture texture[2];
1782
GLFramebuffer framebuffer;
1783
constexpr char kCS[] = R"(#version 310 es
1784
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1785
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1786
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
1787
void main()
1788
{
1789
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1790
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
1791
})";
1792
1793
constexpr int kWidth = 1, kHeight = 1;
1794
constexpr int kResultSize = kWidth * kHeight;
1795
constexpr GLuint kInputValues[2][1] = {{200}, {100}};
1796
constexpr GLuint expectedValue_1 = 200;
1797
constexpr GLuint expectedValue_2 = 100;
1798
GLuint outputValues[kResultSize];
1799
1800
glBindTexture(GL_TEXTURE_CUBE_MAP, texture[0]);
1801
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1802
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1803
face++)
1804
{
1805
glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1806
kInputValues[0]);
1807
}
1808
EXPECT_GL_NO_ERROR();
1809
1810
glBindTexture(GL_TEXTURE_CUBE_MAP, texture[1]);
1811
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1812
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1813
face++)
1814
{
1815
glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1816
kInputValues[1]);
1817
}
1818
EXPECT_GL_NO_ERROR();
1819
1820
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1821
glUseProgram(program.get());
1822
1823
glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
1824
EXPECT_GL_NO_ERROR();
1825
glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1826
EXPECT_GL_NO_ERROR();
1827
glDispatchCompute(1, 1, 1);
1828
EXPECT_GL_NO_ERROR();
1829
1830
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1831
glUseProgram(0);
1832
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1833
1834
for (GLenum face = 0; face < 6; face++)
1835
{
1836
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1837
GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
1838
EXPECT_GL_NO_ERROR();
1839
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1840
EXPECT_GL_NO_ERROR();
1841
1842
if (face == 4)
1843
{
1844
for (int i = 0; i < kResultSize; i++)
1845
{
1846
EXPECT_EQ(expectedValue_1, outputValues[i]);
1847
}
1848
}
1849
else
1850
{
1851
for (int i = 0; i < kResultSize; i++)
1852
{
1853
EXPECT_EQ(expectedValue_2, outputValues[i]);
1854
}
1855
}
1856
}
1857
}
1858
1859
// Test to bind kinds of texture types, bind either the entire texture
1860
// level or a single layer or face of the face level.
1861
TEST_P(ComputeShaderTest, BindImageTextureWithMixTextureTypes)
1862
{
1863
// GL_FRAMEBUFFER_BARRIER_BIT is invalid on Nvidia Linux platform.
1864
// http://anglebug.com/3736
1865
ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL() && IsLinux());
1866
1867
// http://anglebug.com/5072
1868
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
1869
1870
GLTexture texture[4];
1871
GLFramebuffer framebuffer;
1872
const char csSource[] =
1873
R"(#version 310 es
1874
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1875
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
1876
layout(r32ui, binding = 1) readonly uniform highp uimage2D uImage_2;
1877
layout(r32ui, binding = 2) readonly uniform highp uimage3D uImage_3;
1878
layout(r32ui, binding = 3) writeonly uniform highp uimage2D uImage_4;
1879
void main()
1880
{
1881
uvec4 value_1 = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
1882
uvec4 value_2 = imageLoad(uImage_2, ivec2(gl_LocalInvocationID.xy));
1883
uvec4 value_3 = imageLoad(uImage_3, ivec3(gl_LocalInvocationID.xyz));
1884
imageStore(uImage_4, ivec2(gl_LocalInvocationID.xy), value_1 + value_2 + value_3);
1885
})";
1886
1887
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
1888
constexpr int kResultSize = kWidth * kHeight;
1889
constexpr GLuint kInputValues2D[1] = {11};
1890
constexpr GLuint KInputValues2DArray[2] = {23, 35};
1891
constexpr GLuint KInputValues3D[2] = {102, 67};
1892
constexpr GLuint KInputValuesCube[1] = {232};
1893
1894
constexpr GLuint expectedValue_1 = 148;
1895
constexpr GLuint expectedValue_2 = 232;
1896
GLuint outputValues[kResultSize];
1897
1898
glBindTexture(GL_TEXTURE_2D, texture[0]);
1899
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
1900
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1901
kInputValues2D);
1902
EXPECT_GL_NO_ERROR();
1903
1904
glBindTexture(GL_TEXTURE_2D_ARRAY, texture[1]);
1905
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32UI, kWidth, kHeight, kDepth);
1906
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1907
GL_UNSIGNED_INT, KInputValues2DArray);
1908
EXPECT_GL_NO_ERROR();
1909
1910
glBindTexture(GL_TEXTURE_3D, texture[2]);
1911
glTexStorage3D(GL_TEXTURE_3D, 1, GL_R32UI, kWidth, kHeight, kDepth);
1912
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RED_INTEGER,
1913
GL_UNSIGNED_INT, KInputValues3D);
1914
EXPECT_GL_NO_ERROR();
1915
1916
glBindTexture(GL_TEXTURE_CUBE_MAP, texture[3]);
1917
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_R32UI, kWidth, kHeight);
1918
for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1919
face++)
1920
{
1921
glTexSubImage2D(face, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
1922
KInputValuesCube);
1923
}
1924
EXPECT_GL_NO_ERROR();
1925
1926
ANGLE_GL_COMPUTE_PROGRAM(program, csSource);
1927
glUseProgram(program.get());
1928
1929
glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1930
EXPECT_GL_NO_ERROR();
1931
glBindImageTexture(1, texture[1], 0, GL_FALSE, 1, GL_READ_ONLY, GL_R32UI);
1932
EXPECT_GL_NO_ERROR();
1933
glBindImageTexture(2, texture[2], 0, GL_TRUE, 0, GL_READ_ONLY, GL_R32UI);
1934
EXPECT_GL_NO_ERROR();
1935
glBindImageTexture(3, texture[3], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
1936
EXPECT_GL_NO_ERROR();
1937
glDispatchCompute(1, 1, 1);
1938
EXPECT_GL_NO_ERROR();
1939
1940
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1941
glUseProgram(0);
1942
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
1943
1944
for (GLenum face = 0; face < 6; face++)
1945
{
1946
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
1947
GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[3], 0);
1948
EXPECT_GL_NO_ERROR();
1949
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
1950
EXPECT_GL_NO_ERROR();
1951
1952
if (face == 4)
1953
{
1954
for (int i = 0; i < kResultSize; i++)
1955
{
1956
EXPECT_EQ(expectedValue_1, outputValues[i]);
1957
}
1958
}
1959
else
1960
{
1961
for (int i = 0; i < kResultSize; i++)
1962
{
1963
EXPECT_EQ(expectedValue_2, outputValues[i]);
1964
}
1965
}
1966
}
1967
}
1968
1969
// Verify an INVALID_OPERATION error is reported when querying GL_COMPUTE_WORK_GROUP_SIZE for a
1970
// program which has not been linked successfully or which does not contain objects to form a
1971
// compute shader.
1972
TEST_P(ComputeShaderTest, QueryComputeWorkGroupSize)
1973
{
1974
constexpr char kVS[] = R"(#version 310 es
1975
void main()
1976
{
1977
})";
1978
1979
constexpr char kFS[] = R"(#version 310 es
1980
void main()
1981
{
1982
})";
1983
1984
GLint workGroupSize[3];
1985
1986
ANGLE_GL_PROGRAM(graphicsProgram, kVS, kFS);
1987
glGetProgramiv(graphicsProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
1988
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1989
1990
GLuint computeProgram = glCreateProgram();
1991
GLShader computeShader(GL_COMPUTE_SHADER);
1992
glAttachShader(computeProgram, computeShader);
1993
glLinkProgram(computeProgram);
1994
glDetachShader(computeProgram, computeShader);
1995
1996
GLint linkStatus;
1997
glGetProgramiv(computeProgram, GL_LINK_STATUS, &linkStatus);
1998
ASSERT_GL_FALSE(linkStatus);
1999
2000
glGetProgramiv(computeProgram, GL_COMPUTE_WORK_GROUP_SIZE, workGroupSize);
2001
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2002
2003
glDeleteProgram(computeProgram);
2004
2005
ASSERT_GL_NO_ERROR();
2006
}
2007
2008
// Use groupMemoryBarrier and barrier to sync reads/writes order and the execution
2009
// order of multiple shader invocations in compute shader.
2010
TEST_P(ComputeShaderTest, GroupMemoryBarrierAndBarrierTest)
2011
{
2012
// TODO([email protected]): Figure out why we get this error message
2013
// that shader uses features not recognized by this D3D version.
2014
ANGLE_SKIP_TEST_IF((IsAMD() || IsNVIDIA()) && IsD3D11());
2015
ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
2016
2017
// http://anglebug.com/5072
2018
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2019
2020
GLTexture texture;
2021
GLFramebuffer framebuffer;
2022
2023
// Each invocation first stores a single value in an image, then each invocation sums up
2024
// all the values in the image and stores the sum in the image. groupMemoryBarrier is
2025
// used to order reads/writes to variables stored in memory accessible to other shader
2026
// invocations, and barrier is used to control the relative execution order of multiple
2027
// shader invocations used to process a local work group.
2028
constexpr char kCS[] = R"(#version 310 es
2029
layout(local_size_x=2, local_size_y=2, local_size_z=1) in;
2030
layout(r32i, binding = 0) uniform highp iimage2D image;
2031
void main()
2032
{
2033
uint x = gl_LocalInvocationID.x;
2034
uint y = gl_LocalInvocationID.y;
2035
imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(x + y));
2036
groupMemoryBarrier();
2037
barrier();
2038
int sum = 0;
2039
for (int i = 0; i < 2; i++)
2040
{
2041
for(int j = 0; j < 2; j++)
2042
{
2043
sum += imageLoad(image, ivec2(i, j)).x;
2044
}
2045
}
2046
groupMemoryBarrier();
2047
barrier();
2048
imageStore(image, ivec2(gl_LocalInvocationID.xy), ivec4(sum));
2049
})";
2050
2051
constexpr int kWidth = 2, kHeight = 2;
2052
glBindTexture(GL_TEXTURE_2D, texture);
2053
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32I, kWidth, kHeight);
2054
EXPECT_GL_NO_ERROR();
2055
2056
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2057
glUseProgram(program.get());
2058
2059
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
2060
EXPECT_GL_NO_ERROR();
2061
2062
glDispatchCompute(1, 1, 1);
2063
EXPECT_GL_NO_ERROR();
2064
2065
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2066
GLuint outputValues[kWidth * kHeight];
2067
constexpr GLuint kExpectedValue = 4;
2068
glUseProgram(0);
2069
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2070
2071
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2072
EXPECT_GL_NO_ERROR();
2073
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_INT, outputValues);
2074
EXPECT_GL_NO_ERROR();
2075
2076
for (int i = 0; i < kWidth * kHeight; i++)
2077
{
2078
EXPECT_EQ(kExpectedValue, outputValues[i]);
2079
}
2080
}
2081
2082
// Verify that a link error is generated when the sum of the number of active image uniforms and
2083
// active shader storage blocks in a compute shader exceeds GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
2084
TEST_P(ComputeShaderTest, ExceedCombinedShaderOutputResourcesInCS)
2085
{
2086
GLint maxCombinedShaderOutputResources;
2087
GLint maxComputeShaderStorageBlocks;
2088
GLint maxComputeImageUniforms;
2089
2090
glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &maxCombinedShaderOutputResources);
2091
glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &maxComputeShaderStorageBlocks);
2092
glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &maxComputeImageUniforms);
2093
2094
ANGLE_SKIP_TEST_IF(maxCombinedShaderOutputResources >=
2095
maxComputeShaderStorageBlocks + maxComputeImageUniforms);
2096
2097
std::ostringstream computeShaderStream;
2098
computeShaderStream << "#version 310 es\n"
2099
"layout(local_size_x = 3, local_size_y = 1, local_size_z = 1) in;\n"
2100
"layout(shared, binding = 0) buffer blockName"
2101
"{\n"
2102
" uint data;\n"
2103
"} instance["
2104
<< maxComputeShaderStorageBlocks << "];\n";
2105
2106
ASSERT_GE(maxComputeImageUniforms, 4);
2107
int numImagesInArray = maxComputeImageUniforms / 2;
2108
int numImagesNonArray = maxComputeImageUniforms - numImagesInArray;
2109
for (int i = 0; i < numImagesNonArray; ++i)
2110
{
2111
computeShaderStream << "layout(r32f, binding = " << i << ") uniform highp image2D image"
2112
<< i << ";\n";
2113
}
2114
2115
computeShaderStream << "layout(r32f, binding = " << numImagesNonArray
2116
<< ") uniform highp image2D imageArray[" << numImagesInArray << "];\n";
2117
2118
computeShaderStream << "void main()\n"
2119
"{\n"
2120
" uint val = 0u;\n"
2121
" vec4 val2 = vec4(0.0);\n";
2122
2123
for (int i = 0; i < maxComputeShaderStorageBlocks; ++i)
2124
{
2125
computeShaderStream << " val += instance[" << i << "].data; \n";
2126
}
2127
2128
for (int i = 0; i < numImagesNonArray; ++i)
2129
{
2130
computeShaderStream << " val2 += imageLoad(image" << i
2131
<< ", ivec2(gl_LocalInvocationID.xy)); \n";
2132
}
2133
2134
for (int i = 0; i < numImagesInArray; ++i)
2135
{
2136
computeShaderStream << " val2 += imageLoad(imageArray[" << i << "]"
2137
<< ", ivec2(gl_LocalInvocationID.xy)); \n";
2138
}
2139
2140
computeShaderStream << " instance[0].data = val + uint(val2.x);\n"
2141
"}\n";
2142
2143
GLuint computeProgram = CompileComputeProgram(computeShaderStream.str().c_str());
2144
EXPECT_EQ(0u, computeProgram);
2145
}
2146
2147
// Test that uniform block with struct member in compute shader is supported.
2148
TEST_P(ComputeShaderTest, UniformBlockWithStructMember)
2149
{
2150
constexpr char kCS[] = R"(#version 310 es
2151
layout(local_size_x=8) in;
2152
layout(rgba8) uniform highp readonly image2D mImage2DInput;
2153
layout(rgba8) uniform highp writeonly image2D mImage2DOutput;
2154
struct S {
2155
ivec3 a;
2156
ivec2 b;
2157
};
2158
2159
layout(std140, binding=0) uniform blockName {
2160
S bd;
2161
} instanceName;
2162
void main()
2163
{
2164
ivec2 t1 = instanceName.bd.b;
2165
vec4 result2d = imageLoad(mImage2DInput, t1);
2166
imageStore(mImage2DOutput, ivec2(gl_LocalInvocationID.xy), result2d);
2167
})";
2168
2169
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2170
EXPECT_GL_NO_ERROR();
2171
}
2172
2173
// Verify shared non-array variables can work correctly.
2174
TEST_P(ComputeShaderTest, NonArraySharedVariable)
2175
{
2176
// http://anglebug.com/5072
2177
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2178
2179
const char kCSShader[] = R"(#version 310 es
2180
layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2181
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2182
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2183
shared uint temp;
2184
void main()
2185
{
2186
if (gl_LocalInvocationID == uvec3(0, 0, 0))
2187
{
2188
temp = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2189
}
2190
groupMemoryBarrier();
2191
barrier();
2192
if (gl_LocalInvocationID == uvec3(1, 1, 0))
2193
{
2194
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(temp));
2195
}
2196
else
2197
{
2198
uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2199
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(inputValue));
2200
}
2201
})";
2202
2203
const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
2204
const std::array<GLuint, 4> expectedValues = {{250, 200, 150, 250}};
2205
runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2206
expectedValues);
2207
}
2208
2209
// Verify shared non-struct array variables can work correctly.
2210
TEST_P(ComputeShaderTest, NonStructArrayAsSharedVariable)
2211
{
2212
// http://anglebug.com/5072
2213
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2214
2215
const char kCSShader[] = R"(#version 310 es
2216
layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2217
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2218
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2219
shared uint sharedData[2][2];
2220
void main()
2221
{
2222
uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2223
sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = inputData;
2224
groupMemoryBarrier();
2225
barrier();
2226
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2227
uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x]));
2228
})";
2229
2230
const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
2231
const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
2232
runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2233
expectedValues);
2234
}
2235
2236
// Verify shared struct array variables work correctly.
2237
TEST_P(ComputeShaderTest, StructArrayAsSharedVariable)
2238
{
2239
// http://anglebug.com/5072
2240
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2241
2242
const char kCSShader[] = R"(#version 310 es
2243
layout (local_size_x = 2, local_size_y = 2, local_size_z = 1) in;
2244
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2245
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2246
struct SharedStruct
2247
{
2248
uint data;
2249
};
2250
shared SharedStruct sharedData[2][2];
2251
void main()
2252
{
2253
uint inputData = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2254
sharedData[gl_LocalInvocationID.x][gl_LocalInvocationID.y].data = inputData;
2255
groupMemoryBarrier();
2256
barrier();
2257
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2258
uvec4(sharedData[gl_LocalInvocationID.y][gl_LocalInvocationID.x].data));
2259
})";
2260
2261
const std::array<GLuint, 4> inputData = {{250, 200, 150, 100}};
2262
const std::array<GLuint, 4> expectedValues = {{250, 150, 200, 100}};
2263
runSharedMemoryTest<GLuint, 2, 2>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2264
expectedValues);
2265
}
2266
2267
// Verify using atomic functions without return value can work correctly.
2268
TEST_P(ComputeShaderTest, AtomicFunctionsNoReturnValue)
2269
{
2270
// http://anglebug.com/5072
2271
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2272
2273
// Fails on AMD windows drivers. http://anglebug.com/3872
2274
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2275
2276
// Fails to link on Android. http://anglebug.com/3874
2277
ANGLE_SKIP_TEST_IF(IsAndroid());
2278
2279
ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
2280
2281
const char kCSShader[] = R"(#version 310 es
2282
layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in;
2283
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2284
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2285
2286
const uint kSumIndex = 0u;
2287
const uint kMinIndex = 1u;
2288
const uint kMaxIndex = 2u;
2289
const uint kOrIndex = 3u;
2290
const uint kAndIndex = 4u;
2291
const uint kXorIndex = 5u;
2292
const uint kExchangeIndex = 6u;
2293
const uint kCompSwapIndex = 7u;
2294
2295
shared highp uint results[8];
2296
2297
void main()
2298
{
2299
if (gl_LocalInvocationID.x == kMinIndex || gl_LocalInvocationID.x == kAndIndex)
2300
{
2301
results[gl_LocalInvocationID.x] = 0xFFFFu;
2302
}
2303
else if (gl_LocalInvocationID.x == kCompSwapIndex)
2304
{
2305
results[gl_LocalInvocationID.x] = 1u;
2306
}
2307
else
2308
{
2309
results[gl_LocalInvocationID.x] = 0u;
2310
}
2311
memoryBarrierShared();
2312
barrier();
2313
2314
uint value = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2315
atomicAdd(results[kSumIndex], value);
2316
atomicMin(results[kMinIndex], value);
2317
atomicMax(results[kMaxIndex], value);
2318
atomicOr(results[kOrIndex], value);
2319
atomicAnd(results[kAndIndex], value);
2320
atomicXor(results[kXorIndex], value);
2321
atomicExchange(results[kExchangeIndex], value);
2322
atomicCompSwap(results[kCompSwapIndex], value, 256u);
2323
memoryBarrierShared();
2324
barrier();
2325
2326
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2327
uvec4(results[gl_LocalInvocationID.x]));
2328
})";
2329
2330
const std::array<GLuint, 8> inputData = {{1, 2, 4, 8, 16, 32, 64, 128}};
2331
const std::array<GLuint, 8> expectedValues = {{255, 1, 128, 255, 0, 255, 128, 256}};
2332
runSharedMemoryTest<GLuint, 8, 1>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
2333
expectedValues);
2334
}
2335
2336
// Verify using atomic functions in a non-initializer single assignment can work correctly.
2337
TEST_P(ComputeShaderTest, AtomicFunctionsInNonInitializerSingleAssignment)
2338
{
2339
// http://anglebug.com/5072
2340
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2341
2342
// Fails on AMD windows drivers. http://anglebug.com/3872
2343
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2344
2345
const char kCSShader[] = R"(#version 310 es
2346
layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2347
layout (r32i, binding = 0) readonly uniform highp iimage2D srcImage;
2348
layout (r32i, binding = 1) writeonly uniform highp iimage2D dstImage;
2349
2350
shared highp int sharedVariable;
2351
2352
shared highp int inputData[9];
2353
shared highp int outputData[9];
2354
2355
void main()
2356
{
2357
int inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2358
inputData[gl_LocalInvocationID.x] = inputValue;
2359
memoryBarrierShared();
2360
barrier();
2361
2362
if (gl_LocalInvocationID.x == 0u)
2363
{
2364
sharedVariable = 0;
2365
2366
outputData[0] = atomicAdd(sharedVariable, inputData[0]);
2367
outputData[1] = atomicMin(sharedVariable, inputData[1]);
2368
outputData[2] = atomicMax(sharedVariable, inputData[2]);
2369
outputData[3] = atomicAnd(sharedVariable, inputData[3]);
2370
outputData[4] = atomicOr(sharedVariable, inputData[4]);
2371
outputData[5] = atomicXor(sharedVariable, inputData[5]);
2372
outputData[6] = atomicExchange(sharedVariable, inputData[6]);
2373
outputData[7] = atomicCompSwap(sharedVariable, 64, inputData[7]);
2374
outputData[8] = atomicAdd(sharedVariable, inputData[8]);
2375
}
2376
memoryBarrierShared();
2377
barrier();
2378
2379
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2380
ivec4(outputData[gl_LocalInvocationID.x]));
2381
})";
2382
2383
const std::array<GLint, 9> inputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2384
const std::array<GLint, 9> expectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
2385
runSharedMemoryTest<GLint, 9, 1>(kCSShader, GL_R32I, GL_INT, inputData, expectedValues);
2386
}
2387
2388
// Verify using atomic functions in an initializers and using unsigned int works correctly.
2389
TEST_P(ComputeShaderTest, AtomicFunctionsInitializerWithUnsigned)
2390
{
2391
// http://anglebug.com/5072
2392
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2393
2394
// Fails on AMD windows drivers. http://anglebug.com/3872
2395
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2396
2397
constexpr char kCShader[] = R"(#version 310 es
2398
layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2399
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2400
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2401
2402
shared highp uint sharedVariable;
2403
2404
shared highp uint inputData[9];
2405
shared highp uint outputData[9];
2406
2407
void main()
2408
{
2409
uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2410
inputData[gl_LocalInvocationID.x] = inputValue;
2411
memoryBarrierShared();
2412
barrier();
2413
2414
if (gl_LocalInvocationID.x == 0u)
2415
{
2416
sharedVariable = 0u;
2417
2418
uint addValue = atomicAdd(sharedVariable, inputData[0]);
2419
outputData[0] = addValue;
2420
uint minValue = atomicMin(sharedVariable, inputData[1]);
2421
outputData[1] = minValue;
2422
uint maxValue = atomicMax(sharedVariable, inputData[2]);
2423
outputData[2] = maxValue;
2424
uint andValue = atomicAnd(sharedVariable, inputData[3]);
2425
outputData[3] = andValue;
2426
uint orValue = atomicOr(sharedVariable, inputData[4]);
2427
outputData[4] = orValue;
2428
uint xorValue = atomicXor(sharedVariable, inputData[5]);
2429
outputData[5] = xorValue;
2430
uint exchangeValue = atomicExchange(sharedVariable, inputData[6]);
2431
outputData[6] = exchangeValue;
2432
uint compSwapValue = atomicCompSwap(sharedVariable, 64u, inputData[7]);
2433
outputData[7] = compSwapValue;
2434
uint sharedVariable = atomicAdd(sharedVariable, inputData[8]);
2435
outputData[8] = sharedVariable;
2436
2437
}
2438
memoryBarrierShared();
2439
barrier();
2440
2441
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2442
uvec4(outputData[gl_LocalInvocationID.x]));
2443
})";
2444
2445
constexpr std::array<GLuint, 9> kInputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2446
constexpr std::array<GLuint, 9> kExpectedValues = {{0, 1, 1, 4, 0, 16, 48, 64, 128}};
2447
runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2448
kExpectedValues);
2449
}
2450
2451
// Verify using atomic functions inside expressions as unsigned int.
2452
TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithUnsigned)
2453
{
2454
// http://anglebug.com/5072
2455
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2456
2457
// Fails on AMD windows drivers. http://anglebug.com/3872
2458
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
2459
2460
constexpr char kCShader[] = R"(#version 310 es
2461
layout (local_size_x = 9, local_size_y = 1, local_size_z = 1) in;
2462
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2463
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2464
2465
shared highp uint sharedVariable;
2466
2467
shared highp uint inputData[9];
2468
shared highp uint outputData[9];
2469
2470
void main()
2471
{
2472
uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2473
inputData[gl_LocalInvocationID.x] = inputValue;
2474
memoryBarrierShared();
2475
barrier();
2476
2477
if (gl_LocalInvocationID.x == 0u)
2478
{
2479
sharedVariable = 0u;
2480
2481
outputData[0] = 1u + atomicAdd(sharedVariable, inputData[0]);
2482
outputData[1] = 1u + atomicMin(sharedVariable, inputData[1]);
2483
outputData[2] = 1u + atomicMax(sharedVariable, inputData[2]);
2484
outputData[3] = 1u + atomicAnd(sharedVariable, inputData[3]);
2485
outputData[4] = 1u + atomicOr(sharedVariable, inputData[4]);
2486
outputData[5] = 1u + atomicXor(sharedVariable, inputData[5]);
2487
outputData[6] = 1u + atomicExchange(sharedVariable, inputData[6]);
2488
outputData[7] = 1u + atomicCompSwap(sharedVariable, 64u, inputData[7]);
2489
outputData[8] = 1u + atomicAdd(sharedVariable, inputData[8]);
2490
}
2491
memoryBarrierShared();
2492
barrier();
2493
2494
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2495
uvec4(outputData[gl_LocalInvocationID.x]));
2496
})";
2497
2498
constexpr std::array<GLuint, 9> kInputData = {{1, 2, 4, 8, 16, 32, 64, 128, 1}};
2499
constexpr std::array<GLuint, 9> kExpectedValues = {{1, 2, 2, 5, 1, 17, 49, 65, 129}};
2500
runSharedMemoryTest<GLuint, 9, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2501
kExpectedValues);
2502
}
2503
2504
// Verify using nested atomic functions in expressions.
2505
TEST_P(ComputeShaderTest, AtomicFunctionsReturnWithMultipleTypes)
2506
{
2507
// http://anglebug.com/5072
2508
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2509
2510
constexpr char kCShader[] = R"(#version 310 es
2511
layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;
2512
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
2513
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
2514
2515
shared highp uint sharedVariable;
2516
shared highp int indexVariable;
2517
2518
shared highp uint inputData[4];
2519
shared highp uint outputData[4];
2520
2521
void main()
2522
{
2523
uint inputValue = imageLoad(srcImage, ivec2(gl_LocalInvocationID.xy)).x;
2524
inputData[gl_LocalInvocationID.x] = inputValue;
2525
memoryBarrierShared();
2526
barrier();
2527
2528
if (gl_LocalInvocationID.x == 0u)
2529
{
2530
sharedVariable = 0u;
2531
indexVariable = 2;
2532
2533
outputData[0] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2534
outputData[1] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2535
outputData[2] = 1u + atomicAdd(sharedVariable, inputData[atomicAdd(indexVariable, -1)]);
2536
outputData[3] = atomicAdd(sharedVariable, 0u);
2537
2538
}
2539
memoryBarrierShared();
2540
barrier();
2541
2542
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy),
2543
uvec4(outputData[gl_LocalInvocationID.x]));
2544
})";
2545
2546
constexpr std::array<GLuint, 4> kInputData = {{1, 2, 3, 0}};
2547
constexpr std::array<GLuint, 4> kExpectedValues = {{1, 4, 6, 6}};
2548
runSharedMemoryTest<GLuint, 4, 1>(kCShader, GL_R32UI, GL_UNSIGNED_INT, kInputData,
2549
kExpectedValues);
2550
}
2551
2552
// Basic uniform buffer functionality.
2553
TEST_P(ComputeShaderTest, UniformBuffer)
2554
{
2555
// http://anglebug.com/5072
2556
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2557
2558
GLTexture texture;
2559
GLBuffer buffer;
2560
GLFramebuffer framebuffer;
2561
constexpr char kCS[] = R"(#version 310 es
2562
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2563
uniform uni
2564
{
2565
uvec4 value;
2566
};
2567
layout(rgba32ui, binding = 0) writeonly uniform highp uimage2D uImage;
2568
void main()
2569
{
2570
imageStore(uImage, ivec2(gl_LocalInvocationID.xy), value);
2571
})";
2572
2573
constexpr int kWidth = 1, kHeight = 1;
2574
constexpr GLuint kInputValues[4] = {56, 57, 58, 59};
2575
2576
glBindTexture(GL_TEXTURE_2D, texture);
2577
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth, kHeight);
2578
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
2579
kInputValues);
2580
EXPECT_GL_NO_ERROR();
2581
2582
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2583
glUseProgram(program.get());
2584
2585
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
2586
EXPECT_NE(uniformBufferIndex, -1);
2587
GLuint data[4] = {201, 202, 203, 204};
2588
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
2589
glBufferData(GL_UNIFORM_BUFFER, sizeof(GLuint) * 4, data, GL_STATIC_DRAW);
2590
glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
2591
glUniformBlockBinding(program, uniformBufferIndex, 0);
2592
EXPECT_GL_NO_ERROR();
2593
2594
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
2595
EXPECT_GL_NO_ERROR();
2596
2597
glDispatchCompute(1, 1, 1);
2598
EXPECT_GL_NO_ERROR();
2599
2600
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2601
GLuint outputValues[kWidth * kHeight * 4];
2602
glUseProgram(0);
2603
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2604
2605
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
2606
EXPECT_GL_NO_ERROR();
2607
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
2608
EXPECT_GL_NO_ERROR();
2609
2610
for (int i = 0; i < kWidth * kHeight * 4; i++)
2611
{
2612
EXPECT_EQ(data[i], outputValues[i]);
2613
}
2614
}
2615
2616
// Test that storing data to image and then loading the same image data works correctly.
2617
TEST_P(ComputeShaderTest, StoreImageThenLoad)
2618
{
2619
// http://anglebug.com/5072
2620
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2621
2622
const char kCSSource[] = R"(#version 310 es
2623
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2624
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2625
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
2626
void main()
2627
{
2628
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2629
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
2630
})";
2631
2632
constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
2633
GLTexture texture[3];
2634
glBindTexture(GL_TEXTURE_2D, texture[0]);
2635
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2636
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
2637
EXPECT_GL_NO_ERROR();
2638
2639
glBindTexture(GL_TEXTURE_2D, texture[1]);
2640
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2641
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
2642
EXPECT_GL_NO_ERROR();
2643
2644
glBindTexture(GL_TEXTURE_2D, texture[2]);
2645
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2646
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
2647
EXPECT_GL_NO_ERROR();
2648
2649
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2650
glUseProgram(program.get());
2651
2652
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2653
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2654
2655
glDispatchCompute(1, 1, 1);
2656
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2657
EXPECT_GL_NO_ERROR();
2658
2659
glBindImageTexture(0, texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2660
glBindImageTexture(1, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2661
2662
glDispatchCompute(1, 1, 1);
2663
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2664
EXPECT_GL_NO_ERROR();
2665
2666
GLuint outputValue;
2667
GLFramebuffer framebuffer;
2668
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2669
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
2670
glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
2671
EXPECT_GL_NO_ERROR();
2672
2673
EXPECT_EQ(300u, outputValue);
2674
}
2675
2676
// Test that loading image data and then storing data to the same image works correctly.
2677
TEST_P(ComputeShaderTest, LoadImageThenStore)
2678
{
2679
// http://anglebug.com/5072
2680
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
2681
2682
const char kCSSource[] = R"(#version 310 es
2683
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2684
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
2685
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
2686
void main()
2687
{
2688
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
2689
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
2690
})";
2691
2692
constexpr GLuint kInputValues[3][1] = {{300}, {200}, {100}};
2693
GLTexture texture[3];
2694
glBindTexture(GL_TEXTURE_2D, texture[0]);
2695
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2696
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[0]);
2697
EXPECT_GL_NO_ERROR();
2698
2699
glBindTexture(GL_TEXTURE_2D, texture[1]);
2700
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2701
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[1]);
2702
EXPECT_GL_NO_ERROR();
2703
2704
glBindTexture(GL_TEXTURE_2D, texture[2]);
2705
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 1, 1);
2706
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, kInputValues[2]);
2707
EXPECT_GL_NO_ERROR();
2708
2709
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2710
glUseProgram(program.get());
2711
2712
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2713
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2714
2715
glDispatchCompute(1, 1, 1);
2716
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2717
EXPECT_GL_NO_ERROR();
2718
2719
glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
2720
glBindImageTexture(1, texture[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
2721
2722
glDispatchCompute(1, 1, 1);
2723
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
2724
EXPECT_GL_NO_ERROR();
2725
2726
GLuint outputValue;
2727
GLFramebuffer framebuffer;
2728
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
2729
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[0], 0);
2730
glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValue);
2731
EXPECT_GL_NO_ERROR();
2732
2733
EXPECT_EQ(100u, outputValue);
2734
}
2735
2736
// Test that the length of a struct buffer variable is supported.
2737
TEST_P(ComputeShaderTest, ShaderStorageBlocksStructLength)
2738
{
2739
const char kCSSource[] = R"(#version 310 es
2740
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
2741
2742
struct Particle
2743
{
2744
int len;
2745
};
2746
2747
layout(binding = 0, std430) readonly buffer Buf1
2748
{
2749
Particle particlesRead[];
2750
};
2751
2752
layout(binding = 1, std430) buffer Buf2
2753
{
2754
Particle particlesWrite[];
2755
};
2756
2757
void main()
2758
{
2759
int index = int(gl_GlobalInvocationID.x);
2760
particlesWrite[index].len = particlesRead.length();
2761
})";
2762
2763
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2764
EXPECT_GL_NO_ERROR();
2765
}
2766
2767
// Test that scalar buffer variables are supported.
2768
TEST_P(ComputeShaderTest, ShaderStorageBlocksScalar)
2769
{
2770
const char kCSSource[] = R"(#version 310 es
2771
layout(local_size_x=1) in;
2772
layout(std140, binding = 0) buffer blockA {
2773
uvec3 uv;
2774
float f;
2775
} instanceA;
2776
layout(std140, binding = 1) buffer blockB {
2777
vec2 v;
2778
uint u[3];
2779
float f;
2780
};
2781
void main()
2782
{
2783
f = instanceA.f;
2784
})";
2785
2786
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2787
EXPECT_GL_NO_ERROR();
2788
}
2789
2790
// Test that vector buffer variables are supported.
2791
TEST_P(ComputeShaderTest, ShaderStorageBlocksVector)
2792
{
2793
const char kCSSource[] = R"(#version 310 es
2794
layout(local_size_x=1) in;
2795
layout(std140, binding = 0) buffer blockA {
2796
vec2 f;
2797
} instanceA;
2798
layout(std140, binding = 1) buffer blockB {
2799
vec3 f;
2800
};
2801
void main()
2802
{
2803
f[1] = instanceA.f[0];
2804
})";
2805
2806
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2807
EXPECT_GL_NO_ERROR();
2808
}
2809
2810
// Test that matrix buffer variables are supported.
2811
TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrix)
2812
{
2813
const char kCSSource[] = R"(#version 310 es
2814
layout(local_size_x=1) in;
2815
layout(std140, binding = 0) buffer blockA {
2816
mat3x4 m;
2817
} instanceA;
2818
layout(std140, binding = 1) buffer blockB {
2819
mat3x4 m;
2820
};
2821
void main()
2822
{
2823
m[0][1] = instanceA.m[0][1];
2824
})";
2825
2826
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2827
EXPECT_GL_NO_ERROR();
2828
}
2829
2830
// Test that scalar array buffer variables are supported.
2831
TEST_P(ComputeShaderTest, ShaderStorageBlocksScalarArray)
2832
{
2833
const char kCSSource[] = R"(#version 310 es
2834
layout(local_size_x=8) in;
2835
layout(std140, binding = 0) buffer blockA {
2836
float f[8];
2837
} instanceA;
2838
layout(std140, binding = 1) buffer blockB {
2839
float f[8];
2840
};
2841
void main()
2842
{
2843
f[gl_LocalInvocationIndex] = instanceA.f[gl_LocalInvocationIndex];
2844
})";
2845
2846
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2847
EXPECT_GL_NO_ERROR();
2848
}
2849
2850
// Test that vector array buffer variables are supported.
2851
TEST_P(ComputeShaderTest, ShaderStorageBlocksVectorArray)
2852
{
2853
const char kCSSource[] = R"(#version 310 es
2854
layout(local_size_x=4) in;
2855
layout(std140, binding = 0) buffer blockA {
2856
vec2 v[4];
2857
} instanceA;
2858
layout(std140, binding = 1) buffer blockB {
2859
vec4 v[4];
2860
};
2861
void main()
2862
{
2863
v[0][gl_LocalInvocationIndex] = instanceA.v[gl_LocalInvocationIndex][1];
2864
})";
2865
2866
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2867
EXPECT_GL_NO_ERROR();
2868
}
2869
2870
// Test that matrix array buffer variables are supported.
2871
TEST_P(ComputeShaderTest, ShaderStorageBlocksMatrixArray)
2872
{
2873
const char kCSSource[] = R"(#version 310 es
2874
layout(local_size_x=8) in;
2875
layout(std140, binding = 0) buffer blockA {
2876
float v1[5];
2877
mat4 m[8];
2878
} instanceA;
2879
layout(std140, binding = 1) buffer blockB {
2880
vec2 v1[3];
2881
mat4 m[8];
2882
};
2883
void main()
2884
{
2885
float data = instanceA.m[gl_LocalInvocationIndex][0][0];
2886
m[gl_LocalInvocationIndex][gl_LocalInvocationIndex][gl_LocalInvocationIndex] = data;
2887
})";
2888
2889
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2890
EXPECT_GL_NO_ERROR();
2891
}
2892
2893
// Test that shader storage blocks only in assignment right is supported.
2894
TEST_P(ComputeShaderTest, ShaderStorageBlocksInAssignmentRight)
2895
{
2896
const char kCSSource[] = R"(#version 310 es
2897
layout(local_size_x=8) in;
2898
layout(std140, binding = 0) buffer blockA {
2899
float data[8];
2900
} instanceA;
2901
layout(r32f, binding = 0) writeonly uniform highp image2D imageOut;
2902
2903
void main()
2904
{
2905
float data = 1.0;
2906
data = instanceA.data[gl_LocalInvocationIndex];
2907
imageStore(imageOut, ivec2(gl_LocalInvocationID.xy), vec4(data));
2908
})";
2909
2910
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2911
EXPECT_GL_NO_ERROR();
2912
}
2913
2914
// Test that shader storage blocks with unsized array are supported.
2915
TEST_P(ComputeShaderTest, ShaderStorageBlocksWithUnsizedArray)
2916
{
2917
const char kCSSource[] = R"(#version 310 es
2918
layout(local_size_x=8) in;
2919
layout(std140, binding = 0) buffer blockA {
2920
float v[];
2921
} instanceA;
2922
layout(std140, binding = 0) buffer blockB {
2923
float v[];
2924
} instanceB[1];
2925
2926
void main()
2927
{
2928
float data = instanceA.v[gl_LocalInvocationIndex];
2929
instanceB[0].v[gl_LocalInvocationIndex * 2u + 1u] = data;
2930
}
2931
)";
2932
2933
ANGLE_GL_COMPUTE_PROGRAM(program, kCSSource);
2934
EXPECT_GL_NO_ERROR();
2935
}
2936
2937
// Test that EOpIndexDirect/EOpIndexIndirect/EOpIndexDirectStruct nodes in ssbo EOpIndexInDirect
2938
// don't need to calculate the offset and should be translated by OutputHLSL directly.
2939
TEST_P(ComputeShaderTest, IndexAndDotOperatorsInSSBOIndexIndirectOperator)
2940
{
2941
constexpr char kComputeShaderSource[] = R"(#version 310 es
2942
layout(local_size_x=1) in;
2943
layout(std140, binding = 0) buffer blockA {
2944
float v[4];
2945
};
2946
layout(std140, binding = 1) buffer blockB {
2947
float v[4];
2948
} instanceB[1];
2949
struct S
2950
{
2951
uvec4 index[2];
2952
} s;
2953
void main()
2954
{
2955
s.index[0] = uvec4(0u, 1u, 2u, 3u);
2956
float data = v[s.index[0].y];
2957
instanceB[0].v[s.index[0].x] = data;
2958
})";
2959
2960
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2961
EXPECT_GL_NO_ERROR();
2962
}
2963
2964
// Test that swizzle node in non-SSBO symbol works well.
2965
TEST_P(ComputeShaderTest, ShaderStorageBlocksWithNonSSBOSwizzle)
2966
{
2967
constexpr char kComputeShaderSource[] = R"(#version 310 es
2968
layout(local_size_x=8) in;
2969
layout(std140, binding = 0) buffer blockA {
2970
float v[8];
2971
};
2972
layout(std140, binding = 1) buffer blockB {
2973
float v[8];
2974
} instanceB[1];
2975
2976
void main()
2977
{
2978
float data = v[gl_GlobalInvocationID.x];
2979
instanceB[0].v[gl_GlobalInvocationID.x] = data;
2980
})";
2981
2982
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2983
EXPECT_GL_NO_ERROR();
2984
}
2985
2986
// Test that swizzle node in SSBO symbol works well.
2987
TEST_P(ComputeShaderTest, ShaderStorageBlocksWithSSBOSwizzle)
2988
{
2989
constexpr char kComputeShaderSource[] = R"(#version 310 es
2990
layout(local_size_x=1) in;
2991
layout(std140, binding = 0) buffer blockA {
2992
vec2 v;
2993
};
2994
layout(std140, binding = 1) buffer blockB {
2995
float v;
2996
} instanceB[1];
2997
2998
void main()
2999
{
3000
instanceB[0].v = v.x;
3001
})";
3002
3003
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3004
EXPECT_GL_NO_ERROR();
3005
}
3006
3007
// Test that a large struct array in std140 uniform block won't consume too much time.
3008
TEST_P(ComputeShaderTest, LargeStructArraySize)
3009
{
3010
constexpr char kComputeShaderSource[] = R"(#version 310 es
3011
layout(local_size_x=8) in;
3012
precision mediump float;
3013
3014
struct InstancingData
3015
{
3016
mat4 transformation;
3017
};
3018
3019
#define MAX_INSTANCE_COUNT 800
3020
3021
layout(std140) uniform InstanceBlock
3022
{
3023
InstancingData instances[MAX_INSTANCE_COUNT];
3024
};
3025
3026
layout(std140, binding = 1) buffer blockB {
3027
mat4 v[];
3028
} instanceB;
3029
3030
void main()
3031
{
3032
instanceB.v[gl_GlobalInvocationID.x] = instances[gl_GlobalInvocationID.x].transformation;
3033
})";
3034
3035
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
3036
EXPECT_GL_NO_ERROR();
3037
}
3038
3039
// Check that it is not possible to create a compute shader when the context does not support ES
3040
// 3.10
3041
TEST_P(ComputeShaderTestES3, NotSupported)
3042
{
3043
GLuint computeShaderHandle = glCreateShader(GL_COMPUTE_SHADER);
3044
EXPECT_EQ(0u, computeShaderHandle);
3045
EXPECT_GL_ERROR(GL_INVALID_ENUM);
3046
}
3047
3048
// The contents of shared variables should be cleared to zero at the beginning of shader execution.
3049
TEST_P(WebGL2ComputeTest, sharedVariablesShouldBeZero)
3050
{
3051
// http://anglebug.com/3226
3052
ANGLE_SKIP_TEST_IF(IsD3D11());
3053
3054
// Fails on Android, AMD/windows and Intel/windows. Probably works by chance on other
3055
// platforms, so suppressing on all platforms to avoid possible flakiness.
3056
// http://anglebug.com/3869
3057
ANGLE_SKIP_TEST_IF(IsVulkan());
3058
3059
// http://anglebug.com/4092
3060
ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
3061
ANGLE_SKIP_TEST_IF(IsOpenGL() &&
3062
((getClientMajorVersion() == 3) && (getClientMinorVersion() >= 1)));
3063
3064
const char kCSShader[] = R"(#version 310 es
3065
layout (local_size_x = 4, local_size_y = 4, local_size_z = 1) in;
3066
layout (r32ui, binding = 0) readonly uniform highp uimage2D srcImage;
3067
layout (r32ui, binding = 1) writeonly uniform highp uimage2D dstImage;
3068
struct S {
3069
float f;
3070
int i;
3071
uint u;
3072
bool b;
3073
vec4 v[64];
3074
};
3075
3076
shared S vars[16];
3077
void main()
3078
{
3079
S zeroS;
3080
zeroS.f = 0.0f;
3081
zeroS.i = 0;
3082
zeroS.u = 0u;
3083
zeroS.b = false;
3084
for (int i = 0; i < 64; i++)
3085
{
3086
zeroS.v[i] = vec4(0.0f);
3087
}
3088
3089
uint tid = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 4u;
3090
uint value = (zeroS == vars[tid] ? 127u : 0u);
3091
imageStore(dstImage, ivec2(gl_LocalInvocationID.xy), uvec4(value));
3092
})";
3093
3094
const std::array<GLuint, 16> inputData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
3095
const std::array<GLuint, 16> expectedValues = {
3096
{127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127}};
3097
runSharedMemoryTest<GLuint, 4, 4>(kCSShader, GL_R32UI, GL_UNSIGNED_INT, inputData,
3098
expectedValues);
3099
}
3100
3101
// Test uniform dirty in compute shader, and verify the contents.
3102
TEST_P(ComputeShaderTest, UniformDirty)
3103
{
3104
// http://anglebug.com/5072
3105
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3106
3107
// glReadPixels is getting the result of the first dispatch call. http://anglebug.com/3879
3108
ANGLE_SKIP_TEST_IF(IsVulkan() && IsWindows() && (IsAMD() || IsNVIDIA()));
3109
3110
GLTexture texture[2];
3111
GLFramebuffer framebuffer;
3112
constexpr char kCS[] = R"(#version 310 es
3113
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3114
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3115
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3116
uniform uint factor;
3117
void main()
3118
{
3119
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3120
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value * factor);
3121
})";
3122
3123
constexpr int kWidth = 1, kHeight = 1;
3124
constexpr GLuint kInputValues[2][1] = {{200}, {100}};
3125
3126
glBindTexture(GL_TEXTURE_2D, texture[0]);
3127
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3128
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3129
kInputValues[0]);
3130
EXPECT_GL_NO_ERROR();
3131
3132
glBindTexture(GL_TEXTURE_2D, texture[1]);
3133
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3134
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3135
kInputValues[1]);
3136
EXPECT_GL_NO_ERROR();
3137
3138
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3139
glUseProgram(program);
3140
3141
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3142
EXPECT_GL_NO_ERROR();
3143
3144
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3145
EXPECT_GL_NO_ERROR();
3146
3147
glUniform1ui(glGetUniformLocation(program, "factor"), 2);
3148
EXPECT_GL_NO_ERROR();
3149
3150
glDispatchCompute(1, 1, 1);
3151
EXPECT_GL_NO_ERROR();
3152
3153
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3154
3155
glUniform1ui(glGetUniformLocation(program, "factor"), 3);
3156
EXPECT_GL_NO_ERROR();
3157
3158
glDispatchCompute(1, 1, 1);
3159
EXPECT_GL_NO_ERROR();
3160
3161
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3162
GLuint outputValues[kWidth * kHeight];
3163
GLuint expectedValue = 600;
3164
glUseProgram(0);
3165
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3166
3167
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3168
EXPECT_GL_NO_ERROR();
3169
glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
3170
EXPECT_GL_NO_ERROR();
3171
3172
for (int i = 0; i < kWidth * kHeight; i++)
3173
{
3174
EXPECT_EQ(expectedValue, outputValues[i]) << " index " << i;
3175
}
3176
}
3177
3178
// Test storage buffer bound is unchanged, shader writes it, buffer content should be updated.
3179
TEST_P(ComputeShaderTest, StorageBufferBoundUnchanged)
3180
{
3181
// http://anglebug.com/4092
3182
ANGLE_SKIP_TEST_IF(isSwiftshader());
3183
constexpr char kCS[] = R"(#version 310 es
3184
layout(local_size_x=16, local_size_y=16) in;
3185
precision highp usampler2D;
3186
uniform usampler2D tex;
3187
uniform uint factor;
3188
layout(std140, binding = 0) buffer buf {
3189
uint outData[16][16];
3190
};
3191
3192
void main()
3193
{
3194
uint x = gl_LocalInvocationID.x;
3195
uint y = gl_LocalInvocationID.y;
3196
float xCoord = float(x) / float(16);
3197
float yCoord = float(y) / float(16);
3198
outData[y][x] = texture(tex, vec2(xCoord, yCoord)).x + factor;
3199
})";
3200
3201
constexpr unsigned int kWidth = 16;
3202
constexpr unsigned int kHeight = 16;
3203
GLTexture tex;
3204
glBindTexture(GL_TEXTURE_2D, tex);
3205
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3206
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3207
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth, kHeight);
3208
GLuint texels[kHeight][kWidth] = {{0}};
3209
for (unsigned int y = 0; y < kHeight; ++y)
3210
{
3211
for (unsigned int x = 0; x < kWidth; ++x)
3212
{
3213
texels[y][x] = x + y * kWidth;
3214
}
3215
}
3216
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
3217
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT,
3218
texels);
3219
glBindTexture(GL_TEXTURE_2D, 0);
3220
3221
// The array stride are rounded up to the base alignment of a vec4 for std140 layout.
3222
constexpr unsigned int kArrayStride = 16;
3223
GLBuffer ssbo;
3224
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3225
glBufferData(GL_SHADER_STORAGE_BUFFER, kWidth * kHeight * kArrayStride, nullptr,
3226
GL_STREAM_DRAW);
3227
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3228
EXPECT_GL_NO_ERROR();
3229
3230
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3231
glUseProgram(program);
3232
3233
glActiveTexture(GL_TEXTURE0);
3234
glBindTexture(GL_TEXTURE_2D, tex);
3235
glUniform1i(glGetUniformLocation(program, "tex"), 0);
3236
glUniform1ui(glGetUniformLocation(program, "factor"), 2);
3237
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
3238
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
3239
3240
glDispatchCompute(1, 1, 1);
3241
3242
const GLuint *ptr1 = reinterpret_cast<const GLuint *>(glMapBufferRange(
3243
GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
3244
EXPECT_GL_NO_ERROR();
3245
for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
3246
{
3247
EXPECT_EQ(idx + 2, *(ptr1 + idx * kArrayStride / 4));
3248
}
3249
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3250
glUniform1ui(glGetUniformLocation(program, "factor"), 3);
3251
glDispatchCompute(1, 1, 1);
3252
3253
const GLuint *ptr2 = reinterpret_cast<const GLuint *>(glMapBufferRange(
3254
GL_SHADER_STORAGE_BUFFER, 0, kWidth * kHeight * kArrayStride, GL_MAP_READ_BIT));
3255
EXPECT_GL_NO_ERROR();
3256
for (unsigned int idx = 0; idx < kWidth * kHeight; idx++)
3257
{
3258
EXPECT_EQ(idx + 3, *(ptr2 + idx * kArrayStride / 4));
3259
}
3260
}
3261
3262
// Test imageSize to access mipmap slice.
3263
TEST_P(ComputeShaderTest, ImageSizeMipmapSlice)
3264
{
3265
// TODO([email protected]): http://anglebug.com/3101
3266
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
3267
3268
// http://anglebug.com/4392
3269
ANGLE_SKIP_TEST_IF(IsWindows() && IsNVIDIA() && IsD3D11());
3270
3271
GLTexture texture[2];
3272
GLFramebuffer framebuffer;
3273
const char kCS[] = R"(#version 310 es
3274
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3275
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3276
layout(rgba32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3277
void main()
3278
{
3279
ivec2 size = imageSize(uImage_1);
3280
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), uvec4(size, 0, 0));
3281
})";
3282
3283
constexpr int kWidth1 = 8, kHeight1 = 4, kWidth2 = 1, kHeight2 = 1;
3284
constexpr GLuint kInputValues[] = {0, 0, 0, 0};
3285
3286
glBindTexture(GL_TEXTURE_2D, texture[0]);
3287
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);
3288
EXPECT_GL_NO_ERROR();
3289
3290
glBindTexture(GL_TEXTURE_2D, texture[1]);
3291
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, kWidth2, kHeight2);
3292
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
3293
kInputValues);
3294
EXPECT_GL_NO_ERROR();
3295
3296
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3297
glUseProgram(program);
3298
3299
glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3300
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
3301
3302
glDispatchCompute(1, 1, 1);
3303
EXPECT_GL_NO_ERROR();
3304
3305
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3306
GLuint outputValues[kWidth2 * kHeight2 * 4];
3307
constexpr GLuint expectedValue[] = {4, 2};
3308
glUseProgram(0);
3309
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3310
3311
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3312
EXPECT_GL_NO_ERROR();
3313
glReadPixels(0, 0, kWidth2, kHeight2, GL_RGBA_INTEGER, GL_UNSIGNED_INT, outputValues);
3314
EXPECT_GL_NO_ERROR();
3315
3316
for (int i = 0; i < kWidth2 * kHeight2; i++)
3317
{
3318
EXPECT_EQ(expectedValue[i], outputValues[i]);
3319
EXPECT_EQ(expectedValue[i + 1], outputValues[i + 1]);
3320
}
3321
}
3322
3323
// Test imageLoad to access mipmap slice.
3324
TEST_P(ComputeShaderTest, ImageLoadMipmapSlice)
3325
{
3326
// TODO([email protected]): http://anglebug.com/3101
3327
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
3328
3329
GLTexture texture[2];
3330
GLFramebuffer framebuffer;
3331
constexpr char kCS[] = R"(#version 310 es
3332
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3333
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3334
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3335
void main()
3336
{
3337
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3338
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
3339
})";
3340
3341
constexpr int kWidth1 = 2, kHeight1 = 2, kWidth2 = 1, kHeight2 = 1;
3342
constexpr GLuint kInputValues11[] = {3, 3, 3, 3};
3343
constexpr GLuint kInputValues12[] = {2};
3344
constexpr GLuint kInputValues2[] = {1};
3345
3346
glBindTexture(GL_TEXTURE_2D, texture[0]);
3347
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth1, kHeight1);
3348
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3349
kInputValues11);
3350
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3351
kInputValues12);
3352
EXPECT_GL_NO_ERROR();
3353
3354
glBindTexture(GL_TEXTURE_2D, texture[1]);
3355
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth2, kHeight2);
3356
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3357
kInputValues2);
3358
EXPECT_GL_NO_ERROR();
3359
3360
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3361
glUseProgram(program);
3362
3363
glBindImageTexture(0, texture[0], 1, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3364
glBindImageTexture(1, texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3365
3366
glDispatchCompute(1, 1, 1);
3367
EXPECT_GL_NO_ERROR();
3368
3369
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3370
GLuint outputValues;
3371
constexpr GLuint expectedValue = 2;
3372
glUseProgram(0);
3373
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3374
3375
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3376
EXPECT_GL_NO_ERROR();
3377
glReadPixels(0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);
3378
EXPECT_GL_NO_ERROR();
3379
EXPECT_EQ(expectedValue, outputValues);
3380
}
3381
3382
// Test imageStore to access mipmap slice.
3383
TEST_P(ComputeShaderTest, ImageStoreMipmapSlice)
3384
{
3385
// TODO([email protected]): http://anglebug.com/3101
3386
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3387
3388
GLTexture texture[2];
3389
GLFramebuffer framebuffer;
3390
constexpr char kCS[] = R"(#version 310 es
3391
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3392
layout(r32ui, binding = 0) readonly uniform highp uimage2D uImage_1;
3393
layout(r32ui, binding = 1) writeonly uniform highp uimage2D uImage_2;
3394
void main()
3395
{
3396
uvec4 value = imageLoad(uImage_1, ivec2(gl_LocalInvocationID.xy));
3397
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
3398
})";
3399
3400
constexpr int kWidth1 = 1, kHeight1 = 1, kWidth2 = 2, kHeight2 = 2;
3401
constexpr GLuint kInputValues1[] = {3};
3402
constexpr GLuint kInputValues21[] = {2, 2, 2, 2};
3403
constexpr GLuint kInputValues22[] = {1};
3404
3405
glBindTexture(GL_TEXTURE_2D, texture[0]);
3406
glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, kWidth1, kHeight1);
3407
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3408
kInputValues1);
3409
EXPECT_GL_NO_ERROR();
3410
3411
glBindTexture(GL_TEXTURE_2D, texture[1]);
3412
glTexStorage2D(GL_TEXTURE_2D, 2, GL_R32UI, kWidth2, kHeight2);
3413
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth2, kHeight2, GL_RED_INTEGER, GL_UNSIGNED_INT,
3414
kInputValues21);
3415
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT,
3416
kInputValues22);
3417
EXPECT_GL_NO_ERROR();
3418
3419
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3420
glUseProgram(program);
3421
3422
glBindImageTexture(0, texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
3423
glBindImageTexture(1, texture[1], 1, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
3424
3425
glDispatchCompute(1, 1, 1);
3426
EXPECT_GL_NO_ERROR();
3427
3428
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3429
GLuint outputValues;
3430
constexpr GLuint expectedValue = 3;
3431
glUseProgram(0);
3432
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3433
3434
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 1);
3435
EXPECT_GL_NO_ERROR();
3436
glReadPixels(0, 0, kWidth1, kHeight1, GL_RED_INTEGER, GL_UNSIGNED_INT, &outputValues);
3437
EXPECT_GL_NO_ERROR();
3438
EXPECT_EQ(expectedValue, outputValues);
3439
}
3440
3441
// Test that a resource is bound on render pipeline output, and then it's bound as the compute
3442
// pipeline input. It works well. See http://anglebug.com/3658
3443
TEST_P(ComputeShaderTest, DrawTexture1DispatchTexture2)
3444
{
3445
// http://anglebug.com/5072
3446
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3447
3448
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"));
3449
3450
const char kCSSource[] = R"(#version 310 es
3451
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3452
precision highp sampler2D;
3453
uniform sampler2D tex;
3454
layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3455
void main()
3456
{
3457
vec4 value = texelFetch(tex, ivec2(gl_LocalInvocationID.xy), 0);
3458
imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(value.x - 1.0, 1.0, 0.0, value.w - 1.0));
3459
})";
3460
3461
const char kVSSource[] = R"(#version 310 es
3462
layout (location = 0) in vec2 pos;
3463
out vec2 texCoord;
3464
void main(void) {
3465
texCoord = 0.5*pos + 0.5;
3466
gl_Position = vec4(pos, 0.0, 1.0);
3467
})";
3468
3469
const char kFSSource[] = R"(#version 310 es
3470
precision highp float;
3471
uniform sampler2D tex;
3472
in vec2 texCoord;
3473
out vec4 fragColor;
3474
void main(void) {
3475
fragColor = texture(tex, texCoord);
3476
})";
3477
3478
GLuint aPosLoc = 0;
3479
ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3480
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3481
glBindAttribLocation(program, aPosLoc, "pos");
3482
GLuint buffer;
3483
glGenBuffers(1, &buffer);
3484
glBindBuffer(GL_ARRAY_BUFFER, buffer);
3485
GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3486
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3487
glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3488
glEnableVertexAttribArray(aPosLoc);
3489
3490
constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3491
constexpr GLfloat kZero[4] = {0.0, 0.0, 0.0, 0.0};
3492
GLFramebuffer framebuffer;
3493
GLTexture texture[3];
3494
glBindTexture(GL_TEXTURE_2D, texture[0]);
3495
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3496
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3497
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3498
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3499
3500
glBindTexture(GL_TEXTURE_2D, texture[1]);
3501
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3502
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);
3503
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3504
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3505
3506
glBindTexture(GL_TEXTURE_2D, texture[2]);
3507
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3508
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kZero);
3509
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3510
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3511
3512
glUseProgram(program);
3513
glActiveTexture(GL_TEXTURE0);
3514
glBindTexture(GL_TEXTURE_2D, texture[0]);
3515
glUniform1i(glGetUniformLocation(program, "tex"), 0);
3516
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
3517
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[1], 0);
3518
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3519
EXPECT_GL_NO_ERROR();
3520
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3521
GLfloat actual[4];
3522
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);
3523
EXPECT_GL_NO_ERROR();
3524
EXPECT_EQ(1.0, actual[0]);
3525
EXPECT_EQ(0.0, actual[1]);
3526
EXPECT_EQ(0.0, actual[2]);
3527
EXPECT_EQ(1.0, actual[3]);
3528
3529
glUseProgram(csProgram);
3530
glActiveTexture(GL_TEXTURE0);
3531
glBindTexture(GL_TEXTURE_2D, texture[1]);
3532
glUniform1i(glGetUniformLocation(program, "tex"), 0);
3533
glBindImageTexture(0, texture[2], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3534
glDispatchCompute(1, 1, 1);
3535
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
3536
3537
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
3538
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture[2], 0);
3539
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, actual);
3540
EXPECT_GL_NO_ERROR();
3541
EXPECT_EQ(0.0, actual[0]);
3542
EXPECT_EQ(1.0, actual[1]);
3543
EXPECT_EQ(0.0, actual[2]);
3544
EXPECT_EQ(0.0, actual[3]);
3545
}
3546
3547
// Test that render pipeline and compute pipeline access to the same texture.
3548
// Steps:
3549
// 1. DispatchCompute.
3550
// 2. DrawArrays.
3551
TEST_P(ComputeShaderTest, DispatchDraw)
3552
{
3553
// http://anglebug.com/5072
3554
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3555
3556
const char kCSSource[] = R"(#version 310 es
3557
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3558
layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3559
void main()
3560
{
3561
imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));
3562
})";
3563
3564
const char kVSSource[] = R"(#version 310 es
3565
layout (location = 0) in vec2 pos;
3566
out vec2 texCoord;
3567
void main(void) {
3568
texCoord = 0.5*pos + 0.5;
3569
gl_Position = vec4(pos, 0.0, 1.0);
3570
})";
3571
3572
const char kFSSource[] = R"(#version 310 es
3573
precision highp float;
3574
uniform sampler2D tex;
3575
in vec2 texCoord;
3576
out vec4 fragColor;
3577
void main(void) {
3578
fragColor = texture(tex, texCoord);
3579
})";
3580
3581
GLuint aPosLoc = 0;
3582
ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3583
glBindAttribLocation(program, aPosLoc, "pos");
3584
GLuint buffer;
3585
glGenBuffers(1, &buffer);
3586
glBindBuffer(GL_ARRAY_BUFFER, buffer);
3587
GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3588
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3589
glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3590
glEnableVertexAttribArray(aPosLoc);
3591
3592
constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3593
GLTexture texture;
3594
glBindTexture(GL_TEXTURE_2D, texture);
3595
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3596
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3597
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3598
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3599
EXPECT_GL_NO_ERROR();
3600
3601
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3602
glUseProgram(csProgram);
3603
3604
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3605
3606
glDispatchCompute(1, 1, 1);
3607
EXPECT_GL_NO_ERROR();
3608
3609
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3610
glUseProgram(program);
3611
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3612
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
3613
}
3614
3615
// Test that render pipeline and compute pipeline access to the same texture.
3616
// Steps:
3617
// 1. DrawArrays.
3618
// 2. DispatchCompute.
3619
// 3. DispatchCompute.
3620
// 4. DrawArrays.
3621
TEST_P(ComputeShaderTest, DrawDispatchDispatchDraw)
3622
{
3623
// http://anglebug.com/5072
3624
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3625
3626
// Fails on AMD windows drivers. http://anglebug.com/3871
3627
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
3628
3629
const char kCSSource[] = R"(#version 310 es
3630
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3631
layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3632
uniform float factor;
3633
void main()
3634
{
3635
imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(factor, 0.0, 1.0, 1.0));
3636
})";
3637
3638
const char kVSSource[] = R"(#version 310 es
3639
layout (location = 0) in vec2 pos;
3640
out vec2 texCoord;
3641
void main(void) {
3642
texCoord = 0.5*pos + 0.5;
3643
gl_Position = vec4(pos, 0.0, 1.0);
3644
})";
3645
3646
const char kFSSource[] = R"(#version 310 es
3647
precision highp float;
3648
uniform sampler2D tex;
3649
in vec2 texCoord;
3650
out vec4 fragColor;
3651
void main(void) {
3652
fragColor = texture(tex, texCoord);
3653
})";
3654
3655
GLuint aPosLoc = 0;
3656
ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3657
glBindAttribLocation(program, aPosLoc, "pos");
3658
GLuint buffer;
3659
glGenBuffers(1, &buffer);
3660
glBindBuffer(GL_ARRAY_BUFFER, buffer);
3661
GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3662
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3663
glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3664
glEnableVertexAttribArray(aPosLoc);
3665
3666
constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3667
GLTexture texture;
3668
glBindTexture(GL_TEXTURE_2D, texture);
3669
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3670
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3671
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3672
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3673
glUseProgram(program);
3674
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3675
EXPECT_GL_NO_ERROR();
3676
3677
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3678
glUseProgram(csProgram);
3679
glUniform1f(glGetUniformLocation(csProgram, "factor"), 0.0);
3680
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3681
EXPECT_GL_NO_ERROR();
3682
3683
glDispatchCompute(1, 1, 1);
3684
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3685
EXPECT_GL_NO_ERROR();
3686
3687
glUniform1f(glGetUniformLocation(csProgram, "factor"), 1.0);
3688
glDispatchCompute(1, 1, 1);
3689
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3690
EXPECT_GL_NO_ERROR();
3691
3692
glUseProgram(program);
3693
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3694
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::magenta);
3695
}
3696
3697
// Test that render pipeline and compute pipeline access to the same texture.
3698
// Steps:
3699
// 1. DispatchCompute.
3700
// 2. DrawArrays.
3701
// 3. DrawArrays.
3702
// 4. DispatchCompute.
3703
TEST_P(ComputeShaderTest, DispatchDrawDrawDispatch)
3704
{
3705
// http://anglebug.com/5072
3706
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3707
3708
const char kCSSource[] = R"(#version 310 es
3709
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3710
layout(rgba32f, binding = 0) writeonly uniform highp image2D image;
3711
3712
void main()
3713
{
3714
imageStore(image, ivec2(gl_LocalInvocationID.xy), vec4(0.0, 0.0, 1.0, 1.0));
3715
})";
3716
3717
const char kVSSource[] = R"(#version 310 es
3718
layout (location = 0) in vec2 pos;
3719
out vec2 texCoord;
3720
void main(void) {
3721
texCoord = 0.5*pos + 0.5;
3722
gl_Position = vec4(pos, 0.0, 1.0);
3723
})";
3724
3725
const char kFSSource[] = R"(#version 310 es
3726
precision highp float;
3727
uniform sampler2D tex;
3728
in vec2 texCoord;
3729
uniform float factor;
3730
out vec4 fragColor;
3731
void main(void) {
3732
fragColor = texture(tex, texCoord) + vec4(factor, 0.0, 0.0, 0.0);
3733
})";
3734
3735
GLuint aPosLoc = 0;
3736
ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3737
glBindAttribLocation(program, aPosLoc, "pos");
3738
GLuint buffer;
3739
glGenBuffers(1, &buffer);
3740
glBindBuffer(GL_ARRAY_BUFFER, buffer);
3741
GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3742
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 8, vertices, GL_STATIC_DRAW);
3743
glVertexAttribPointer(aPosLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
3744
glEnableVertexAttribArray(aPosLoc);
3745
3746
constexpr GLfloat kInputValues[4] = {1.0, 0.0, 0.0, 1.0};
3747
GLTexture texture;
3748
glBindTexture(GL_TEXTURE_2D, texture);
3749
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3750
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_FLOAT, kInputValues);
3751
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3752
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3753
3754
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3755
glUseProgram(csProgram);
3756
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
3757
3758
glDispatchCompute(1, 1, 1);
3759
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3760
EXPECT_GL_NO_ERROR();
3761
3762
glUseProgram(program);
3763
glUniform1f(glGetUniformLocation(program, "factor"), 0.0);
3764
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3765
EXPECT_GL_NO_ERROR();
3766
3767
glUniform1f(glGetUniformLocation(program, "factor"), 1.0);
3768
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3769
EXPECT_GL_NO_ERROR();
3770
3771
glUseProgram(csProgram);
3772
glDispatchCompute(1, 1, 1);
3773
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3774
EXPECT_GL_NO_ERROR();
3775
3776
glUseProgram(program);
3777
glUniform1f(glGetUniformLocation(program, "factor"), 0.0);
3778
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3779
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::blue);
3780
}
3781
3782
// Test that invalid memory barrier will produce an error.
3783
TEST_P(ComputeShaderTest, InvalidMemoryBarrier)
3784
{
3785
GLbitfield barriers = 0;
3786
glMemoryBarrier(barriers);
3787
EXPECT_GL_ERROR(GL_INVALID_VALUE);
3788
}
3789
3790
// test atomic counter increment
3791
// http://anglebug.com/3246
3792
TEST_P(ComputeShaderTest, AtomicCounterIncrement)
3793
{
3794
constexpr char kComputeShader[] = R"(#version 310 es
3795
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3796
layout(binding = 1, std430) buffer Output {
3797
uint preGet[1];
3798
uint increment[1];
3799
uint postGet[1];
3800
} sb_in;
3801
layout(binding=0) uniform atomic_uint counter0;
3802
3803
void main(void)
3804
{
3805
uint id = (gl_GlobalInvocationID.x);
3806
sb_in.preGet[0u] = atomicCounter(counter0);
3807
sb_in.increment[0u] = atomicCounterIncrement(counter0);
3808
sb_in.postGet[0u] = atomicCounter(counter0);
3809
}
3810
)";
3811
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
3812
EXPECT_GL_NO_ERROR();
3813
3814
glUseProgram(program);
3815
3816
constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
3817
3818
GLBuffer shaderStorageBuffer;
3819
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3820
glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
3821
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
3822
EXPECT_GL_NO_ERROR();
3823
3824
constexpr GLuint atomicBufferInitialData[] = {2u};
3825
GLuint atomicBuffer;
3826
glGenBuffers(1, &atomicBuffer);
3827
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicBuffer);
3828
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomicBufferInitialData), atomicBufferInitialData,
3829
GL_DYNAMIC_DRAW);
3830
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicBuffer);
3831
EXPECT_GL_NO_ERROR();
3832
3833
glDispatchCompute(1, 1, 1);
3834
glFinish();
3835
EXPECT_GL_NO_ERROR();
3836
3837
// read back
3838
const GLuint *ptr = reinterpret_cast<const GLuint *>(
3839
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
3840
EXPECT_EQ(2u, ptr[0]);
3841
EXPECT_EQ(2u, ptr[1]);
3842
EXPECT_EQ(3u, ptr[2]);
3843
3844
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3845
}
3846
3847
// Create a 'very large' array inside of a function in a compute shader.
3848
TEST_P(ComputeShaderTest, VeryLargeArrayInsideFunction)
3849
{
3850
constexpr char kComputeShader[] = R"(#version 310 es
3851
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3852
layout(binding = 0, std430) buffer Output {
3853
int value[1];
3854
} output_data;
3855
3856
void main()
3857
{
3858
int values[1000];
3859
for (int i = 0; i < values.length(); i++)
3860
{
3861
values[i] = 0;
3862
}
3863
3864
int total = 0;
3865
for (int i = 0; i < values.length(); i++)
3866
{
3867
total += i;
3868
values[i] = total;
3869
}
3870
output_data.value[0u] = values[1000-1];
3871
})";
3872
3873
ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShader);
3874
EXPECT_GL_NO_ERROR();
3875
3876
glUseProgram(program);
3877
3878
constexpr unsigned int kBytesPerComponent = sizeof(GLint);
3879
3880
GLBuffer shaderStorageBuffer;
3881
glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3882
glBufferData(GL_SHADER_STORAGE_BUFFER, 1 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
3883
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
3884
EXPECT_GL_NO_ERROR();
3885
3886
glDispatchCompute(1, 1, 1);
3887
glFinish();
3888
EXPECT_GL_NO_ERROR();
3889
3890
// read back
3891
const GLint *ptr = reinterpret_cast<const GLint *>(
3892
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 1 * kBytesPerComponent, GL_MAP_READ_BIT));
3893
EXPECT_EQ(499500, ptr[0]);
3894
3895
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3896
}
3897
3898
// Test that render pipeline and compute pipeline access to the same texture.
3899
// Steps:
3900
// 1. Clear the texture and DrawArrays.
3901
// 2. DispatchCompute to set the image's first pixel to a specific color.
3902
// 3. DrawArrays and check data.
3903
TEST_P(ComputeShaderTest, DrawDispatchDrawPreserve)
3904
{
3905
// http://anglebug.com/5072
3906
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
3907
3908
const char kCSSource[] = R"(#version 310 es
3909
layout(local_size_x=1, local_size_y=1) in;
3910
layout(rgba8, binding = 0) writeonly uniform highp image2D image;
3911
void main()
3912
{
3913
imageStore(image, ivec2(0, 0), vec4(0.0, 0.0, 1.0, 1.0));
3914
})";
3915
3916
const char kVSSource[] = R"(#version 310 es
3917
layout (location = 0) in vec2 pos;
3918
in vec4 inTex;
3919
out vec4 texCoord;
3920
void main(void) {
3921
texCoord = inTex;
3922
gl_Position = vec4(pos, 0.0, 1.0);
3923
})";
3924
3925
const char kFSSource[] = R"(#version 310 es
3926
precision highp float;
3927
uniform sampler2D tex;
3928
in vec4 texCoord;
3929
out vec4 fragColor;
3930
void main(void) {
3931
fragColor = texture(tex, texCoord.xy);
3932
})";
3933
GLuint aPosLoc = 0;
3934
ANGLE_GL_PROGRAM(program, kVSSource, kFSSource);
3935
glBindAttribLocation(program, aPosLoc, "pos");
3936
3937
unsigned char *data = new unsigned char[4 * getWindowWidth() * getWindowHeight()];
3938
for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
3939
{
3940
data[i * 4] = 0xff;
3941
data[i * 4 + 1] = 0;
3942
data[i * 4 + 2] = 0;
3943
data[i * 4 + 3] = 0xff;
3944
}
3945
GLTexture texture;
3946
glBindTexture(GL_TEXTURE_2D, texture);
3947
glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, getWindowWidth(), getWindowHeight());
3948
// Clear the texture level 0 to Red.
3949
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA,
3950
GL_UNSIGNED_BYTE, data);
3951
for (int i = 0; i < getWindowWidth() * getWindowHeight(); i++)
3952
{
3953
data[i * 4] = 0;
3954
data[i * 4 + 1] = 0xff;
3955
data[i * 4 + 2] = 0;
3956
data[i * 4 + 3] = 0xff;
3957
}
3958
// Clear the texture level 1 to Green.
3959
glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, getWindowWidth() / 2, getWindowHeight() / 2, GL_RGBA,
3960
GL_UNSIGNED_BYTE, data);
3961
delete[] data;
3962
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3963
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3964
glUseProgram(program);
3965
GLfloat vertices[] = {-1, -1, 1, -1, -1, 1, 1, 1};
3966
GLfloat texCoords[] = {0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
3967
GLint pos = glGetAttribLocation(program, "pos");
3968
glEnableVertexAttribArray(pos);
3969
glVertexAttribPointer(pos, 2, GL_FLOAT, GL_FALSE, 0, vertices);
3970
GLint posTex = glGetAttribLocation(program, "inTex");
3971
glEnableVertexAttribArray(posTex);
3972
glVertexAttribPointer(posTex, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
3973
3974
// Draw with level 0, the whole framebuffer should be Red.
3975
glViewport(0, 0, getWindowWidth(), getWindowHeight());
3976
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3977
EXPECT_GL_NO_ERROR();
3978
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
3979
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
3980
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
3981
// Draw with level 1, a quarter of the framebuffer should be Green.
3982
glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
3983
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3984
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3985
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
3986
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
3987
3988
// Clear the texture level 0's (0, 0) position to Blue.
3989
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
3990
ANGLE_GL_COMPUTE_PROGRAM(csProgram, kCSSource);
3991
glUseProgram(csProgram);
3992
glDispatchCompute(1, 1, 1);
3993
glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3994
EXPECT_GL_NO_ERROR();
3995
glFinish();
3996
3997
glUseProgram(program);
3998
// Draw with level 0, the first position should be Blue.
3999
glViewport(0, 0, getWindowWidth(), getWindowHeight());
4000
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4001
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
4002
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
4003
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
4004
// Draw with level 1, a quarter of the framebuffer should be Green.
4005
glViewport(0, 0, getWindowWidth() / 2, getWindowHeight() / 2);
4006
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4007
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4008
EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::green);
4009
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2 - 1, getWindowHeight() / 2 - 1, GLColor::green);
4010
}
4011
4012
// Test that maxComputeWorkGroupCount is valid number.
4013
TEST_P(ComputeShaderTest, ValidateMaxComputeWorkGroupCount)
4014
{
4015
constexpr char kCS[] = R"(#version 310 es
4016
layout(local_size_x=1) in;
4017
void main()
4018
{
4019
})";
4020
4021
GLuint program = glCreateProgram();
4022
GLuint cs = CompileShader(GL_COMPUTE_SHADER, kCS);
4023
EXPECT_NE(0u, cs);
4024
4025
glAttachShader(program, cs);
4026
glDeleteShader(cs);
4027
4028
GLint x, y, z;
4029
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &x);
4030
EXPECT_LE(65535, x);
4031
EXPECT_GE(std::numeric_limits<GLint>::max(), x);
4032
4033
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &y);
4034
EXPECT_LE(65535, y);
4035
EXPECT_GE(std::numeric_limits<GLint>::max(), y);
4036
4037
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &z);
4038
EXPECT_LE(65535, z);
4039
EXPECT_GE(std::numeric_limits<GLint>::max(), z);
4040
4041
glDeleteProgram(program);
4042
EXPECT_GL_NO_ERROR();
4043
}
4044
4045
// Validate that on Vulkan, compute pipeline driver uniforms descriptor set is updated after an
4046
// internal compute-based UtilsVk function is used. The latter is achieved through a draw with a
4047
// vertex buffer whose format is not natively supported. Atomic counters are used to make sure the
4048
// compute pipeline uses the driver uniforms descriptor set.
4049
TEST_P(ComputeShaderTest, DispatchConvertVertexDispatch)
4050
{
4051
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_vertex_type_10_10_10_2"));
4052
4053
constexpr uint32_t kVertexCount = 6;
4054
4055
constexpr char kCS[] = R"(#version 310 es
4056
layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4057
4058
layout(binding = 0) uniform atomic_uint ac;
4059
4060
layout(binding=0, std140) buffer VertexData
4061
{
4062
uint data[];
4063
};
4064
4065
void main()
4066
{
4067
atomicCounterIncrement(ac);
4068
data[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;
4069
})";
4070
4071
constexpr char kVS[] = R"(#version 310 es
4072
precision mediump float;
4073
4074
layout(location = 0) in vec4 position;
4075
layout(location = 1) in uvec4 data;
4076
4077
out vec4 color;
4078
4079
void main() {
4080
color = data.x < 6u && data.y == 0u && data.z == 0u && data.w == 0u
4081
? vec4(0.0, 1.0, 0.0, 1.0) : vec4(1.0, 0.0, 0.0, 1.0);
4082
gl_Position = position;
4083
})";
4084
4085
constexpr char kFS[] = R"(#version 310 es
4086
precision mediump float;
4087
in vec4 color;
4088
out vec4 colorOut;
4089
void main() {
4090
colorOut = color;
4091
})";
4092
4093
ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4094
ANGLE_GL_PROGRAM(programVSFS, kVS, kFS);
4095
EXPECT_GL_NO_ERROR();
4096
4097
// Create atomic counter buffer
4098
GLBuffer atomicCounterBuffer;
4099
constexpr GLuint kInitialAcbData = 0;
4100
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4101
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(kInitialAcbData), &kInitialAcbData,
4102
GL_STATIC_DRAW);
4103
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
4104
EXPECT_GL_NO_ERROR();
4105
4106
// Create vertex buffer
4107
constexpr unsigned kVertexBufferInitData[kVertexCount] = {};
4108
GLBuffer vertexBuffer;
4109
glBindBuffer(GL_SHADER_STORAGE_BUFFER, vertexBuffer);
4110
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kVertexBufferInitData), kVertexBufferInitData,
4111
GL_STATIC_DRAW);
4112
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, vertexBuffer);
4113
EXPECT_GL_NO_ERROR();
4114
4115
// Create position buffer
4116
constexpr GLfloat positions[kVertexCount * 2] = {1.0, 1.0, -1.0, 1.0, -1.0, -1.0,
4117
1.0, 1.0, -1.0, -1.0, 1.0, -1.0};
4118
GLBuffer positionBuffer;
4119
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4120
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);
4121
EXPECT_GL_NO_ERROR();
4122
4123
// Create vertex array
4124
GLVertexArray vao;
4125
glBindVertexArray(vao);
4126
4127
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4128
glEnableVertexAttribArray(0);
4129
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
4130
4131
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
4132
glEnableVertexAttribArray(1);
4133
glVertexAttribPointer(1, 4, GL_UNSIGNED_INT_10_10_10_2_OES, false, 0, 0);
4134
EXPECT_GL_NO_ERROR();
4135
4136
// Fill the vertex buffer with a dispatch call
4137
glUseProgram(programCS);
4138
glDispatchCompute(1, 1, 1);
4139
EXPECT_GL_NO_ERROR();
4140
4141
glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
4142
4143
// Draw using the vertex buffer, causing vertex format conversion in compute (in the Vulkan
4144
// backend)
4145
glUseProgram(programVSFS);
4146
glBindVertexArray(vao);
4147
glDrawArrays(GL_TRIANGLES, 0, kVertexCount);
4148
EXPECT_GL_NO_ERROR();
4149
4150
// Issue another dispatch call. The driver uniforms descriptor set must be rebound.
4151
glUseProgram(programCS);
4152
glDispatchCompute(1, 1, 1);
4153
EXPECT_GL_NO_ERROR();
4154
4155
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4156
4157
// Verify that the atomic counter has the expected value.
4158
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
4159
GLuint *mappedBuffer = static_cast<GLuint *>(
4160
glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
4161
EXPECT_EQ(kVertexCount * 2, mappedBuffer[0]);
4162
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
4163
}
4164
4165
// Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
4166
// made. Blit stencil may issue a dispatch call.
4167
TEST_P(ComputeShaderTest, DispatchBlitStencilDispatch)
4168
{
4169
// http://anglebug.com/5533
4170
ANGLE_SKIP_TEST_IF(IsQualcomm() && IsOpenGLES());
4171
4172
// http://anglebug.com/5072
4173
ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux() && IsOpenGL());
4174
4175
constexpr GLsizei kSize = 1;
4176
4177
constexpr char kCS[] = R"(#version 310 es
4178
layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4179
4180
uniform vec4 data;
4181
4182
layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4183
4184
void main()
4185
{
4186
imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4187
})";
4188
4189
ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4190
EXPECT_GL_NO_ERROR();
4191
4192
// Create a framebuffer with stencil buffer. Use multisampled textures so the future blit
4193
// cannot use vkCmdBlitImage.
4194
GLTexture color;
4195
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color);
4196
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, true);
4197
4198
GLTexture depthStencil;
4199
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depthStencil);
4200
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_DEPTH24_STENCIL8, kSize, kSize,
4201
true);
4202
4203
GLFramebuffer fbo;
4204
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4205
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color,
4206
0);
4207
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE,
4208
depthStencil, 0);
4209
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4210
ASSERT_GL_NO_ERROR();
4211
4212
// Clear the stencil and make sure it's done.
4213
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
4214
glClearStencil(0x55);
4215
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4216
4217
glEnable(GL_STENCIL_TEST);
4218
glStencilFunc(GL_EQUAL, 0x55, 0xFF);
4219
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4220
glStencilMask(0xFF);
4221
4222
ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
4223
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
4224
ASSERT_GL_NO_ERROR();
4225
4226
GLTexture colorCopy;
4227
glBindTexture(GL_TEXTURE_2D, colorCopy);
4228
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4229
4230
GLFramebuffer copyFbo;
4231
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
4232
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorCopy, 0);
4233
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
4234
glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
4235
ASSERT_GL_NO_ERROR();
4236
4237
glBindFramebuffer(GL_READ_FRAMEBUFFER, copyFbo);
4238
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4239
4240
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4241
4242
// Setup image for compute call
4243
GLTexture computeOut;
4244
glBindTexture(GL_TEXTURE_2D, computeOut);
4245
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4246
glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4247
ASSERT_GL_NO_ERROR();
4248
4249
// Issue a dispatch call.
4250
glUseProgram(programCS);
4251
GLint uniformLoc = glGetUniformLocation(programCS, "data");
4252
ASSERT_NE(uniformLoc, -1);
4253
4254
glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4255
glDispatchCompute(1, 1, 1);
4256
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4257
ASSERT_GL_NO_ERROR();
4258
4259
// Blit the stencil texture. This may use a compute shader internally.
4260
GLTexture depthStencilCopy;
4261
glBindTexture(GL_TEXTURE_2D, depthStencilCopy);
4262
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH24_STENCIL8, kSize, kSize);
4263
ASSERT_GL_NO_ERROR();
4264
4265
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, copyFbo);
4266
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
4267
depthStencilCopy, 0);
4268
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
4269
ASSERT_GL_NO_ERROR();
4270
4271
glBlitFramebuffer(0, 0, kSize, kSize, 0, 0, kSize, kSize, GL_STENCIL_BUFFER_BIT, GL_NEAREST);
4272
ASSERT_GL_NO_ERROR();
4273
4274
// Issue another dispatch call.
4275
glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
4276
glDispatchCompute(1, 1, 1);
4277
ASSERT_GL_NO_ERROR();
4278
4279
// Verify the results.
4280
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4281
glBindFramebuffer(GL_FRAMEBUFFER, copyFbo);
4282
glBindTexture(GL_TEXTURE_2D, computeOut);
4283
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
4284
ASSERT_GL_NO_ERROR();
4285
4286
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4287
4288
// Verify the blit copy results.
4289
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
4290
ASSERT_GL_NO_ERROR();
4291
4292
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
4293
}
4294
4295
// Validate that on Vulkan, compute pipeline is correctly bound after an internal dispatch call is
4296
// made. Generate mipmap may issue a dispatch call.
4297
TEST_P(ComputeShaderTest, DispatchGenerateMipmapDispatch)
4298
{
4299
constexpr GLsizei kSize = 8;
4300
4301
constexpr char kCS[] = R"(#version 310 es
4302
layout(local_size_x=6, local_size_y=1, local_size_z=1) in;
4303
4304
uniform vec4 data;
4305
4306
layout(rgba8, binding = 0) writeonly uniform highp image2D image;
4307
4308
void main()
4309
{
4310
imageStore(image, ivec2(gl_LocalInvocationID.xy), data);
4311
})";
4312
4313
ANGLE_GL_COMPUTE_PROGRAM(programCS, kCS);
4314
EXPECT_GL_NO_ERROR();
4315
4316
GLTexture color;
4317
glBindTexture(GL_TEXTURE_2D, color);
4318
glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, kSize, kSize);
4319
4320
const std::vector<GLColor> kInitialColor(kSize * kSize, GLColor::green);
4321
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE,
4322
kInitialColor.data());
4323
4324
// Setup image for compute call
4325
GLTexture computeOut;
4326
glBindTexture(GL_TEXTURE_2D, computeOut);
4327
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4328
glBindImageTexture(0, computeOut, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
4329
ASSERT_GL_NO_ERROR();
4330
4331
// Issue a dispatch call.
4332
glUseProgram(programCS);
4333
GLint uniformLoc = glGetUniformLocation(programCS, "data");
4334
ASSERT_NE(uniformLoc, -1);
4335
4336
glUniform4f(uniformLoc, 0.0f, 0.0f, 1.0f, 1.0f);
4337
glDispatchCompute(1, 1, 1);
4338
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4339
ASSERT_GL_NO_ERROR();
4340
4341
// Generate mipmap on the texture. This may use a compute shader internally.
4342
glBindTexture(GL_TEXTURE_2D, color);
4343
glGenerateMipmap(GL_TEXTURE_2D);
4344
4345
// Issue another dispatch call.
4346
glUniform4f(uniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
4347
glDispatchCompute(1, 1, 1);
4348
ASSERT_GL_NO_ERROR();
4349
4350
// Verify the results.
4351
GLFramebuffer fbo;
4352
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4353
glBindTexture(GL_TEXTURE_2D, computeOut);
4354
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, computeOut, 0);
4355
ASSERT_GL_NO_ERROR();
4356
4357
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4358
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
4359
}
4360
4361
// Write to image array with an aliasing format.
4362
TEST_P(ComputeShaderTest, AliasingFormatForImageArray)
4363
{
4364
// http://anglebug.com/5352
4365
ANGLE_SKIP_TEST_IF(IsD3D11());
4366
4367
constexpr char kCS[] = R"(#version 310 es
4368
layout(local_size_x=1, local_size_y=1, local_size_z=2) in;
4369
layout(r32ui, binding = 0) writeonly uniform highp uimage2DArray image;
4370
void main()
4371
{
4372
uint yellow = 0xFF00FFFFu;
4373
imageStore(image, ivec3(gl_LocalInvocationID.xyz), uvec4(yellow, 0, 0, 0));
4374
})";
4375
4376
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
4377
4378
const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);
4379
4380
GLTexture texture;
4381
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
4382
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);
4383
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4384
GL_UNSIGNED_BYTE, kInitData.data());
4385
EXPECT_GL_NO_ERROR();
4386
4387
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4388
glUseProgram(program);
4389
4390
// Output yellow to both layers.
4391
glBindImageTexture(0, texture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R32UI);
4392
glDispatchCompute(1, 1, 1);
4393
EXPECT_GL_NO_ERROR();
4394
4395
// Verify results.
4396
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4397
EXPECT_GL_NO_ERROR();
4398
4399
GLFramebuffer framebuffer;
4400
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
4401
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);
4402
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);
4403
EXPECT_GL_NO_ERROR();
4404
4405
glReadBuffer(GL_COLOR_ATTACHMENT0);
4406
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4407
4408
glReadBuffer(GL_COLOR_ATTACHMENT1);
4409
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4410
}
4411
4412
// Write to one layer of image array with an aliasing format.
4413
TEST_P(ComputeShaderTest, AliasingFormatForOneLayerOfImageArray)
4414
{
4415
// http://anglebug.com/5352
4416
ANGLE_SKIP_TEST_IF(IsD3D11());
4417
4418
constexpr char kCS[] = R"(#version 310 es
4419
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4420
layout(r32ui, binding = 0) writeonly uniform highp uimage2D image;
4421
void main()
4422
{
4423
uint yellow = 0xFF00FFFFu;
4424
imageStore(image, ivec2(gl_LocalInvocationID.xy), uvec4(yellow, 0, 0, 0));
4425
})";
4426
4427
constexpr int kWidth = 1, kHeight = 1, kDepth = 2;
4428
4429
const std::vector<GLColor> kInitData(kWidth * kHeight * kDepth, GLColor::black);
4430
4431
GLTexture texture;
4432
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
4433
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, kWidth, kHeight, kDepth);
4434
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4435
GL_UNSIGNED_BYTE, kInitData.data());
4436
EXPECT_GL_NO_ERROR();
4437
4438
GLFramebuffer framebuffer;
4439
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
4440
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 0);
4441
glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, texture, 0, 1);
4442
EXPECT_GL_NO_ERROR();
4443
4444
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4445
glUseProgram(program);
4446
4447
// Output yellow to layer 0.
4448
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
4449
glDispatchCompute(1, 1, 1);
4450
EXPECT_GL_NO_ERROR();
4451
4452
// Verify that only layer 0 was changed.
4453
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4454
EXPECT_GL_NO_ERROR();
4455
4456
glReadBuffer(GL_COLOR_ATTACHMENT0);
4457
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4458
4459
glReadBuffer(GL_COLOR_ATTACHMENT1);
4460
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4461
4462
// Reset texture back to black.
4463
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kWidth, kHeight, kDepth, GL_RGBA,
4464
GL_UNSIGNED_BYTE, kInitData.data());
4465
4466
// Output yellow to layer 1.
4467
glBindImageTexture(0, texture, 0, GL_FALSE, 1, GL_WRITE_ONLY, GL_R32UI);
4468
glDispatchCompute(1, 1, 1);
4469
EXPECT_GL_NO_ERROR();
4470
4471
// Verify that only layer 1 was changed.
4472
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
4473
EXPECT_GL_NO_ERROR();
4474
4475
glReadBuffer(GL_COLOR_ATTACHMENT0);
4476
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
4477
4478
glReadBuffer(GL_COLOR_ATTACHMENT1);
4479
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
4480
}
4481
4482
// Test glMemoryBarrier(CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT) by writing to persistenly mapped
4483
// buffer from a compute shader.
4484
TEST_P(ComputeShaderTest, WriteToPersistentBuffer)
4485
{
4486
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
4487
4488
constexpr char kCS[] = R"(#version 310 es
4489
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
4490
layout(std140, binding = 0) buffer block {
4491
uvec4 data;
4492
} outBlock;
4493
void main()
4494
{
4495
outBlock.data += uvec4(1);
4496
})";
4497
4498
ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
4499
glUseProgram(program);
4500
4501
constexpr std::array<uint32_t, 4> kInitData = {};
4502
4503
GLBuffer coherentBuffer;
4504
glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4505
glBufferStorageEXT(
4506
GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),
4507
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
4508
4509
GLBuffer nonCoherentBuffer;
4510
glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4511
glBufferStorageEXT(GL_SHADER_STORAGE_BUFFER, sizeof(kInitData), kInitData.data(),
4512
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
4513
4514
// Map the buffers for read and write.
4515
glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4516
uint32_t *coherentMapped = reinterpret_cast<uint32_t *>(glMapBufferRange(
4517
GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),
4518
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT));
4519
ASSERT_GL_NO_ERROR();
4520
4521
glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4522
uint32_t *nonCoherentMapped = reinterpret_cast<uint32_t *>(
4523
glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(kInitData),
4524
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT));
4525
ASSERT_GL_NO_ERROR();
4526
4527
constexpr std::array<uint32_t, 4> kCoherentExpectedData = {
4528
0x12354678u,
4529
0x2468ACE0u,
4530
0x13579BDFu,
4531
0x76543210u,
4532
};
4533
4534
constexpr std::array<uint32_t, 4> kNonCoherentExpectedData = {
4535
0x9ABCDEF0u,
4536
0xFDB97531u,
4537
0x1F2E3D4Bu,
4538
0x5A697887u,
4539
};
4540
4541
coherentMapped[0] = kCoherentExpectedData[0] - 1;
4542
coherentMapped[1] = kCoherentExpectedData[1] - 1;
4543
coherentMapped[2] = kCoherentExpectedData[2] - 1;
4544
coherentMapped[3] = kCoherentExpectedData[3] - 1;
4545
4546
nonCoherentMapped[0] = kNonCoherentExpectedData[0] - 1;
4547
nonCoherentMapped[1] = kNonCoherentExpectedData[1] - 1;
4548
nonCoherentMapped[2] = kNonCoherentExpectedData[2] - 1;
4549
nonCoherentMapped[3] = kNonCoherentExpectedData[3] - 1;
4550
4551
// Test coherent write
4552
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, coherentBuffer);
4553
glDispatchCompute(1, 1, 1);
4554
EXPECT_GL_NO_ERROR();
4555
4556
glFinish();
4557
EXPECT_EQ(coherentMapped[0], kCoherentExpectedData[0]);
4558
EXPECT_EQ(coherentMapped[1], kCoherentExpectedData[1]);
4559
EXPECT_EQ(coherentMapped[2], kCoherentExpectedData[2]);
4560
EXPECT_EQ(coherentMapped[3], kCoherentExpectedData[3]);
4561
4562
// Test non-coherent write
4563
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, nonCoherentBuffer);
4564
glDispatchCompute(1, 1, 1);
4565
4566
glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT);
4567
EXPECT_GL_NO_ERROR();
4568
4569
glFinish();
4570
EXPECT_EQ(nonCoherentMapped[0], kNonCoherentExpectedData[0]);
4571
EXPECT_EQ(nonCoherentMapped[1], kNonCoherentExpectedData[1]);
4572
EXPECT_EQ(nonCoherentMapped[2], kNonCoherentExpectedData[2]);
4573
EXPECT_EQ(nonCoherentMapped[3], kNonCoherentExpectedData[3]);
4574
4575
glBindBuffer(GL_SHADER_STORAGE_BUFFER, coherentBuffer);
4576
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4577
glBindBuffer(GL_SHADER_STORAGE_BUFFER, nonCoherentBuffer);
4578
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4579
EXPECT_GL_NO_ERROR();
4580
}
4581
4582
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTest);
4583
ANGLE_INSTANTIATE_TEST_ES31_AND(ComputeShaderTest, WithDirectSPIRVGeneration(ES31_VULKAN()));
4584
4585
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ComputeShaderTestES3);
4586
ANGLE_INSTANTIATE_TEST_ES3(ComputeShaderTestES3);
4587
4588
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WebGL2ComputeTest);
4589
ANGLE_INSTANTIATE_TEST_ES31(WebGL2ComputeTest);
4590
} // namespace
4591
4592