1 //
2 // Copyright 2017 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 // ShaderStorageBufferTest:
7 // Various tests related for shader storage buffers.
8 //
9
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12
13 using namespace angle;
14
15 namespace
16 {
17
18 struct MatrixCase
19 {
MatrixCase__anon3b3142410111::MatrixCase20 MatrixCase(unsigned cols,
21 unsigned rows,
22 unsigned matrixStride,
23 const char *computeShaderSource,
24 const float *inputData)
25 : mColumns(cols),
26 mRows(rows),
27 mMatrixStride(matrixStride),
28 mComputeShaderSource(computeShaderSource),
29 mInputdata(inputData)
30 {}
31 unsigned int mColumns;
32 unsigned int mRows;
33 unsigned int mMatrixStride;
34 const char *mComputeShaderSource;
35 const float *mInputdata;
36 const unsigned int kBytesPerComponent = sizeof(float);
37 };
38
39 struct VectorCase
40 {
VectorCase__anon3b3142410111::VectorCase41 VectorCase(unsigned components,
42 const char *computeShaderSource,
43 const GLuint *inputData,
44 const GLuint *expectedData)
45 : mComponents(components),
46 mComputeShaderSource(computeShaderSource),
47 mInputdata(inputData),
48 mExpectedData(expectedData)
49 {}
50 unsigned int mComponents;
51 const char *mComputeShaderSource;
52 const GLuint *mInputdata;
53 const GLuint *mExpectedData;
54 const unsigned int kBytesPerComponent = sizeof(GLuint);
55 };
56
57 class ShaderStorageBufferTest31 : public ANGLETest<>
58 {
59 protected:
ShaderStorageBufferTest31()60 ShaderStorageBufferTest31()
61 {
62 setWindowWidth(128);
63 setWindowHeight(128);
64 setConfigRedBits(8);
65 setConfigGreenBits(8);
66 setConfigBlueBits(8);
67 setConfigAlphaBits(8);
68
69 // Test flakiness was noticed when reusing displays.
70 forceNewDisplay();
71 }
72
runMatrixTest(const MatrixCase & matrixCase)73 void runMatrixTest(const MatrixCase &matrixCase)
74 {
75 ANGLE_GL_COMPUTE_PROGRAM(program, matrixCase.mComputeShaderSource);
76 glUseProgram(program);
77
78 // Create shader storage buffer
79 GLBuffer shaderStorageBuffer[2];
80 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
81 glBufferData(GL_SHADER_STORAGE_BUFFER, matrixCase.mRows * matrixCase.mMatrixStride,
82 matrixCase.mInputdata, GL_STATIC_DRAW);
83 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
84 glBufferData(GL_SHADER_STORAGE_BUFFER, matrixCase.mRows * matrixCase.mMatrixStride, nullptr,
85 GL_STATIC_DRAW);
86
87 // Bind shader storage buffer
88 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
89 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
90
91 glDispatchCompute(1, 1, 1);
92 glFinish();
93
94 // Read back shader storage buffer
95 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
96 const GLfloat *ptr = reinterpret_cast<const GLfloat *>(
97 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
98 matrixCase.mRows * matrixCase.mMatrixStride, GL_MAP_READ_BIT));
99
100 for (unsigned int row = 0; row < matrixCase.mRows; row++)
101 {
102 for (unsigned int col = 0; col < matrixCase.mColumns; col++)
103 {
104 GLfloat expected = matrixCase.mInputdata[row * (matrixCase.mMatrixStride /
105 matrixCase.kBytesPerComponent) +
106 col];
107 GLfloat actual =
108 *(ptr + row * (matrixCase.mMatrixStride / matrixCase.kBytesPerComponent) + col);
109
110 EXPECT_EQ(expected, actual) << " at row " << row << " and column " << col;
111 }
112 }
113
114 EXPECT_GL_NO_ERROR();
115 }
116
runVectorTest(const VectorCase & vectorCase)117 void runVectorTest(const VectorCase &vectorCase)
118 {
119 ANGLE_GL_COMPUTE_PROGRAM(program, vectorCase.mComputeShaderSource);
120 glUseProgram(program);
121
122 // Create shader storage buffer
123 GLBuffer shaderStorageBuffer[2];
124 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
125 glBufferData(GL_SHADER_STORAGE_BUFFER,
126 vectorCase.mComponents * vectorCase.kBytesPerComponent, vectorCase.mInputdata,
127 GL_STATIC_DRAW);
128 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
129 glBufferData(GL_SHADER_STORAGE_BUFFER,
130 vectorCase.mComponents * vectorCase.kBytesPerComponent, nullptr,
131 GL_STATIC_DRAW);
132
133 // Bind shader storage buffer
134 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
135 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
136
137 glDispatchCompute(1, 1, 1);
138 glFinish();
139
140 // Read back shader storage buffer
141 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
142 const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
143 GL_SHADER_STORAGE_BUFFER, 0, vectorCase.mComponents * vectorCase.kBytesPerComponent,
144 GL_MAP_READ_BIT));
145 for (unsigned int idx = 0; idx < vectorCase.mComponents; idx++)
146 {
147 EXPECT_EQ(vectorCase.mExpectedData[idx], *(ptr + idx));
148 }
149
150 EXPECT_GL_NO_ERROR();
151 }
152 };
153
154 // Matched block names within a shader interface must match in terms of having the same number of
155 // declarations with the same sequence of types.
TEST_P(ShaderStorageBufferTest31,MatchedBlockNameWithDifferentMemberType)156 TEST_P(ShaderStorageBufferTest31, MatchedBlockNameWithDifferentMemberType)
157 {
158 constexpr char kVS[] =
159 "#version 310 es\n"
160 "buffer blockName {\n"
161 " float data;\n"
162 "};\n"
163 "void main()\n"
164 "{\n"
165 "}\n";
166 constexpr char kFS[] =
167 "#version 310 es\n"
168 "buffer blockName {\n"
169 " uint data;\n"
170 "};\n"
171 "void main()\n"
172 "{\n"
173 "}\n";
174
175 GLuint program = CompileProgram(kVS, kFS);
176 EXPECT_EQ(0u, program);
177 }
178
179 // Linking should fail if blocks in vertex shader exceed GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS.
TEST_P(ShaderStorageBufferTest31,ExceedMaxVertexShaderStorageBlocks)180 TEST_P(ShaderStorageBufferTest31, ExceedMaxVertexShaderStorageBlocks)
181 {
182 std::ostringstream instanceCount;
183 GLint maxVertexShaderStorageBlocks = 0;
184 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
185 EXPECT_GL_NO_ERROR();
186 instanceCount << maxVertexShaderStorageBlocks;
187
188 const std::string &vertexShaderSource =
189 "#version 310 es\n"
190 "layout(shared) buffer blockName {\n"
191 " uint data;\n"
192 "} instance[" +
193 instanceCount.str() +
194 " + 1];\n"
195 "void main()\n"
196 "{\n"
197 "}\n";
198 constexpr char kFS[] =
199 "#version 310 es\n"
200 "void main()\n"
201 "{\n"
202 "}\n";
203
204 GLuint program = CompileProgram(vertexShaderSource.c_str(), kFS);
205 EXPECT_EQ(0u, program);
206 }
207
208 // Linking should fail if the sum of the number of active shader storage blocks exceeds
209 // MAX_COMBINED_SHADER_STORAGE_BLOCKS.
TEST_P(ShaderStorageBufferTest31,ExceedMaxCombinedShaderStorageBlocks)210 TEST_P(ShaderStorageBufferTest31, ExceedMaxCombinedShaderStorageBlocks)
211 {
212 std::ostringstream vertexInstanceCount;
213 GLint maxVertexShaderStorageBlocks = 0;
214 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &maxVertexShaderStorageBlocks);
215 vertexInstanceCount << maxVertexShaderStorageBlocks;
216
217 GLint maxFragmentShaderStorageBlocks = 0;
218 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
219
220 GLint maxCombinedShaderStorageBlocks = 0;
221 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedShaderStorageBlocks);
222 EXPECT_GL_NO_ERROR();
223
224 ASSERT_GE(maxCombinedShaderStorageBlocks, maxVertexShaderStorageBlocks);
225 ASSERT_GE(maxCombinedShaderStorageBlocks, maxFragmentShaderStorageBlocks);
226
227 // As SPEC allows MAX_VERTEX_SHADER_STORAGE_BLOCKS and MAX_FRAGMENT_SHADER_STORAGE_BLOCKS to be
228 // 0, in this situation we should skip this test to prevent these unexpected compile errors.
229 ANGLE_SKIP_TEST_IF(maxVertexShaderStorageBlocks == 0 || maxFragmentShaderStorageBlocks == 0);
230
231 GLint fragmentShaderStorageBlocks =
232 maxCombinedShaderStorageBlocks - maxVertexShaderStorageBlocks + 1;
233 ANGLE_SKIP_TEST_IF(fragmentShaderStorageBlocks > maxFragmentShaderStorageBlocks);
234
235 std::ostringstream fragmentInstanceCount;
236 fragmentInstanceCount << fragmentShaderStorageBlocks;
237
238 const std::string &vertexShaderSource =
239 "#version 310 es\n"
240 "layout(shared) buffer blockName0 {\n"
241 " uint data;\n"
242 "} instance0[" +
243 vertexInstanceCount.str() +
244 "];\n"
245 "void main()\n"
246 "{\n"
247 "}\n";
248 const std::string &fragmentShaderSource =
249 "#version 310 es\n"
250 "layout(shared) buffer blockName1 {\n"
251 " uint data;\n"
252 "} instance1[" +
253 fragmentInstanceCount.str() +
254 "];\n"
255 "void main()\n"
256 "{\n"
257 "}\n";
258
259 GLuint program = CompileProgram(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
260 EXPECT_EQ(0u, program);
261 }
262
263 // Linking should not fail if block size in shader equals to GL_MAX_SHADER_STORAGE_BLOCK_SIZE.
264 // Linking should fail if block size in shader exceeds GL_MAX_SHADER_STORAGE_BLOCK_SIZE.
TEST_P(ShaderStorageBufferTest31,ExceedMaxShaderStorageBlockSize)265 TEST_P(ShaderStorageBufferTest31, ExceedMaxShaderStorageBlockSize)
266 {
267 GLint maxShaderStorageBlockSize = 0;
268 glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxShaderStorageBlockSize);
269 EXPECT_GL_NO_ERROR();
270
271 // Linking should not fail if block size in shader equals to GL_MAX_SHADER_STORAGE_BLOCK_SIZE.
272 std::ostringstream blockArraySize;
273 blockArraySize << (maxShaderStorageBlockSize / 4);
274 const std::string &computeShaderSource =
275 "#version 310 es\n"
276 "layout (local_size_x = 1) in;\n"
277 "layout(std430) buffer FullSizeBlock\n"
278 "{\n"
279 "uint data[" +
280 blockArraySize.str() +
281 "];\n"
282 "};\n"
283 "void main()\n"
284 "{\n"
285 "for (int i=0; i<" +
286 blockArraySize.str() +
287 "; i++)\n"
288 "{\n"
289 "data[i] = uint(0);\n"
290 "};\n"
291 "}\n";
292
293 GLuint ComputeProgram = CompileComputeProgram(computeShaderSource.c_str(), true);
294 EXPECT_NE(0u, ComputeProgram);
295 glDeleteProgram(ComputeProgram);
296
297 // Linking should fail if block size in shader exceeds GL_MAX_SHADER_STORAGE_BLOCK_SIZE.
298 std::ostringstream exceedBlockArraySize;
299 exceedBlockArraySize << (maxShaderStorageBlockSize / 4 + 1);
300 const std::string &exceedComputeShaderSource =
301 "#version 310 es\n"
302 "layout (local_size_x = 1) in;\n"
303 "layout(std430) buffer FullSizeBlock\n"
304 "{\n"
305 "uint data[" +
306 exceedBlockArraySize.str() +
307 "];\n"
308 "};\n"
309 "void main()\n"
310 "{\n"
311 "for (int i=0; i<" +
312 exceedBlockArraySize.str() +
313 "; i++)\n"
314 "{\n"
315 "data[i] = uint(0);\n"
316 "};\n"
317 "}\n";
318
319 GLuint exceedComputeProgram = CompileComputeProgram(exceedComputeShaderSource.c_str(), true);
320 EXPECT_EQ(0u, exceedComputeProgram);
321 glDeleteProgram(exceedComputeProgram);
322 }
323
324 // Test shader storage buffer read write.
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferReadWrite)325 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferReadWrite)
326 {
327 constexpr char kCS[] =
328 "#version 310 es\n"
329 "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
330 "layout(std140, binding = 1) buffer blockName {\n"
331 " uint data[2];\n"
332 "} instanceName;\n"
333 "void main()\n"
334 "{\n"
335 " instanceName.data[0] = 3u;\n"
336 " instanceName.data[1] = 4u;\n"
337 "}\n";
338
339 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
340
341 glUseProgram(program);
342
343 constexpr unsigned int kElementCount = 2;
344 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
345 constexpr unsigned int kArrayStride = 16;
346 // Create shader storage buffer
347 GLBuffer shaderStorageBuffer;
348 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
349 glBufferData(GL_SHADER_STORAGE_BUFFER, kElementCount * kArrayStride, nullptr, GL_STATIC_DRAW);
350
351 // Bind shader storage buffer
352 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
353
354 // Dispath compute
355 glDispatchCompute(1, 1, 1);
356
357 glFinish();
358
359 // Read back shader storage buffer
360 constexpr unsigned int kExpectedValues[2] = {3u, 4u};
361 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
362 void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kElementCount * kArrayStride,
363 GL_MAP_READ_BIT);
364 for (unsigned int idx = 0; idx < kElementCount; idx++)
365 {
366 EXPECT_EQ(kExpectedValues[idx],
367 *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
368 idx * kArrayStride)));
369 }
370 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
371 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
372
373 EXPECT_GL_NO_ERROR();
374 }
375
376 // Test shader storage buffer write followed by glTexSUbData and followed by shader storage write
377 // again.
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferReadWriteAndBufferSubData)378 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferReadWriteAndBufferSubData)
379 {
380 constexpr char kCS[] =
381 "#version 310 es\n"
382 "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
383 "layout(std140, binding = 1) buffer blockName {\n"
384 " uint data[2];\n"
385 "} instanceName;\n"
386 "void main()\n"
387 "{\n"
388 " instanceName.data[0] = 3u;\n"
389 " instanceName.data[1] = 4u;\n"
390 "}\n";
391
392 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
393
394 glUseProgram(program);
395
396 int bufferAlignOffset;
397 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &bufferAlignOffset);
398
399 constexpr unsigned int kElementCount = 2;
400 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
401 constexpr unsigned int kArrayStride = 16;
402 constexpr unsigned int kMiddlePaddingSize = 1024;
403 unsigned int kShaderUsedSize = kElementCount * kArrayStride;
404 unsigned int kOffset1 = (kShaderUsedSize + bufferAlignOffset - 1) & ~(bufferAlignOffset - 1);
405 unsigned int kOffset2 = kOffset1 + kMiddlePaddingSize;
406 unsigned int kBufferSize = kOffset2 + kShaderUsedSize;
407
408 for (int loop = 0; loop < 2; loop++)
409 {
410 // Create shader storage buffer
411 GLBuffer shaderStorageBuffer;
412 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
413 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, nullptr, GL_DYNAMIC_DRAW);
414
415 // Bind shader storage buffer and dispath compute
416 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
417 glDispatchCompute(1, 1, 1);
418 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
419 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer, kOffset2,
420 kShaderUsedSize);
421 glDispatchCompute(1, 1, 1);
422 EXPECT_GL_NO_ERROR();
423
424 if (loop == 1)
425 {
426 // Make write operation finished but read operation pending. We don't care actual
427 // rendering result but just to have a unflushed rendering using the buffer so that it
428 // will appears as pending.
429 glFinish();
430 constexpr char kVS[] = R"(attribute vec4 in_attrib;
431 varying vec4 v_attrib;
432 void main()
433 {
434 v_attrib = in_attrib;
435 gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
436 gl_PointSize = 100.0;
437 })";
438 constexpr char kFS[] = R"(precision mediump float;
439 varying vec4 v_attrib;
440 void main()
441 {
442 gl_FragColor = v_attrib;
443 })";
444 GLuint readProgram = CompileProgram(kVS, kFS);
445 ASSERT_NE(readProgram, 0U);
446 GLint attribLocation = glGetAttribLocation(readProgram, "in_attrib");
447 ASSERT_NE(attribLocation, -1);
448 glUseProgram(readProgram);
449 ASSERT_GL_NO_ERROR();
450 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
451 glBindBuffer(GL_ARRAY_BUFFER, shaderStorageBuffer);
452 glVertexAttribPointer(attribLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, 4, nullptr);
453 glEnableVertexAttribArray(attribLocation);
454 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, shaderStorageBuffer);
455 glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
456 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
457 ASSERT_GL_NO_ERROR();
458 }
459
460 // Use subData to update middle portion of data to trigger acquireAndUpdate code path in
461 // ANGLE
462 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
463 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
464 constexpr unsigned int kMiddlePaddingValue = 0x55555555u;
465 std::vector<unsigned int> kMiddlePaddingValues(kMiddlePaddingSize / sizeof(unsigned int),
466 kMiddlePaddingValue);
467 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kOffset1, kMiddlePaddingSize,
468 kMiddlePaddingValues.data());
469
470 // Read back shader storage buffer
471 constexpr unsigned int kExpectedValues[2] = {3u, 4u};
472 const GLbyte *ptr0 = reinterpret_cast<const GLbyte *>(
473 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
474 for (unsigned int idx = 0; idx < kElementCount; idx++)
475 {
476 EXPECT_EQ(kExpectedValues[idx],
477 *(reinterpret_cast<const GLuint *>(ptr0 + idx * kArrayStride)));
478 }
479
480 const GLbyte *ptr1 = reinterpret_cast<const GLbyte *>(ptr0 + kOffset1);
481 for (unsigned int idx = 0; idx < kMiddlePaddingSize / sizeof(unsigned int); idx++)
482 {
483 EXPECT_EQ(kMiddlePaddingValue, reinterpret_cast<const GLuint *>(ptr1)[idx]);
484 }
485
486 const GLbyte *ptr2 = ptr1 + kMiddlePaddingSize;
487 for (unsigned int idx = 0; idx < kElementCount; idx++)
488 {
489 EXPECT_EQ(kExpectedValues[idx],
490 *(reinterpret_cast<const GLuint *>(ptr2 + idx * kArrayStride)));
491 }
492
493 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
494 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
495
496 EXPECT_GL_NO_ERROR();
497 }
498 }
499
500 // Tests modifying an existing shader storage buffer
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferReadWriteSame)501 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferReadWriteSame)
502 {
503 constexpr char kComputeShaderSource[] =
504 R"(#version 310 es
505 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
506 layout(std140, binding = 0) buffer block {
507 uint data;
508 } instance;
509 void main()
510 {
511 uint temp = instance.data;
512 instance.data = temp + 1u;
513 }
514 )";
515
516 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
517
518 glUseProgram(program);
519
520 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
521 constexpr unsigned int kInitialData = 123u;
522
523 // Create shader storage buffer
524 GLBuffer shaderStorageBuffer;
525
526 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
527 glBufferData(GL_SHADER_STORAGE_BUFFER, kBytesPerComponent, &kInitialData, GL_STATIC_DRAW);
528
529 // Bind shader storage buffer
530 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
531
532 glDispatchCompute(1, 1, 1);
533
534 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
535
536 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
537 const void *bufferData =
538 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT);
539
540 constexpr unsigned int kExpectedData = 124u;
541 EXPECT_EQ(kExpectedData, *static_cast<const GLuint *>(bufferData));
542 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
543
544 // Running shader twice to make sure that the buffer gets updated correctly 123->124->125
545 glDispatchCompute(1, 1, 1);
546
547 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_PIXEL_BUFFER_BARRIER_BIT);
548
549 bufferData = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT);
550
551 constexpr unsigned int kExpectedData2 = 125u;
552 EXPECT_EQ(kExpectedData2, *static_cast<const GLuint *>(bufferData));
553
554 // Verify re-using the SSBO buffer with a PBO contains expected data.
555 // This will read-back from FBO using a PBO into the same SSBO buffer.
556
557 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
558
559 GLTexture texture;
560 glBindTexture(GL_TEXTURE_2D, texture);
561 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight());
562
563 GLFramebuffer framebuffer;
564 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
565 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
566
567 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
568 glClear(GL_COLOR_BUFFER_BIT);
569
570 glBindBuffer(GL_PIXEL_PACK_BUFFER, shaderStorageBuffer);
571 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
572 EXPECT_GL_NO_ERROR();
573
574 void *mappedPtr =
575 glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT);
576 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
577 EXPECT_GL_NO_ERROR();
578
579 EXPECT_EQ(GLColor::red, dataColor[0]);
580 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
581 EXPECT_GL_NO_ERROR();
582
583 // Verify that binding the buffer back to the SSBO keeps the expected data.
584
585 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
586
587 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
588 const GLColor *ptr = reinterpret_cast<GLColor *>(
589 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT));
590 EXPECT_EQ(GLColor::red, *ptr);
591
592 EXPECT_GL_NO_ERROR();
593 }
594
595 // Tests reading and writing to a shader storage buffer bound at an offset.
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferReadWriteOffset)596 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferReadWriteOffset)
597 {
598 constexpr char kCS[] = R"(#version 310 es
599 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
600
601 layout(std140, binding = 0) buffer block0 {
602 uint data[2];
603 } instance0;
604
605 void main()
606 {
607 instance0.data[0] = 3u;
608 instance0.data[1] = 4u;
609 }
610 )";
611
612 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
613
614 glUseProgram(program);
615
616 constexpr unsigned int kElementCount = 2;
617 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
618 constexpr unsigned int kArrayStride = 16;
619 // Create shader storage buffer
620 GLBuffer shaderStorageBuffer;
621 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
622
623 int bufferAlignOffset;
624 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &bufferAlignOffset);
625
626 constexpr int kBufferSize = kElementCount * kArrayStride;
627 const int unalignedBytes = kBufferSize % bufferAlignOffset;
628 const int alignCorrection = unalignedBytes == 0 ? 0 : bufferAlignOffset - unalignedBytes;
629 const int kBufferOffset = kBufferSize + alignCorrection;
630
631 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferOffset + kBufferSize, nullptr, GL_STATIC_DRAW);
632
633 // Bind shader storage buffer at an offset
634 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer, kBufferOffset, kBufferSize);
635 EXPECT_GL_NO_ERROR();
636
637 glDispatchCompute(1, 1, 1);
638 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
639
640 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
641
642 // Bind the buffer at a separate location
643 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer, 0, kBufferSize);
644 EXPECT_GL_NO_ERROR();
645
646 glDispatchCompute(1, 1, 1);
647 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
648
649 // Read back shader storage buffer
650 constexpr unsigned int kExpectedValues[2] = {3u, 4u};
651 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
652 void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT);
653 for (unsigned int idx = 0; idx < kElementCount; idx++)
654 {
655 EXPECT_EQ(kExpectedValues[idx],
656 *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
657 idx * kArrayStride)));
658 }
659 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
660
661 ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, kBufferOffset, kBufferSize, GL_MAP_READ_BIT);
662 for (unsigned int idx = 0; idx < kElementCount; idx++)
663 {
664 EXPECT_EQ(kExpectedValues[idx],
665 *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
666 idx * kArrayStride)));
667 }
668 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
669
670 EXPECT_GL_NO_ERROR();
671 }
672
673 // Test that access/write to vector data in shader storage buffer.
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferVector)674 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferVector)
675 {
676 constexpr char kComputeShaderSource[] =
677 R"(#version 310 es
678 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
679 layout(std140, binding = 0) buffer blockIn {
680 uvec2 data;
681 } instanceIn;
682 layout(std140, binding = 1) buffer blockOut {
683 uvec2 data;
684 } instanceOut;
685 void main()
686 {
687 instanceOut.data[0] = instanceIn.data[0];
688 instanceOut.data[1] = instanceIn.data[1];
689 }
690 )";
691
692 constexpr unsigned int kComponentCount = 2;
693 constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
694
695 VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kInputValues);
696 runVectorTest(vectorCase);
697 }
698
699 // Test that the shader works well with an active SSBO but not statically used.
TEST_P(ShaderStorageBufferTest31,ActiveSSBOButNotStaticallyUsed)700 TEST_P(ShaderStorageBufferTest31, ActiveSSBOButNotStaticallyUsed)
701 {
702 // http://anglebug.com/42262382
703 ANGLE_SKIP_TEST_IF(IsAndroid() && IsPixel2() && IsVulkan());
704
705 constexpr char kComputeShaderSource[] =
706 R"(#version 310 es
707 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
708 layout(std140, binding = 0) buffer blockIn {
709 uvec2 data;
710 } instanceIn;
711 layout(std140, binding = 1) buffer blockOut {
712 uvec2 data;
713 } instanceOut;
714 layout(std140, binding = 2) buffer blockC {
715 uvec2 data;
716 } instanceC;
717 void main()
718 {
719 instanceOut.data[0] = instanceIn.data[0];
720 instanceOut.data[1] = instanceIn.data[1];
721 }
722 )";
723
724 GLBuffer shaderStorageBufferC;
725 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBufferC);
726 glBufferData(GL_SHADER_STORAGE_BUFFER, 32, nullptr, GL_STATIC_DRAW);
727 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, shaderStorageBufferC);
728
729 constexpr unsigned int kComponentCount = 2;
730 constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
731
732 VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kInputValues);
733 runVectorTest(vectorCase);
734 }
735
736 // Test that access/write to swizzle scalar data in shader storage block.
TEST_P(ShaderStorageBufferTest31,ScalarSwizzleTest)737 TEST_P(ShaderStorageBufferTest31, ScalarSwizzleTest)
738 {
739 constexpr char kComputeShaderSource[] =
740 R"(#version 310 es
741 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
742 layout(std140, binding = 0) buffer blockIn {
743 uvec2 data;
744 } instanceIn;
745 layout(std140, binding = 1) buffer blockOut {
746 uvec2 data;
747 } instanceOut;
748 void main()
749 {
750 instanceOut.data.x = instanceIn.data.y;
751 instanceOut.data.y = instanceIn.data.x;
752 }
753 )";
754
755 constexpr unsigned int kComponentCount = 2;
756 constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
757 constexpr GLuint kExpectedValues[kComponentCount] = {4u, 3u};
758
759 VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kExpectedValues);
760 runVectorTest(vectorCase);
761 }
762
763 // Test that access/write to swizzle vector data in shader storage block.
TEST_P(ShaderStorageBufferTest31,VectorSwizzleTest)764 TEST_P(ShaderStorageBufferTest31, VectorSwizzleTest)
765 {
766 constexpr char kComputeShaderSource[] =
767 R"(#version 310 es
768 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
769 layout(std140, binding = 0) buffer blockIn {
770 uvec2 data;
771 } instanceIn;
772 layout(std140, binding = 1) buffer blockOut {
773 uvec2 data;
774 } instanceOut;
775 void main()
776 {
777 instanceOut.data.yx = instanceIn.data.xy;
778 }
779 )";
780
781 constexpr unsigned int kComponentCount = 2;
782 constexpr GLuint kInputValues[kComponentCount] = {3u, 4u};
783 constexpr GLuint kExpectedValues[kComponentCount] = {4u, 3u};
784
785 VectorCase vectorCase(kComponentCount, kComputeShaderSource, kInputValues, kExpectedValues);
786 runVectorTest(vectorCase);
787 }
788
789 // Test that access/write to swizzle vector data in column_major matrix in shader storage block.
TEST_P(ShaderStorageBufferTest31,VectorSwizzleInColumnMajorMatrixTest)790 TEST_P(ShaderStorageBufferTest31, VectorSwizzleInColumnMajorMatrixTest)
791 {
792 constexpr char kComputeShaderSource[] =
793 R"(#version 310 es
794 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
795 layout(std140, binding = 0) buffer blockIn {
796 layout(column_major) mat2x3 data;
797 } instanceIn;
798 layout(std140, binding = 1) buffer blockOut {
799 layout(column_major) mat2x3 data;
800 } instanceOut;
801 void main()
802 {
803 instanceOut.data[0].xyz = instanceIn.data[0].xyz;
804 instanceOut.data[1].xyz = instanceIn.data[1].xyz;
805 }
806 )";
807
808 constexpr unsigned int kColumns = 2;
809 constexpr unsigned int kRows = 3;
810 constexpr unsigned int kBytesPerComponent = sizeof(float);
811 constexpr unsigned int kMatrixStride = 16;
812 constexpr float kInputDada[kColumns * (kMatrixStride / kBytesPerComponent)] = {
813 0.1, 0.2, 0.3, 0.0, 0.4, 0.5, 0.6, 0.0};
814 MatrixCase matrixCase(kRows, kColumns, kMatrixStride, kComputeShaderSource, kInputDada);
815 runMatrixTest(matrixCase);
816 }
817
818 // Test that access/write to swizzle vector data in row_major matrix in shader storage block.
TEST_P(ShaderStorageBufferTest31,VectorSwizzleInRowMajorMatrixTest)819 TEST_P(ShaderStorageBufferTest31, VectorSwizzleInRowMajorMatrixTest)
820 {
821 ANGLE_SKIP_TEST_IF(IsAndroid());
822
823 constexpr char kComputeShaderSource[] =
824 R"(#version 310 es
825 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
826 layout(std140, binding = 0) buffer blockIn {
827 layout(row_major) mat2x3 data;
828 } instanceIn;
829 layout(std140, binding = 1) buffer blockOut {
830 layout(row_major) mat2x3 data;
831 } instanceOut;
832 void main()
833 {
834 instanceOut.data[0].xyz = instanceIn.data[0].xyz;
835 instanceOut.data[1].xyz = instanceIn.data[1].xyz;
836 }
837 )";
838
839 constexpr unsigned int kColumns = 2;
840 constexpr unsigned int kRows = 3;
841 constexpr unsigned int kBytesPerComponent = sizeof(float);
842 // std140 layout requires that base alignment and stride of arrays of scalars and vectors are
843 // rounded up a multiple of the base alignment of a vec4.
844 constexpr unsigned int kMatrixStride = 16;
845 constexpr float kInputDada[kRows * (kMatrixStride / kBytesPerComponent)] = {
846 0.1, 0.2, 0.0, 0.0, 0.3, 0.4, 0.0, 0.0, 0.5, 0.6, 0.0, 0.0};
847 MatrixCase matrixCase(kColumns, kRows, kMatrixStride, kComputeShaderSource, kInputDada);
848 runMatrixTest(matrixCase);
849 }
850
851 // Test that access/write to scalar data in matrix in shader storage block with row major.
TEST_P(ShaderStorageBufferTest31,ScalarDataInMatrixInSSBOWithRowMajorQualifier)852 TEST_P(ShaderStorageBufferTest31, ScalarDataInMatrixInSSBOWithRowMajorQualifier)
853 {
854 // TODO([email protected]): Figure out why it fails on Intel Linux platform.
855 // http://anglebug.com/40644618
856 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
857 ANGLE_SKIP_TEST_IF(IsAndroid());
858
859 constexpr char kComputeShaderSource[] =
860 R"(#version 310 es
861 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
862 layout(std140, binding = 0) buffer blockIn {
863 layout(row_major) mat2x3 data;
864 } instanceIn;
865 layout(std140, binding = 1) buffer blockOut {
866 layout(row_major) mat2x3 data;
867 } instanceOut;
868 void main()
869 {
870 instanceOut.data[0][0] = instanceIn.data[0][0];
871 instanceOut.data[0][1] = instanceIn.data[0][1];
872 instanceOut.data[0][2] = instanceIn.data[0][2];
873 instanceOut.data[1][0] = instanceIn.data[1][0];
874 instanceOut.data[1][1] = instanceIn.data[1][1];
875 instanceOut.data[1][2] = instanceIn.data[1][2];
876 }
877 )";
878
879 constexpr unsigned int kColumns = 2;
880 constexpr unsigned int kRows = 3;
881 constexpr unsigned int kBytesPerComponent = sizeof(float);
882 // std140 layout requires that base alignment and stride of arrays of scalars and vectors are
883 // rounded up a multiple of the base alignment of a vec4.
884 constexpr unsigned int kMatrixStride = 16;
885 constexpr float kInputDada[kRows * (kMatrixStride / kBytesPerComponent)] = {
886 0.1, 0.2, 0.0, 0.0, 0.3, 0.4, 0.0, 0.0, 0.5, 0.6, 0.0, 0.0};
887 MatrixCase matrixCase(kColumns, kRows, kMatrixStride, kComputeShaderSource, kInputDada);
888 runMatrixTest(matrixCase);
889 }
890
TEST_P(ShaderStorageBufferTest31,VectorDataInMatrixInSSBOWithRowMajorQualifier)891 TEST_P(ShaderStorageBufferTest31, VectorDataInMatrixInSSBOWithRowMajorQualifier)
892 {
893 ANGLE_SKIP_TEST_IF(IsAndroid());
894
895 constexpr char kComputeShaderSource[] =
896 R"(#version 310 es
897 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
898 layout(std140, binding = 0) buffer blockIn {
899 layout(row_major) mat2x3 data;
900 } instanceIn;
901 layout(std140, binding = 1) buffer blockOut {
902 layout(row_major) mat2x3 data;
903 } instanceOut;
904 void main()
905 {
906 instanceOut.data[0] = instanceIn.data[0];
907 instanceOut.data[1] = instanceIn.data[1];
908 }
909 )";
910
911 constexpr unsigned int kColumns = 2;
912 constexpr unsigned int kRows = 3;
913 constexpr unsigned int kBytesPerComponent = sizeof(float);
914 // std140 layout requires that base alignment and stride of arrays of scalars and vectors are
915 // rounded up a multiple of the base alignment of a vec4.
916 constexpr unsigned int kMatrixStride = 16;
917 constexpr float kInputDada[kRows * (kMatrixStride / kBytesPerComponent)] = {
918 0.1, 0.2, 0.0, 0.0, 0.3, 0.4, 0.0, 0.0, 0.5, 0.6, 0.0, 0.0};
919 MatrixCase matrixCase(kColumns, kRows, kMatrixStride, kComputeShaderSource, kInputDada);
920 runMatrixTest(matrixCase);
921 }
922
TEST_P(ShaderStorageBufferTest31,MatrixDataInSSBOWithRowMajorQualifier)923 TEST_P(ShaderStorageBufferTest31, MatrixDataInSSBOWithRowMajorQualifier)
924 {
925 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
926
927 constexpr char kComputeShaderSource[] =
928 R"(#version 310 es
929 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
930 layout(std140, binding = 0) buffer blockIn {
931 layout(row_major) mat2x3 data;
932 } instanceIn;
933 layout(std140, binding = 1) buffer blockOut {
934 layout(row_major) mat2x3 data;
935 } instanceOut;
936 void main()
937 {
938 instanceOut.data = instanceIn.data;
939 }
940 )";
941
942 constexpr unsigned int kColumns = 2;
943 constexpr unsigned int kRows = 3;
944 constexpr unsigned int kBytesPerComponent = sizeof(float);
945 // std140 layout requires that base alignment and stride of arrays of scalars and vectors are
946 // rounded up a multiple of the base alignment of a vec4.
947 constexpr unsigned int kMatrixStride = 16;
948 constexpr float kInputDada[kRows * (kMatrixStride / kBytesPerComponent)] = {
949 0.1, 0.2, 0.0, 0.0, 0.3, 0.4, 0.0, 0.0, 0.5, 0.6, 0.0, 0.0};
950 MatrixCase matrixCase(kColumns, kRows, kMatrixStride, kComputeShaderSource, kInputDada);
951 runMatrixTest(matrixCase);
952 }
953
954 // Test that access/write to scalar data in structure matrix in shader storage block with row major.
TEST_P(ShaderStorageBufferTest31,ScalarDataInMatrixInStructureInSSBOWithRowMajorQualifier)955 TEST_P(ShaderStorageBufferTest31, ScalarDataInMatrixInStructureInSSBOWithRowMajorQualifier)
956 {
957 // TODO([email protected]): Figure out why it fails on Intel Linux platform.
958 // http://anglebug.com/40644618
959 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
960 ANGLE_SKIP_TEST_IF(IsAndroid());
961
962 constexpr char kComputeShaderSource[] =
963 R"(#version 310 es
964 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
965 struct S
966 {
967 mat2x3 data;
968 };
969 layout(std140, binding = 0) buffer blockIn {
970 layout(row_major) S s;
971 } instanceIn;
972 layout(std140, binding = 1) buffer blockOut {
973 layout(row_major) S s;
974 } instanceOut;
975 void main()
976 {
977 instanceOut.s.data[0][0] = instanceIn.s.data[0][0];
978 instanceOut.s.data[0][1] = instanceIn.s.data[0][1];
979 instanceOut.s.data[0][2] = instanceIn.s.data[0][2];
980 instanceOut.s.data[1][0] = instanceIn.s.data[1][0];
981 instanceOut.s.data[1][1] = instanceIn.s.data[1][1];
982 instanceOut.s.data[1][2] = instanceIn.s.data[1][2];
983 }
984 )";
985
986 constexpr unsigned int kColumns = 2;
987 constexpr unsigned int kRows = 3;
988 constexpr unsigned int kBytesPerComponent = sizeof(float);
989 // std140 layout requires that base alignment and stride of arrays of scalars and vectors are
990 // rounded up a multiple of the base alignment of a vec4.
991 constexpr unsigned int kMatrixStride = 16;
992 constexpr float kInputDada[kRows * (kMatrixStride / kBytesPerComponent)] = {
993 0.1, 0.2, 0.0, 0.0, 0.3, 0.4, 0.0, 0.0, 0.5, 0.6, 0.0, 0.0};
994 MatrixCase matrixCase(kColumns, kRows, kMatrixStride, kComputeShaderSource, kInputDada);
995 runMatrixTest(matrixCase);
996 }
997
998 // Test that access/write to column major matrix data in shader storage buffer.
TEST_P(ShaderStorageBufferTest31,ScalarDataInMatrixInSSBO)999 TEST_P(ShaderStorageBufferTest31, ScalarDataInMatrixInSSBO)
1000 {
1001 constexpr char kComputeShaderSource[] =
1002 R"(#version 310 es
1003 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1004 layout(std140, binding = 0) buffer blockIn {
1005 mat2x3 data;
1006 } instanceIn;
1007 layout(std140, binding = 1) buffer blockOut {
1008 mat2x3 data;
1009 } instanceOut;
1010 void main()
1011 {
1012 instanceOut.data[0][0] = instanceIn.data[0][0];
1013 instanceOut.data[0][1] = instanceIn.data[0][1];
1014 instanceOut.data[0][2] = instanceIn.data[0][2];
1015 instanceOut.data[1][0] = instanceIn.data[1][0];
1016 instanceOut.data[1][1] = instanceIn.data[1][1];
1017 instanceOut.data[1][2] = instanceIn.data[1][2];
1018 }
1019 )";
1020
1021 constexpr unsigned int kColumns = 2;
1022 constexpr unsigned int kRows = 3;
1023 constexpr unsigned int kBytesPerComponent = sizeof(float);
1024 constexpr unsigned int kMatrixStride = 16;
1025 constexpr float kInputDada[kColumns * (kMatrixStride / kBytesPerComponent)] = {
1026 0.1, 0.2, 0.3, 0.0, 0.4, 0.5, 0.6, 0.0};
1027 MatrixCase matrixCase(kRows, kColumns, kMatrixStride, kComputeShaderSource, kInputDada);
1028 runMatrixTest(matrixCase);
1029 }
1030
TEST_P(ShaderStorageBufferTest31,VectorDataInMatrixInSSBOWithColumnMajorQualifier)1031 TEST_P(ShaderStorageBufferTest31, VectorDataInMatrixInSSBOWithColumnMajorQualifier)
1032 {
1033 constexpr char kComputeShaderSource[] =
1034 R"(#version 310 es
1035 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1036 layout(std140, binding = 0) buffer blockIn {
1037 layout(column_major) mat2x3 data;
1038 } instanceIn;
1039 layout(std140, binding = 1) buffer blockOut {
1040 layout(column_major) mat2x3 data;
1041 } instanceOut;
1042 void main()
1043 {
1044 instanceOut.data[0] = instanceIn.data[0];
1045 instanceOut.data[1] = instanceIn.data[1];
1046 }
1047 )";
1048
1049 constexpr unsigned int kColumns = 2;
1050 constexpr unsigned int kRows = 3;
1051 constexpr unsigned int kBytesPerComponent = sizeof(float);
1052 constexpr unsigned int kMatrixStride = 16;
1053 constexpr float kInputDada[kColumns * (kMatrixStride / kBytesPerComponent)] = {
1054 0.1, 0.2, 0.3, 0.0, 0.4, 0.5, 0.6, 0.0};
1055 MatrixCase matrixCase(kRows, kColumns, kMatrixStride, kComputeShaderSource, kInputDada);
1056 runMatrixTest(matrixCase);
1057 }
1058
TEST_P(ShaderStorageBufferTest31,MatrixDataInSSBOWithColumnMajorQualifier)1059 TEST_P(ShaderStorageBufferTest31, MatrixDataInSSBOWithColumnMajorQualifier)
1060 {
1061 constexpr char kComputeShaderSource[] =
1062 R"(#version 310 es
1063 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1064 layout(std140, binding = 0) buffer blockIn {
1065 layout(column_major) mat2x3 data;
1066 } instanceIn;
1067 layout(std140, binding = 1) buffer blockOut {
1068 layout(column_major) mat2x3 data;
1069 } instanceOut;
1070 void main()
1071 {
1072 instanceOut.data = instanceIn.data;
1073 }
1074 )";
1075
1076 constexpr unsigned int kColumns = 2;
1077 constexpr unsigned int kRows = 3;
1078 constexpr unsigned int kBytesPerComponent = sizeof(float);
1079 constexpr unsigned int kMatrixStride = 16;
1080 constexpr float kInputDada[kColumns * (kMatrixStride / kBytesPerComponent)] = {
1081 0.1, 0.2, 0.3, 0.0, 0.4, 0.5, 0.6, 0.0};
1082 MatrixCase matrixCase(kRows, kColumns, kMatrixStride, kComputeShaderSource, kInputDada);
1083 runMatrixTest(matrixCase);
1084 }
1085
1086 // Test that access/write to structure data in shader storage buffer.
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferStructureArray)1087 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferStructureArray)
1088 {
1089 constexpr char kComputeShaderSource[] =
1090 R"(#version 310 es
1091 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1092 struct S
1093 {
1094 uvec2 uvData;
1095 uint uiData[2];
1096 };
1097 layout(std140, binding = 0) buffer blockIn {
1098 S s[2];
1099 uint lastData;
1100 } instanceIn;
1101 layout(std140, binding = 1) buffer blockOut {
1102 S s[2];
1103 uint lastData;
1104 } instanceOut;
1105 void main()
1106 {
1107 instanceOut.s[0].uvData = instanceIn.s[0].uvData;
1108 instanceOut.s[0].uiData[0] = instanceIn.s[0].uiData[0];
1109 instanceOut.s[0].uiData[1] = instanceIn.s[0].uiData[1];
1110 instanceOut.s[1].uvData = instanceIn.s[1].uvData;
1111 instanceOut.s[1].uiData[0] = instanceIn.s[1].uiData[0];
1112 instanceOut.s[1].uiData[1] = instanceIn.s[1].uiData[1];
1113 instanceOut.lastData = instanceIn.lastData;
1114 }
1115 )";
1116
1117 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1118
1119 glUseProgram(program);
1120
1121 std::array<GLuint, 4> kUVData = {{
1122 1u,
1123 2u,
1124 0u,
1125 0u,
1126 }};
1127 std::array<GLuint, 8> kUIData = {{
1128 3u,
1129 0u,
1130 0u,
1131 0u,
1132 4u,
1133 0u,
1134 0u,
1135 0u,
1136 }};
1137 GLuint kLastData = 5u;
1138
1139 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
1140 constexpr unsigned int kStructureStride = 48;
1141 constexpr unsigned int totalSize = kStructureStride * 2 + sizeof(kLastData);
1142
1143 // Create shader storage buffer
1144 GLBuffer shaderStorageBuffer[2];
1145 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1146 glBufferData(GL_SHADER_STORAGE_BUFFER, totalSize, nullptr, GL_STATIC_DRAW);
1147 GLint offset = 0;
1148 // upload data to instanceIn.s[0]
1149 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUVData.size() * kBytesPerComponent,
1150 kUVData.data());
1151 offset += (kUVData.size() * kBytesPerComponent);
1152 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUIData.size() * kBytesPerComponent,
1153 kUIData.data());
1154 offset += (kUIData.size() * kBytesPerComponent);
1155 // upload data to instanceIn.s[1]
1156 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUVData.size() * kBytesPerComponent,
1157 kUVData.data());
1158 offset += (kUVData.size() * kBytesPerComponent);
1159 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUIData.size() * kBytesPerComponent,
1160 kUIData.data());
1161 offset += (kUIData.size() * kBytesPerComponent);
1162 // upload data to instanceIn.lastData
1163 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, sizeof(kLastData), &kLastData);
1164
1165 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1166 glBufferData(GL_SHADER_STORAGE_BUFFER, totalSize, nullptr, GL_STATIC_DRAW);
1167
1168 // Bind shader storage buffer
1169 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1170 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1171
1172 glDispatchCompute(1, 1, 1);
1173 glFinish();
1174
1175 // Read back shader storage buffer
1176 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1177 constexpr float kExpectedValues[5] = {1u, 2u, 3u, 4u, 5u};
1178 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1179 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, totalSize, GL_MAP_READ_BIT));
1180 // instanceOut.s[0]
1181 EXPECT_EQ(kExpectedValues[0], *ptr);
1182 EXPECT_EQ(kExpectedValues[1], *(ptr + 1));
1183 EXPECT_EQ(kExpectedValues[2], *(ptr + 4));
1184 EXPECT_EQ(kExpectedValues[3], *(ptr + 8));
1185 // instanceOut.s[1]
1186 ptr += kStructureStride / kBytesPerComponent;
1187 EXPECT_EQ(kExpectedValues[0], *ptr);
1188 EXPECT_EQ(kExpectedValues[1], *(ptr + 1));
1189 EXPECT_EQ(kExpectedValues[2], *(ptr + 4));
1190 EXPECT_EQ(kExpectedValues[3], *(ptr + 8));
1191 // instanceOut.lastData
1192 ptr += kStructureStride / kBytesPerComponent;
1193 EXPECT_EQ(kExpectedValues[4], *(ptr));
1194
1195 EXPECT_GL_NO_ERROR();
1196 }
1197
1198 // Test that access/write to array of array structure data in shader storage buffer.
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferStructureArrayOfArray)1199 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferStructureArrayOfArray)
1200 {
1201 constexpr char kComputeShaderSource[] = R"(#version 310 es
1202 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1203 struct S
1204 {
1205 uvec2 uvData;
1206 uint uiData[2];
1207 };
1208 layout(std140, binding = 0) buffer blockIn {
1209 S s[3][2];
1210 uint lastData;
1211 } instanceIn;
1212 layout(std140, binding = 1) buffer blockOut {
1213 S s[3][2];
1214 uint lastData;
1215 } instanceOut;
1216 void main()
1217 {
1218 instanceOut.s[1][0].uvData = instanceIn.s[1][0].uvData;
1219 instanceOut.s[1][0].uiData[0] = instanceIn.s[1][0].uiData[0];
1220 instanceOut.s[1][0].uiData[1] = instanceIn.s[1][0].uiData[1];
1221 instanceOut.s[1][1].uvData = instanceIn.s[1][1].uvData;
1222 instanceOut.s[1][1].uiData[0] = instanceIn.s[1][1].uiData[0];
1223 instanceOut.s[1][1].uiData[1] = instanceIn.s[1][1].uiData[1];
1224
1225 instanceOut.lastData = instanceIn.lastData;
1226 }
1227 )";
1228
1229 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1230
1231 glUseProgram(program);
1232
1233 std::array<GLuint, 4> kUVData = {{
1234 1u,
1235 2u,
1236 0u,
1237 0u,
1238 }};
1239 std::array<GLuint, 8> kUIData = {{
1240 3u,
1241 0u,
1242 0u,
1243 0u,
1244 4u,
1245 0u,
1246 0u,
1247 0u,
1248 }};
1249 GLuint kLastData = 5u;
1250
1251 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
1252 constexpr unsigned int kStructureStride = 48;
1253 constexpr unsigned int kStructureArrayDimension0 = 3;
1254 constexpr unsigned int kStructureArrayDimension1 = 2;
1255 constexpr unsigned int kLastDataOffset =
1256 kStructureStride * kStructureArrayDimension0 * kStructureArrayDimension1;
1257 constexpr unsigned int totalSize = kLastDataOffset + sizeof(kLastData);
1258
1259 GLBuffer shaderStorageBuffer[2];
1260 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1261 glBufferData(GL_SHADER_STORAGE_BUFFER, totalSize, nullptr, GL_STATIC_DRAW);
1262 // offset of instanceIn.s[1][0]
1263 GLint offset = kStructureStride * (kStructureArrayDimension1 * 1 + 0);
1264 GLuint uintOffset = offset / kBytesPerComponent;
1265 // upload data to instanceIn.s[1][0]
1266 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUVData.size() * kBytesPerComponent,
1267 kUVData.data());
1268 offset += (kUVData.size() * kBytesPerComponent);
1269 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUIData.size() * kBytesPerComponent,
1270 kUIData.data());
1271 offset += (kUIData.size() * kBytesPerComponent);
1272 // upload data to instanceIn.s[1][1]
1273 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUVData.size() * kBytesPerComponent,
1274 kUVData.data());
1275 offset += (kUVData.size() * kBytesPerComponent);
1276 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kUIData.size() * kBytesPerComponent,
1277 kUIData.data());
1278 // upload data to instanceIn.lastData
1279 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kLastDataOffset, sizeof(kLastData), &kLastData);
1280
1281 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1282 glBufferData(GL_SHADER_STORAGE_BUFFER, totalSize, nullptr, GL_STATIC_DRAW);
1283
1284 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1285 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1286
1287 glDispatchCompute(1, 1, 1);
1288 glFinish();
1289
1290 // Read back shader storage buffer
1291 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1292 constexpr float kExpectedValues[5] = {1u, 2u, 3u, 4u, 5u};
1293 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1294 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, totalSize, GL_MAP_READ_BIT));
1295
1296 // instanceOut.s[0][0]
1297 EXPECT_EQ(kExpectedValues[0], *(ptr + uintOffset));
1298 EXPECT_EQ(kExpectedValues[1], *(ptr + uintOffset + 1));
1299 EXPECT_EQ(kExpectedValues[2], *(ptr + uintOffset + 4));
1300 EXPECT_EQ(kExpectedValues[3], *(ptr + uintOffset + 8));
1301
1302 // instanceOut.s[0][1]
1303 EXPECT_EQ(kExpectedValues[0], *(ptr + uintOffset + 12));
1304 EXPECT_EQ(kExpectedValues[1], *(ptr + uintOffset + 13));
1305 EXPECT_EQ(kExpectedValues[2], *(ptr + uintOffset + 16));
1306 EXPECT_EQ(kExpectedValues[3], *(ptr + uintOffset + 20));
1307
1308 // instanceOut.lastData
1309 EXPECT_EQ(kExpectedValues[4], *(ptr + (kLastDataOffset / kBytesPerComponent)));
1310
1311 EXPECT_GL_NO_ERROR();
1312 }
1313
1314 // Test that access/write to vector data in std430 shader storage block.
TEST_P(ShaderStorageBufferTest31,VectorArrayInSSBOWithStd430Qualifier)1315 TEST_P(ShaderStorageBufferTest31, VectorArrayInSSBOWithStd430Qualifier)
1316 {
1317 constexpr char kComputeShaderSource[] = R"(#version 310 es
1318 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1319 layout(std430, binding = 0) buffer blockIn {
1320 uvec2 data[2];
1321 } instanceIn;
1322 layout(std430, binding = 1) buffer blockOut {
1323 uvec2 data[2];
1324 } instanceOut;
1325 void main()
1326 {
1327 instanceOut.data[0] = instanceIn.data[0];
1328 instanceOut.data[1] = instanceIn.data[1];
1329 }
1330 )";
1331
1332 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1333
1334 glUseProgram(program);
1335
1336 constexpr unsigned int kElementCount = 2;
1337 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
1338 constexpr unsigned int kArrayStride = 8;
1339 constexpr unsigned int kComponentCount = kArrayStride / kBytesPerComponent;
1340 constexpr unsigned int kExpectedValues[kElementCount][kComponentCount] = {{1u, 2u}, {3u, 4u}};
1341 // Create shader storage buffer
1342 GLBuffer shaderStorageBuffer[2];
1343 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1344 glBufferData(GL_SHADER_STORAGE_BUFFER, kElementCount * kArrayStride, kExpectedValues,
1345 GL_STATIC_DRAW);
1346 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1347 glBufferData(GL_SHADER_STORAGE_BUFFER, kElementCount * kArrayStride, nullptr, GL_STATIC_DRAW);
1348
1349 // Bind shader storage buffer
1350 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1351 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1352
1353 glDispatchCompute(1, 1, 1);
1354
1355 glFinish();
1356
1357 // Read back shader storage buffer
1358 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1359 const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
1360 GL_SHADER_STORAGE_BUFFER, 0, kElementCount * kArrayStride, GL_MAP_READ_BIT));
1361 for (unsigned int idx = 0; idx < kElementCount; idx++)
1362 {
1363 for (unsigned int idy = 0; idy < kComponentCount; idy++)
1364 {
1365 EXPECT_EQ(kExpectedValues[idx][idy], *(ptr + idx * kComponentCount + idy));
1366 }
1367 }
1368
1369 EXPECT_GL_NO_ERROR();
1370 }
1371
1372 // Test that access/write to matrix data in std430 shader storage block.
TEST_P(ShaderStorageBufferTest31,MatrixInSSBOWithStd430Qualifier)1373 TEST_P(ShaderStorageBufferTest31, MatrixInSSBOWithStd430Qualifier)
1374 {
1375 constexpr char kComputeShaderSource[] = R"(#version 310 es
1376 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1377 layout(std430, binding = 0) buffer blockIn {
1378 mat2 data;
1379 } instanceIn;
1380 layout(std430, binding = 1) buffer blockOut {
1381 mat2 data;
1382 } instanceOut;
1383 void main()
1384 {
1385 instanceOut.data = instanceIn.data;
1386 }
1387 )";
1388
1389 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1390
1391 glUseProgram(program);
1392
1393 constexpr unsigned int kColumns = 2;
1394 constexpr unsigned int kRows = 2;
1395 constexpr unsigned int kBytesPerComponent = sizeof(float);
1396 constexpr unsigned int kMatrixStride = kRows * kBytesPerComponent;
1397 constexpr float kInputDada[kColumns * kRows] = {0.1, 0.2, 0.4, 0.5};
1398 MatrixCase matrixCase(kRows, kColumns, kMatrixStride, kComputeShaderSource, kInputDada);
1399 runMatrixTest(matrixCase);
1400 }
1401
1402 // Test that access/write to structure data in std430 shader storage block.
TEST_P(ShaderStorageBufferTest31,StructureInSSBOWithStd430Qualifier)1403 TEST_P(ShaderStorageBufferTest31, StructureInSSBOWithStd430Qualifier)
1404 {
1405 constexpr char kComputeShaderSource[] = R"(#version 310 es
1406 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1407 struct S
1408 {
1409 uvec2 u;
1410 };
1411 layout(std430, binding = 0) buffer blockIn {
1412 uint i1;
1413 S s;
1414 uint i2;
1415 } instanceIn;
1416 layout(std430, binding = 1) buffer blockOut {
1417 uint i1;
1418 S s;
1419 uint i2;
1420 } instanceOut;
1421 void main()
1422 {
1423 instanceOut.i1 = instanceIn.i1;
1424 instanceOut.s.u = instanceIn.s.u;
1425 instanceOut.i2 = instanceIn.i2;
1426 }
1427 )";
1428
1429 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1430 glUseProgram(program);
1431
1432 GLuint kI1Data = 1u;
1433 std::array<GLuint, 2> kUData = {{
1434 2u,
1435 3u,
1436 }};
1437 GLuint kI2Data = 4u;
1438
1439 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
1440 constexpr unsigned int kStructureStartOffset = 8;
1441 constexpr unsigned int kStructureSize = 8;
1442 constexpr unsigned int kTotalSize = kStructureStartOffset + kStructureSize + kBytesPerComponent;
1443
1444 // Create shader storage buffer
1445 GLBuffer shaderStorageBuffer[2];
1446 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1447 glBufferData(GL_SHADER_STORAGE_BUFFER, kTotalSize, nullptr, GL_STATIC_DRAW);
1448 // upload data to instanceIn.i1
1449 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, &kI1Data);
1450 // upload data to instanceIn.s.u
1451 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kStructureStartOffset, kStructureSize, kUData.data());
1452 // upload data to instanceIn.i2
1453 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kStructureStartOffset + kStructureSize,
1454 kBytesPerComponent, &kI2Data);
1455
1456 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1457 glBufferData(GL_SHADER_STORAGE_BUFFER, kTotalSize, nullptr, GL_STATIC_DRAW);
1458
1459 // Bind shader storage buffer
1460 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1461 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1462
1463 glDispatchCompute(1, 1, 1);
1464 glFinish();
1465
1466 // Read back shader storage buffer
1467 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1468 GLuint kExpectedValues[4] = {1u, 2u, 3u, 4u};
1469 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1470 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kTotalSize, GL_MAP_READ_BIT));
1471 EXPECT_EQ(kExpectedValues[0], *ptr);
1472 ptr += (kStructureStartOffset / kBytesPerComponent);
1473 EXPECT_EQ(kExpectedValues[1], *ptr);
1474 EXPECT_EQ(kExpectedValues[2], *(ptr + 1));
1475 ptr += (kStructureSize / kBytesPerComponent);
1476 EXPECT_EQ(kExpectedValues[3], *ptr);
1477
1478 EXPECT_GL_NO_ERROR();
1479 }
1480
1481 // Test that access/write to structure of structure data in std430 shader storage block.
TEST_P(ShaderStorageBufferTest31,StructureOfStructureInSSBOWithStd430Qualifier)1482 TEST_P(ShaderStorageBufferTest31, StructureOfStructureInSSBOWithStd430Qualifier)
1483 {
1484 constexpr char kComputeShaderSource[] = R"(#version 310 es
1485 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1486 struct S2
1487 {
1488 uvec3 u2;
1489 };
1490 struct S1
1491 {
1492 uvec2 u1;
1493 S2 s2;
1494 };
1495 layout(std430, binding = 0) buffer blockIn {
1496 uint i1;
1497 S1 s1;
1498 uint i2;
1499 } instanceIn;
1500 layout(std430, binding = 1) buffer blockOut {
1501 uint i1;
1502 S1 s1;
1503 uint i2;
1504 } instanceOut;
1505 void main()
1506 {
1507 instanceOut.i1 = instanceIn.i1;
1508 instanceOut.s1.u1 = instanceIn.s1.u1;
1509 instanceOut.s1.s2.u2 = instanceIn.s1.s2.u2;
1510 instanceOut.i2 = instanceIn.i2;
1511 }
1512 )";
1513
1514 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1515 glUseProgram(program);
1516
1517 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
1518 constexpr unsigned int kStructureS1StartOffset = 16;
1519 constexpr unsigned int kStructureS2StartOffset = 32;
1520 constexpr unsigned int kStructureS1Size = 32;
1521 constexpr unsigned int kTotalSize =
1522 kStructureS1StartOffset + kStructureS1Size + kBytesPerComponent;
1523
1524 GLuint kI1Data = 1u;
1525 std::array<GLuint, 2> kU1Data = {{2u, 3u}};
1526 std::array<GLuint, 3> kU2Data = {{4u, 5u, 6u}};
1527 GLuint kI2Data = 7u;
1528
1529 // Create shader storage buffer
1530 GLBuffer shaderStorageBuffer[2];
1531 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1532 glBufferData(GL_SHADER_STORAGE_BUFFER, kTotalSize, nullptr, GL_STATIC_DRAW);
1533 // upload data to instanceIn.i1
1534 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, &kI1Data);
1535 // upload data to instanceIn.s1.u1
1536 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kStructureS1StartOffset,
1537 kU1Data.size() * kBytesPerComponent, kU1Data.data());
1538 // upload data to instanceIn.s1.s2.u2
1539 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kStructureS2StartOffset,
1540 kU2Data.size() * kBytesPerComponent, kU2Data.data());
1541 // upload data to instanceIn.i2
1542 glBufferSubData(GL_SHADER_STORAGE_BUFFER, kStructureS1StartOffset + kStructureS1Size,
1543 kBytesPerComponent, &kI2Data);
1544
1545 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1546 glBufferData(GL_SHADER_STORAGE_BUFFER, kTotalSize, nullptr, GL_STATIC_DRAW);
1547
1548 // Bind shader storage buffer
1549 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1550 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1551
1552 glDispatchCompute(1, 1, 1);
1553 glFinish();
1554
1555 // Read back shader storage buffer
1556 GLuint kExpectedValues[7] = {1u, 2u, 3u, 4u, 5u, 6u, 7u};
1557 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1558 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1559 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kTotalSize, GL_MAP_READ_BIT));
1560 EXPECT_EQ(kExpectedValues[0], *ptr);
1561 ptr += (kStructureS1StartOffset / kBytesPerComponent);
1562 EXPECT_EQ(kExpectedValues[1], *ptr);
1563 EXPECT_EQ(kExpectedValues[2], *(ptr + 1));
1564 ptr += ((kStructureS2StartOffset - kStructureS1StartOffset) / kBytesPerComponent);
1565 EXPECT_EQ(kExpectedValues[3], *ptr);
1566 EXPECT_EQ(kExpectedValues[4], *(ptr + 1));
1567 EXPECT_EQ(kExpectedValues[5], *(ptr + 2));
1568 ptr += ((kStructureS1Size - kStructureS2StartOffset) / kBytesPerComponent);
1569 EXPECT_EQ(kExpectedValues[6], *(ptr + 4));
1570
1571 EXPECT_GL_NO_ERROR();
1572 }
1573
1574 // Test atomic memory functions.
TEST_P(ShaderStorageBufferTest31,AtomicMemoryFunctions)1575 TEST_P(ShaderStorageBufferTest31, AtomicMemoryFunctions)
1576 {
1577 constexpr char kCS[] = R"(#version 310 es
1578 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
1579 layout(std140, binding = 1) buffer blockName {
1580 uint data[2];
1581 } instanceName;
1582
1583 void main()
1584 {
1585 instanceName.data[0] = 0u;
1586 instanceName.data[1] = 0u;
1587 atomicAdd(instanceName.data[0], 5u);
1588 atomicMax(instanceName.data[1], 7u);
1589 })";
1590
1591 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
1592
1593 glUseProgram(program);
1594
1595 constexpr unsigned int kElementCount = 2;
1596 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
1597 constexpr unsigned int kArrayStride = 16;
1598 // Create shader storage buffer
1599 GLBuffer shaderStorageBuffer;
1600 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
1601 glBufferData(GL_SHADER_STORAGE_BUFFER, kElementCount * kArrayStride, nullptr, GL_STATIC_DRAW);
1602
1603 // Bind shader storage buffer
1604 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer);
1605
1606 // Dispath compute
1607 glDispatchCompute(1, 1, 1);
1608
1609 glFinish();
1610
1611 // Read back shader storage buffer
1612 constexpr unsigned int kExpectedValues[2] = {5u, 7u};
1613 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
1614 void *ptr = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kElementCount * kArrayStride,
1615 GL_MAP_READ_BIT);
1616 for (unsigned int idx = 0; idx < kElementCount; idx++)
1617 {
1618 EXPECT_EQ(kExpectedValues[idx],
1619 *(reinterpret_cast<const GLuint *>(reinterpret_cast<const GLbyte *>(ptr) +
1620 idx * kArrayStride)));
1621 }
1622 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1623 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1624
1625 EXPECT_GL_NO_ERROR();
1626 }
1627
1628 // Test multiple storage buffers work correctly when program switching. In angle, storage buffer
1629 // bindings are updated accord to current program. If switch program, need to update storage buffer
1630 // bindings again.
TEST_P(ShaderStorageBufferTest31,MultiStorageBuffersForMultiPrograms)1631 TEST_P(ShaderStorageBufferTest31, MultiStorageBuffersForMultiPrograms)
1632 {
1633 constexpr char kCS1[] = R"(#version 310 es
1634 layout(local_size_x=3, local_size_y=1, local_size_z=1) in;
1635 layout(binding = 1) buffer Output {
1636 uint result1[];
1637 } sb_out1;
1638 void main()
1639 {
1640 highp uint offset = gl_LocalInvocationID.x;
1641 sb_out1.result1[gl_LocalInvocationIndex] = gl_LocalInvocationIndex + 1u;
1642 })";
1643
1644 constexpr char kCS2[] = R"(#version 310 es
1645 layout(local_size_x=3, local_size_y=1, local_size_z=1) in;
1646 layout(binding = 2) buffer Output {
1647 uint result2[];
1648 } sb_out2;
1649 void main()
1650 {
1651 highp uint offset = gl_LocalInvocationID.x;
1652 sb_out2.result2[gl_LocalInvocationIndex] = gl_LocalInvocationIndex + 2u;
1653 })";
1654
1655 constexpr unsigned int numInvocations = 3;
1656 int arrayStride1 = 0, arrayStride2 = 0;
1657 GLenum props[] = {GL_ARRAY_STRIDE};
1658 GLBuffer shaderStorageBuffer1, shaderStorageBuffer2;
1659
1660 ANGLE_GL_COMPUTE_PROGRAM(program1, kCS1);
1661 ANGLE_GL_COMPUTE_PROGRAM(program2, kCS2);
1662 EXPECT_GL_NO_ERROR();
1663
1664 unsigned int outVarIndex1 =
1665 glGetProgramResourceIndex(program1, GL_BUFFER_VARIABLE, "Output.result1");
1666 glGetProgramResourceiv(program1, GL_BUFFER_VARIABLE, outVarIndex1, 1, props, 1, 0,
1667 &arrayStride1);
1668 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer1);
1669 glBufferData(GL_SHADER_STORAGE_BUFFER, numInvocations * arrayStride1, nullptr, GL_STREAM_READ);
1670 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer1);
1671 EXPECT_GL_NO_ERROR();
1672
1673 unsigned int outVarIndex2 =
1674 glGetProgramResourceIndex(program2, GL_BUFFER_VARIABLE, "Output.result2");
1675 glGetProgramResourceiv(program2, GL_BUFFER_VARIABLE, outVarIndex2, 1, props, 1, 0,
1676 &arrayStride2);
1677 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer2);
1678 glBufferData(GL_SHADER_STORAGE_BUFFER, numInvocations * arrayStride2, nullptr, GL_STREAM_READ);
1679 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, shaderStorageBuffer2);
1680 EXPECT_GL_NO_ERROR();
1681
1682 glUseProgram(program1);
1683 glDispatchCompute(1, 1, 1);
1684 EXPECT_GL_NO_ERROR();
1685 glUseProgram(program2);
1686 glDispatchCompute(1, 1, 1);
1687 EXPECT_GL_NO_ERROR();
1688
1689 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer1);
1690 const void *ptr1 =
1691 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * arrayStride1, GL_MAP_READ_BIT);
1692 for (unsigned int idx = 0; idx < numInvocations; idx++)
1693 {
1694 EXPECT_EQ(idx + 1, *((const GLuint *)((const GLbyte *)ptr1 + idx * arrayStride1)));
1695 }
1696 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1697 EXPECT_GL_NO_ERROR();
1698
1699 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer2);
1700 const void *ptr2 =
1701 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * arrayStride2, GL_MAP_READ_BIT);
1702 EXPECT_GL_NO_ERROR();
1703 for (unsigned int idx = 0; idx < numInvocations; idx++)
1704 {
1705 EXPECT_EQ(idx + 2, *((const GLuint *)((const GLbyte *)ptr2 + idx * arrayStride2)));
1706 }
1707 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1708 EXPECT_GL_NO_ERROR();
1709
1710 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1711 EXPECT_GL_NO_ERROR();
1712 }
1713
1714 // Test that function calling is supported in SSBO access chain.
TEST_P(ShaderStorageBufferTest31,FunctionCallInSSBOAccessChain)1715 TEST_P(ShaderStorageBufferTest31, FunctionCallInSSBOAccessChain)
1716 {
1717 constexpr char kComputeShaderSource[] = R"(#version 310 es
1718 layout (local_size_x=4) in;
1719 highp uint getIndex (in highp uvec2 localID, uint element)
1720 {
1721 return localID.x + element;
1722 }
1723 layout(binding=0, std430) buffer Storage
1724 {
1725 highp uint values[];
1726 } sb_store;
1727
1728 void main()
1729 {
1730 sb_store.values[getIndex(gl_LocalInvocationID.xy, 0u)] = gl_LocalInvocationIndex;
1731 }
1732 )";
1733
1734 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1735 EXPECT_GL_NO_ERROR();
1736 }
1737
1738 // Test that unary operator is supported in SSBO access chain.
TEST_P(ShaderStorageBufferTest31,UnaryOperatorInSSBOAccessChain)1739 TEST_P(ShaderStorageBufferTest31, UnaryOperatorInSSBOAccessChain)
1740 {
1741 constexpr char kComputeShaderSource[] = R"(#version 310 es
1742 layout (local_size_x=4) in;
1743 layout(binding=0, std430) buffer Storage
1744 {
1745 highp uint values[];
1746 } sb_store;
1747
1748 void main()
1749 {
1750 uint invocationNdx = gl_LocalInvocationIndex;
1751 sb_store.values[++invocationNdx] = invocationNdx;
1752 }
1753 )";
1754
1755 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1756 EXPECT_GL_NO_ERROR();
1757 }
1758
1759 // Test that ternary operator is supported in SSBO access chain.
TEST_P(ShaderStorageBufferTest31,TernaryOperatorInSSBOAccessChain)1760 TEST_P(ShaderStorageBufferTest31, TernaryOperatorInSSBOAccessChain)
1761 {
1762 constexpr char kComputeShaderSource[] = R"(#version 310 es
1763 layout (local_size_x=4) in;
1764 layout(binding=0, std430) buffer Storage
1765 {
1766 highp uint values[];
1767 } sb_store;
1768
1769 void main()
1770 {
1771 sb_store.values[gl_LocalInvocationIndex > 2u ? gl_NumWorkGroups.x : gl_NumWorkGroups.y]
1772 = gl_LocalInvocationIndex;
1773 }
1774 )";
1775
1776 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1777 EXPECT_GL_NO_ERROR();
1778 }
1779
1780 // Tests that alignment is correct for bools inside a SSB and that the values
1781 // are written correctly by a trivial shader. Currently tests only the alignment
1782 // of the initial block.
TEST_P(ShaderStorageBufferTest31,LoadAndStoreBooleanValue)1783 TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanValue)
1784 {
1785 // TODO([email protected]): Figure out why it fails on Intel Linux platform.
1786 // http://anglebug.com/40644618
1787 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
1788
1789 constexpr char kComputeShaderSource[] = R"(#version 310 es
1790 layout (local_size_x=1) in;
1791 layout(binding=0, std140) buffer Storage0
1792 {
1793 bool b1;
1794 bool b2;
1795 bool b3;
1796 } sb_load;
1797 layout(binding=1, std140) buffer Storage1
1798 {
1799 bool b1;
1800 bool b2;
1801 bool b3;
1802 } sb_store;
1803 void main()
1804 {
1805 sb_store.b1 = sb_load.b1;
1806 sb_store.b2 = sb_load.b2;
1807 sb_store.b3 = sb_load.b3;
1808 }
1809 )";
1810
1811 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1812 EXPECT_GL_NO_ERROR();
1813
1814 glUseProgram(program);
1815
1816 constexpr GLuint kB1Value = 1u;
1817 constexpr GLuint kB2Value[2] = {0u, 1u};
1818 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
1819 // Create shader storage buffer
1820 GLBuffer shaderStorageBuffer[2];
1821 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1822 glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
1823 GLint offset = 0;
1824 // upload data to sb_load.b1
1825 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kBytesPerComponent, &kB1Value);
1826 offset += kBytesPerComponent;
1827 // upload data to sb_load.b2
1828 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, 2 * kBytesPerComponent, kB2Value);
1829
1830 constexpr GLuint kStoreBufferContents[3] = {0x1BCD1234, 0x2BCD1234, 0x3BCD1234};
1831 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1832 glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, kStoreBufferContents,
1833 GL_STATIC_DRAW);
1834
1835 // Bind shader storage buffer
1836 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1837 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1838
1839 glDispatchCompute(1, 1, 1);
1840 glFinish();
1841
1842 // Read back shader storage buffer
1843 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1844 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1845 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
1846 EXPECT_EQ(kB1Value, ptr[0]);
1847 EXPECT_EQ(kB2Value[0], ptr[1]);
1848 EXPECT_EQ(kB2Value[1], ptr[2]);
1849
1850 EXPECT_GL_NO_ERROR();
1851 }
1852
1853 // Tests that alignment is correct for bvecs3 inside a SSB and that the
1854 // values are written correctly by a trivial shader. Currently tests only the
1855 // alignment of the initial block.
TEST_P(ShaderStorageBufferTest31,LoadAndStoreBooleanVec3)1856 TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanVec3)
1857 {
1858 // TODO([email protected]): Figure out why it fails on Intel Linux platform.
1859 // http://anglebug.com/40644618
1860 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
1861
1862 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
1863
1864 constexpr char kComputeShaderSource[] = R"(#version 310 es
1865 layout (local_size_x=1) in;
1866 layout(binding=0, std140) buffer Storage0
1867 {
1868 bvec3 b;
1869 } sb_load;
1870 layout(binding=1, std140) buffer Storage1
1871 {
1872 bvec3 b;
1873 } sb_store;
1874 void main()
1875 {
1876 sb_store.b = sb_load.b;
1877 }
1878 )";
1879
1880 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1881 EXPECT_GL_NO_ERROR();
1882
1883 glUseProgram(program);
1884
1885 constexpr GLuint kBValues[3] = {1u, 0u, 1u};
1886 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
1887 // Create shader storage buffer
1888 GLBuffer shaderStorageBuffer[2];
1889 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1890 glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, nullptr, GL_STATIC_DRAW);
1891 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, &kBValues);
1892
1893 constexpr GLuint kStoreBufferContents[3] = {0x1BCD1234, 0x2BCD1234, 0x3BCD1234};
1894 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1895 glBufferData(GL_SHADER_STORAGE_BUFFER, 3 * kBytesPerComponent, kStoreBufferContents,
1896 GL_STATIC_DRAW);
1897
1898 // Bind shader storage buffer
1899 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1900 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1901
1902 glDispatchCompute(1, 1, 1);
1903 glFinish();
1904
1905 // Read back shader storage buffer
1906 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1907 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1908 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 3 * kBytesPerComponent, GL_MAP_READ_BIT));
1909 EXPECT_EQ(kBValues[0], ptr[0]);
1910 EXPECT_EQ(kBValues[1], ptr[1]);
1911 EXPECT_EQ(kBValues[2], ptr[2]);
1912
1913 EXPECT_GL_NO_ERROR();
1914 }
1915
1916 // Tests that alignment is correct for bool + bvecs2 inside a SSB and that the
1917 // values are written correctly by a trivial shader. Currently tests only the
1918 // alignment of the initial block. Compare to LoadAndStoreBooleanVec3 to see how
1919 // the alignment rules affect the memory layout.
TEST_P(ShaderStorageBufferTest31,LoadAndStoreBooleanVarAndVec2)1920 TEST_P(ShaderStorageBufferTest31, LoadAndStoreBooleanVarAndVec2)
1921 {
1922 // TODO([email protected]): Figure out why it fails on Intel Linux platform.
1923 // http://anglebug.com/40644618
1924 ANGLE_SKIP_TEST_IF(IsIntel() && IsLinux());
1925
1926 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
1927
1928 constexpr char kComputeShaderSource[] = R"(#version 310 es
1929 layout (local_size_x=1) in;
1930 layout(binding=0, std140) buffer Storage0
1931 {
1932 bool b1;
1933 bvec2 b2;
1934 } sb_load;
1935 layout(binding=1, std140) buffer Storage1
1936 {
1937 bool b1;
1938 bvec2 b2;
1939 } sb_store;
1940 void main()
1941 {
1942 sb_store.b1 = sb_load.b1;
1943 sb_store.b2 = sb_load.b2;
1944 }
1945 )";
1946 // https://www.khronos.org/registry/OpenGL/specs/es/3.1/es_spec_3.1.pdf
1947 // 7.6.2.2 Standard Uniform Block Layout
1948
1949 // ... A structure and each structure member have a base offset and a base
1950 // alignment, from which an aligned offset is computed by rounding the base
1951 // offset up to a multiple of the base alignment. The base offset of the
1952 // first member of a structure is taken from the aligned offset of the
1953 // structure itself. ... The members of a toplevel uniform block are laid
1954 // out in buffer storage by treating the uniform block as a structure with a
1955 // base offset of zero.
1956
1957 // 1. If the member is a scalar consuming N basic machine units, the base
1958 // alignment is N.
1959
1960 // 2. If the member is a two- or four-component vector with components
1961 // consuming N basic machine units, the base alignment is 2N or 4N,
1962 // respectively
1963
1964 // b1 N == 4, basic offset 0, alignment 4, is at 0..3
1965 // b2 N == 4, basic offset 4, alignment 2*4 = 8, is at 8..16.
1966
1967 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
1968 EXPECT_GL_NO_ERROR();
1969
1970 glUseProgram(program);
1971 constexpr GLuint kAlignPadding = 0x1abcd789u;
1972 constexpr GLuint kBValues[] = {1u, kAlignPadding, 0u, 1u};
1973 constexpr unsigned int kSsbSize = sizeof(kBValues);
1974 // Create shader storage buffer
1975 GLBuffer shaderStorageBuffer[2];
1976 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
1977 glBufferData(GL_SHADER_STORAGE_BUFFER, kSsbSize, nullptr, GL_STATIC_DRAW);
1978 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kSsbSize, &kBValues);
1979
1980 constexpr GLuint kStoreBufferContents[4] = {0x1BCD1234, 0x2BCD1234, 0x3BCD1234, 0x3BCD1277};
1981 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1982 glBufferData(GL_SHADER_STORAGE_BUFFER, kSsbSize, kStoreBufferContents, GL_STATIC_DRAW);
1983
1984 // Bind shader storage buffer
1985 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
1986 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
1987
1988 glDispatchCompute(1, 1, 1);
1989 glFinish();
1990
1991 // Read back shader storage buffer
1992 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
1993 const GLuint *ptr = reinterpret_cast<const GLuint *>(
1994 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSsbSize, GL_MAP_READ_BIT));
1995 EXPECT_EQ(kBValues[0], ptr[0]);
1996 // Index 1 is padding.
1997 EXPECT_EQ(kBValues[2], ptr[2]);
1998 EXPECT_EQ(kBValues[3], ptr[3]);
1999
2000 EXPECT_GL_NO_ERROR();
2001 }
2002
2003 // Test that non-structure array of arrays is supported in SSBO.
TEST_P(ShaderStorageBufferTest31,SimpleArrayOfArrays)2004 TEST_P(ShaderStorageBufferTest31, SimpleArrayOfArrays)
2005 {
2006 constexpr char kComputeShaderSource[] = R"(#version 310 es
2007 layout (local_size_x=1) in;
2008 layout(binding=0, std140) buffer Storage0
2009 {
2010 uint a[2][2][2];
2011 uint b;
2012 } sb_load;
2013 layout(binding=1, std140) buffer Storage1
2014 {
2015 uint a[2][2][2];
2016 uint b;
2017 } sb_store;
2018 void main()
2019 {
2020 sb_store.a[0][0][0] = sb_load.a[0][0][0];
2021 sb_store.a[0][0][1] = sb_load.a[0][0][1];
2022 sb_store.a[0][1][0] = sb_load.a[0][1][0];
2023 sb_store.a[0][1][1] = sb_load.a[0][1][1];
2024 sb_store.a[1][0][0] = sb_load.a[1][0][0];
2025 sb_store.a[1][0][1] = sb_load.a[1][0][1];
2026 sb_store.a[1][1][0] = sb_load.a[1][1][0];
2027 sb_store.a[1][1][1] = sb_load.a[1][1][1];
2028 sb_store.b = sb_load.b;
2029 }
2030 )";
2031
2032 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2033 glUseProgram(program);
2034
2035 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
2036 // The array stride are rounded up to the base alignment of a vec4 for std140 layout.
2037 constexpr unsigned int kArrayStride = 16;
2038 constexpr unsigned int kDimension0 = 2;
2039 constexpr unsigned int kDimension1 = 2;
2040 constexpr unsigned int kDimension2 = 2;
2041 constexpr unsigned int kAElementCount = kDimension0 * kDimension1 * kDimension2;
2042 constexpr unsigned int kAComponentCountPerDimension = kArrayStride / kBytesPerComponent;
2043 constexpr unsigned int kTotalSize = kArrayStride * kAElementCount + kBytesPerComponent;
2044
2045 constexpr GLuint kInputADatas[kAElementCount * kAComponentCountPerDimension] = {
2046 1u, 0u, 0u, 0u, 2u, 0u, 0u, 0u, 3u, 0u, 0u, 0u, 4u, 0u, 0u, 0u,
2047 5u, 0u, 0u, 0u, 6u, 0u, 0u, 0u, 7u, 0u, 0u, 0u, 8u, 0u, 0u, 0u};
2048 constexpr GLuint kInputBData = 9u;
2049
2050 // Create shader storage buffer
2051 GLBuffer shaderStorageBuffer[2];
2052 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2053 glBufferData(GL_SHADER_STORAGE_BUFFER, kTotalSize, nullptr, GL_STATIC_DRAW);
2054 GLint offset = 0;
2055 // upload data to sb_load.a
2056 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kAElementCount * kArrayStride, kInputADatas);
2057 offset += (kAElementCount * kArrayStride);
2058 // upload data to sb_load.b
2059 glBufferSubData(GL_SHADER_STORAGE_BUFFER, offset, kBytesPerComponent, &kInputBData);
2060
2061 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2062 glBufferData(GL_SHADER_STORAGE_BUFFER, kTotalSize, nullptr, GL_STATIC_DRAW);
2063
2064 // Bind shader storage buffer
2065 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2066 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2067
2068 glDispatchCompute(1, 1, 1);
2069 glFinish();
2070
2071 // Read back shader storage buffer
2072 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2073 constexpr GLuint kExpectedADatas[kAElementCount] = {1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u};
2074 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2075 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kTotalSize, GL_MAP_READ_BIT));
2076 for (unsigned i = 0u; i < kDimension0; i++)
2077 {
2078 for (unsigned j = 0u; j < kDimension1; j++)
2079 {
2080 for (unsigned k = 0u; k < kDimension2; k++)
2081 {
2082 unsigned index = i * (kDimension1 * kDimension2) + j * kDimension2 + k;
2083 EXPECT_EQ(kExpectedADatas[index],
2084 *(ptr + index * (kArrayStride / kBytesPerComponent)));
2085 }
2086 }
2087 }
2088
2089 ptr += (kAElementCount * (kArrayStride / kBytesPerComponent));
2090 EXPECT_EQ(kInputBData, *ptr);
2091
2092 EXPECT_GL_NO_ERROR();
2093 }
2094
2095 // Test that the length of unsized array is supported.
TEST_P(ShaderStorageBufferTest31,UnsizedArrayLength)2096 TEST_P(ShaderStorageBufferTest31, UnsizedArrayLength)
2097 {
2098 constexpr char kComputeShaderSource[] =
2099 R"(#version 310 es
2100 layout (local_size_x=1) in;
2101 layout(std430, binding = 0) buffer Storage0 {
2102 uint buf1[2];
2103 uint buf2[];
2104 } sb_load;
2105 layout(std430, binding = 1) buffer Storage1 {
2106 int unsizedArrayLength;
2107 uint buf1[2];
2108 uint buf2[];
2109 } sb_store;
2110
2111 void main()
2112 {
2113 sb_store.unsizedArrayLength = sb_store.buf2.length();
2114 for (int i = 0; i < sb_load.buf1.length(); i++) {
2115 sb_store.buf1[i] = sb_load.buf1[i];
2116 }
2117 for (int i = 0; i < sb_load.buf2.length(); i++) {
2118 sb_store.buf2[i] = sb_load.buf2[i];
2119 }
2120 }
2121 )";
2122
2123 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2124 glUseProgram(program);
2125
2126 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
2127 constexpr unsigned int kLoadBlockElementCount = 5;
2128 constexpr unsigned int kStoreBlockElementCount = 6;
2129 constexpr unsigned int kInputValues[kLoadBlockElementCount] = {1u, 2u, 3u, 4u, 5u};
2130 constexpr unsigned int kExpectedValues[kStoreBlockElementCount] = {3u, 1u, 2u, 3u, 4u, 5u};
2131 GLBuffer shaderStorageBuffer[2];
2132 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2133 glBufferData(GL_SHADER_STORAGE_BUFFER, kLoadBlockElementCount * kBytesPerComponent,
2134 &kInputValues, GL_STATIC_DRAW);
2135 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2136 glBufferData(GL_SHADER_STORAGE_BUFFER, kStoreBlockElementCount * kBytesPerComponent, nullptr,
2137 GL_STATIC_DRAW);
2138
2139 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2140 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2141
2142 glDispatchCompute(1, 1, 1);
2143 glFinish();
2144
2145 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2146 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2147 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kStoreBlockElementCount * kBytesPerComponent,
2148 GL_MAP_READ_BIT));
2149 for (unsigned int i = 0; i < kStoreBlockElementCount; i++)
2150 {
2151 EXPECT_EQ(kExpectedValues[i], *(ptr + i));
2152 }
2153
2154 EXPECT_GL_NO_ERROR();
2155 }
2156
2157 // Test back to back that the length of unsized array is correct after respecifying the buffer
2158 // size to be smaller than the first
TEST_P(ShaderStorageBufferTest31,UnsizedArrayLengthRespecifySize)2159 TEST_P(ShaderStorageBufferTest31, UnsizedArrayLengthRespecifySize)
2160 {
2161 // http://anglebug.com/42263171
2162 ANGLE_SKIP_TEST_IF(IsD3D11() || (IsAndroid() && IsOpenGLES()));
2163
2164 constexpr char kComputeShaderSource[] =
2165 R"(#version 310 es
2166 layout (local_size_x=1) in;
2167 layout(std430, binding = 0) buffer Storage0 {
2168 uint buf1[2];
2169 uint buf2[];
2170 } sb_load;
2171 layout(std430, binding = 1) buffer Storage1 {
2172 int unsizedArrayLength;
2173 uint buf1[2];
2174 uint buf2[];
2175 } sb_store;
2176
2177 void main()
2178 {
2179 sb_store.unsizedArrayLength = sb_store.buf2.length();
2180 for (int i = 0; i < sb_load.buf1.length(); i++) {
2181 sb_store.buf1[i] = sb_load.buf1[i];
2182 }
2183 for (int i = 0; i < sb_load.buf2.length(); i++) {
2184 sb_store.buf2[i] = sb_load.buf2[i];
2185 }
2186 }
2187 )";
2188
2189 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2190 glUseProgram(program);
2191
2192 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
2193 constexpr unsigned int kLoadBlockElementCount = 5;
2194 constexpr unsigned int kStoreBlockElementCount = 6;
2195 constexpr unsigned int kInputValues[kLoadBlockElementCount] = {1u, 2u, 3u, 4u, 5u};
2196 constexpr unsigned int kExpectedValues[kStoreBlockElementCount] = {3u, 1u, 2u, 3u, 4u, 5u};
2197 GLBuffer shaderStorageBuffer[2];
2198 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2199 glBufferData(GL_SHADER_STORAGE_BUFFER, kLoadBlockElementCount * kBytesPerComponent,
2200 &kInputValues, GL_STATIC_DRAW);
2201 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2202 glBufferData(GL_SHADER_STORAGE_BUFFER, kStoreBlockElementCount * kBytesPerComponent, nullptr,
2203 GL_STATIC_DRAW);
2204
2205 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2206 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2207
2208 glDispatchCompute(1, 1, 1);
2209 glFinish();
2210
2211 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2212 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2213 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kStoreBlockElementCount * kBytesPerComponent,
2214 GL_MAP_READ_BIT));
2215 for (unsigned int i = 0; i < kStoreBlockElementCount; i++)
2216 {
2217 EXPECT_EQ(kExpectedValues[i], *(ptr + i));
2218 }
2219 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2220
2221 EXPECT_GL_NO_ERROR();
2222
2223 // Respecify these SSBOs to be smaller
2224 constexpr unsigned int kSmallerLoadBlockElementCount = 3;
2225 constexpr unsigned int kSmallerStoreBlockElementCount = 4;
2226 constexpr unsigned int kSmallerInputValues[kSmallerLoadBlockElementCount] = {1u, 2u, 3u};
2227 constexpr unsigned int kSmallerExpectedValues[kSmallerStoreBlockElementCount] = {1u, 1u, 2u,
2228 3u};
2229
2230 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2231 glBufferData(GL_SHADER_STORAGE_BUFFER, kSmallerLoadBlockElementCount * kBytesPerComponent,
2232 &kSmallerInputValues, GL_STATIC_DRAW);
2233 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2234 glBufferData(GL_SHADER_STORAGE_BUFFER, kSmallerStoreBlockElementCount * kBytesPerComponent,
2235 nullptr, GL_STATIC_DRAW);
2236
2237 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2238 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2239
2240 glDispatchCompute(1, 1, 1);
2241 glFinish();
2242
2243 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2244 const GLuint *ptr2 = reinterpret_cast<const GLuint *>(
2245 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
2246 kSmallerStoreBlockElementCount * kBytesPerComponent, GL_MAP_READ_BIT));
2247 for (unsigned int i = 0; i < kSmallerStoreBlockElementCount; i++)
2248 {
2249 EXPECT_EQ(kSmallerExpectedValues[i], *(ptr2 + i));
2250 }
2251
2252 EXPECT_GL_NO_ERROR();
2253 }
2254
2255 // Test that compond assignment operator for buffer variable is correctly handled.
TEST_P(ShaderStorageBufferTest31,CompoundAssignmentOperator)2256 TEST_P(ShaderStorageBufferTest31, CompoundAssignmentOperator)
2257 {
2258 constexpr char kComputeShaderSource[] =
2259 R"(#version 310 es
2260 layout (local_size_x=1) in;
2261 layout(binding=0, std140) buffer Storage0
2262 {
2263 uint b;
2264 } sb_load;
2265 layout(binding=1, std140) buffer Storage1
2266 {
2267 uint b;
2268 } sb_store;
2269 void main()
2270 {
2271 uint temp = 2u;
2272 temp += sb_load.b;
2273 sb_store.b += temp;
2274 sb_store.b += sb_load.b;
2275 }
2276 )";
2277
2278 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2279 glUseProgram(program);
2280
2281 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
2282 constexpr unsigned int kInputValue = 1u;
2283 constexpr unsigned int kExpectedValue = 5u;
2284 GLBuffer shaderStorageBuffer[2];
2285 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2286 glBufferData(GL_SHADER_STORAGE_BUFFER, kBytesPerComponent, &kInputValue, GL_STATIC_DRAW);
2287 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2288 glBufferData(GL_SHADER_STORAGE_BUFFER, kBytesPerComponent, &kInputValue, GL_STATIC_DRAW);
2289
2290 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2291 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2292
2293 glDispatchCompute(1, 1, 1);
2294 glFinish();
2295
2296 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2297 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2298 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT));
2299 EXPECT_EQ(kExpectedValue, *ptr);
2300
2301 EXPECT_GL_NO_ERROR();
2302 }
2303
2304 // Test that BufferData change propagate to context state.
TEST_P(ShaderStorageBufferTest31,DependentBufferChange)2305 TEST_P(ShaderStorageBufferTest31, DependentBufferChange)
2306 {
2307 // Test fail on Nexus devices. http://anglebug.com/42264770
2308 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
2309
2310 constexpr char kComputeShaderSource[] =
2311 R"(#version 310 es
2312 layout (local_size_x=1) in;
2313 layout(binding=0, std140) buffer Storage0
2314 {
2315 uint b;
2316 } sb_load;
2317 layout(binding=1, std140) buffer Storage1
2318 {
2319 uint b;
2320 } sb_store;
2321 void main()
2322 {
2323 sb_store.b += sb_load.b;
2324 }
2325 )";
2326
2327 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2328 glUseProgram(program);
2329
2330 constexpr unsigned int kBufferSize = 4096;
2331 constexpr unsigned int kBufferElementCount = kBufferSize / sizeof(unsigned int);
2332 std::array<unsigned int, kBufferElementCount> kBufferData = {};
2333 GLBuffer shaderStorageBuffer[2];
2334 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2335 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, kBufferData.data(), GL_STATIC_DRAW);
2336 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2337 kBufferData[0] = 5; // initial value
2338 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, kBufferData.data(), GL_STATIC_DRAW);
2339
2340 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2341 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2342
2343 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2344 kBufferData[0] = 7;
2345 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, kBufferData.data(), GL_STATIC_DRAW);
2346 glDispatchCompute(1, 1, 1);
2347 kBufferData[0] = 11;
2348 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT);
2349 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, kBufferData.data(), GL_STATIC_DRAW);
2350 glDispatchCompute(1, 1, 1);
2351
2352 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2353 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2354 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2355 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
2356 constexpr unsigned int kExpectedValue = 5 + 7 + 11;
2357 EXPECT_EQ(kExpectedValue, *ptr);
2358
2359 EXPECT_GL_NO_ERROR();
2360 }
2361
2362 // Test that readonly binary operator for buffer variable is correctly handled.
TEST_P(ShaderStorageBufferTest31,ReadonlyBinaryOperator)2363 TEST_P(ShaderStorageBufferTest31, ReadonlyBinaryOperator)
2364 {
2365 constexpr char kComputeShaderSource[] =
2366 R"(#version 310 es
2367 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2368 layout(std430, binding = 0) buffer blockIn1 {
2369 uvec2 data1;
2370 };
2371 layout(std430, binding = 1) buffer blockIn2 {
2372 uvec2 data2;
2373 };
2374 layout(std430, binding = 2) buffer blockIn3 {
2375 uvec2 data;
2376 } instanceIn3;
2377 layout(std430, binding = 3) buffer blockOut {
2378 uvec2 data;
2379 } instanceOut;
2380 void main()
2381 {
2382 instanceOut.data = data1 + data2 + instanceIn3.data;
2383 }
2384 )";
2385
2386 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2387 glUseProgram(program);
2388
2389 constexpr unsigned int kComponentCount = 2;
2390 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
2391 constexpr unsigned int kInputValues1[kComponentCount] = {1u, 2u};
2392 constexpr unsigned int kInputValues2[kComponentCount] = {3u, 4u};
2393 constexpr unsigned int kInputValues3[kComponentCount] = {5u, 6u};
2394 // Create shader storage buffer
2395 GLBuffer shaderStorageBuffer[4];
2396 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2397 glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, kInputValues1,
2398 GL_STATIC_DRAW);
2399 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2400 glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, kInputValues2,
2401 GL_STATIC_DRAW);
2402 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[2]);
2403 glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, kInputValues3,
2404 GL_STATIC_DRAW);
2405 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[3]);
2406 glBufferData(GL_SHADER_STORAGE_BUFFER, kComponentCount * kBytesPerComponent, nullptr,
2407 GL_STATIC_DRAW);
2408
2409 // Bind shader storage buffer
2410 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2411 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2412 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, shaderStorageBuffer[2]);
2413 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, shaderStorageBuffer[3]);
2414
2415 glDispatchCompute(1, 1, 1);
2416 glFinish();
2417
2418 // Read back shader storage buffer
2419 constexpr unsigned int kExpectedValues[kComponentCount] = {9u, 12u};
2420 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[3]);
2421 const GLuint *ptr = reinterpret_cast<const GLuint *>(glMapBufferRange(
2422 GL_SHADER_STORAGE_BUFFER, 0, kComponentCount * kBytesPerComponent, GL_MAP_READ_BIT));
2423 for (unsigned int idx = 0; idx < kComponentCount; idx++)
2424 {
2425 EXPECT_EQ(kExpectedValues[idx], *(ptr + idx));
2426 }
2427
2428 EXPECT_GL_NO_ERROR();
2429 }
2430
2431 // Test that ssbo as an argument of a function can be translated.
TEST_P(ShaderStorageBufferTest31,SSBOAsFunctionArgument)2432 TEST_P(ShaderStorageBufferTest31, SSBOAsFunctionArgument)
2433 {
2434 constexpr char kComputeShaderSource[] =
2435 R"(#version 310 es
2436 layout(local_size_x = 1) in;
2437
2438 layout(std430, binding = 0) buffer Block
2439 {
2440 uint var1;
2441 uint var2;
2442 };
2443
2444 bool compare(uint a, uint b)
2445 {
2446 return a == b;
2447 }
2448
2449 uint increase(inout uint a)
2450 {
2451 a++;
2452 return a;
2453 }
2454
2455 void main(void)
2456 {
2457 bool isEqual = compare(var1, 2u);
2458 if (isEqual)
2459 {
2460 var2 += increase(var1);
2461 }
2462 }
2463 )";
2464
2465 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2466 glUseProgram(program);
2467
2468 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
2469 constexpr unsigned int kInputValues[2] = {2u, 2u};
2470 constexpr unsigned int kExpectedValues[2] = {3u, 5u};
2471 GLBuffer shaderStorageBuffer;
2472 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
2473 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * kBytesPerComponent, &kInputValues, GL_STATIC_DRAW);
2474
2475 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
2476
2477 glDispatchCompute(1, 1, 1);
2478 glFinish();
2479
2480 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
2481 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2482 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 2 * kBytesPerComponent, GL_MAP_READ_BIT));
2483 EXPECT_EQ(kExpectedValues[0], *ptr);
2484 EXPECT_EQ(kExpectedValues[1], *(ptr + 1));
2485
2486 EXPECT_GL_NO_ERROR();
2487 }
2488
2489 // Test that ssbo as unary operand works well.
TEST_P(ShaderStorageBufferTest31,SSBOAsUnaryOperand)2490 TEST_P(ShaderStorageBufferTest31, SSBOAsUnaryOperand)
2491 {
2492 constexpr char kComputeShaderSource[] =
2493 R"(#version 310 es
2494 layout (local_size_x=1) in;
2495 layout(binding=0, std140) buffer Storage0
2496 {
2497 uint b;
2498 } sb_load;
2499 layout(binding=1, std140) buffer Storage1
2500 {
2501 uint i;
2502 } sb_store;
2503 void main()
2504 {
2505 sb_store.i = +sb_load.b;
2506 ++sb_store.i;
2507 }
2508 )";
2509
2510 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2511 glUseProgram(program);
2512
2513 constexpr unsigned int kBytesPerComponent = sizeof(unsigned int);
2514 constexpr unsigned kInputValue = 1u;
2515 constexpr unsigned int kExpectedValue = 2u;
2516 GLBuffer shaderStorageBuffer[2];
2517 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
2518 glBufferData(GL_SHADER_STORAGE_BUFFER, kBytesPerComponent, &kInputValue, GL_STATIC_DRAW);
2519 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2520 glBufferData(GL_SHADER_STORAGE_BUFFER, kBytesPerComponent, &kInputValue, GL_STATIC_DRAW);
2521
2522 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
2523 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
2524
2525 glDispatchCompute(1, 1, 1);
2526 glFinish();
2527
2528 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
2529 const GLuint *ptr = reinterpret_cast<const GLuint *>(
2530 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT));
2531 EXPECT_EQ(kExpectedValue, *ptr);
2532
2533 EXPECT_GL_NO_ERROR();
2534 }
2535
2536 // Test that uniform can be used as the index of buffer variable.
TEST_P(ShaderStorageBufferTest31,UniformUsedAsIndexOfBufferVariable)2537 TEST_P(ShaderStorageBufferTest31, UniformUsedAsIndexOfBufferVariable)
2538 {
2539 constexpr char kComputeShaderSource[] =
2540 R"(#version 310 es
2541 layout (local_size_x=4) in;
2542 layout(std140, binding = 0) uniform CB
2543 {
2544 uint index;
2545 } cb;
2546
2547 layout(binding=0, std140) buffer Storage0
2548 {
2549 uint data[];
2550 } sb_load;
2551 layout(binding=1, std140) buffer Storage1
2552 {
2553 uint data[];
2554 } sb_store;
2555 void main()
2556 {
2557 sb_store.data[gl_LocalInvocationIndex] = sb_load.data[gl_LocalInvocationID.x + cb.index];
2558 }
2559 )";
2560
2561 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2562 EXPECT_GL_NO_ERROR();
2563 }
2564
2565 // Test that inactive but statically used SSBOs with unsized array are handled correctly.
2566 //
2567 // Glslang wrapper used to replace the layout/qualifier of an inactive SSBO with |struct|,
2568 // effectively turning the interface block declaration into a struct definition. This generally
2569 // worked except for SSBOs with an unsized array. This test makes sure this special case is
2570 // now properly handled.
TEST_P(ShaderStorageBufferTest31,InactiveButStaticallyUsedWithUnsizedArray)2571 TEST_P(ShaderStorageBufferTest31, InactiveButStaticallyUsedWithUnsizedArray)
2572 {
2573 constexpr char kComputeShaderSource[] =
2574 R"(#version 310 es
2575 layout (local_size_x=1) in;
2576 layout(binding=0, std140) buffer Storage
2577 {
2578 uint data[];
2579 } sb;
2580 void main()
2581 {
2582 if (false)
2583 {
2584 sb.data[0] = 1u;
2585 }
2586 }
2587 )";
2588
2589 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2590 EXPECT_GL_NO_ERROR();
2591
2592 glUseProgram(program);
2593 glDispatchCompute(1, 1, 1);
2594 EXPECT_GL_NO_ERROR();
2595 }
2596
2597 // Verify the size of the buffer with unsized struct array is calculated correctly
TEST_P(ShaderStorageBufferTest31,BigStructUnsizedStructArraySize)2598 TEST_P(ShaderStorageBufferTest31, BigStructUnsizedStructArraySize)
2599 {
2600 // TODO(http://anglebug.com/42262259)
2601 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
2602
2603 constexpr char kComputeShaderSource[] =
2604 R"(#version 310 es
2605 layout (local_size_x=1) in;
2606
2607 struct S
2608 {
2609 mat4 m; // 4 vec4 = 16 floats
2610 vec4 a[10]; // 10 vec4 = 40 floats
2611 };
2612
2613 layout(binding=0) buffer B
2614 {
2615 vec4 precedingMember; // 4 floats
2616 S precedingMemberUnsizedArray[]; // 56 floats
2617 } b;
2618
2619 void main()
2620 {
2621 if (false)
2622 {
2623 b.precedingMember = vec4(1.0, 1.0, 1.0, 1.0);
2624 }
2625 }
2626 )";
2627
2628 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2629 EXPECT_GL_NO_ERROR();
2630
2631 glUseProgram(program);
2632 glDispatchCompute(1, 1, 1);
2633 EXPECT_GL_NO_ERROR();
2634
2635 GLuint resourceIndex = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "B");
2636 EXPECT_GL_NO_ERROR();
2637 EXPECT_NE(resourceIndex, 0xFFFFFFFF);
2638
2639 GLenum property = GL_BUFFER_DATA_SIZE;
2640 GLint queryData = -1;
2641 glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, resourceIndex, 1, &property, 1,
2642 nullptr, &queryData);
2643 EXPECT_GL_NO_ERROR();
2644
2645 // 60 * sizeof(float) = 240
2646 // Vulkan rounds up to the required buffer alignment, so >= 240
2647 EXPECT_GE(queryData, 240);
2648 }
2649
2650 // Verify the size of the buffer with unsized float array is calculated correctly
TEST_P(ShaderStorageBufferTest31,BigStructUnsizedFloatArraySize)2651 TEST_P(ShaderStorageBufferTest31, BigStructUnsizedFloatArraySize)
2652 {
2653 // TODO(http://anglebug.com/42262259)
2654 ANGLE_SKIP_TEST_IF(IsAMD() && IsWindows() && IsOpenGL());
2655
2656 constexpr char kComputeShaderSource[] =
2657 R"(#version 310 es
2658 layout (local_size_x=1) in;
2659
2660 layout(binding=0) buffer B
2661 {
2662 vec4 precedingMember; // 4 floats
2663 float precedingMemberUnsizedArray[]; // "1" float
2664 } b;
2665
2666 void main()
2667 {
2668 if (false)
2669 {
2670 b.precedingMember = vec4(1.0, 1.0, 1.0, 1.0);
2671 }
2672 }
2673 )";
2674
2675 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2676 EXPECT_GL_NO_ERROR();
2677
2678 glUseProgram(program);
2679 glDispatchCompute(1, 1, 1);
2680 EXPECT_GL_NO_ERROR();
2681
2682 GLuint resourceIndex = glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, "B");
2683 EXPECT_GL_NO_ERROR();
2684 EXPECT_NE(resourceIndex, 0xFFFFFFFF);
2685
2686 GLenum property = GL_BUFFER_DATA_SIZE;
2687 GLint queryData = -1;
2688 glGetProgramResourceiv(program, GL_SHADER_STORAGE_BLOCK, resourceIndex, 1, &property, 1,
2689 nullptr, &queryData);
2690 EXPECT_GL_NO_ERROR();
2691
2692 // 5 * sizeof(float) = 20
2693 // Vulkan rounds up to the required buffer alignment, so >= 20
2694 EXPECT_GE(queryData, 20);
2695 }
2696
2697 // Tests that shader write before pixel pack/unpack works
TEST_P(ShaderStorageBufferTest31,ShaderStorageBufferWriteThenPixelPackUnpack)2698 TEST_P(ShaderStorageBufferTest31, ShaderStorageBufferWriteThenPixelPackUnpack)
2699 {
2700 // Create two textures and framebuffers and make sure they are initialized.
2701 GLTexture color1;
2702 glBindTexture(GL_TEXTURE_2D, color1);
2703 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2704
2705 GLFramebuffer framebuffer1;
2706 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2707 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
2708
2709 glClearColor(255, 0, 255, 255);
2710 glClear(GL_COLOR_BUFFER_BIT);
2711 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
2712
2713 GLTexture color2;
2714 glBindTexture(GL_TEXTURE_2D, color2);
2715 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2716
2717 GLFramebuffer framebuffer2;
2718 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2719 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color2, 0);
2720
2721 glClearColor(0, 0, 255, 255);
2722 glClear(GL_COLOR_BUFFER_BIT);
2723 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2724
2725 constexpr char kComputeShaderSource[] =
2726 R"(#version 310 es
2727 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2728 layout(std430, binding = 0) buffer block {
2729 uint data[2];
2730 } outBlock;
2731 void main()
2732 {
2733 // Output red to index 0, and green to index 1.
2734 outBlock.data[0] = 0xFF0000FFu;
2735 outBlock.data[1] = 0xFF00FF00u;
2736 }
2737 )";
2738
2739 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2740
2741 glUseProgram(program);
2742
2743 constexpr GLsizei kBufferSize = sizeof(GLuint) * 2;
2744 constexpr std::array<GLuint, 2> kBufferInitData = {0x01234567u, 0x89ABCDEFu};
2745
2746 // Create a shader storage buffer
2747 GLBuffer buffer;
2748
2749 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
2750 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, kBufferInitData.data(), GL_STATIC_DRAW);
2751
2752 // Bind shader storage buffer and write to it.
2753 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
2754
2755 glDispatchCompute(1, 1, 1);
2756 EXPECT_GL_NO_ERROR();
2757
2758 // Issue a memory barrier for pixel pack/unpack operations.
2759 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
2760 EXPECT_GL_NO_ERROR();
2761
2762 // Use a pixel pack operation to overwrite the output of the compute shader at index 0. Uses
2763 // the second framebuffer which is blue.
2764 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
2765 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2766 EXPECT_GL_NO_ERROR();
2767
2768 // Use a pixel unpack operation to re-initialize the other framebuffer with the results from the
2769 // compute shader.
2770 glBindTexture(GL_TEXTURE_2D, color1);
2771 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
2772 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2773 reinterpret_cast<void *>(sizeof(GLuint)));
2774 EXPECT_GL_NO_ERROR();
2775
2776 // Verify that the first framebuffer is now green
2777 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
2778 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer1);
2779 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2780
2781 // Verify the contents of the buffer. It should have blue as the first index and green as the
2782 // second.
2783 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2784 GLColor *bufferContents = static_cast<GLColor *>(
2785 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
2786 EXPECT_GL_NO_ERROR();
2787
2788 EXPECT_EQ(GLColor::blue, bufferContents[0]);
2789 EXPECT_EQ(GLColor::green, bufferContents[1]);
2790 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2791 EXPECT_GL_NO_ERROR();
2792 }
2793
2794 // Tests that shader write after pixel pack/unpack works
TEST_P(ShaderStorageBufferTest31,PixelPackUnpackThenShaderStorageBufferWrite)2795 TEST_P(ShaderStorageBufferTest31, PixelPackUnpackThenShaderStorageBufferWrite)
2796 {
2797 swapBuffers();
2798 // Create two textures and framebuffers and make sure they are initialized.
2799 GLTexture color1;
2800 glBindTexture(GL_TEXTURE_2D, color1);
2801 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2802
2803 GLFramebuffer framebuffer1;
2804 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1);
2805 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color1, 0);
2806
2807 glClearColor(255, 0, 255, 255);
2808 glClear(GL_COLOR_BUFFER_BIT);
2809 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
2810
2811 GLTexture color2;
2812 glBindTexture(GL_TEXTURE_2D, color2);
2813 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
2814
2815 GLFramebuffer framebuffer2;
2816 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer2);
2817 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color2, 0);
2818
2819 glClearColor(0, 0, 255, 255);
2820 glClear(GL_COLOR_BUFFER_BIT);
2821 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2822
2823 constexpr GLsizei kBufferSize = sizeof(GLuint) * 2;
2824 constexpr std::array<GLuint, 2> kBufferInitData = {0x01234567u, 0xFF00FF00u};
2825
2826 // Create a shader storage buffer
2827 GLBuffer buffer;
2828
2829 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
2830 glBufferData(GL_SHADER_STORAGE_BUFFER, kBufferSize, kBufferInitData.data(), GL_STATIC_DRAW);
2831
2832 // Use a pixel pack operation to overwrite the buffer at index 0. Uses the second framebuffer
2833 // which is blue.
2834 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
2835 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2836 EXPECT_GL_NO_ERROR();
2837
2838 // Use a pixel unpack operation to re-initialize the other framebuffer with the contents of the
2839 // buffer, which is green.
2840 glBindTexture(GL_TEXTURE_2D, color1);
2841 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
2842 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE,
2843 reinterpret_cast<void *>(sizeof(GLuint)));
2844 EXPECT_GL_NO_ERROR();
2845
2846 // Issue a memory barrier for pixel pack/unpack operations.
2847 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
2848
2849 // Issue a dispatch call that overwrites the buffer, also verifying that the results of the pack
2850 // operation is correct.
2851 constexpr char kComputeShaderSource[] =
2852 R"(#version 310 es
2853 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2854 layout(std430, binding = 0) buffer block {
2855 uint data[2];
2856 } outBlock;
2857 void main()
2858 {
2859 if (outBlock.data[0] == 0xFFFF0000u)
2860 {
2861 outBlock.data[0] = 0x11223344u;
2862 }
2863 else
2864 {
2865 outBlock.data[0] = 0xABCDABCDu;
2866 }
2867 outBlock.data[1] = 0x55667788u;
2868 }
2869 )";
2870
2871 ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
2872
2873 glUseProgram(program);
2874
2875 // Bind shader storage buffer and write to it.
2876 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
2877
2878 glDispatchCompute(1, 1, 1);
2879 EXPECT_GL_NO_ERROR();
2880
2881 // Verify that the first framebuffer is now green
2882 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
2883 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer1);
2884 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2885
2886 // Verify that the second framebuffer is still blue
2887 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
2888 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer2);
2889 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
2890
2891 // Verify the contents of the buffer.
2892 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2893 uint32_t *bufferContents = static_cast<uint32_t *>(
2894 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT));
2895 EXPECT_GL_NO_ERROR();
2896
2897 EXPECT_EQ(bufferContents[0], 0x11223344u);
2898 EXPECT_EQ(bufferContents[1], 0x55667788u);
2899 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2900 EXPECT_GL_NO_ERROR();
2901 }
2902
2903 // Tests that reading from an SSBO inside a function in the fragment shader works.
TEST_P(ShaderStorageBufferTest31,FragReadSSBOInFunction)2904 TEST_P(ShaderStorageBufferTest31, FragReadSSBOInFunction)
2905 {
2906 GLint maxFragmentShaderStorageBlocks;
2907 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &maxFragmentShaderStorageBlocks);
2908
2909 ANGLE_SKIP_TEST_IF(maxFragmentShaderStorageBlocks < 1);
2910
2911 constexpr std::array<float, 4> kBufferInitValue = {1.0f, 0.0f, 1.0f, 1.0f};
2912 GLBuffer buffer;
2913 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
2914 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(kBufferInitValue), kBufferInitValue.data(),
2915 GL_STATIC_DRAW);
2916 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
2917
2918 // Create a program that reads from the SSBO in the fragment shader.
2919 constexpr char kFS[] = R"(#version 310 es
2920 precision mediump float;
2921
2922 out vec4 colorOut;
2923
2924 layout(binding = 0, std430) buffer block {
2925 vec4 color;
2926 } instance;
2927
2928 vec4 func() {
2929 vec4 temp = instance.color;
2930 return temp;
2931 }
2932
2933 void main() {
2934 colorOut = func();
2935 })";
2936
2937 GLuint vs = CompileShader(GL_VERTEX_SHADER, essl31_shaders::vs::Simple());
2938 GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
2939
2940 const GLuint program = glCreateProgram();
2941 glAttachShader(program, vs);
2942 glAttachShader(program, fs);
2943 glLinkProgram(program);
2944 CheckLinkStatusAndReturnProgram(program, true);
2945
2946 glUseProgram(program);
2947 GLint positionLoc = glGetAttribLocation(program, essl31_shaders::PositionAttrib());
2948 ASSERT_NE(-1, positionLoc);
2949
2950 const std::array<Vector3, 6> &quadVertices = GetQuadVertices();
2951 const size_t posBufferSize = quadVertices.size() * sizeof(Vector3);
2952
2953 GLBuffer posBuffer;
2954 glBindBuffer(GL_ARRAY_BUFFER, posBuffer);
2955 glBufferData(GL_ARRAY_BUFFER, posBufferSize, quadVertices.data(), GL_STATIC_DRAW);
2956 glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2957 glEnableVertexAttribArray(positionLoc);
2958
2959 glUseProgram(program);
2960
2961 glDrawArrays(GL_TRIANGLES, 0, 6);
2962 EXPECT_GL_NO_ERROR();
2963
2964 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
2965 }
2966
2967 // Tests reading from an SSBO in a function. In this case, we also modify SSBO to check the result.
TEST_P(ShaderStorageBufferTest31,ReadSSBOInFunction)2968 TEST_P(ShaderStorageBufferTest31, ReadSSBOInFunction)
2969 {
2970 constexpr char kCS[] = R"(#version 310 es
2971 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
2972
2973 layout(std430, binding = 0) buffer block {
2974 uint data;
2975 } instance;
2976
2977 uint func()
2978 {
2979 return instance.data;
2980 }
2981 void main() {
2982 instance.data = func() + 1u;
2983 })";
2984
2985 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
2986
2987 glUseProgram(program);
2988
2989 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
2990 constexpr unsigned int kInitialData = 123u;
2991
2992 // Create shader storage buffer
2993 GLBuffer shaderStorageBuffer;
2994
2995 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
2996 glBufferData(GL_SHADER_STORAGE_BUFFER, kBytesPerComponent, &kInitialData, GL_STATIC_DRAW);
2997
2998 // Bind shader storage buffer
2999 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
3000
3001 glDispatchCompute(1, 1, 1);
3002
3003 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
3004
3005 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3006 const void *bufferData =
3007 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kBytesPerComponent, GL_MAP_READ_BIT);
3008
3009 constexpr unsigned int kExpectedData = 124u;
3010 EXPECT_EQ(kExpectedData, *static_cast<const GLuint *>(bufferData));
3011 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3012
3013 EXPECT_GL_NO_ERROR();
3014 }
3015
3016 // Tests whole-array assignment to an SSBO.
TEST_P(ShaderStorageBufferTest31,AggregateArrayAssignmentSSBO)3017 TEST_P(ShaderStorageBufferTest31, AggregateArrayAssignmentSSBO)
3018 {
3019 constexpr char kCS[] = R"(#version 310 es
3020
3021 layout(std430, binding = 0) buffer block {
3022 int a[4];
3023 } instance;
3024
3025 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3026 void main() {
3027 instance.a = int[4](0, 1, 2, 3);
3028 })";
3029
3030 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3031
3032 glUseProgram(program);
3033
3034 constexpr unsigned int kBytesPerComponent = sizeof(GLuint);
3035 constexpr unsigned int kElementCount = 4;
3036
3037 // Create shader storage buffer
3038 GLBuffer shaderStorageBuffer;
3039
3040 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3041 glBufferData(GL_SHADER_STORAGE_BUFFER, kElementCount * kBytesPerComponent, nullptr,
3042 GL_STATIC_DRAW);
3043
3044 // Bind shader storage buffer
3045 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
3046
3047 glDispatchCompute(1, 1, 1);
3048
3049 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
3050
3051 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3052 const void *bufferData = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
3053 kElementCount * kBytesPerComponent, GL_MAP_READ_BIT);
3054
3055 for (unsigned int idx = 0; idx < kElementCount; idx++)
3056 {
3057 EXPECT_EQ(static_cast<const GLuint *>(bufferData)[idx], idx);
3058 }
3059 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3060
3061 EXPECT_GL_NO_ERROR();
3062 }
3063
3064 // Tests whole-struct assignment to an SSBO.
TEST_P(ShaderStorageBufferTest31,AggregateStructAssignmentSSBO)3065 TEST_P(ShaderStorageBufferTest31, AggregateStructAssignmentSSBO)
3066 {
3067 constexpr char kCS[] = R"(#version 310 es
3068
3069 struct StructValues {
3070 float f;
3071 int i;
3072 };
3073
3074
3075 layout(std430, binding = 0) buffer block {
3076 StructValues s;
3077 } instance;
3078
3079 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3080 void main() {
3081 instance.s = StructValues(123.0f, 321);
3082 })";
3083
3084 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3085
3086 glUseProgram(program);
3087
3088 constexpr size_t kSize = sizeof(GLfloat) + sizeof(GLint);
3089
3090 // Create shader storage buffer
3091 GLBuffer shaderStorageBuffer;
3092
3093 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3094 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize, nullptr, GL_STATIC_DRAW);
3095
3096 // Bind shader storage buffer
3097 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
3098
3099 glDispatchCompute(1, 1, 1);
3100
3101 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
3102
3103 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3104 const void *bufferData = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize, GL_MAP_READ_BIT);
3105
3106 EXPECT_EQ(static_cast<const GLfloat *>(bufferData)[0], 123.0f);
3107 EXPECT_EQ(static_cast<const GLint *>(bufferData)[1], 321);
3108
3109 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3110
3111 EXPECT_GL_NO_ERROR();
3112 }
3113
3114 // Test that certain floating-point values are unchanged after constant folding.
TEST_P(ShaderStorageBufferTest31,ConstantFoldingPrecision)3115 TEST_P(ShaderStorageBufferTest31, ConstantFoldingPrecision)
3116 {
3117 constexpr char kCS[] = R"(#version 310 es
3118
3119 layout(std430, binding = 0) buffer block {
3120 float f;
3121 } instance;
3122
3123 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
3124 void main() {
3125 instance.f = intBitsToFloat(0x0da5cc2f);
3126 })";
3127
3128 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3129
3130 glUseProgram(program);
3131
3132 constexpr size_t kSize = sizeof(GLfloat);
3133
3134 // Create shader storage buffer
3135 GLBuffer shaderStorageBuffer;
3136
3137 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3138 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize, nullptr, GL_STATIC_DRAW);
3139
3140 // Bind shader storage buffer
3141 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer);
3142
3143 glDispatchCompute(1, 1, 1);
3144
3145 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
3146
3147 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer);
3148 const void *bufferData = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize, GL_MAP_READ_BIT);
3149
3150 int32_t result = static_cast<const int32_t *>(bufferData)[0];
3151
3152 // Compare against the int32_t representation of the float passed to
3153 // intBitsToFloat() in the shader.
3154 EXPECT_EQ(result, 0x0da5cc2f);
3155
3156 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3157
3158 EXPECT_GL_NO_ERROR();
3159 }
3160
3161 // Tests two SSBOs in the fragment shader.
TEST_P(ShaderStorageBufferTest31,TwoSSBOsInFragmentShader)3162 TEST_P(ShaderStorageBufferTest31, TwoSSBOsInFragmentShader)
3163 {
3164 constexpr char kFS[] = R"(#version 310 es
3165 precision mediump float;
3166
3167 layout(binding = 0, std430) buffer block0 {
3168 float value;
3169 } result0;
3170
3171 layout(binding = 1, std430) buffer block1 {
3172 float value;
3173 } result1;
3174
3175 void main() {
3176 result0.value = 0.5f;
3177 result1.value = 42.0f;
3178 }
3179 )";
3180
3181 constexpr size_t kSize[2] = {sizeof(GLfloat), sizeof(GLfloat)};
3182 ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
3183
3184 // Create shader storage buffers
3185 GLBuffer shaderStorageBuffer[2];
3186
3187 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
3188 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize[0], nullptr, GL_STATIC_DRAW);
3189
3190 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
3191 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize[1], nullptr, GL_STATIC_DRAW);
3192
3193 // Bind shader storage buffers
3194 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
3195 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
3196
3197 drawQuad(program, essl31_shaders::PositionAttrib(), 0.95f);
3198 ASSERT_GL_NO_ERROR();
3199
3200 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
3201 const void *buffer0Data =
3202 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize[0], GL_MAP_READ_BIT);
3203 EXPECT_EQ(static_cast<const GLfloat *>(buffer0Data)[0], 0.5f);
3204
3205 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3206
3207 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
3208 const void *buffer1Data =
3209 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize[1], GL_MAP_READ_BIT);
3210 EXPECT_EQ(static_cast<const GLfloat *>(buffer1Data)[0], 42.0f);
3211
3212 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3213
3214 EXPECT_GL_NO_ERROR();
3215 }
3216
3217 // Tests two SSBOs in a compute shader.
TEST_P(ShaderStorageBufferTest31,TwoSSBOsInComputeShader)3218 TEST_P(ShaderStorageBufferTest31, TwoSSBOsInComputeShader)
3219 {
3220 constexpr char kCS[] = R"(#version 310 es
3221
3222 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3223
3224 layout(binding = 0, std430) buffer block0 {
3225 float value;
3226 } result0;
3227
3228 layout(binding = 1, std430) buffer block1 {
3229 float value;
3230 } result1;
3231
3232 void main() {
3233 result0.value = 0.5f;
3234 result1.value = 42.0f;
3235 }
3236 )";
3237
3238 constexpr size_t kSize[2] = {sizeof(GLfloat), sizeof(GLfloat)};
3239 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3240 glUseProgram(program);
3241
3242 // Create shader storage buffers
3243 GLBuffer shaderStorageBuffer[2];
3244
3245 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
3246 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize[0], nullptr, GL_STATIC_DRAW);
3247
3248 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
3249 glBufferData(GL_SHADER_STORAGE_BUFFER, kSize[1], nullptr, GL_STATIC_DRAW);
3250
3251 // Bind shader storage buffers
3252 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, shaderStorageBuffer[0]);
3253 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, shaderStorageBuffer[1]);
3254
3255 glDispatchCompute(1, 1, 1);
3256 ASSERT_GL_NO_ERROR();
3257
3258 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3259
3260 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[0]);
3261 const void *buffer0Data =
3262 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize[0], GL_MAP_READ_BIT);
3263 EXPECT_EQ(static_cast<const GLfloat *>(buffer0Data)[0], 0.5f);
3264
3265 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3266
3267 glBindBuffer(GL_SHADER_STORAGE_BUFFER, shaderStorageBuffer[1]);
3268 const void *buffer1Data =
3269 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize[1], GL_MAP_READ_BIT);
3270 EXPECT_EQ(static_cast<const GLfloat *>(buffer1Data)[0], 42.0f);
3271
3272 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3273
3274 EXPECT_GL_NO_ERROR();
3275 }
3276
3277 // Test that buffer self-copy works when buffer is used as SSBO
TEST_P(ShaderStorageBufferTest31,CopyBufferSubDataSelfDependency)3278 TEST_P(ShaderStorageBufferTest31, CopyBufferSubDataSelfDependency)
3279 {
3280 constexpr char kCS[] = R"(#version 310 es
3281
3282 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
3283
3284 layout(binding = 0, std430) buffer SSBO
3285 {
3286 uvec4 data[128];
3287 };
3288
3289 void main()
3290 {
3291 data[12] += uvec4(1);
3292 data[12+64] += uvec4(10);
3293 }
3294 )";
3295
3296 ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
3297 glUseProgram(program);
3298
3299 constexpr uint32_t kUVec4Size = 4 * sizeof(uint32_t);
3300 constexpr uint32_t kSSBOSize = 128 * kUVec4Size;
3301 constexpr uint32_t kData1Offset = 12 * kUVec4Size;
3302 constexpr uint32_t kData2Offset = 76 * kUVec4Size;
3303
3304 // Init data is 4 times the size of SSBO as the buffer is created larger than the SSBO
3305 // throughout the test.
3306 constexpr uint32_t kInitValue = 12345;
3307 const std::vector<uint32_t> kInitData(kSSBOSize, kInitValue);
3308
3309 // Set up a throw-away buffer just to make buffer suballocations not use offset 0.
3310 GLBuffer throwaway;
3311 glBindBuffer(GL_SHADER_STORAGE_BUFFER, throwaway);
3312 glBufferData(GL_SHADER_STORAGE_BUFFER, 1024, nullptr, GL_DYNAMIC_DRAW);
3313
3314 // Set up the buffer
3315 GLBuffer buffer;
3316 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
3317 glBufferData(GL_SHADER_STORAGE_BUFFER, kSSBOSize * 2, kInitData.data(), GL_DYNAMIC_DRAW);
3318
3319 // Bind at offset 0. After the dispatch call: [12] is +1, [76] is +10
3320 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kSSBOSize);
3321 glDispatchCompute(1, 1, 1);
3322
3323 // Duplicate the buffer in the second half. Barrier needed for glCopyBufferSubData. After the
3324 // copy: [128+12] is +1, [128+76] is +10
3325 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3326 glCopyBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, kSSBOSize,
3327 kSSBOSize);
3328
3329 // Barrier needed before writing to the buffer in the shader.
3330 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
3331
3332 // Bind at offset 128. After the dispatch call: [128+12] is +2, [128+76] is +20
3333 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, kSSBOSize, kSSBOSize);
3334 glDispatchCompute(1, 1, 1);
3335
3336 // Do a small self-copy. Barrier needed for glCopyBufferSubData.
3337 // After the copy: [64+12] = [128+12] (i.e. +2)
3338 constexpr uint32_t kCopySrcOffset = (128 + 4) * kUVec4Size;
3339 constexpr uint32_t kCopyDstOffset = (64 + 4) * kUVec4Size;
3340 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3341 glCopyBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER, kCopySrcOffset,
3342 kCopyDstOffset, kData1Offset);
3343
3344 // Barrier needed before writing to the buffer in the shader.
3345 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
3346
3347 // Bind at offset 64. After the dispatch call: [64+12] is +3, [64+76] (i.e. [128+12]) is +12
3348 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, kCopySrcOffset - kCopyDstOffset,
3349 kSSBOSize);
3350 glDispatchCompute(1, 1, 1);
3351
3352 // Validate results. Barrier needed for glMapBufferRange
3353 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3354 std::vector<uint32_t> result(kSSBOSize / 2);
3355 const void *bufferData =
3356 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSSBOSize * 2, GL_MAP_READ_BIT);
3357 memcpy(result.data(), bufferData, kSSBOSize * 2);
3358 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3359
3360 for (size_t index = 0; index < kSSBOSize * 2 / kUVec4Size; ++index)
3361 {
3362 size_t offset = index * 4;
3363 uint32_t increment = 0;
3364 if (index == kData1Offset / kUVec4Size)
3365 {
3366 increment = 1;
3367 }
3368 else if (index == kData2Offset / kUVec4Size)
3369 {
3370 increment = 3;
3371 }
3372 else if (index == (kSSBOSize + kData1Offset) / kUVec4Size)
3373 {
3374 increment = 12;
3375 }
3376 else if (index == (kSSBOSize + kData2Offset) / kUVec4Size)
3377 {
3378 increment = 20;
3379 }
3380
3381 for (size_t component = 0; component < 4; ++component)
3382 {
3383 EXPECT_EQ(result[offset + component], kInitValue + increment)
3384 << component << " " << index << " " << increment;
3385 }
3386 }
3387
3388 // Do a big copy again, but this time the buffer is unused by the GPU.
3389 // After this call: [12] is +12, [76] is +20
3390 glCopyBufferSubData(GL_SHADER_STORAGE_BUFFER, GL_SHADER_STORAGE_BUFFER, kSSBOSize, 0,
3391 kSSBOSize);
3392
3393 // Barrier needed before writing to the buffer in the shader.
3394 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
3395
3396 // Bind at offset 0. After the dispatch call: [12] is +13, [76] is +30
3397 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, 0, kSSBOSize);
3398 glDispatchCompute(1, 1, 1);
3399
3400 // Validate results. Barrier needed for glMapBufferRange
3401 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3402 bufferData = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSSBOSize * 2, GL_MAP_READ_BIT);
3403 memcpy(result.data(), bufferData, kSSBOSize * 2);
3404 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3405
3406 for (size_t index = 0; index < kSSBOSize * 2 / kUVec4Size; ++index)
3407 {
3408 size_t offset = index * 4;
3409 uint32_t increment = 0;
3410 if (index == kData1Offset / kUVec4Size)
3411 {
3412 increment = 13;
3413 }
3414 else if (index == kData2Offset / kUVec4Size)
3415 {
3416 increment = 30;
3417 }
3418 else if (index == (kSSBOSize + kData1Offset) / kUVec4Size)
3419 {
3420 increment = 12;
3421 }
3422 else if (index == (kSSBOSize + kData2Offset) / kUVec4Size)
3423 {
3424 increment = 20;
3425 }
3426
3427 for (size_t component = 0; component < 4; ++component)
3428 {
3429 EXPECT_EQ(result[offset + component], kInitValue + increment)
3430 << component << " " << index << " " << increment;
3431 }
3432 }
3433 }
3434
3435 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ShaderStorageBufferTest31);
3436 ANGLE_INSTANTIATE_TEST_ES31_AND(ShaderStorageBufferTest31,
3437 ES31_VULKAN().enable(Feature::PreferCPUForBufferSubData));
3438
3439 } // namespace
3440