1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24 #include "gl4cShaderStorageBufferObjectTests.hpp"
25 #include "glwEnums.hpp"
26 #include "tcuMatrix.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include <assert.h>
29 #include <cmath>
30 #include <cstdarg>
31
32 namespace gl4cts
33 {
34 using namespace glw;
35
36 namespace
37 {
38 typedef tcu::Vec2 vec2;
39 typedef tcu::Vec3 vec3;
40 typedef tcu::Vec4 vec4;
41 typedef tcu::IVec4 ivec4;
42 typedef tcu::UVec4 uvec4;
43 typedef tcu::Mat4 mat4;
44
45 enum ShaderStage
46 {
47 vertex,
48 fragment,
49 compute
50 };
51
52 enum BufferLayout
53 {
54 std140,
55 std430,
56 shared,
57 packed
58 };
59
60 enum ElementType
61 {
62 vector,
63 matrix_cm,
64 matrix_rm,
65 structure
66 };
67
68 enum BindingSeq
69 {
70 bindbasebefore,
71 bindbaseafter,
72 bindrangeoffset,
73 bindrangesize
74 };
75
76 const char *const kGLSLVer = "#version 430 core\n";
77
78 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
79 {
Title()80 virtual std::string Title()
81 {
82 return "";
83 }
84
Purpose()85 virtual std::string Purpose()
86 {
87 return "";
88 }
89
Method()90 virtual std::string Method()
91 {
92 return "";
93 }
94
PassCriteria()95 virtual std::string PassCriteria()
96 {
97 return "";
98 }
99
100 public:
SupportedInVS(int requiredVS)101 bool SupportedInVS(int requiredVS)
102 {
103 GLint blocksVS;
104 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
105 if (blocksVS >= requiredVS)
106 return true;
107 else
108 {
109 std::ostringstream reason;
110 reason << "Required " << requiredVS << " VS storage blocks but only " << blocksVS << " available."
111 << std::endl;
112 OutputNotSupported(reason.str());
113 return false;
114 }
115 }
116
SupportedInTCS(int requiredTCS)117 bool SupportedInTCS(int requiredTCS)
118 {
119 GLint blocksTCS;
120 glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &blocksTCS);
121 if (blocksTCS >= requiredTCS)
122 return true;
123 else
124 {
125 std::ostringstream reason;
126 reason << "Required " << requiredTCS << " TCS storage blocks but only " << blocksTCS << " available."
127 << std::endl;
128 OutputNotSupported(reason.str());
129 return false;
130 }
131 }
132
SupportedInTES(int requiredTES)133 bool SupportedInTES(int requiredTES)
134 {
135 GLint blocksTES;
136 glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &blocksTES);
137 if (blocksTES >= requiredTES)
138 return true;
139 else
140 {
141 std::ostringstream reason;
142 reason << "Required " << requiredTES << " TES storage blocks but only " << blocksTES << " available."
143 << std::endl;
144 OutputNotSupported(reason.str());
145 return false;
146 }
147 }
148
SupportedInGS(int requiredGS)149 bool SupportedInGS(int requiredGS)
150 {
151 GLint blocksGS;
152 glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &blocksGS);
153 if (blocksGS >= requiredGS)
154 return true;
155 else
156 {
157 std::ostringstream reason;
158 reason << "Required " << requiredGS << " GS storage blocks but only " << blocksGS << " available."
159 << std::endl;
160 OutputNotSupported(reason.str());
161 return false;
162 }
163 }
164
getWindowWidth()165 int getWindowWidth()
166 {
167 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
168 return renderTarget.getWidth();
169 }
170
getWindowHeight()171 int getWindowHeight()
172 {
173 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
174 return renderTarget.getHeight();
175 }
176
ColorEqual(const vec3 & c0,const vec3 & c1,const vec4 & epsilon)177 inline bool ColorEqual(const vec3 &c0, const vec3 &c1, const vec4 &epsilon)
178 {
179 if (fabs(c0[0] - c1[0]) > epsilon[0])
180 return false;
181 if (fabs(c0[1] - c1[1]) > epsilon[1])
182 return false;
183 if (fabs(c0[2] - c1[2]) > epsilon[2])
184 return false;
185 return true;
186 }
187
CheckProgram(GLuint program)188 bool CheckProgram(GLuint program)
189 {
190 GLint status;
191 glGetProgramiv(program, GL_LINK_STATUS, &status);
192
193 if (status == GL_FALSE)
194 {
195 GLint attached_shaders;
196 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
197
198 if (attached_shaders > 0)
199 {
200 std::vector<GLuint> shaders(attached_shaders);
201 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
202
203 for (GLint i = 0; i < attached_shaders; ++i)
204 {
205 GLenum type;
206 glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint *>(&type));
207
208 switch (type)
209 {
210 case GL_VERTEX_SHADER:
211 m_context.getTestContext().getLog()
212 << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
213 break;
214 case GL_TESS_CONTROL_SHADER:
215 m_context.getTestContext().getLog()
216 << tcu::TestLog::Message << "*** Tessellation Control Shader ***"
217 << tcu::TestLog::EndMessage;
218 break;
219 case GL_TESS_EVALUATION_SHADER:
220 m_context.getTestContext().getLog()
221 << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
222 << tcu::TestLog::EndMessage;
223 break;
224 case GL_GEOMETRY_SHADER:
225 m_context.getTestContext().getLog()
226 << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
227 break;
228 case GL_FRAGMENT_SHADER:
229 m_context.getTestContext().getLog()
230 << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
231 break;
232 case GL_COMPUTE_SHADER:
233 m_context.getTestContext().getLog()
234 << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
235 break;
236 default:
237 m_context.getTestContext().getLog()
238 << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
239 break;
240 }
241
242 GLint length;
243 glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
244 if (length > 0)
245 {
246 std::vector<GLchar> source(length);
247 glGetShaderSource(shaders[i], length, NULL, &source[0]);
248 m_context.getTestContext().getLog()
249 << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
250 }
251 glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
252 if (length > 0)
253 {
254 std::vector<GLchar> log(length);
255 glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
256 m_context.getTestContext().getLog()
257 << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
258 }
259 }
260 }
261 GLint length;
262 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
263 if (length > 0)
264 {
265 std::vector<GLchar> log(length);
266 glGetProgramInfoLog(program, length, NULL, &log[0]);
267 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
268 }
269 }
270
271 return status == GL_TRUE ? true : false;
272 }
273
CreateProgram(const std::string & vs,const std::string & tcs,const std::string & tes,const std::string & gs,const std::string & fs)274 GLuint CreateProgram(const std::string &vs, const std::string &tcs, const std::string &tes, const std::string &gs,
275 const std::string &fs)
276 {
277 const GLuint p = glCreateProgram();
278 if (!vs.empty())
279 {
280 const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
281 glAttachShader(p, sh);
282 glDeleteShader(sh);
283 const char *const src[2] = {kGLSLVer, vs.c_str()};
284 glShaderSource(sh, 2, src, NULL);
285 glCompileShader(sh);
286 }
287 if (!tcs.empty())
288 {
289 const GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
290 glAttachShader(p, sh);
291 glDeleteShader(sh);
292 const char *const src[2] = {kGLSLVer, tcs.c_str()};
293 glShaderSource(sh, 2, src, NULL);
294 glCompileShader(sh);
295 }
296 if (!tes.empty())
297 {
298 const GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
299 glAttachShader(p, sh);
300 glDeleteShader(sh);
301 const char *const src[2] = {kGLSLVer, tes.c_str()};
302 glShaderSource(sh, 2, src, NULL);
303 glCompileShader(sh);
304 }
305 if (!gs.empty())
306 {
307 const GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
308 glAttachShader(p, sh);
309 glDeleteShader(sh);
310 const char *const src[2] = {kGLSLVer, gs.c_str()};
311 glShaderSource(sh, 2, src, NULL);
312 glCompileShader(sh);
313 }
314 if (!fs.empty())
315 {
316 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
317 glAttachShader(p, sh);
318 glDeleteShader(sh);
319 const char *const src[2] = {kGLSLVer, fs.c_str()};
320 glShaderSource(sh, 2, src, NULL);
321 glCompileShader(sh);
322 }
323 return p;
324 }
325
CreateProgram(const std::string & vs,const std::string & fs)326 GLuint CreateProgram(const std::string &vs, const std::string &fs)
327 {
328 const GLuint p = glCreateProgram();
329
330 if (!vs.empty())
331 {
332 const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
333 glAttachShader(p, sh);
334 glDeleteShader(sh);
335 const char *const src[2] = {kGLSLVer, vs.c_str()};
336 glShaderSource(sh, 2, src, NULL);
337 glCompileShader(sh);
338 }
339 if (!fs.empty())
340 {
341 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
342 glAttachShader(p, sh);
343 glDeleteShader(sh);
344 const char *const src[2] = {kGLSLVer, fs.c_str()};
345 glShaderSource(sh, 2, src, NULL);
346 glCompileShader(sh);
347 }
348
349 return p;
350 }
351
CreateProgramCS(const std::string & cs)352 GLuint CreateProgramCS(const std::string &cs)
353 {
354 const GLuint p = glCreateProgram();
355
356 if (!cs.empty())
357 {
358 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
359 glAttachShader(p, sh);
360 glDeleteShader(sh);
361 const char *const src[2] = {kGLSLVer, cs.c_str()};
362 glShaderSource(sh, 2, src, NULL);
363 glCompileShader(sh);
364 }
365 return p;
366 }
367
BuildShaderProgram(GLenum type,const std::string & source)368 GLuint BuildShaderProgram(GLenum type, const std::string &source)
369 {
370 if (type == GL_COMPUTE_SHADER)
371 {
372 const char *const src[3] = {kGLSLVer, "#extension GL_ARB_compute_shader : require\n", source.c_str()};
373 return glCreateShaderProgramv(type, 3, src);
374 }
375
376 const char *const src[2] = {kGLSLVer, source.c_str()};
377 return glCreateShaderProgramv(type, 2, src);
378 }
379
ValidateReadBuffer(int x,int y,int w,int h,const vec3 & expected)380 bool ValidateReadBuffer(int x, int y, int w, int h, const vec3 &expected)
381 {
382 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
383 const tcu::PixelFormat &pixelFormat = renderTarget.getPixelFormat();
384 vec4 g_color_eps = vec4(
385 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
386 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
387
388 std::vector<vec3> display(w * h);
389 glReadPixels(x, y, w, h, GL_RGB, GL_FLOAT, &display[0]);
390
391 bool result = true;
392 for (int j = 0; j < h; ++j)
393 {
394 for (int i = 0; i < w; ++i)
395 {
396 if (!ColorEqual(display[j * w + i], expected, g_color_eps))
397 {
398 m_context.getTestContext().getLog()
399 << tcu::TestLog::Message << "Color at (" << x + i << ", " << y + j << ") is ("
400 << display[j * w + i][0] << " " << display[j * w + i][1] << " " << display[j * w + i][2]
401 << ") should be (" << expected[0] << " " << expected[1] << " " << expected[2] << ")."
402 << tcu::TestLog::EndMessage;
403 result = false;
404 }
405 }
406 }
407
408 return result;
409 }
410
ValidateWindow4Quads(const vec3 & lb,const vec3 & rb,const vec3 & rt,const vec3 & lt,int * bad_pixels=NULL)411 bool ValidateWindow4Quads(const vec3 &lb, const vec3 &rb, const vec3 &rt, const vec3 <, int *bad_pixels = NULL)
412 {
413 const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
414 const tcu::PixelFormat &pixelFormat = renderTarget.getPixelFormat();
415 vec4 g_color_eps = vec4(
416 1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
417 1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
418
419 const int width = 100;
420 const int height = 100;
421 std::vector<vec3> fb(width * height);
422 glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, &fb[0]);
423
424 bool status = true;
425 int bad = 0;
426
427 // left-bottom quad
428 for (int y = 10; y < height / 2 - 10; ++y)
429 {
430 for (int x = 10; x < width / 2 - 10; ++x)
431 {
432 const int idx = y * width + x;
433 if (!ColorEqual(fb[idx], lb, g_color_eps))
434 {
435 m_context.getTestContext().getLog()
436 << tcu::TestLog::Message << "First bad color (" << x << ", " << y << "): " << fb[idx][0] << " "
437 << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
438 status = false;
439 bad++;
440 }
441 }
442 }
443 if (!status)
444 {
445 m_context.getTestContext().getLog()
446 << tcu::TestLog::Message << "Left-bottom quad checking failed. Bad pixels: " << bad
447 << tcu::TestLog::EndMessage;
448 //return status;
449 }
450 // right-bottom quad
451 for (int y = 10; y < height / 2 - 10; ++y)
452 {
453 for (int x = width / 2 + 10; x < width - 10; ++x)
454 {
455 const int idx = y * width + x;
456 if (!ColorEqual(fb[idx], rb, g_color_eps))
457 {
458 m_context.getTestContext().getLog()
459 << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
460 << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
461 status = false;
462 bad++;
463 }
464 }
465 }
466 if (!status)
467 {
468 m_context.getTestContext().getLog()
469 << tcu::TestLog::Message << "right-bottom quad checking failed. Bad pixels: " << bad
470 << tcu::TestLog::EndMessage;
471 //return status;
472 }
473 // right-top quad
474 for (int y = height / 2 + 10; y < height - 10; ++y)
475 {
476 for (int x = width / 2 + 10; x < width - 10; ++x)
477 {
478 const int idx = y * width + x;
479 if (!ColorEqual(fb[idx], rt, g_color_eps))
480 {
481 m_context.getTestContext().getLog()
482 << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
483 << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
484 status = false;
485 bad++;
486 }
487 }
488 }
489 if (!status)
490 {
491 m_context.getTestContext().getLog()
492 << tcu::TestLog::Message << "right-top quad checking failed. Bad pixels: " << bad
493 << tcu::TestLog::EndMessage;
494 //return status;
495 }
496 // left-top quad
497 for (int y = height / 2 + 10; y < height - 10; ++y)
498 {
499 for (int x = 10; x < width / 2 - 10; ++x)
500 {
501 const int idx = y * width + x;
502 if (!ColorEqual(fb[idx], lt, g_color_eps))
503 {
504 m_context.getTestContext().getLog()
505 << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
506 << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
507 status = false;
508 bad++;
509 }
510 }
511 }
512 if (!status)
513 {
514 m_context.getTestContext().getLog()
515 << tcu::TestLog::Message << "left-top quad checking failed. Bad pixels: " << bad
516 << tcu::TestLog::EndMessage;
517 //return status;
518 }
519 // middle horizontal line should be black
520 for (int y = height / 2 - 2; y < height / 2 + 2; ++y)
521 {
522 for (int x = 0; x < width; ++x)
523 {
524 const int idx = y * width + x;
525 if (!ColorEqual(fb[idx], vec3(0), g_color_eps))
526 {
527 m_context.getTestContext().getLog()
528 << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
529 << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
530 status = false;
531 bad++;
532 }
533 }
534 }
535 if (!status)
536 {
537 m_context.getTestContext().getLog()
538 << tcu::TestLog::Message << "middle horizontal line checking failed. Bad pixels: " << bad
539 << tcu::TestLog::EndMessage;
540 //return status;
541 }
542 // middle vertical line should be black
543 for (int y = 0; y < height; ++y)
544 {
545 for (int x = width / 2 - 2; x < width / 2 + 2; ++x)
546 {
547 const int idx = y * width + x;
548 if (!ColorEqual(fb[idx], vec3(0), g_color_eps))
549 {
550 m_context.getTestContext().getLog()
551 << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
552 << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
553 status = false;
554 bad++;
555 }
556 }
557 }
558 if (!status)
559 {
560 m_context.getTestContext().getLog()
561 << tcu::TestLog::Message << "middle vertical line checking failed. Bad pixels: " << bad
562 << tcu::TestLog::EndMessage;
563 //return status;
564 }
565
566 if (bad_pixels)
567 *bad_pixels = bad;
568 m_context.getTestContext().getLog()
569 << tcu::TestLog::Message << "Bad pixels: " << (bad_pixels == NULL ? 0 : *bad_pixels)
570 << ", counted bad: " << bad << tcu::TestLog::EndMessage;
571 return status;
572 }
573
Translation(float tx,float ty,float tz)574 const mat4 Translation(float tx, float ty, float tz)
575 {
576 float d[] = {1.0f, 0.0f, 0.0f, tx, 0.0f, 1.0f, 0.0f, ty, 0.0f, 0.0f, 1.0f, tz, 0.0f, 0.0f, 0.0f, 1.0f};
577 return mat4(d);
578 }
579
GLenumToString(GLenum e)580 const char *GLenumToString(GLenum e)
581 {
582 switch (e)
583 {
584 case GL_SHADER_STORAGE_BUFFER_BINDING:
585 return "GL_SHADER_STORAGE_BUFFER_BINDING";
586 case GL_SHADER_STORAGE_BUFFER_START:
587 return "GL_SHADER_STORAGE_BUFFER_START";
588 case GL_SHADER_STORAGE_BUFFER_SIZE:
589 return "GL_SHADER_STORAGE_BUFFER_SIZE";
590 case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
591 return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS";
592 case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS:
593 return "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS";
594 case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS:
595 return "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS";
596 case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS:
597 return "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS";
598 case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
599 return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
600 case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
601 return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS";
602 case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
603 return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
604 case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
605 return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE";
606 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
607 return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS";
608 case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
609 return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES";
610 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
611 return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
612
613 default:
614 assert(0);
615 break;
616 }
617 return NULL;
618 }
619 };
620
621 //-----------------------------------------------------------------------------
622 // 1.1 BasicBasic
623 //-----------------------------------------------------------------------------
624
625 class BasicBasic : public ShaderStorageBufferObjectBase
626 {
627 GLuint m_program;
628 GLuint m_buffer;
629 GLuint m_vertex_array;
630
RunIteration(GLuint index)631 bool RunIteration(GLuint index)
632 {
633 glClear(GL_COLOR_BUFFER_BIT);
634 glShaderStorageBlockBinding(m_program, 0, index);
635 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, m_buffer);
636 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
637 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, 0);
638
639 return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
640 }
641
Setup()642 virtual long Setup()
643 {
644 m_program = 0;
645 m_buffer = 0;
646 m_vertex_array = 0;
647 return NO_ERROR;
648 }
649
Run()650 virtual long Run()
651 {
652 if (!SupportedInVS(1))
653 return NOT_SUPPORTED;
654
655 const char *const glsl_vs =
656 NL "layout(std430, binding = 1) buffer InputBuffer {" NL " vec4 position[3];" NL "} g_input_buffer;" NL
657 "void main() {" NL " gl_Position = g_input_buffer.position[gl_VertexID];" NL "}";
658
659 const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
660 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
661
662 m_program = CreateProgram(glsl_vs, glsl_fs);
663 glLinkProgram(m_program);
664 if (!CheckProgram(m_program))
665 return ERROR;
666
667 const float data[12] = {-1.0f, -1.0f, 0.0f, 1.0f, 3.0f, -1.0f, 0.0f, 1.0f, -1.0f, 3.0f, 0.0f, 1.0f};
668 glGenBuffers(1, &m_buffer);
669 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
670 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
671 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
672
673 glGenVertexArrays(1, &m_vertex_array);
674 glBindVertexArray(m_vertex_array);
675
676 glUseProgram(m_program);
677
678 for (GLuint i = 0; i < 8; ++i)
679 {
680 if (!RunIteration(i))
681 return ERROR;
682 }
683 return NO_ERROR;
684 }
685
Cleanup()686 virtual long Cleanup()
687 {
688 glUseProgram(0);
689 glDeleteProgram(m_program);
690 glDeleteBuffers(1, &m_buffer);
691 glDeleteVertexArrays(1, &m_vertex_array);
692 return NO_ERROR;
693 }
694 };
695
696 class BasicBasicCS : public ShaderStorageBufferObjectBase
697 {
698 GLuint m_program;
699 GLuint m_buffer;
700
Setup()701 virtual long Setup()
702 {
703 m_program = 0;
704 m_buffer = 0;
705 return NO_ERROR;
706 }
707
Run()708 virtual long Run()
709 {
710 const char *const glsl_cs = NL "layout(local_size_x = 1) in;" NL "buffer Buffer {" NL " int result;" NL "};" NL
711 "void main() {" NL " result = 7;" NL "}";
712 m_program = CreateProgramCS(glsl_cs);
713 glLinkProgram(m_program);
714 if (!CheckProgram(m_program))
715 return ERROR;
716
717 glGenBuffers(1, &m_buffer);
718 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
719 glBufferData(GL_SHADER_STORAGE_BUFFER, 4, 0, GL_STATIC_READ);
720 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
721
722 glUseProgram(m_program);
723 glDispatchCompute(1, 1, 1);
724 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
725
726 GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
727 if (!out_data)
728 return ERROR;
729 if (*out_data == 7)
730 return NO_ERROR;
731 else
732 return ERROR;
733 }
734
Cleanup()735 virtual long Cleanup()
736 {
737 glUseProgram(0);
738 glDeleteProgram(m_program);
739 glDeleteBuffers(1, &m_buffer);
740 return NO_ERROR;
741 }
742 };
743 //-----------------------------------------------------------------------------
744 // 1.2 BasicMax
745 //-----------------------------------------------------------------------------
746
747 class BasicMax : public ShaderStorageBufferObjectBase
748 {
Check(GLenum e,GLint64 value,bool max_value)749 bool Check(GLenum e, GLint64 value, bool max_value)
750 {
751 GLint i;
752 GLint64 i64;
753 GLfloat f;
754 GLdouble d;
755 GLboolean b;
756
757 glGetIntegerv(e, &i);
758 glGetInteger64v(e, &i64);
759 glGetFloatv(e, &f);
760 glGetDoublev(e, &d);
761 glGetBooleanv(e, &b);
762
763 bool status = true;
764 if (max_value)
765 {
766 if (static_cast<GLint64>(i) < value)
767 status = false;
768 if (i64 < value)
769 status = false;
770 if (static_cast<GLint64>(f) < value)
771 status = false;
772 if (static_cast<GLint64>(d) < value)
773 status = false;
774
775 if (!status)
776 {
777 m_context.getTestContext().getLog()
778 << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at least "
779 << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
780 }
781 }
782 else
783 {
784 if (static_cast<GLint64>(i) > value)
785 status = false;
786 if (i64 > value)
787 status = false;
788 if (static_cast<GLint64>(f) > value)
789 status = false;
790 if (static_cast<GLint64>(d) > value)
791 status = false;
792
793 if (!status)
794 {
795 m_context.getTestContext().getLog()
796 << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at most "
797 << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
798 }
799 }
800 return status;
801 }
802
Run()803 virtual long Run()
804 {
805 if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
806 return ERROR;
807 if (!Check(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, 0, true))
808 return ERROR;
809 if (!Check(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, 0, true))
810 return ERROR;
811 if (!Check(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, 0, true))
812 return ERROR;
813 if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 8, true))
814 return ERROR;
815 if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 8, true))
816 return ERROR;
817 if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 8, true))
818 return ERROR;
819 if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 16777216 /* 2^24 */, true))
820 return ERROR;
821 if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 8, true))
822 return ERROR;
823 if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8, true))
824 return ERROR;
825 if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
826 return ERROR;
827 return NO_ERROR;
828 }
829 };
830 //-----------------------------------------------------------------------------
831 // 1.3 BasicBinding
832 //-----------------------------------------------------------------------------
833
834 class BasicBinding : public ShaderStorageBufferObjectBase
835 {
836 GLuint m_buffer[4];
837
Check(GLenum e,GLuint expected)838 bool Check(GLenum e, GLuint expected)
839 {
840 GLint i;
841 GLint64 i64;
842 GLfloat f;
843 GLdouble d;
844 GLboolean b;
845
846 glGetIntegerv(e, &i);
847 glGetInteger64v(e, &i64);
848 glGetFloatv(e, &f);
849 glGetDoublev(e, &d);
850 glGetBooleanv(e, &b);
851
852 bool status = true;
853 if (static_cast<GLuint>(i) != expected)
854 status = false;
855 if (static_cast<GLuint>(i64) != expected)
856 status = false;
857 if (static_cast<GLuint>(f) != expected)
858 status = false;
859 if (static_cast<GLuint>(d) != expected)
860 status = false;
861 if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
862 status = false;
863
864 if (!status)
865 {
866 m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " is " << i
867 << " should be " << expected << tcu::TestLog::EndMessage;
868 }
869 return status;
870 }
871
CheckIndexed(GLenum e,GLuint index,GLuint expected)872 bool CheckIndexed(GLenum e, GLuint index, GLuint expected)
873 {
874 GLint i;
875 GLint64 i64;
876 GLfloat f;
877 GLdouble d;
878 GLboolean b;
879
880 glGetIntegeri_v(e, index, &i);
881 glGetInteger64i_v(e, index, &i64);
882 glGetFloati_v(e, index, &f);
883 glGetDoublei_v(e, index, &d);
884 glGetBooleani_v(e, index, &b);
885
886 bool status = true;
887 if (static_cast<GLuint>(i) != expected)
888 status = false;
889 if (static_cast<GLuint>(i64) != expected)
890 status = false;
891 if (static_cast<GLuint>(f) != expected)
892 status = false;
893 if (static_cast<GLuint>(d) != expected)
894 status = false;
895 if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
896 status = false;
897
898 if (!status)
899 {
900 m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " at index " << index
901 << " is " << i << " should be " << expected << tcu::TestLog::EndMessage;
902 }
903 return status;
904 }
905
Setup()906 virtual long Setup()
907 {
908 memset(m_buffer, 0, sizeof(m_buffer));
909 return NO_ERROR;
910 }
911
Run()912 virtual long Run()
913 {
914 // check default state
915 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
916 return ERROR;
917 for (GLuint i = 0; i < 8; ++i)
918 {
919 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
920 return ERROR;
921 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
922 return ERROR;
923 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
924 return ERROR;
925 }
926
927 glGenBuffers(4, m_buffer);
928 for (GLuint i = 0; i < 8; ++i)
929 {
930 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0]);
931
932 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
933 return ERROR;
934 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
935 return ERROR;
936 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
937 return ERROR;
938 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
939 return ERROR;
940
941 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
942
943 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
944 return ERROR;
945 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
946 return ERROR;
947 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
948 return ERROR;
949 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
950 return ERROR;
951 }
952
953 for (GLuint i = 0; i < 8; ++i)
954 {
955 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0], 256, 512);
956
957 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
958 return ERROR;
959 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
960 return ERROR;
961 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 256))
962 return ERROR;
963 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 512))
964 return ERROR;
965
966 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 512, 128);
967
968 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
969 return ERROR;
970 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
971 return ERROR;
972 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
973 return ERROR;
974 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
975 return ERROR;
976
977 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 0, 0);
978
979 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
980 return ERROR;
981 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
982 return ERROR;
983 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
984 return ERROR;
985 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
986 return ERROR;
987 }
988
989 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[2]);
990 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[2]))
991 return ERROR;
992 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 0, m_buffer[2]))
993 return ERROR;
994 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 0, 0))
995 return ERROR;
996 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 0, 0))
997 return ERROR;
998
999 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_buffer[3]);
1000 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[3]))
1001 return ERROR;
1002 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 5, m_buffer[3]))
1003 return ERROR;
1004 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 5, 0))
1005 return ERROR;
1006 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 5, 0))
1007 return ERROR;
1008
1009 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_buffer[1], 2048, 1000);
1010 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[1]))
1011 return ERROR;
1012 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 7, m_buffer[1]))
1013 return ERROR;
1014 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 7, 2048))
1015 return ERROR;
1016 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 7, 1000))
1017 return ERROR;
1018
1019 glDeleteBuffers(4, m_buffer);
1020 memset(m_buffer, 0, sizeof(m_buffer));
1021
1022 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
1023 return ERROR;
1024 for (GLuint i = 0; i < 8; ++i)
1025 {
1026 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
1027 return ERROR;
1028 }
1029
1030 return NO_ERROR;
1031 }
1032
Cleanup()1033 virtual long Cleanup()
1034 {
1035 glDeleteBuffers(4, m_buffer);
1036 return NO_ERROR;
1037 }
1038 };
1039 //-----------------------------------------------------------------------------
1040 // 1.4 BasicSyntax
1041 //-----------------------------------------------------------------------------
1042
1043 class BasicSyntax : public ShaderStorageBufferObjectBase
1044 {
1045 GLuint m_program;
1046 GLuint m_buffer;
1047 GLuint m_vertex_array;
1048
RunIteration(const char * vs,const char * fs)1049 bool RunIteration(const char *vs, const char *fs)
1050 {
1051 if (m_program != 0)
1052 glDeleteProgram(m_program);
1053 m_program = CreateProgram(vs, fs);
1054 glLinkProgram(m_program);
1055 if (!CheckProgram(m_program))
1056 return false;
1057
1058 glClear(GL_COLOR_BUFFER_BIT);
1059 glUseProgram(m_program);
1060 glDrawArrays(GL_TRIANGLES, 0, 3);
1061
1062 return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
1063 }
1064
Setup()1065 virtual long Setup()
1066 {
1067 m_program = 0;
1068 m_buffer = 0;
1069 m_vertex_array = 0;
1070 return NO_ERROR;
1071 }
1072
Run()1073 virtual long Run()
1074 {
1075 if (!SupportedInVS(1))
1076 return NOT_SUPPORTED;
1077
1078 const int kCount = 8;
1079 const char *const glsl_vs[kCount] = {
1080 NL "layout(std430) buffer Buffer {" NL " vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1081 " gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1082 NL "coherent buffer Buffer {" NL " buffer vec4 position0;" NL " coherent vec4 position1;" NL
1083 " restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
1084 " if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1085 " if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1086 " if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1087 NL "layout(std140, binding = 0) readonly buffer Buffer {" NL " readonly vec4 position[];" NL "};" NL
1088 "void main() {" NL " gl_Position = position[gl_VertexID];" NL "}",
1089 NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1090 "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1091 " restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1092 " gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1093 NL "buffer Buffer {" NL " vec4 position[3];" NL "} g_buffer[1];" NL "void main() {" NL
1094 " gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1095 NL "layout(shared) coherent buffer Buffer {" NL " restrict volatile vec4 position0;" NL
1096 " buffer readonly vec4 position1;" NL " vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
1097 " if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1098 " else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1099 " else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1100 NL "layout(packed) coherent buffer Buffer {" NL " vec4 position01[];" NL " vec4 position2;" NL
1101 "} g_buffer;" NL "void main() {" NL " if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1102 " else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1103 " else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1104 NL "layout(std430) coherent buffer Buffer {" NL " coherent vec4 position01[];" NL " vec4 position2[];" NL
1105 "} g_buffer;" NL "void main() {" NL " switch (gl_VertexID) {" NL
1106 " case 0: gl_Position = g_buffer.position01[0]; break;" NL
1107 " case 1: gl_Position = g_buffer.position01[1]; break;" NL
1108 " case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL " }" NL "}",
1109 };
1110 const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1111 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1112
1113 // full viewport triangle
1114 const float data[12] = {-1.0f, -1.0f, 0.0f, 1.0f, 3.0f, -1.0f, 0.0f, 1.0f, -1.0f, 3.0f, 0.0f, 1.0f};
1115 glGenBuffers(1, &m_buffer);
1116 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1117 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1118
1119 glGenVertexArrays(1, &m_vertex_array);
1120 glBindVertexArray(m_vertex_array);
1121
1122 for (int i = 0; i < kCount; ++i)
1123 {
1124 if (!RunIteration(glsl_vs[i], glsl_fs))
1125 return ERROR;
1126 }
1127
1128 return NO_ERROR;
1129 }
1130
Cleanup()1131 virtual long Cleanup()
1132 {
1133 glUseProgram(0);
1134 glDeleteProgram(m_program);
1135 glDeleteBuffers(1, &m_buffer);
1136 glDeleteVertexArrays(1, &m_vertex_array);
1137 return NO_ERROR;
1138 }
1139 };
1140 //-----------------------------------------------------------------------------
1141 // 1.5 BasicSyntaxSSO
1142 //-----------------------------------------------------------------------------
1143
1144 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1145 {
1146 GLuint m_pipeline;
1147 GLuint m_vsp, m_fsp;
1148 GLuint m_buffer;
1149 GLuint m_vertex_array;
1150
RunIteration(const char * vs)1151 bool RunIteration(const char *vs)
1152 {
1153 if (m_vsp != 0)
1154 glDeleteProgram(m_vsp);
1155 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, vs);
1156 if (!CheckProgram(m_vsp))
1157 return false;
1158
1159 glClear(GL_COLOR_BUFFER_BIT);
1160 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
1161 glDrawArrays(GL_TRIANGLES, 0, 3);
1162
1163 return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
1164 }
1165
Setup()1166 virtual long Setup()
1167 {
1168 m_pipeline = 0;
1169 m_vsp = m_fsp = 0;
1170 m_buffer = 0;
1171 m_vertex_array = 0;
1172 return NO_ERROR;
1173 }
1174
Run()1175 virtual long Run()
1176 {
1177 if (!SupportedInVS(1))
1178 return NOT_SUPPORTED;
1179 const int kCount = 8;
1180 const char *const glsl_vs[kCount] = {
1181 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std430) buffer Buffer {" NL
1182 " vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1183 " gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1184 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "coherent buffer Buffer {" NL
1185 " vec4 position0;" NL " coherent vec4 position1;" NL " restrict readonly vec4 position2;" NL
1186 "} g_input_buffer;" NL "void main() {" NL
1187 " if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1188 " if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1189 " if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1190 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL
1191 "layout(std140, binding = 0) readonly buffer Buffer {" NL " readonly vec4 position[];" NL "};" NL
1192 "void main() {" NL " gl_Position = position[gl_VertexID];" NL "}",
1193 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL
1194 "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1195 "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1196 " restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1197 " gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1198 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "buffer Buffer {" NL " vec4 position[3];" NL
1199 "} g_buffer[1];" NL "void main() {" NL " gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1200 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(shared) coherent buffer Buffer {" NL
1201 " restrict volatile vec4 position0;" NL " readonly vec4 position1;" NL " vec4 position2;" NL
1202 "} g_buffer[1];" NL "void main() {" NL " if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1203 " else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1204 " else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1205 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(packed) coherent buffer Buffer {" NL
1206 " vec4 position01[];" NL " vec4 position2;" NL "} g_buffer;" NL "void main() {" NL
1207 " if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1208 " else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1209 " else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1210 NL "out gl_PerVertex {" NL " vec4 gl_Position;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL
1211 " coherent vec4 position01[];" NL " vec4 position2[];" NL "} g_buffer;" NL "void main() {" NL
1212 " switch (gl_VertexID) {" NL " case 0: gl_Position = g_buffer.position01[0]; break;" NL
1213 " case 1: gl_Position = g_buffer.position01[1]; break;" NL
1214 " case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL " }" NL "}",
1215 };
1216 const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1217 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1218 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
1219 if (!CheckProgram(m_fsp))
1220 return ERROR;
1221
1222 glGenProgramPipelines(1, &m_pipeline);
1223 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
1224
1225 // full viewport triangle
1226 const float data[12] = {-1.0f, -1.0f, 0.0f, 1.0f, 3.0f, -1.0f, 0.0f, 1.0f, -1.0f, 3.0f, 0.0f, 1.0f};
1227 glGenBuffers(1, &m_buffer);
1228 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1229 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1230
1231 glBindProgramPipeline(m_pipeline);
1232
1233 glGenVertexArrays(1, &m_vertex_array);
1234 glBindVertexArray(m_vertex_array);
1235
1236 for (int i = 0; i < kCount; ++i)
1237 {
1238 if (!RunIteration(glsl_vs[i]))
1239 return ERROR;
1240 }
1241
1242 return NO_ERROR;
1243 }
1244
Cleanup()1245 virtual long Cleanup()
1246 {
1247 glDeleteProgramPipelines(1, &m_pipeline);
1248 glDeleteProgram(m_vsp);
1249 glDeleteProgram(m_fsp);
1250 glDeleteBuffers(1, &m_buffer);
1251 glDeleteVertexArrays(1, &m_vertex_array);
1252 return NO_ERROR;
1253 }
1254 };
1255 //-----------------------------------------------------------------------------
1256 // 1.6.x BasicStdLayoutBase
1257 //-----------------------------------------------------------------------------
1258
1259 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1260 {
1261 GLuint m_program;
1262 GLuint m_buffer[2];
1263 GLuint m_vertex_array;
1264
1265 virtual const char *GetInput(std::vector<GLubyte> &in_data) = 0;
1266
Setup()1267 virtual long Setup()
1268 {
1269 m_program = 0;
1270 memset(m_buffer, 0, sizeof(m_buffer));
1271 m_vertex_array = 0;
1272 return NO_ERROR;
1273 }
1274
Run()1275 virtual long Run()
1276 {
1277 if (!SupportedInVS(2))
1278 return NOT_SUPPORTED;
1279 std::vector<GLubyte> in_data;
1280 const char *glsl_vs = GetInput(in_data);
1281
1282 m_program = CreateProgram(glsl_vs, "");
1283 glLinkProgram(m_program);
1284 if (!CheckProgram(m_program))
1285 return ERROR;
1286
1287 glGenBuffers(2, m_buffer);
1288
1289 // output buffer
1290 std::vector<GLubyte> out_data(in_data.size());
1291 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1292 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &out_data[0], GL_STATIC_DRAW);
1293
1294 // input buffer
1295 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1296 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1297
1298 glGenVertexArrays(1, &m_vertex_array);
1299 glEnable(GL_RASTERIZER_DISCARD);
1300
1301 glUseProgram(m_program);
1302 glBindVertexArray(m_vertex_array);
1303 glDrawArrays(GL_POINTS, 0, 1);
1304
1305 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
1306 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1307 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), &out_data[0]);
1308
1309 bool status = true;
1310 for (size_t i = 0; i < in_data.size(); ++i)
1311 {
1312 if (in_data[i] != out_data[i])
1313 {
1314 m_context.getTestContext().getLog()
1315 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1316 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1317 status = false;
1318 }
1319 }
1320 if (!status)
1321 return ERROR;
1322 return NO_ERROR;
1323 }
1324
Cleanup()1325 virtual long Cleanup()
1326 {
1327 glDisable(GL_RASTERIZER_DISCARD);
1328 glUseProgram(0);
1329 glDeleteProgram(m_program);
1330 glDeleteBuffers(2, m_buffer);
1331 glDeleteVertexArrays(1, &m_vertex_array);
1332 return NO_ERROR;
1333 }
1334 };
1335
1336 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1337 {
1338 GLuint m_program;
1339 GLuint m_buffer[2];
1340
1341 virtual const char *GetInput(std::vector<GLubyte> &in_data) = 0;
1342
Setup()1343 virtual long Setup()
1344 {
1345 m_program = 0;
1346 memset(m_buffer, 0, sizeof(m_buffer));
1347 return NO_ERROR;
1348 }
1349
Run()1350 virtual long Run()
1351 {
1352 std::vector<GLubyte> in_data;
1353 std::stringstream ss;
1354 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
1355
1356 m_program = CreateProgramCS(ss.str());
1357 glLinkProgram(m_program);
1358 if (!CheckProgram(m_program))
1359 return ERROR;
1360
1361 glGenBuffers(2, m_buffer);
1362
1363 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1364 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1365 std::vector<GLubyte> out_d(in_data.size());
1366 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1367 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)out_d.size(), &out_d[0], GL_STATIC_DRAW);
1368
1369 glUseProgram(m_program);
1370 glDispatchCompute(1, 1, 1);
1371
1372 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1373 GLubyte *out_data =
1374 (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1375 if (!out_data)
1376 return ERROR;
1377
1378 bool status = true;
1379
1380 for (size_t i = 0; i < in_data.size(); ++i)
1381 {
1382 if (in_data[i] != out_data[i])
1383 {
1384 m_context.getTestContext().getLog()
1385 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1386 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1387 status = false;
1388 }
1389 }
1390 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1391 if (!status)
1392 return ERROR;
1393 return NO_ERROR;
1394 }
1395
Cleanup()1396 virtual long Cleanup()
1397 {
1398 glUseProgram(0);
1399 glDeleteProgram(m_program);
1400 glDeleteBuffers(2, m_buffer);
1401 return NO_ERROR;
1402 }
1403 };
1404 //-----------------------------------------------------------------------------
1405 // 1.6.1 BasicStd430LayoutCase1
1406 //-----------------------------------------------------------------------------
GetInput430c1(std::vector<GLubyte> & in_data)1407 const char *GetInput430c1(std::vector<GLubyte> &in_data)
1408 {
1409 in_data.resize(6 * 4);
1410 float *fp = reinterpret_cast<float *>(&in_data[0]);
1411 int *ip = reinterpret_cast<int *>(&in_data[0]);
1412 fp[0] = 1.0f;
1413 fp[1] = 2.0f;
1414 fp[2] = 3.0f;
1415 fp[3] = 4.0f;
1416 ip[4] = 5;
1417 ip[5] = 6;
1418
1419 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1420 " ivec2 data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL " float data0;" NL
1421 " float data1[3];" NL " ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1422 " g_output.data0 = g_input.data0;" NL
1423 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1424 " g_output.data2 = g_input.data2;" NL "}";
1425 }
1426
1427 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1428 {
GetInput(std::vector<GLubyte> & in_data)1429 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1430 {
1431 return GetInput430c1(in_data);
1432 }
1433 };
1434
1435 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1436 {
GetInput(std::vector<GLubyte> & in_data)1437 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1438 {
1439 return GetInput430c1(in_data);
1440 }
1441 };
1442 //-----------------------------------------------------------------------------
1443 // 1.6.2 BasicStd430LayoutCase2
1444 //-----------------------------------------------------------------------------
GetInput430c2(std::vector<GLubyte> & in_data)1445 const char *GetInput430c2(std::vector<GLubyte> &in_data)
1446 {
1447 in_data.resize(20 * 4);
1448 float *fp = reinterpret_cast<float *>(&in_data[0]);
1449 fp[0] = 1.0f;
1450 fp[1] = 2.0f;
1451 fp[2] = 3.0f;
1452 fp[3] = 4.0f;
1453 fp[4] = 5.0f;
1454 fp[5] = 6.0f;
1455 fp[8] = 7.0f;
1456 fp[9] = 8.0f;
1457 fp[10] = 9.0f;
1458 fp[12] = 10.0f;
1459 fp[13] = 11.0f;
1460 fp[14] = 12.0f;
1461 fp[16] = 13.0f;
1462
1463 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1464 " vec2 data2;" NL " readonly vec3 data3[2];" NL " float data4;" NL "} g_input;" NL
1465 "layout(std430, binding = 1) buffer Output {" NL " float data0;" NL " float data1[3];" NL
1466 " vec2 data2;" NL " vec3 data3[2];" NL " float data4;" NL "} g_output;" NL "void main() {" NL
1467 " g_output.data0 = g_input.data0;" NL
1468 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1469 " g_output.data2 = g_input.data2;" NL
1470 " for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1471 " g_output.data4 = g_input.data4;" NL "}";
1472 }
1473
1474 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1475 {
GetInput(std::vector<GLubyte> & in_data)1476 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1477 {
1478 return GetInput430c2(in_data);
1479 }
1480 };
1481
1482 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1483 {
GetInput(std::vector<GLubyte> & in_data)1484 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1485 {
1486 return GetInput430c2(in_data);
1487 }
1488 };
1489
1490 //-----------------------------------------------------------------------------
1491 // 1.6.3 BasicStd430LayoutCase3
1492 //-----------------------------------------------------------------------------
GetInput430c3(std::vector<GLubyte> & in_data)1493 const char *GetInput430c3(std::vector<GLubyte> &in_data)
1494 {
1495 in_data.resize(16 * 4);
1496 float *fp = reinterpret_cast<float *>(&in_data[0]);
1497 fp[0] = 1.0f;
1498 fp[1] = 2.0f;
1499 fp[2] = 3.0f;
1500 fp[3] = 0.0f;
1501 fp[4] = 4.0f;
1502 fp[5] = 5.0f;
1503 fp[6] = 6.0f;
1504 fp[7] = 0.0f;
1505 fp[8] = 7.0f;
1506 fp[9] = 8.0f;
1507 fp[10] = 9.0f;
1508 fp[11] = 10.0f;
1509 fp[12] = 11.0f;
1510 fp[13] = 12.0f;
1511 fp[14] = 13.0f;
1512 fp[15] = 14.0f;
1513
1514 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat2x3 data0;" NL
1515 " layout(row_major) mat4x2 data1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
1516 " layout(column_major) mat2x3 data0;" NL " layout(row_major) mat4x2 data1;" NL "} g_output;" NL
1517 "void main() {" NL " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL "}";
1518 }
1519
1520 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1521 {
GetInput(std::vector<GLubyte> & in_data)1522 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1523 {
1524 return GetInput430c3(in_data);
1525 }
1526 };
1527
1528 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1529 {
GetInput(std::vector<GLubyte> & in_data)1530 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1531 {
1532 return GetInput430c3(in_data);
1533 }
1534 };
1535
1536 //-----------------------------------------------------------------------------
1537 // 1.6.4 BasicStd430LayoutCase4
1538 //-----------------------------------------------------------------------------
GetInput430c4(std::vector<GLubyte> & in_data)1539 const char *GetInput430c4(std::vector<GLubyte> &in_data)
1540 {
1541 in_data.resize(20 * 4);
1542 float *fp = reinterpret_cast<float *>(&in_data[0]);
1543 fp[0] = 1.0f;
1544 fp[1] = 2.0f;
1545 fp[2] = 3.0f;
1546 fp[3] = 4.0f;
1547 fp[4] = 5.0f;
1548 fp[5] = 6.0f;
1549 fp[6] = 7.0f;
1550 fp[7] = 8.0f;
1551 fp[8] = 9.0f;
1552 fp[9] = 10.0f;
1553 fp[10] = 11.0f;
1554 fp[12] = 12.0f;
1555 fp[13] = 13.0f;
1556 fp[14] = 14.0f;
1557 fp[16] = 15.0f;
1558
1559 return NL "layout(std430, binding = 0) buffer Input {" NL " mat4x2 data0;" NL " mat2x3 data1;" NL
1560 " float data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL " mat4x2 data0;" NL
1561 " mat2x3 data1;" NL " float data2;" NL "} g_output;" NL "void main() {" NL
1562 " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL
1563 " g_output.data2 = g_input.data2;" NL "}";
1564 }
1565
1566 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1567 {
GetInput(std::vector<GLubyte> & in_data)1568 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1569 {
1570 return GetInput430c4(in_data);
1571 }
1572 };
1573
1574 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1575 {
GetInput(std::vector<GLubyte> & in_data)1576 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1577 {
1578 return GetInput430c4(in_data);
1579 }
1580 };
1581
1582 //-----------------------------------------------------------------------------
1583 // 1.6.5 BasicStd430LayoutCase5
1584 //-----------------------------------------------------------------------------
GetInput430c5(std::vector<GLubyte> & in_data)1585 const char *GetInput430c5(std::vector<GLubyte> &in_data)
1586 {
1587 in_data.resize(8 * 4);
1588 float *fp = reinterpret_cast<float *>(&in_data[0]);
1589 fp[0] = 1.0f;
1590 fp[1] = 3.0f;
1591 fp[2] = 5.0f;
1592 fp[3] = 7.0f;
1593 fp[4] = 2.0f;
1594 fp[5] = 4.0f;
1595 fp[6] = 6.0f;
1596 fp[7] = 8.0f;
1597
1598 return NL "layout(std430, binding = 0, row_major) buffer Input {" NL " mat4x2 data0;" NL "} g_input;" NL
1599 "layout(std430, binding = 1, row_major) buffer Output {" NL " mat4x2 data0;" NL "} g_output;" NL
1600 "void main() {" NL " g_output.data0 = g_input.data0;" NL "}";
1601 }
1602
1603 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1604 {
GetInput(std::vector<GLubyte> & in_data)1605 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1606 {
1607 return GetInput430c5(in_data);
1608 }
1609 };
1610
1611 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1612 {
GetInput(std::vector<GLubyte> & in_data)1613 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1614 {
1615 return GetInput430c5(in_data);
1616 }
1617 };
1618
1619 //-----------------------------------------------------------------------------
1620 // 1.6.6 BasicStd430LayoutCase6
1621 //-----------------------------------------------------------------------------
GetInput430c6(std::vector<GLubyte> & in_data)1622 const char *GetInput430c6(std::vector<GLubyte> &in_data)
1623 {
1624 in_data.resize(92 * 4);
1625 float *fp = reinterpret_cast<float *>(&in_data[0]);
1626 fp[0] = 1.0f;
1627 fp[1] = 2.0f;
1628 fp[2] = 3.0f;
1629 fp[3] = 4.0f;
1630 fp[4] = 5.0f;
1631 fp[5] = 0.0f;
1632 fp[6] = 6.0f;
1633 fp[7] = 7.0f;
1634 fp[8] = 8.0f;
1635 fp[9] = 9.0f;
1636 fp[10] = 10.0f;
1637 fp[11] = 11.0f;
1638 fp[12] = 12.0f;
1639 fp[13] = 0.0f;
1640 fp[14] = 0.0f;
1641 fp[15] = 0.0f;
1642 fp[16] = 13.0f;
1643 fp[17] = 14.0f;
1644 fp[18] = 15.0f;
1645 fp[19] = 0.0f;
1646 fp[20] = 16.0f;
1647 fp[21] = 17.0f;
1648 fp[22] = 18.0f;
1649 fp[23] = 0.0f;
1650 fp[24] = 19.0f;
1651 fp[25] = 20.0f;
1652 fp[26] = 21.0f;
1653 fp[27] = 22.0f;
1654 fp[28] = 23.0f;
1655 fp[29] = 24.0f;
1656 fp[30] = 25.0f;
1657 fp[31] = 26.0f;
1658 fp[32] = 27.0f;
1659 fp[33] = 28.0f;
1660 fp[34] = 0.0f;
1661 fp[35] = 0.0f;
1662 fp[36] = 29.0f;
1663 fp[37] = 30.0f;
1664 fp[38] = 31.0f;
1665 fp[39] = 0.0f;
1666 fp[40] = 32.0f;
1667 fp[41] = 33.0f;
1668 fp[42] = 34.0f;
1669 fp[43] = 0.0f;
1670 fp[44] = 35.0f;
1671 fp[45] = 36.0f;
1672 fp[46] = 37.0f;
1673 fp[47] = 0.0f;
1674 fp[48] = 38.0f;
1675 fp[49] = 39.0f;
1676 fp[50] = 40.0f;
1677 fp[51] = 0.0f;
1678 fp[52] = 41.0f;
1679 fp[53] = 42.0f;
1680 fp[54] = 43.0f;
1681 fp[55] = 0.0f;
1682 fp[56] = 44.0f;
1683 fp[57] = 45.0f;
1684 fp[58] = 46.0f;
1685 fp[59] = 0.0f;
1686 fp[60] = 47.0f;
1687 fp[61] = 48.0f;
1688 fp[62] = 49.0f;
1689 fp[63] = 50.0f;
1690 fp[64] = 51.0f;
1691 fp[65] = 52.0f;
1692 fp[66] = 53.0f;
1693 fp[67] = 54.0f;
1694 fp[68] = 55.0f;
1695 fp[69] = 56.0f;
1696 fp[70] = 57.0f;
1697 fp[71] = 58.0f;
1698 fp[72] = 59.0f;
1699 fp[73] = 60.0f;
1700 fp[74] = 61.0f;
1701 fp[75] = 62.0f;
1702 fp[76] = 63.0f;
1703 fp[77] = 64.0f;
1704 fp[78] = 65.0f;
1705 fp[79] = 66.0f;
1706 fp[80] = 67.0f;
1707 fp[81] = 68.0f;
1708 fp[82] = 69.0f;
1709 fp[83] = 70.0f;
1710 fp[84] = 71.0f;
1711 fp[85] = 72.0f;
1712 fp[86] = 73.0f;
1713 fp[87] = 74.0f;
1714 fp[88] = 75.0f;
1715 fp[89] = 76.0f;
1716 fp[90] = 77.0f;
1717 fp[91] = 78.0f;
1718
1719 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0[2];" NL " float data1[3];" NL
1720 " vec2 data2;" NL " float data3[5];" NL " vec3 data4[2];" NL " float data5[2];" NL
1721 " mat2 data6[2];" NL " mat3 data7[2];" NL " mat4 data8[2];" NL "} g_input;" NL
1722 "layout(std430, binding = 1) buffer Output {" NL " float data0[2];" NL " float data1[3];" NL
1723 " vec2 data2;" NL " float data3[5];" NL " vec3 data4[2];" NL " float data5[2];" NL
1724 " mat2 data6[2];" NL " mat3 data7[2];" NL " mat4 data8[2];" NL "} g_output;" NL "void main() {" NL
1725 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
1726 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1727 " g_output.data2 = g_input.data2;" NL
1728 " for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1729 " for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
1730 " for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
1731 " for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL
1732 " for (int i = 0; i < g_input.data7.length(); ++i) g_output.data7[i] = g_input.data7[i];" NL
1733 " for (int i = 0; i < g_input.data8.length(); ++i) g_output.data8[i] = g_input.data8[i];" NL "}";
1734 }
1735
1736 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1737 {
GetInput(std::vector<GLubyte> & in_data)1738 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1739 {
1740 return GetInput430c6(in_data);
1741 }
1742 };
1743
1744 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1745 {
GetInput(std::vector<GLubyte> & in_data)1746 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1747 {
1748 return GetInput430c6(in_data);
1749 }
1750 };
1751
1752 //-----------------------------------------------------------------------------
1753 // 1.6.7 BasicStd430LayoutCase7
1754 //-----------------------------------------------------------------------------
GetInput430c7(std::vector<GLubyte> & in_data)1755 const char *GetInput430c7(std::vector<GLubyte> &in_data)
1756 {
1757 in_data.resize(36 * 4);
1758 int *ip = reinterpret_cast<int *>(&in_data[0]);
1759 float *fp = reinterpret_cast<float *>(&in_data[0]);
1760 ip[0] = 1;
1761 ip[1] = 0;
1762 ip[2] = 2;
1763 ip[3] = 3;
1764 fp[4] = 4.0f;
1765 fp[5] = 0.0f;
1766 fp[6] = 0.0f;
1767 fp[7] = 0.0f;
1768 fp[8] = 5.0f;
1769 fp[9] = 6.0f;
1770 fp[10] = 7.0f;
1771 fp[11] = 0.0f;
1772 fp[12] = 8.0f;
1773 fp[13] = 0.0f;
1774 fp[14] = 0.0f;
1775 fp[15] = 0.0f;
1776 fp[16] = 9.0f;
1777 fp[17] = 10.0f;
1778 fp[18] = 11.0f;
1779 fp[19] = 0.0f;
1780 ip[20] = 12;
1781 ip[21] = 13;
1782 ip[22] = 14;
1783 ip[23] = 15;
1784 fp[24] = 16.0f;
1785 fp[25] = 0.0f;
1786 fp[26] = 0.0f;
1787 fp[27] = 0.0f;
1788 fp[28] = 17.0f;
1789 fp[29] = 18.0f;
1790 fp[30] = 19.0f;
1791 fp[31] = 0.0f;
1792 ip[32] = 20;
1793 ip[33] = 21;
1794 ip[34] = 22;
1795 ip[35] = 23;
1796
1797 return NL "struct Struct0 {" NL " ivec2 m0;" NL "};" NL "struct Struct1 {" NL " vec3 m0;" NL "};" NL
1798 "struct Struct3 {" NL " int m0;" NL "};" NL "struct Struct2 {" NL " float m0;" NL " Struct1 m1;" NL
1799 " Struct0 m2;" NL " int m3;" NL " Struct3 m4;" NL "};" NL
1800 "layout(std430, binding = 0) buffer Input {" NL " int data0;" NL " Struct0 data1;" NL
1801 " float data2;" NL " Struct1 data3;" NL " Struct2 data4[2];" NL "} g_input;" NL
1802 "layout(std430, binding = 1) buffer Output {" NL " int data0;" NL " Struct0 data1;" NL
1803 " float data2;" NL " Struct1 data3;" NL " Struct2 data4[2];" NL "} g_output;" NL "void main() {" NL
1804 " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL
1805 " g_output.data2 = g_input.data2;" NL " g_output.data3 = g_input.data3;" NL
1806 " for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL "}";
1807 }
1808
1809 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1810 {
GetInput(std::vector<GLubyte> & in_data)1811 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1812 {
1813 return GetInput430c7(in_data);
1814 }
1815 };
1816
1817 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1818 {
GetInput(std::vector<GLubyte> & in_data)1819 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1820 {
1821 return GetInput430c7(in_data);
1822 }
1823 };
1824
1825 //-----------------------------------------------------------------------------
1826 // 1.7.1 BasicStd140LayoutCase1
1827 //-----------------------------------------------------------------------------
GetInput140c1(std::vector<GLubyte> & in_data)1828 const char *GetInput140c1(std::vector<GLubyte> &in_data)
1829 {
1830 in_data.resize(8 * 4);
1831 float *fp = reinterpret_cast<float *>(&in_data[0]);
1832 fp[0] = 1.0f;
1833 fp[1] = 0.0f;
1834 fp[2] = 0.0f;
1835 fp[3] = 0.0f;
1836 fp[4] = 2.0f;
1837
1838 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0[2];" NL "} g_input;" NL
1839 "layout(std140, binding = 1) buffer Output {" NL " float data0[2];" NL "} g_output;" NL
1840 "void main() {" NL
1841 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1842 }
1843
1844 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1845 {
GetInput(std::vector<GLubyte> & in_data)1846 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1847 {
1848 return GetInput140c1(in_data);
1849 }
1850 };
1851
1852 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1853 {
GetInput(std::vector<GLubyte> & in_data)1854 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1855 {
1856 return GetInput140c1(in_data);
1857 }
1858 };
1859 //-----------------------------------------------------------------------------
1860 // 1.7.2 BasicStd140LayoutCase2
1861 //-----------------------------------------------------------------------------
GetInput140c2(std::vector<GLubyte> & in_data)1862 const char *GetInput140c2(std::vector<GLubyte> &in_data)
1863 {
1864 in_data.resize(20 * 4);
1865 float *fp = reinterpret_cast<float *>(&in_data[0]);
1866 int *ip = reinterpret_cast<int *>(&in_data[0]);
1867 fp[0] = 1.0f;
1868 fp[1] = 0.0f;
1869 fp[2] = 0.0f;
1870 fp[3] = 0.0f;
1871 fp[4] = 2.0f;
1872 fp[5] = 0.0f;
1873 fp[6] = 0.0f;
1874 fp[7] = 0.0f;
1875 fp[8] = 3.0f;
1876 fp[9] = 0.0f;
1877 fp[10] = 0.0f;
1878 fp[11] = 0.0f;
1879 fp[12] = 4.0f;
1880 fp[13] = 0.0f;
1881 fp[14] = 0.0f;
1882 fp[15] = 0.0f;
1883 ip[16] = 5;
1884 ip[17] = 6;
1885
1886 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1887 " ivec2 data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL " float data0;" NL
1888 " float data1[3];" NL " ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1889 " g_output.data0 = g_input.data0;" NL
1890 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1891 " g_output.data2 = g_input.data2;" NL "}";
1892 }
1893
1894 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1895 {
GetInput(std::vector<GLubyte> & in_data)1896 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1897 {
1898 return GetInput140c2(in_data);
1899 }
1900 };
1901
1902 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1903 {
GetInput(std::vector<GLubyte> & in_data)1904 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1905 {
1906 return GetInput140c2(in_data);
1907 }
1908 };
1909 //-----------------------------------------------------------------------------
1910 // 1.7.3 BasicStd140LayoutCase3
1911 //-----------------------------------------------------------------------------
GetInput140c3(std::vector<GLubyte> & in_data)1912 const char *GetInput140c3(std::vector<GLubyte> &in_data)
1913 {
1914 in_data.resize(32 * 4);
1915 float *fp = reinterpret_cast<float *>(&in_data[0]);
1916 fp[0] = 1.0f;
1917 fp[1] = 0.0f;
1918 fp[2] = 0.0f;
1919 fp[3] = 0.0f;
1920 fp[4] = 2.0f;
1921 fp[5] = 0.0f;
1922 fp[6] = 0.0f;
1923 fp[7] = 0.0f;
1924 fp[8] = 3.0f;
1925 fp[9] = 0.0f;
1926 fp[10] = 0.0f;
1927 fp[11] = 0.0f;
1928 fp[12] = 4.0f;
1929 fp[13] = 0.0f;
1930 fp[14] = 0.0f;
1931 fp[15] = 0.0f;
1932 fp[16] = 5.0f;
1933 fp[17] = 6.0f;
1934 fp[18] = 0.0f;
1935 fp[19] = 0.0f;
1936 fp[20] = 7.0f;
1937 fp[21] = 8.0f;
1938 fp[22] = 9.0f;
1939 fp[23] = 0.0f;
1940 fp[24] = 10.0f;
1941 fp[25] = 11.0f;
1942 fp[26] = 12.0f;
1943 fp[27] = 0.0f;
1944 fp[28] = 13.0f;
1945
1946 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1947 " vec2 data2;" NL " readonly vec3 data3[2];" NL " float data4;" NL "} g_input;" NL
1948 "layout(std140, binding = 1) buffer Output {" NL " float data0;" NL " float data1[3];" NL
1949 " vec2 data2;" NL " vec3 data3[2];" NL " float data4;" NL "} g_output;" NL "void main() {" NL
1950 " g_output.data0 = g_input.data0;" NL
1951 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1952 " g_output.data2 = g_input.data2;" NL
1953 " for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1954 " g_output.data4 = g_input.data4;" NL "}";
1955 }
1956
1957 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1958 {
GetInput(std::vector<GLubyte> & in_data)1959 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1960 {
1961 return GetInput140c3(in_data);
1962 }
1963 };
1964
1965 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1966 {
GetInput(std::vector<GLubyte> & in_data)1967 virtual const char *GetInput(std::vector<GLubyte> &in_data)
1968 {
1969 return GetInput140c3(in_data);
1970 }
1971 };
1972
1973 //-----------------------------------------------------------------------------
1974 // 1.7.4 BasicStd140LayoutCase4
1975 //-----------------------------------------------------------------------------
GetInput140c4(std::vector<GLubyte> & in_data)1976 const char *GetInput140c4(std::vector<GLubyte> &in_data)
1977 {
1978 in_data.resize(28 * 4);
1979 float *fp = reinterpret_cast<float *>(&in_data[0]);
1980 fp[0] = 1.0f;
1981 fp[1] = 2.0f;
1982 fp[2] = 0.0f;
1983 fp[3] = 0.0f;
1984 fp[4] = 3.0f;
1985 fp[5] = 4.0f;
1986 fp[6] = 0.0f;
1987 fp[7] = 0.0f;
1988 fp[8] = 5.0f;
1989 fp[9] = 6.0f;
1990 fp[10] = 0.0f;
1991 fp[11] = 0.0f;
1992 fp[12] = 7.0f;
1993 fp[13] = 8.0f;
1994 fp[14] = 0.0f;
1995 fp[15] = 0.0f;
1996 fp[16] = 9.0f;
1997 fp[17] = 10.0f;
1998 fp[18] = 11.0f;
1999 fp[19] = 0.0f;
2000 fp[20] = 12.0f;
2001 fp[21] = 13.0f;
2002 fp[22] = 14.0f;
2003 fp[23] = 0.0f;
2004 fp[24] = 15.0f;
2005
2006 return NL "layout(std140, binding = 0) buffer Input {" NL " mat4x2 data0;" NL " mat2x3 data1;" NL
2007 " float data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL " mat4x2 data0;" NL
2008 " mat2x3 data1;" NL " float data2;" NL "} g_output;" NL "void main() {" NL
2009 " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL
2010 " g_output.data2 = g_input.data2;" NL "}";
2011 }
2012
2013 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
2014 {
GetInput(std::vector<GLubyte> & in_data)2015 virtual const char *GetInput(std::vector<GLubyte> &in_data)
2016 {
2017 return GetInput140c4(in_data);
2018 }
2019 };
2020
2021 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
2022 {
GetInput(std::vector<GLubyte> & in_data)2023 virtual const char *GetInput(std::vector<GLubyte> &in_data)
2024 {
2025 return GetInput140c4(in_data);
2026 }
2027 };
2028 //-----------------------------------------------------------------------------
2029 // 1.7.5 BasicStd140LayoutCase5
2030 //-----------------------------------------------------------------------------
GetInput140c5(std::vector<GLubyte> & in_data)2031 const char *GetInput140c5(std::vector<GLubyte> &in_data)
2032 {
2033 in_data.resize(8 * 4);
2034 float *fp = reinterpret_cast<float *>(&in_data[0]);
2035 fp[0] = 1.0f;
2036 fp[1] = 2.0f;
2037 fp[2] = 3.0f;
2038 fp[3] = 4.0f;
2039 fp[4] = 5.0f;
2040 fp[5] = 6.0f;
2041 fp[6] = 7.0f;
2042 fp[7] = 8.0f;
2043
2044 return NL "layout(std140, binding = 0, row_major) buffer Input {" NL " mat4x2 data0;" NL "} g_input;" NL
2045 "layout(std140, binding = 1, row_major) buffer Output {" NL " mat4x2 data0;" NL "} g_output;" NL
2046 "void main() {" NL " g_output.data0 = g_input.data0;" NL "}";
2047 }
2048
2049 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
2050 {
GetInput(std::vector<GLubyte> & in_data)2051 virtual const char *GetInput(std::vector<GLubyte> &in_data)
2052 {
2053 return GetInput140c5(in_data);
2054 }
2055 };
2056
2057 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2058 {
GetInput(std::vector<GLubyte> & in_data)2059 virtual const char *GetInput(std::vector<GLubyte> &in_data)
2060 {
2061 return GetInput140c5(in_data);
2062 }
2063 };
2064
2065 //-----------------------------------------------------------------------------
2066 // 1.7.6 BasicStd140LayoutCase6
2067 //-----------------------------------------------------------------------------
GetInput140c6(std::vector<GLubyte> & in_data)2068 const char *GetInput140c6(std::vector<GLubyte> &in_data)
2069 {
2070 in_data.resize(96 * 4);
2071 float *fp = reinterpret_cast<float *>(&in_data[0]);
2072 fp[0] = 1.0f;
2073 fp[1] = 0.0f;
2074 fp[2] = 0.0f;
2075 fp[3] = 0.0f;
2076 fp[4] = 2.0f;
2077 fp[5] = 0.0f;
2078 fp[6] = 0.0f;
2079 fp[7] = 0.0f;
2080 fp[8] = 3.0f;
2081 fp[9] = 0.0f;
2082 fp[10] = 0.0f;
2083 fp[11] = 0.0f;
2084 fp[12] = 4.0f;
2085 fp[13] = 0.0f;
2086 fp[14] = 0.0f;
2087 fp[15] = 0.0f;
2088 fp[16] = 5.0f;
2089 fp[17] = 0.0f;
2090 fp[18] = 0.0f;
2091 fp[19] = 0.0f;
2092 fp[20] = 6.0f;
2093 fp[21] = 7.0f;
2094 fp[22] = 8.0f;
2095 fp[23] = 9.0f;
2096 fp[24] = 10.0f;
2097 fp[25] = 11.0f;
2098 fp[26] = 0.0f;
2099 fp[27] = 0.0f;
2100 fp[28] = 12.0f;
2101 fp[29] = 13.0f;
2102 fp[30] = 0.0f;
2103 fp[31] = 0.0f;
2104 fp[32] = 14.0f;
2105 fp[33] = 15.0f;
2106 fp[34] = 0.0f;
2107 fp[35] = 0.0f;
2108 fp[36] = 16.0f;
2109 fp[37] = 17.0f;
2110 fp[38] = 0.0f;
2111 fp[39] = 0.0f;
2112 fp[40] = 18.0f;
2113 fp[41] = 19.0f;
2114 fp[42] = 20.0f;
2115 fp[43] = 0.0f;
2116 fp[44] = 21.0f;
2117 fp[45] = 22.0f;
2118 fp[46] = 23.0f;
2119 fp[47] = 0.0f;
2120 fp[48] = 24.0f;
2121 fp[49] = 25.0f;
2122 fp[50] = 26.0f;
2123 fp[51] = 0.0f;
2124 fp[52] = 27.0f;
2125 fp[53] = 28.0f;
2126 fp[54] = 29.0f;
2127 fp[55] = 0.0f;
2128 fp[56] = 30.0f;
2129 fp[57] = 31.0f;
2130 fp[58] = 32.0f;
2131 fp[59] = 0.0f;
2132 fp[60] = 33.0f;
2133 fp[61] = 34.0f;
2134 fp[62] = 35.0f;
2135 fp[63] = 0.0f;
2136 fp[64] = 36.0f;
2137 fp[65] = 37.0f;
2138 fp[66] = 38.0f;
2139 fp[67] = 39.0f;
2140 fp[68] = 40.0f;
2141 fp[69] = 41.0f;
2142 fp[70] = 42.0f;
2143 fp[71] = 43.0f;
2144 fp[72] = 44.0f;
2145 fp[73] = 45.0f;
2146 fp[74] = 46.0f;
2147 fp[75] = 47.0f;
2148 fp[76] = 48.0f;
2149 fp[77] = 49.0f;
2150 fp[78] = 50.0f;
2151 fp[79] = 51.0f;
2152 fp[80] = 52.0f;
2153 fp[81] = 68.0f;
2154 fp[82] = 69.0f;
2155 fp[83] = 70.0f;
2156 fp[84] = 56.0f;
2157 fp[85] = 72.0f;
2158 fp[86] = 73.0f;
2159 fp[87] = 74.0f;
2160 fp[88] = 60.0f;
2161 fp[89] = 76.0f;
2162 fp[90] = 77.0f;
2163 fp[91] = 78.0f;
2164 fp[92] = 64.0f;
2165 fp[93] = 80.0f;
2166 fp[94] = 81.0f;
2167 fp[95] = 82.0f;
2168
2169 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0[2];" NL " float data1[3];" NL
2170 " vec2 data2;" NL " vec2 data3;" NL " mat2 data4[2];" NL " mat3 data5[2];" NL " mat4 data6[2];" NL
2171 "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL " float data0[2];" NL
2172 " float data1[3];" NL " vec2 data2;" NL " vec2 data3;" NL " mat2 data4[2];" NL " mat3 data5[2];" NL
2173 " mat4 data6[2];" NL "} g_output;" NL "void main() {" NL
2174 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
2175 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
2176 " g_output.data2 = g_input.data2;" NL " g_output.data3 = g_input.data3;" NL
2177 " for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
2178 " for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
2179 " for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL "}";
2180 }
2181
2182 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2183 {
GetInput(std::vector<GLubyte> & in_data)2184 virtual const char *GetInput(std::vector<GLubyte> &in_data)
2185 {
2186 return GetInput140c6(in_data);
2187 }
2188 };
2189
2190 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2191 {
GetInput(std::vector<GLubyte> & in_data)2192 virtual const char *GetInput(std::vector<GLubyte> &in_data)
2193 {
2194 return GetInput140c6(in_data);
2195 }
2196 };
2197
2198 //-----------------------------------------------------------------------------
2199 // 1.8.1 BasicAtomicCase1
2200 //-----------------------------------------------------------------------------
2201 class BasicAtomicCase1 : public ShaderStorageBufferObjectBase
2202 {
2203 GLuint m_program;
2204 GLuint m_storage_buffer[6];
2205 GLuint m_vertex_array;
2206 GLuint m_vertex_buffer;
2207
Setup()2208 virtual long Setup()
2209 {
2210 m_program = 0;
2211 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2212 m_vertex_array = 0;
2213 m_vertex_buffer = 0;
2214 return NO_ERROR;
2215 }
2216
Run()2217 virtual long Run()
2218 {
2219 if (!SupportedInVS(2))
2220 return NOT_SUPPORTED;
2221 if (!SupportedInGS(2))
2222 return NOT_SUPPORTED;
2223
2224 const char *const glsl_vs =
2225 NL "layout(location = 0) in vec4 g_in_position;" NL
2226 "layout(std430, binding = 0) coherent buffer VSuint {" NL " uint g_uint_out[4];" NL "};" NL
2227 "layout(std430, binding = 1) coherent buffer VSint {" NL " int data[4];" NL "} g_int_out;" NL
2228 "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2229 " gl_Position = g_in_position;" NL NL
2230 " if (atomicExchange(g_uint_out[gl_VertexID], g_uint_value[1]) != 0u) return;" NL
2231 " if (atomicAdd(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2232 " if (atomicMin(g_uint_out[gl_VertexID], g_uint_value[1]) != 3u) return;" NL
2233 " if (atomicMax(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2234 " if (atomicAnd(g_uint_out[gl_VertexID], g_uint_value[3]) != 2u) return;" NL
2235 " if (atomicOr(g_uint_out[gl_VertexID], g_uint_value[4]) != 0u) return;" NL
2236 " if (g_uint_value[0] > 0u) {" NL
2237 " if (atomicXor(g_uint_out[gl_VertexID], g_uint_value[5]) != 3u) return;" NL " }" NL
2238 " if (atomicCompSwap(g_uint_out[gl_VertexID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2239 " g_uint_out[gl_VertexID] = 1u;" NL " return;" NL " }" NL NL
2240 " if (atomicExchange(g_int_out.data[gl_VertexID], 1) != 0) return;" NL
2241 " if (atomicAdd(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2242 " if (atomicMin(g_int_out.data[gl_VertexID], 1) != 3) return;" NL
2243 " if (atomicMax(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2244 " if (atomicAnd(g_int_out.data[gl_VertexID], 0x1) != 2) return;" NL
2245 " if (atomicOr(g_int_out.data[gl_VertexID], 0x3) != 0) return;" NL
2246 " if (atomicXor(g_int_out.data[gl_VertexID], 0x1) != 3) return;" NL
2247 " if (atomicCompSwap(g_int_out.data[gl_VertexID], 0x2, 0x7) != 2) {" NL
2248 " g_int_out.data[gl_VertexID] = 1;" NL " return;" NL " }" NL "}";
2249
2250 const char *const glsl_gs = NL
2251 "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
2252 "layout(std430, binding = 2) coherent buffer GSuint {" NL " uint data[4];" NL "} g_uint_gs;" NL
2253 "layout(std430, binding = 3) coherent buffer GSint {" NL " int data[4];" NL "} g_int_gs;" NL
2254 "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2255 " gl_Position = gl_in[0].gl_Position;" NL " gl_PrimitiveID = gl_PrimitiveIDIn;" NL " EmitVertex();" NL NL
2256 " if (atomicExchange(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[1]) != 0u) return;" NL
2257 " if (atomicAdd(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[2]) != 1u) return;" NL
2258 " if (atomicMin(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[1]) != 3u) return;" NL
2259 " if (atomicMax(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[2]) != 1u) return;" NL
2260 " if (atomicAnd(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[3]) != 2u) return;" NL
2261 " if (atomicOr(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[4]) != 0u) return;" NL
2262 " if (g_uint_value[0] > 0u) {" NL
2263 " if (atomicXor(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[5]) != 3u) return;" NL " }" NL
2264 " if (atomicCompSwap(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2265 " g_uint_gs.data[gl_PrimitiveIDIn] = 1u;" NL " return;" NL " }" NL NL
2266 " if (atomicExchange(g_int_gs.data[gl_PrimitiveIDIn], 1) != 0) return;" NL
2267 " if (atomicAdd(g_int_gs.data[gl_PrimitiveIDIn], 2) != 1) return;" NL
2268 " if (atomicMin(g_int_gs.data[gl_PrimitiveIDIn], 1) != 3) return;" NL
2269 " if (atomicMax(g_int_gs.data[gl_PrimitiveIDIn], 2) != 1) return;" NL
2270 " if (atomicAnd(g_int_gs.data[gl_PrimitiveIDIn], 0x1) != 2) return;" NL
2271 " if (atomicOr(g_int_gs.data[gl_PrimitiveIDIn], 0x3) != 0) return;" NL
2272 " if (atomicXor(g_int_gs.data[gl_PrimitiveIDIn], 0x1) != 3) return;" NL
2273 " if (atomicCompSwap(g_int_gs.data[gl_PrimitiveIDIn], 0x2, 0x7) != 2) {" NL
2274 " g_int_gs.data[gl_PrimitiveIDIn] = 1;" NL " return;" NL " }" NL "}";
2275
2276 const char *const glsl_fs =
2277 NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 4) coherent buffer FSuint {" NL
2278 " uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 5) coherent buffer FSint {" NL
2279 " int data[4];" NL "} g_int_fs;" NL
2280 "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2281 " g_fs_out = vec4(0, 1, 0, 1);" NL NL
2282 " if (atomicExchange(g_uint_fs.data[gl_PrimitiveID], g_uint_value[1]) != 0u) return;" NL
2283 " if (atomicAdd(g_uint_fs.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2284 " if (atomicMin(g_uint_fs.data[gl_PrimitiveID], g_uint_value[1]) != 3u) return;" NL
2285 " if (atomicMax(g_uint_fs.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2286 " if (atomicAnd(g_uint_fs.data[gl_PrimitiveID], g_uint_value[3]) != 2u) return;" NL
2287 " if (atomicOr(g_uint_fs.data[gl_PrimitiveID], g_uint_value[4]) != 0u) return;" NL
2288 " if (g_uint_value[0] > 0u) {" NL
2289 " if (atomicXor(g_uint_fs.data[gl_PrimitiveID], g_uint_value[5]) != 3u) return;" NL " }" NL
2290 " if (atomicCompSwap(g_uint_fs.data[gl_PrimitiveID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2291 " g_uint_fs.data[gl_PrimitiveID] = 1u;" NL " return;" NL " }" NL NL
2292 " if (atomicExchange(g_int_fs.data[gl_PrimitiveID], 1) != 0) return;" NL
2293 " if (atomicAdd(g_int_fs.data[gl_PrimitiveID], 2) != 1) return;" NL
2294 " if (atomicMin(g_int_fs.data[gl_PrimitiveID], 1) != 3) return;" NL
2295 " if (atomicMax(g_int_fs.data[gl_PrimitiveID], 2) != 1) return;" NL
2296 " if (atomicAnd(g_int_fs.data[gl_PrimitiveID], 0x1) != 2) return;" NL
2297 " if (atomicOr(g_int_fs.data[gl_PrimitiveID], 0x3) != 0) return;" NL
2298 " if (atomicXor(g_int_fs.data[gl_PrimitiveID], 0x1) != 3) return;" NL
2299 " if (atomicCompSwap(g_int_fs.data[gl_PrimitiveID], 0x2, 0x7) != 2) {" NL
2300 " g_int_fs.data[gl_PrimitiveID] = 1;" NL " return;" NL " }" NL "}";
2301 m_program = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
2302 glLinkProgram(m_program);
2303 if (!CheckProgram(m_program))
2304 return ERROR;
2305
2306 glGenBuffers(6, m_storage_buffer);
2307 for (GLuint i = 0; i < 6; ++i)
2308 {
2309 const int data[4] = {0};
2310 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2311 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2312 }
2313
2314 /* vertex buffer */
2315 {
2316 const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2317 glGenBuffers(1, &m_vertex_buffer);
2318 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2319 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2320 glBindBuffer(GL_ARRAY_BUFFER, 0);
2321 }
2322
2323 glGenVertexArrays(1, &m_vertex_array);
2324 glBindVertexArray(m_vertex_array);
2325 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2326 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2327 glBindBuffer(GL_ARRAY_BUFFER, 0);
2328 glEnableVertexAttribArray(0);
2329 glBindVertexArray(0);
2330
2331 glClear(GL_COLOR_BUFFER_BIT);
2332 glUseProgram(m_program);
2333 glBindVertexArray(m_vertex_array);
2334 glDrawArrays(GL_POINTS, 0, 4);
2335 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2336
2337 for (int ii = 0; ii < 3; ++ii)
2338 {
2339 /* uint data */
2340 {
2341 GLuint data[4];
2342 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2343 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2344 for (GLuint i = 0; i < 4; ++i)
2345 {
2346 if (data[i] != 7)
2347 {
2348 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2349 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2350 return ERROR;
2351 }
2352 }
2353 }
2354 /* int data */
2355 {
2356 GLint data[4];
2357 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2358 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2359 for (GLint i = 0; i < 4; ++i)
2360 {
2361 if (data[i] != 7)
2362 {
2363 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2364 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2365 return ERROR;
2366 }
2367 }
2368 }
2369 }
2370 return NO_ERROR;
2371 }
2372
Cleanup()2373 virtual long Cleanup()
2374 {
2375 glUseProgram(0);
2376 glDeleteProgram(m_program);
2377 glDeleteBuffers(6, m_storage_buffer);
2378 glDeleteBuffers(1, &m_vertex_buffer);
2379 glDeleteVertexArrays(1, &m_vertex_array);
2380 return NO_ERROR;
2381 }
2382 };
2383
2384 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2385 {
2386 GLuint m_program;
2387 GLuint m_storage_buffer[2];
2388
Setup()2389 virtual long Setup()
2390 {
2391 m_program = 0;
2392 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2393 return NO_ERROR;
2394 }
2395
Run()2396 virtual long Run()
2397 {
2398 const char *const glsl_cs =
2399 NL "layout(local_size_x = 4) in;" NL "layout(std430, binding = 2) coherent buffer FSuint {" NL
2400 " uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 3) coherent buffer FSint {" NL
2401 " int data[4];" NL "} g_int_fs;" NL "uniform uint g_uint_value[8];" NL "void main() {" NL
2402 " if (atomicExchange(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 0u) return;" NL
2403 " if (atomicAdd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" NL
2404 " if (atomicMin(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 3u) return;" NL
2405 " if (atomicMax(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" NL
2406 " if (atomicAnd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[3]) != 2u) return;" NL
2407 " if (atomicOr(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[4]) != 0u) return;" NL
2408 " if (g_uint_value[0] > 0u) {" NL
2409 " if (atomicXor(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[5]) != 3u) return;" NL " }" NL
2410 " if (atomicCompSwap(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[6], g_uint_value[7]) != 2u) "
2411 "{" NL " g_uint_fs.data[gl_LocalInvocationIndex] = 1u;" NL " return;" NL " }" NL
2412 " if (atomicExchange(g_int_fs.data[gl_LocalInvocationIndex], 1) != 0) return;" NL
2413 " if (atomicAdd(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2414 " if (atomicMin(g_int_fs.data[gl_LocalInvocationIndex], 1) != 3) return;" NL
2415 " if (atomicMax(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2416 " if (atomicAnd(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 2) return;" NL
2417 " if (atomicOr(g_int_fs.data[gl_LocalInvocationIndex], 0x3) != 0) return;" NL
2418 " if (atomicXor(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 3) return;" NL
2419 " if (atomicCompSwap(g_int_fs.data[gl_LocalInvocationIndex], 0x2, 0x7) != 2) {" NL
2420 " g_int_fs.data[gl_LocalInvocationIndex] = 1;" NL " return;" NL " }" NL "}";
2421 m_program = CreateProgramCS(glsl_cs);
2422 glLinkProgram(m_program);
2423 if (!CheckProgram(m_program))
2424 return ERROR;
2425
2426 glGenBuffers(2, m_storage_buffer);
2427 for (GLuint i = 0; i < 2; ++i)
2428 {
2429 const int data[4] = {0};
2430 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 2, m_storage_buffer[i]);
2431 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2432 }
2433
2434 glUseProgram(m_program);
2435 GLuint unif[8] = {3, 1, 2, 1, 3, 1, 2, 7};
2436 glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2437 glDispatchCompute(1, 1, 1);
2438 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2439
2440 /* uint data */
2441 {
2442 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
2443 GLuint *data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2444 if (!data)
2445 return ERROR;
2446 for (GLuint i = 0; i < 4; ++i)
2447 {
2448 if (data[i] != 7)
2449 {
2450 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2451 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2452 return ERROR;
2453 }
2454 }
2455 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2456 }
2457 /* int data */
2458 {
2459 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
2460 GLint *data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2461 if (!data)
2462 return ERROR;
2463 for (GLint i = 0; i < 4; ++i)
2464 {
2465 if (data[i] != 7)
2466 {
2467 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2468 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2469 return ERROR;
2470 }
2471 }
2472 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2473 }
2474 return NO_ERROR;
2475 }
2476
Cleanup()2477 virtual long Cleanup()
2478 {
2479 glUseProgram(0);
2480 glDeleteProgram(m_program);
2481 glDeleteBuffers(2, m_storage_buffer);
2482 return NO_ERROR;
2483 }
2484 };
2485 //-----------------------------------------------------------------------------
2486 // 1.8.2 BasicAtomicCase2
2487 //-----------------------------------------------------------------------------
2488 class BasicAtomicCase2 : public ShaderStorageBufferObjectBase
2489 {
2490 GLuint m_program;
2491 GLuint m_storage_buffer[4];
2492 GLuint m_vertex_array;
2493 GLuint m_vertex_buffer;
2494
Setup()2495 virtual long Setup()
2496 {
2497 m_program = 0;
2498 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2499 m_vertex_array = 0;
2500 m_vertex_buffer = 0;
2501 return NO_ERROR;
2502 }
2503
Run()2504 virtual long Run()
2505 {
2506 if (!SupportedInTCS(2))
2507 return NOT_SUPPORTED;
2508 if (!SupportedInTES(2))
2509 return NOT_SUPPORTED;
2510
2511 const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
2512 " gl_Position = g_in_position;" NL "}";
2513
2514 const char *const glsl_tcs = NL
2515 "layout(vertices = 1) out;" NL "layout(std430, binding = 0) buffer TCSuint {" NL " uint g_uint_out[1];" NL
2516 "};" NL "layout(std430, binding = 1) buffer TCSint {" NL " int data[1];" NL "} g_int_out;" NL
2517 "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2518 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;" NL
2519 " if (gl_InvocationID == 0) {" NL " gl_TessLevelInner[0] = 1.0;" NL " gl_TessLevelInner[1] = 1.0;" NL
2520 " gl_TessLevelOuter[0] = 1.0;" NL " gl_TessLevelOuter[1] = 1.0;" NL
2521 " gl_TessLevelOuter[2] = 1.0;" NL " gl_TessLevelOuter[3] = 1.0;" NL " }" NL
2522 " if (atomicAdd(g_uint_out[gl_InvocationID], g_uint_value[0]) != 0u) return;" NL
2523 " if (atomicExchange(g_uint_out[gl_InvocationID], g_uint_value[0]) != 3u) return;" NL
2524 " if (atomicMin(g_uint_out[gl_InvocationID], g_uint_value[1]) != 3u) return;" NL
2525 " if (atomicMax(g_uint_out[gl_InvocationID], g_uint_value[2]) != 1u) return;" NL
2526 " if (atomicAnd(g_uint_out[gl_InvocationID], g_uint_value[3]) != 2u) return;" NL
2527 " if (atomicOr(g_uint_out[gl_InvocationID], g_uint_value[4]) != 0u) return;" NL
2528 " if (g_uint_value[0] > 0u) {" NL
2529 " if (atomicXor(g_uint_out[gl_InvocationID], g_uint_value[5]) != 3u) return;" NL " }" NL
2530 " if (atomicCompSwap(g_uint_out[gl_InvocationID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2531 " g_uint_out[gl_InvocationID] = 1u;" NL " return;" NL " }" NL NL
2532 " if (atomicAdd(g_int_out.data[gl_InvocationID], 3) != 0) return;" NL
2533 " if (atomicExchange(g_int_out.data[gl_InvocationID], 3) != 3) return;" NL
2534 " if (atomicMin(g_int_out.data[gl_InvocationID], 1) != 3) return;" NL
2535 " if (atomicMax(g_int_out.data[gl_InvocationID], 2) != 1) return;" NL
2536 " if (atomicAnd(g_int_out.data[gl_InvocationID], 0x1) != 2) return;" NL
2537 " if (atomicOr(g_int_out.data[gl_InvocationID], 0x3) != 0) return;" NL
2538 " if (atomicXor(g_int_out.data[gl_InvocationID], 0x1) != 3) return;" NL
2539 " if (atomicCompSwap(g_int_out.data[gl_InvocationID], 0x2, 0x7) != 2) {" NL
2540 " g_int_out.data[gl_InvocationID] = 1;" NL " return;" NL " }" NL "}";
2541
2542 const char *const glsl_tes =
2543 NL "layout(quads, point_mode) in;" NL "layout(std430, binding = 2) buffer TESuint {" NL " uint data[1];" NL
2544 "} g_uint_tes;" NL "layout(std430, binding = 3) buffer TESint {" NL " int data[1];" NL "} g_int_tes;" NL
2545 "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2546 " gl_Position = gl_in[0].gl_Position;" NL NL
2547 " if (atomicExchange(g_uint_tes.data[gl_PrimitiveID], g_uint_value[1]) != 0u) return;" NL
2548 " if (atomicAdd(g_uint_tes.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2549 " if (atomicMin(g_uint_tes.data[gl_PrimitiveID], g_uint_value[1]) != 3u) return;" NL
2550 " if (atomicMax(g_uint_tes.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2551 " if (atomicAnd(g_uint_tes.data[gl_PrimitiveID], g_uint_value[3]) != 2u) return;" NL
2552 " if (atomicOr(g_uint_tes.data[gl_PrimitiveID], g_uint_value[4]) != 0u) return;" NL
2553 " if (g_uint_value[0] > 0u) {" NL
2554 " if (atomicXor(g_uint_tes.data[gl_PrimitiveID], g_uint_value[5]) != 3u) return;" NL " }" NL
2555 " if (atomicCompSwap(g_uint_tes.data[gl_PrimitiveID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2556 " g_uint_tes.data[gl_PrimitiveID] = 1u;" NL " return;" NL " }" NL NL
2557 " if (atomicExchange(g_int_tes.data[gl_PrimitiveID], 1) != 0) return;" NL
2558 " if (atomicAdd(g_int_tes.data[gl_PrimitiveID], 2) != 1) return;" NL
2559 " if (atomicMin(g_int_tes.data[gl_PrimitiveID], 1) != 3) return;" NL
2560 " if (atomicMax(g_int_tes.data[gl_PrimitiveID], 2) != 1) return;" NL
2561 " if (atomicAnd(g_int_tes.data[gl_PrimitiveID], 0x1) != 2) return;" NL
2562 " if (atomicOr(g_int_tes.data[gl_PrimitiveID], 0x3) != 0) return;" NL
2563 " if (atomicXor(g_int_tes.data[gl_PrimitiveID], 0x1) != 3) return;" NL
2564 " if (atomicCompSwap(g_int_tes.data[gl_PrimitiveID], 0x2, 0x7) != 2) {" NL
2565 " g_int_tes.data[gl_PrimitiveID] = 1;" NL " return;" NL " }" NL "}";
2566
2567 const char *const glsl_fs =
2568 NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL " g_fs_out = vec4(0, 1, 0, 1);" NL "}";
2569
2570 m_program = CreateProgram(glsl_vs, glsl_tcs, glsl_tes, "", glsl_fs);
2571 glLinkProgram(m_program);
2572 if (!CheckProgram(m_program))
2573 return ERROR;
2574
2575 glGenBuffers(4, m_storage_buffer);
2576 for (GLuint i = 0; i < 4; ++i)
2577 {
2578 const int data[1] = {0};
2579 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2580 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2581 }
2582
2583 /* vertex buffer */
2584 {
2585 const float data[2] = {0.0f, 0.0f};
2586 glGenBuffers(1, &m_vertex_buffer);
2587 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2588 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2589 glBindBuffer(GL_ARRAY_BUFFER, 0);
2590 }
2591
2592 glGenVertexArrays(1, &m_vertex_array);
2593 glBindVertexArray(m_vertex_array);
2594 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2595 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2596 glBindBuffer(GL_ARRAY_BUFFER, 0);
2597 glEnableVertexAttribArray(0);
2598 glBindVertexArray(0);
2599
2600 glClear(GL_COLOR_BUFFER_BIT);
2601 glUseProgram(m_program);
2602 glBindVertexArray(m_vertex_array);
2603 glPatchParameteri(GL_PATCH_VERTICES, 1);
2604 glDrawArrays(GL_PATCHES, 0, 1);
2605 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2606
2607 for (int ii = 0; ii < 2; ++ii)
2608 {
2609 /* uint data */
2610 {
2611 GLuint data[1];
2612 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2613 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2614 for (GLuint i = 0; i < 1; ++i)
2615 {
2616 if (data[i] != 7)
2617 {
2618 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2619 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2620 return ERROR;
2621 }
2622 }
2623 }
2624 /* int data */
2625 {
2626 GLint data[1];
2627 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2628 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2629 for (GLint i = 0; i < 1; ++i)
2630 {
2631 if (data[i] != 7)
2632 {
2633 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2634 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2635 return ERROR;
2636 }
2637 }
2638 }
2639 }
2640 return NO_ERROR;
2641 }
2642
Cleanup()2643 virtual long Cleanup()
2644 {
2645 glPatchParameteri(GL_PATCH_VERTICES, 3);
2646 glUseProgram(0);
2647 glDeleteProgram(m_program);
2648 glDeleteBuffers(4, m_storage_buffer);
2649 glDeleteBuffers(1, &m_vertex_buffer);
2650 glDeleteVertexArrays(1, &m_vertex_array);
2651 return NO_ERROR;
2652 }
2653 };
2654
2655 //-----------------------------------------------------------------------------
2656 // 1.8.3 BasicAtomicCase3
2657 //-----------------------------------------------------------------------------
2658 class BasicAtomicCase3 : public ShaderStorageBufferObjectBase
2659 {
2660 GLuint m_program;
2661 GLuint m_storage_buffer;
2662 GLuint m_vertex_array;
2663 GLuint m_vertex_buffer;
2664
Setup()2665 virtual long Setup()
2666 {
2667 m_program = 0;
2668 m_storage_buffer = 0;
2669 m_vertex_array = 0;
2670 m_vertex_buffer = 0;
2671 return NO_ERROR;
2672 }
2673
Run()2674 virtual long Run()
2675 {
2676 if (!SupportedInVS(1))
2677 return NOT_SUPPORTED;
2678 if (!SupportedInGS(1))
2679 return NOT_SUPPORTED;
2680
2681 const char *const glsl_vs =
2682 NL "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) buffer Buffer {" NL
2683 " uvec4 u[4];" NL " ivec3 i[4];" NL "} g_vs_buffer;" NL "void main() {" NL
2684 " gl_Position = g_in_position;" NL " atomicAdd(g_vs_buffer.u[0].x, g_vs_buffer.u[gl_VertexID][1]);" NL
2685 " atomicAdd(g_vs_buffer.u[0][0], g_vs_buffer.u[gl_VertexID].z);" NL
2686 " atomicAdd(g_vs_buffer.i[0].x, g_vs_buffer.i[gl_VertexID][1]);" NL
2687 " atomicAdd(g_vs_buffer.i[0][0], g_vs_buffer.i[gl_VertexID].z);" NL "}";
2688
2689 const char *const glsl_gs = NL
2690 "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
2691 "layout(std430, binding = 0) buffer Buffer {" NL " uvec4 u[4];" NL " ivec3 i[4];" NL "} g_gs_buffer;" NL
2692 "void main() {" NL " gl_Position = gl_in[0].gl_Position;" NL " gl_PrimitiveID = gl_PrimitiveIDIn;" NL
2693 " EmitVertex();" NL " atomicAdd(g_gs_buffer.u[0].x, g_gs_buffer.u[gl_PrimitiveIDIn][1]);" NL
2694 " atomicAdd(g_gs_buffer.i[0].x, g_gs_buffer.i[gl_PrimitiveIDIn][1]);" NL "}";
2695
2696 const char *const glsl_fs = NL
2697 "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) buffer Buffer {" NL
2698 " uvec4 u[4];" NL " ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2699 " g_fs_out = vec4(0, 1, 0, 1);" NL " atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_PrimitiveID][1]);" NL
2700 " atomicAdd(g_fs_buffer.i[0].x, g_fs_buffer.i[gl_PrimitiveID][1]);" NL "}";
2701
2702 m_program = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
2703 glLinkProgram(m_program);
2704 if (!CheckProgram(m_program))
2705 return ERROR;
2706
2707 /* init storage buffer */
2708 {
2709 glGenBuffers(1, &m_storage_buffer);
2710 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2711 glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2712 ivec4 *ptr = reinterpret_cast<ivec4 *>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
2713 if (!ptr)
2714 return ERROR;
2715 for (int i = 0; i < 4; ++i)
2716 {
2717 ptr[i * 2] = ivec4(0, 1, 2, 0);
2718 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2719 }
2720 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2721 }
2722
2723 /* init vertex buffer */
2724 {
2725 const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2726 glGenBuffers(1, &m_vertex_buffer);
2727 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2728 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2729 glBindBuffer(GL_ARRAY_BUFFER, 0);
2730 }
2731
2732 glGenVertexArrays(1, &m_vertex_array);
2733 glBindVertexArray(m_vertex_array);
2734 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2735 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2736 glBindBuffer(GL_ARRAY_BUFFER, 0);
2737 glEnableVertexAttribArray(0);
2738 glBindVertexArray(0);
2739
2740 glClear(GL_COLOR_BUFFER_BIT);
2741 glUseProgram(m_program);
2742 glBindVertexArray(m_vertex_array);
2743 glDrawArrays(GL_POINTS, 0, 4);
2744 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2745
2746 GLuint u;
2747 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 4, &u);
2748 if (u != 20)
2749 {
2750 m_context.getTestContext().getLog()
2751 << tcu::TestLog::Message << "Data at offset 0 is " << u << " should be 20." << tcu::TestLog::EndMessage;
2752 return ERROR;
2753 }
2754 GLint i;
2755 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLuint) * 4, 4, &i);
2756 if (i != 20)
2757 {
2758 m_context.getTestContext().getLog()
2759 << tcu::TestLog::Message << "Data at offset 0 is " << i << " should be 20." << tcu::TestLog::EndMessage;
2760 return ERROR;
2761 }
2762
2763 return NO_ERROR;
2764 }
2765
Cleanup()2766 virtual long Cleanup()
2767 {
2768 glUseProgram(0);
2769 glDeleteProgram(m_program);
2770 glDeleteBuffers(1, &m_storage_buffer);
2771 glDeleteBuffers(1, &m_vertex_buffer);
2772 glDeleteVertexArrays(1, &m_vertex_array);
2773 return NO_ERROR;
2774 }
2775 };
2776
2777 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2778 {
2779 GLuint m_program;
2780 GLuint m_storage_buffer;
2781
Setup()2782 virtual long Setup()
2783 {
2784 m_program = 0;
2785 m_storage_buffer = 0;
2786 return NO_ERROR;
2787 }
2788
Run()2789 virtual long Run()
2790 {
2791 const char *const glsl_cs =
2792 NL "layout(local_size_y = 4) in;" NL "layout(std430) coherent buffer Buffer {" NL " uvec4 u[4];" NL
2793 " ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2794 " atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y][2]);" NL
2795 " atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y][1]);" NL
2796 " atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y].z);" NL
2797 " atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y].y);" NL "}";
2798 m_program = CreateProgramCS(glsl_cs);
2799 glLinkProgram(m_program);
2800 if (!CheckProgram(m_program))
2801 return ERROR;
2802
2803 /* init storage buffer */
2804 {
2805 glGenBuffers(1, &m_storage_buffer);
2806 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2807 glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2808 ivec4 *ptr = reinterpret_cast<ivec4 *>(
2809 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2810 if (!ptr)
2811 return ERROR;
2812 for (int i = 0; i < 4; ++i)
2813 {
2814 ptr[i * 2] = ivec4(0, 1, 2, 0);
2815 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2816 }
2817 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2818 }
2819
2820 glUseProgram(m_program);
2821 glDispatchCompute(1, 1, 1);
2822 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2823
2824 GLuint *u = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2825 if (!u)
2826 return ERROR;
2827 if (*u != 16)
2828 {
2829 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2830 << " should be 16." << tcu::TestLog::EndMessage;
2831 return ERROR;
2832 }
2833 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2834 GLint *i = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2835 if (!i)
2836 return ERROR;
2837 if (*i != 16)
2838 {
2839 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2840 << " should be 16." << tcu::TestLog::EndMessage;
2841 return ERROR;
2842 }
2843 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2844
2845 return NO_ERROR;
2846 }
2847
Cleanup()2848 virtual long Cleanup()
2849 {
2850 glUseProgram(0);
2851 glDeleteProgram(m_program);
2852 glDeleteBuffers(1, &m_storage_buffer);
2853 return NO_ERROR;
2854 }
2855 };
2856 //-----------------------------------------------------------------------------
2857 // 1.8.4 BasicAtomicCase4
2858 //-----------------------------------------------------------------------------
2859
2860 class BasicAtomicCase4 : public ShaderStorageBufferObjectBase
2861 {
2862 GLuint m_program;
2863 GLuint m_storage_buffer[2];
2864 GLuint m_vertex_array;
2865 GLuint m_vertex_buffer;
2866
Setup()2867 virtual long Setup()
2868 {
2869 m_program = 0;
2870 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2871 m_vertex_array = 0;
2872 m_vertex_buffer = 0;
2873 return NO_ERROR;
2874 }
2875
Run()2876 virtual long Run()
2877 {
2878 if (!SupportedInVS(2))
2879 return NOT_SUPPORTED;
2880
2881 const char *const glsl_vs =
2882 NL "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) buffer Counters {" NL
2883 " uint g_uint_counter;" NL " int g_int_counter;" NL "};" NL
2884 "layout(std430, binding = 1) buffer Output {" NL " uint udata[8];" NL " int idata[8];" NL
2885 "} g_output;" NL "void main() {" NL " gl_Position = g_in_position;" NL
2886 " const uint uidx = atomicAdd(g_uint_counter, 1u);" NL
2887 " const int iidx = atomicAdd(g_int_counter, -1);" NL " g_output.udata[uidx] = uidx;" NL
2888 " g_output.idata[iidx] = iidx;" NL "}";
2889
2890 const char *const glsl_fs =
2891 NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) buffer Counters {" NL
2892 " uint g_uint_counter;" NL " int g_int_counter;" NL "};" NL
2893 "layout(std430, binding = 1) buffer Output {" NL " uint udata[8];" NL " int idata[8];" NL
2894 "} g_output;" NL "void main() {" NL " g_fs_out = vec4(0, 1, 0, 1);" NL
2895 " const uint uidx = atomicAdd(g_uint_counter, 1u);" NL
2896 " const int iidx = atomicAdd(g_int_counter, -1);" NL " g_output.udata[uidx] = uidx;" NL
2897 " g_output.idata[iidx] = iidx;" NL "}";
2898 m_program = CreateProgram(glsl_vs, glsl_fs);
2899 glLinkProgram(m_program);
2900 if (!CheckProgram(m_program))
2901 return ERROR;
2902
2903 glGenBuffers(2, m_storage_buffer);
2904 /* counter buffer */
2905 {
2906 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2907 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2908 int *ptr = reinterpret_cast<int *>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
2909 if (!ptr)
2910 return ERROR;
2911 *ptr++ = 0;
2912 *ptr++ = 7;
2913 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2914 }
2915 /* output buffer */
2916 {
2917 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2918 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2919 }
2920 /* vertex buffer */
2921 {
2922 const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2923 glGenBuffers(1, &m_vertex_buffer);
2924 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2925 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2926 glBindBuffer(GL_ARRAY_BUFFER, 0);
2927 }
2928
2929 glGenVertexArrays(1, &m_vertex_array);
2930 glBindVertexArray(m_vertex_array);
2931 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2932 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2933 glBindBuffer(GL_ARRAY_BUFFER, 0);
2934 glEnableVertexAttribArray(0);
2935 glBindVertexArray(0);
2936
2937 glClear(GL_COLOR_BUFFER_BIT);
2938 glUseProgram(m_program);
2939 glBindVertexArray(m_vertex_array);
2940 glDrawArrays(GL_POINTS, 0, 4);
2941 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2942
2943 GLuint udata[8];
2944 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(udata), udata);
2945 for (GLuint i = 0; i < 8; ++i)
2946 {
2947 if (udata[i] != i)
2948 {
2949 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2950 << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2951 return ERROR;
2952 }
2953 }
2954 GLint idata[8];
2955 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, sizeof(udata), sizeof(idata), idata);
2956 for (GLint i = 0; i < 8; ++i)
2957 {
2958 if (idata[i] != i)
2959 {
2960 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2961 << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2962 return ERROR;
2963 }
2964 }
2965 return NO_ERROR;
2966 }
2967
Cleanup()2968 virtual long Cleanup()
2969 {
2970 glUseProgram(0);
2971 glDeleteProgram(m_program);
2972 glDeleteBuffers(2, m_storage_buffer);
2973 glDeleteBuffers(1, &m_vertex_buffer);
2974 glDeleteVertexArrays(1, &m_vertex_array);
2975 return NO_ERROR;
2976 }
2977 };
2978
2979 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2980 {
2981 GLuint m_program;
2982 GLuint m_storage_buffer[2];
2983
Setup()2984 virtual long Setup()
2985 {
2986 m_program = 0;
2987 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2988 return NO_ERROR;
2989 }
2990
Run()2991 virtual long Run()
2992 {
2993 const char *const glsl_cs =
2994 NL "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;" NL
2995 "layout(std430, binding = 0) coherent buffer Counters {" NL " uint g_uint_counter;" NL
2996 " int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL " uint udata[8];" NL
2997 " int idata[8];" NL "} g_output;" NL "void main() {" NL
2998 " uint uidx = atomicAdd(g_uint_counter, 1u);" NL " int iidx = atomicAdd(g_int_counter, -1);" NL
2999 " g_output.udata[uidx] = uidx;" NL " g_output.idata[iidx] = iidx;" NL "}";
3000 m_program = CreateProgramCS(glsl_cs);
3001 glLinkProgram(m_program);
3002 if (!CheckProgram(m_program))
3003 return ERROR;
3004
3005 glGenBuffers(2, m_storage_buffer);
3006 /* counter buffer */
3007 {
3008 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
3009 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
3010 int *ptr = reinterpret_cast<int *>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
3011 if (!ptr)
3012 return ERROR;
3013 *ptr++ = 0;
3014 *ptr++ = 7;
3015 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3016 }
3017 /* output buffer */
3018 {
3019 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
3020 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
3021 }
3022 glUseProgram(m_program);
3023 glDispatchCompute(1, 1, 1);
3024 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3025
3026 GLuint *udata = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
3027 if (!udata)
3028 return ERROR;
3029 for (GLuint i = 0; i < 8; ++i)
3030 {
3031 if (udata[i] != i)
3032 {
3033 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
3034 << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
3035 return ERROR;
3036 }
3037 }
3038 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3039 GLint *idata = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
3040 if (!idata)
3041 return ERROR;
3042 for (GLint i = 0; i < 8; ++i)
3043 {
3044 if (idata[i] != i)
3045 {
3046 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
3047 << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
3048 return ERROR;
3049 }
3050 }
3051 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3052 return NO_ERROR;
3053 }
3054
Cleanup()3055 virtual long Cleanup()
3056 {
3057 glUseProgram(0);
3058 glDeleteProgram(m_program);
3059 glDeleteBuffers(2, m_storage_buffer);
3060 return NO_ERROR;
3061 }
3062 };
3063 //-----------------------------------------------------------------------------
3064 // 1.9.x BasicStdLayoutBase2
3065 //-----------------------------------------------------------------------------
3066
3067 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
3068 {
3069 GLuint m_program;
3070 GLuint m_buffer[8];
3071 GLuint m_vertex_array;
3072
3073 virtual const char *GetInput(std::vector<GLubyte> in_data[4]) = 0;
3074
Setup()3075 virtual long Setup()
3076 {
3077 m_program = 0;
3078 memset(m_buffer, 0, sizeof(m_buffer));
3079 m_vertex_array = 0;
3080 return NO_ERROR;
3081 }
3082
Run()3083 virtual long Run()
3084 {
3085 if (!SupportedInVS(8))
3086 return NOT_SUPPORTED;
3087 std::vector<GLubyte> in_data[4];
3088 const char *glsl_vs = GetInput(in_data);
3089
3090 m_program = CreateProgram(glsl_vs, "");
3091 glLinkProgram(m_program);
3092 if (!CheckProgram(m_program))
3093 return ERROR;
3094
3095 glGenBuffers(8, m_buffer);
3096
3097 for (GLuint i = 0; i < 4; ++i)
3098 {
3099 // input buffers
3100 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
3101 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
3102
3103 // output buffers
3104 std::vector<GLubyte> out_data(in_data[i].size());
3105 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
3106 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
3107 }
3108
3109 glGenVertexArrays(1, &m_vertex_array);
3110 glEnable(GL_RASTERIZER_DISCARD);
3111
3112 glUseProgram(m_program);
3113 glBindVertexArray(m_vertex_array);
3114 glDrawArrays(GL_POINTS, 0, 1);
3115
3116 bool status = true;
3117 for (int j = 0; j < 4; ++j)
3118 {
3119 std::vector<GLubyte> out_data(in_data[j].size());
3120 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
3121 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3122 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), &out_data[0]);
3123
3124 for (size_t i = 0; i < in_data[j].size(); ++i)
3125 {
3126 if (in_data[j][i] != out_data[i])
3127 {
3128 m_context.getTestContext().getLog()
3129 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
3130 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
3131 << tcu::TestLog::EndMessage;
3132 status = false;
3133 }
3134 }
3135 }
3136 if (!status)
3137 return ERROR;
3138 return NO_ERROR;
3139 }
3140
Cleanup()3141 virtual long Cleanup()
3142 {
3143 glDisable(GL_RASTERIZER_DISCARD);
3144 glUseProgram(0);
3145 glDeleteProgram(m_program);
3146 glDeleteBuffers(8, m_buffer);
3147 glDeleteVertexArrays(1, &m_vertex_array);
3148 return NO_ERROR;
3149 }
3150 };
3151
3152 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
3153 {
3154 GLuint m_program;
3155 GLuint m_buffer[8];
3156
3157 virtual const char *GetInput(std::vector<GLubyte> in_data[4]) = 0;
3158
Setup()3159 virtual long Setup()
3160 {
3161 m_program = 0;
3162 memset(m_buffer, 0, sizeof(m_buffer));
3163 return NO_ERROR;
3164 }
3165
Run()3166 virtual long Run()
3167 {
3168 std::vector<GLubyte> in_data[4];
3169 std::stringstream ss;
3170 GLint blocksCS;
3171 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksCS);
3172 if (blocksCS < 8)
3173 return NO_ERROR;
3174 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
3175 m_program = CreateProgramCS(ss.str());
3176 glLinkProgram(m_program);
3177 if (!CheckProgram(m_program))
3178 return ERROR;
3179
3180 glGenBuffers(8, m_buffer);
3181
3182 for (GLuint i = 0; i < 4; ++i)
3183 {
3184 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
3185 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
3186
3187 std::vector<GLubyte> out_data(in_data[i].size());
3188 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
3189 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
3190 }
3191
3192 glUseProgram(m_program);
3193 glDispatchCompute(1, 1, 1);
3194 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3195
3196 bool status = true;
3197 for (int j = 0; j < 4; ++j)
3198 {
3199 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
3200 GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
3201 GL_MAP_READ_BIT);
3202 if (!out_data)
3203 return ERROR;
3204
3205 for (size_t i = 0; i < in_data[j].size(); ++i)
3206 {
3207 if (in_data[j][i] != out_data[i])
3208 {
3209 m_context.getTestContext().getLog()
3210 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
3211 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
3212 << tcu::TestLog::EndMessage;
3213 status = false;
3214 }
3215 }
3216 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3217 }
3218 if (!status)
3219 return ERROR;
3220 return NO_ERROR;
3221 }
3222
Cleanup()3223 virtual long Cleanup()
3224 {
3225 glUseProgram(0);
3226 glDeleteProgram(m_program);
3227 glDeleteBuffers(8, m_buffer);
3228 return NO_ERROR;
3229 }
3230 };
3231 //-----------------------------------------------------------------------------
3232 // 1.9.1 BasicStdLayoutCase1
3233 //-----------------------------------------------------------------------------
GetInputC1(std::vector<GLubyte> in_data[4])3234 const char *GetInputC1(std::vector<GLubyte> in_data[4])
3235 {
3236 for (int i = 0; i < 4; ++i)
3237 {
3238 in_data[i].resize(1 * 4);
3239 float *fp = reinterpret_cast<float *>(&in_data[i][0]);
3240 fp[0] = static_cast<float>(i + 1) * 1.0f;
3241 }
3242
3243 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL "} g_input[4];" NL
3244 "layout(std430, binding = 4) buffer Output {" NL " float data0;" NL "} g_output[4];" NL
3245 "void main() {" NL " for (int i = 0; i < 4; ++i) {" NL " g_output[i].data0 = g_input[i].data0;" NL
3246 " }" NL "}";
3247 }
3248
3249 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3250 {
GetInput(std::vector<GLubyte> in_data[4])3251 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3252 {
3253 return GetInputC1(in_data);
3254 }
3255 };
3256
3257 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
3258 {
GetInput(std::vector<GLubyte> in_data[4])3259 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3260 {
3261 return GetInputC1(in_data);
3262 }
3263 };
3264
3265 //-----------------------------------------------------------------------------
3266 // 1.9.2 BasicStdLayoutCase2
3267 //-----------------------------------------------------------------------------
GetInputC2(std::vector<GLubyte> in_data[4])3268 const char *GetInputC2(std::vector<GLubyte> in_data[4])
3269 {
3270 /* input 0, std140 */
3271 {
3272 in_data[0].resize(12 * 4);
3273 float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3274 fp[0] = 1.0f;
3275 fp[1] = 0.0f;
3276 fp[2] = 0.0f;
3277 fp[3] = 0.0f;
3278 fp[4] = 2.0f;
3279 fp[5] = 0.0f;
3280 fp[6] = 0.0f;
3281 fp[7] = 0.0f;
3282 fp[8] = 3.0f;
3283 fp[9] = 0.0f;
3284 fp[10] = 0.0f;
3285 fp[11] = 0.0f;
3286 }
3287 /* input 1, std430 */
3288 {
3289 in_data[1].resize(3 * 4);
3290 float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3291 fp[0] = 4.0f;
3292 fp[1] = 5.0f;
3293 fp[2] = 6.0f;
3294 }
3295 /* input 2, std140 */
3296 {
3297 in_data[2].resize(12 * 4);
3298 float *fp = reinterpret_cast<float *>(&in_data[2][0]);
3299 fp[0] = 7.0f;
3300 fp[1] = 0.0f;
3301 fp[2] = 0.0f;
3302 fp[3] = 0.0f;
3303 fp[4] = 8.0f;
3304 fp[5] = 0.0f;
3305 fp[6] = 0.0f;
3306 fp[7] = 0.0f;
3307 fp[8] = 9.0f;
3308 fp[9] = 0.0f;
3309 fp[10] = 0.0f;
3310 fp[11] = 0.0f;
3311 }
3312 /* input 3, std430 */
3313 {
3314 in_data[3].resize(3 * 4);
3315 float *fp = reinterpret_cast<float *>(&in_data[3][0]);
3316 fp[0] = 10.0f;
3317 fp[1] = 11.0f;
3318 fp[2] = 12.0f;
3319 }
3320 return NL "layout(std140, binding = 0) buffer Input0 {" NL " float data0[3];" NL "} g_input0;" NL
3321 "layout(std430, binding = 1) buffer Input1 {" NL " float data0[3];" NL "} g_input1;" NL
3322 "layout(std140, binding = 2) buffer Input2 {" NL " float data0[3];" NL "} g_input2;" NL
3323 "layout(std430, binding = 3) buffer Input3 {" NL " float data0[3];" NL "} g_input3;" NL
3324 "layout(std140, binding = 4) buffer Output0 {" NL " float data0[3];" NL "} g_output0;" NL
3325 "layout(std430, binding = 5) buffer Output1 {" NL " float data0[3];" NL "} g_output1;" NL
3326 "layout(std140, binding = 6) buffer Output2 {" NL " float data0[3];" NL "} g_output2;" NL
3327 "layout(std430, binding = 7) buffer Output3 {" NL " float data0[3];" NL "} g_output3;" NL
3328 "void main() {" NL
3329 " for (int i = 0; i < g_input0.data0.length(); ++i) g_output0.data0[i] = g_input0.data0[i];" NL
3330 " for (int i = 0; i < g_input1.data0.length(); ++i) g_output1.data0[i] = g_input1.data0[i];" NL
3331 " for (int i = 0; i < g_input2.data0.length(); ++i) g_output2.data0[i] = g_input2.data0[i];" NL
3332 " for (int i = 0; i < g_input3.data0.length(); ++i) g_output3.data0[i] = g_input3.data0[i];" NL "}";
3333 }
3334
3335 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3336 {
GetInput(std::vector<GLubyte> in_data[4])3337 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3338 {
3339 return GetInputC2(in_data);
3340 }
3341 };
3342
3343 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3344 {
GetInput(std::vector<GLubyte> in_data[4])3345 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3346 {
3347 return GetInputC2(in_data);
3348 }
3349 };
3350
3351 //-----------------------------------------------------------------------------
3352 // 1.9.3 BasicStdLayoutCase3
3353 //-----------------------------------------------------------------------------
GetInputC3(std::vector<GLubyte> in_data[4])3354 const char *GetInputC3(std::vector<GLubyte> in_data[4])
3355 {
3356 /* input 0, std140 */
3357 {
3358 in_data[0].resize(62 * 4);
3359 float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3360 int *ip = reinterpret_cast<int *>(&in_data[0][0]);
3361 ip[0] = 1;
3362 ip[1] = 0;
3363 ip[2] = 0;
3364 ip[3] = 0;
3365 fp[4] = 2.0f;
3366 fp[5] = 0.0f;
3367 fp[6] = 0.0f;
3368 fp[7] = 0.0f;
3369 fp[8] = 3.0f;
3370 fp[9] = 0.0f;
3371 fp[10] = 0.0f;
3372 fp[11] = 0.0f;
3373 fp[12] = 4.0f;
3374 fp[13] = 0.0f;
3375 fp[14] = 0.0f;
3376 fp[15] = 0.0f;
3377 fp[16] = 5.0f;
3378 fp[17] = 0.0f;
3379 fp[18] = 0.0f;
3380 fp[19] = 0.0f;
3381 fp[20] = 6.0f;
3382 fp[21] = 0.0f;
3383 fp[22] = 0.0f;
3384 fp[23] = 0.0f;
3385 fp[24] = 7.0f;
3386 fp[25] = 8.0f;
3387 fp[26] = 0.0f;
3388 fp[27] = 0.0f;
3389 fp[28] = 9.0f;
3390 fp[29] = 10.0f;
3391 fp[30] = 0.0f;
3392 fp[31] = 0.0f;
3393 fp[32] = 11.0f;
3394 fp[33] = 12.0f;
3395 fp[34] = 0.0f;
3396 fp[35] = 0.0f;
3397 *reinterpret_cast<double *>(fp + 36) = 13.0;
3398 *reinterpret_cast<double *>(fp + 38) = 0.0;
3399 *reinterpret_cast<double *>(fp + 40) = 14.0;
3400 *reinterpret_cast<double *>(fp + 42) = 0.0;
3401 *reinterpret_cast<double *>(fp + 44) = 15.0;
3402 *reinterpret_cast<double *>(fp + 46) = 0.0;
3403 ip[48] = 16;
3404 ip[49] = 0;
3405 ip[50] = 0;
3406 ip[51] = 0;
3407 ip[52] = 0;
3408 ip[53] = 0;
3409 ip[54] = 0;
3410 ip[55] = 0;
3411 *reinterpret_cast<double *>(fp + 56) = 17.0;
3412 *reinterpret_cast<double *>(fp + 58) = 18.0;
3413 *reinterpret_cast<double *>(fp + 60) = 19.0;
3414 }
3415 /* input 1, std430 */
3416 {
3417 in_data[1].resize(32 * 4);
3418 float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3419 int *ip = reinterpret_cast<int *>(&in_data[1][0]);
3420 ip[0] = 1;
3421 fp[1] = 2.0f;
3422 fp[2] = 3.0f;
3423 fp[3] = 4.0f;
3424 fp[4] = 5.0f;
3425 fp[5] = 6.0f;
3426 fp[6] = 7.0f;
3427 fp[7] = 8.0f;
3428 fp[8] = 9.0f;
3429 fp[9] = 10.0f;
3430 fp[10] = 11.0f;
3431 fp[11] = 12.0f;
3432 *reinterpret_cast<double *>(fp + 12) = 13.0;
3433 *reinterpret_cast<double *>(fp + 14) = 14.0;
3434 *reinterpret_cast<double *>(fp + 16) = 15.0;
3435 ip[18] = 16;
3436 ip[19] = 0;
3437 *reinterpret_cast<double *>(fp + 20) = 0.0;
3438 *reinterpret_cast<double *>(fp + 22) = 0.0;
3439 *reinterpret_cast<double *>(fp + 24) = 17.0;
3440 *reinterpret_cast<double *>(fp + 26) = 18.0;
3441 *reinterpret_cast<double *>(fp + 28) = 19.0;
3442 }
3443 /* input 2, std140 */
3444 {
3445 in_data[2].resize(5 * 4);
3446 int *ip = reinterpret_cast<int *>(&in_data[2][0]);
3447 ip[0] = 1;
3448 ip[1] = 0;
3449 ip[2] = 0;
3450 ip[3] = 0;
3451 ip[4] = 2;
3452 }
3453 /* input 3, std430 */
3454 {
3455 in_data[3].resize(2 * 4);
3456 int *ip = reinterpret_cast<int *>(&in_data[3][0]);
3457 ip[0] = 1;
3458 ip[1] = 2;
3459 }
3460 return NL "layout(std140, binding = 0) buffer Input0 {" NL " int data0;" NL " float data1[5];" NL
3461 " mat3x2 data2;" NL " double data3;" NL " double data4[2];" NL " int data5;" NL " dvec3 data6;" NL
3462 "} g_input0;" NL "layout(std430, binding = 1) buffer Input1 {" NL " int data0;" NL " float data1[5];" NL
3463 " mat3x2 data2;" NL " double data3;" NL " double data4[2];" NL " int data5;" NL " dvec3 data6;" NL
3464 "} g_input1;" NL "struct Struct0 {" NL " int data0;" NL "};" NL
3465 "layout(std140, binding = 2) buffer Input2 {" NL " int data0;" NL " Struct0 data1;" NL "} g_input2;" NL
3466 "layout(std430, binding = 3) buffer Input3 {" NL " int data0;" NL " Struct0 data1;" NL "} g_input3;"
3467
3468 NL "layout(std140, binding = 4) buffer Output0 {" NL " int data0;" NL " float data1[5];" NL
3469 " mat3x2 data2;" NL " double data3;" NL " double data4[2];" NL " int data5;" NL " dvec3 data6;" NL
3470 "} g_output0;" NL "layout(std430, binding = 5) buffer Output1 {" NL " int data0;" NL
3471 " float data1[5];" NL " mat3x2 data2;" NL " double data3;" NL " double data4[2];" NL " int data5;" NL
3472 " dvec3 data6;" NL "} g_output1;" NL "layout(std140, binding = 6) buffer Output2 {" NL " int data0;" NL
3473 " Struct0 data1;" NL "} g_output2;" NL "layout(std430, binding = 7) buffer Output3 {" NL
3474 " int data0;" NL " Struct0 data1;" NL "} g_output3;" NL "void main() {" NL
3475 " g_output0.data0 = g_input0.data0;" NL
3476 " for (int i = 0; i < g_input0.data1.length(); ++i) g_output0.data1[i] = g_input0.data1[i];" NL
3477 " g_output0.data2 = g_input0.data2;" NL " g_output0.data3 = g_input0.data3;" NL
3478 " for (int i = 0; i < g_input0.data4.length(); ++i) g_output0.data4[i] = g_input0.data4[i];" NL
3479 " g_output0.data5 = g_input0.data5;" NL " g_output0.data6 = g_input0.data6;"
3480
3481 NL " g_output1.data0 = g_input1.data0;" NL
3482 " for (int i = 0; i < g_input1.data1.length(); ++i) g_output1.data1[i] = g_input1.data1[i];" NL
3483 " g_output1.data2 = g_input1.data2;" NL " g_output1.data3 = g_input1.data3;" NL
3484 " for (int i = 0; i < g_input1.data4.length(); ++i) g_output1.data4[i] = g_input1.data4[i];" NL
3485 " g_output1.data5 = g_input1.data5;" NL " g_output1.data6 = g_input1.data6;"
3486
3487 NL " g_output2.data0 = g_input2.data0;" NL " g_output2.data1 = g_input2.data1;"
3488
3489 NL " g_output3.data0 = g_input3.data0;" NL " g_output3.data1 = g_input3.data1;" NL "}";
3490 }
3491
3492 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3493 {
GetInput(std::vector<GLubyte> in_data[4])3494 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3495 {
3496 return GetInputC3(in_data);
3497 }
3498 };
3499
3500 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3501 {
GetInput(std::vector<GLubyte> in_data[4])3502 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3503 {
3504 return GetInputC3(in_data);
3505 }
3506 };
3507
3508 //-----------------------------------------------------------------------------
3509 // 1.9.4 BasicStdLayoutCase4
3510 //-----------------------------------------------------------------------------
GetInputC4(std::vector<GLubyte> in_data[4])3511 const char *GetInputC4(std::vector<GLubyte> in_data[4])
3512 {
3513 /* input 0, std140 */
3514 {
3515 in_data[0].resize(60 * 4);
3516 float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3517 int *ip = reinterpret_cast<int *>(&in_data[0][0]);
3518 ip[0] = 1;
3519 ip[1] = 0;
3520 ip[2] = 0;
3521 ip[3] = 0;
3522 ip[4] = 2;
3523 ip[5] = 3;
3524 ip[6] = 0;
3525 ip[7] = 0;
3526 ip[8] = 4;
3527 ip[9] = 5;
3528 ip[10] = 0;
3529 ip[11] = 0;
3530 fp[12] = 6.0f;
3531 fp[13] = 0.0f;
3532 fp[14] = 0.0f;
3533 fp[15] = 0.0f;
3534 fp[16] = 7.0f;
3535 fp[17] = 8.0f;
3536 fp[18] = 0.0f;
3537 fp[19] = 0.0f;
3538 ip[20] = 9;
3539 ip[21] = 10;
3540 ip[22] = 11;
3541 ip[23] = 0;
3542 fp[24] = 12.0f;
3543 fp[25] = 13.0f;
3544 fp[26] = 0.0f;
3545 fp[27] = 0.0f;
3546 ip[28] = 14;
3547 ip[29] = 15;
3548 ip[30] = 16;
3549 ip[31] = 0;
3550 fp[32] = 17.0f;
3551 fp[33] = 0.0f;
3552 fp[34] = 0.0f;
3553 fp[35] = 0.0f;
3554 ip[36] = 18;
3555 ip[37] = 0;
3556 ip[38] = 0;
3557 ip[39] = 0;
3558 ip[40] = 19;
3559 ip[41] = 20;
3560 ip[42] = 0;
3561 ip[43] = 0;
3562 ip[44] = 21;
3563 ip[45] = 0;
3564 ip[45] = 0;
3565 ip[45] = 0;
3566 fp[48] = 22.0f;
3567 fp[49] = 23.0f;
3568 fp[50] = 0.0f;
3569 fp[51] = 0.0f;
3570 ip[52] = 24;
3571 ip[53] = 25;
3572 ip[54] = 26;
3573 ip[55] = 0;
3574 fp[56] = 27.0f;
3575 }
3576 /* input 1, std140 */
3577 {
3578 in_data[1].resize(60 * 4);
3579 float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3580 int *ip = reinterpret_cast<int *>(&in_data[1][0]);
3581 ip[0] = 101;
3582 ip[1] = 0;
3583 ip[2] = 0;
3584 ip[3] = 0;
3585 ip[4] = 102;
3586 ip[5] = 103;
3587 ip[6] = 0;
3588 ip[7] = 0;
3589 ip[8] = 104;
3590 ip[9] = 105;
3591 ip[10] = 0;
3592 ip[11] = 0;
3593 fp[12] = 106.0f;
3594 fp[13] = 0.0f;
3595 fp[14] = 0.0f;
3596 fp[15] = 0.0f;
3597 fp[16] = 107.0f;
3598 fp[17] = 108.0f;
3599 fp[18] = 0.0f;
3600 fp[19] = 0.0f;
3601 ip[20] = 109;
3602 ip[21] = 110;
3603 ip[22] = 111;
3604 ip[23] = 0;
3605 fp[24] = 112.0f;
3606 fp[25] = 113.0f;
3607 fp[26] = 0.0f;
3608 fp[27] = 0.0f;
3609 ip[28] = 114;
3610 ip[29] = 115;
3611 ip[30] = 116;
3612 ip[31] = 0;
3613 fp[32] = 117.0f;
3614 fp[33] = 0.0f;
3615 fp[34] = 0.0f;
3616 fp[35] = 0.0f;
3617 ip[36] = 118;
3618 ip[37] = 0;
3619 ip[38] = 0;
3620 ip[39] = 0;
3621 ip[40] = 119;
3622 ip[41] = 120;
3623 ip[42] = 0;
3624 ip[43] = 0;
3625 ip[44] = 121;
3626 ip[45] = 0;
3627 ip[45] = 0;
3628 ip[45] = 0;
3629 fp[48] = 122.0f;
3630 fp[49] = 123.0f;
3631 fp[50] = 0.0f;
3632 fp[51] = 0.0f;
3633 ip[52] = 124;
3634 ip[53] = 125;
3635 ip[54] = 126;
3636 ip[55] = 0;
3637 fp[56] = 127.0f;
3638 }
3639 /* input 2, std430 */
3640 {
3641 in_data[2].resize(48 * 4);
3642 float *fp = reinterpret_cast<float *>(&in_data[2][0]);
3643 int *ip = reinterpret_cast<int *>(&in_data[2][0]);
3644 ip[0] = 1000;
3645 ip[1] = 0;
3646 ip[2] = 1001;
3647 ip[3] = 1002;
3648 ip[4] = 1003;
3649 ip[5] = 1004;
3650 fp[6] = 1005.0f;
3651 fp[7] = 0.0f;
3652 fp[8] = 1006.0f;
3653 fp[9] = 1007.0f;
3654 fp[10] = 0.0f;
3655 fp[11] = 0.0f;
3656 ip[12] = 1008;
3657 ip[13] = 1009;
3658 ip[14] = 1010;
3659 ip[15] = 0;
3660 fp[16] = 1011.0f;
3661 fp[17] = 1012.0f;
3662 fp[18] = 0.0f;
3663 fp[19] = 0.0f;
3664 ip[20] = 1013;
3665 ip[21] = 1014;
3666 ip[22] = 1015;
3667 ip[23] = 0;
3668 fp[24] = 1016.0f;
3669 fp[25] = 0.0f;
3670 fp[26] = 0.0f;
3671 fp[27] = 0.0f;
3672 ip[28] = 1017;
3673 ip[29] = 0;
3674 ip[30] = 1018;
3675 ip[31] = 1019;
3676 ip[32] = 1020;
3677 ip[33] = 0;
3678 ip[34] = 0;
3679 ip[35] = 0;
3680 fp[36] = 1021.0f;
3681 fp[37] = 1022.0f;
3682 fp[38] = 0.0f;
3683 fp[39] = 0.0f;
3684 ip[40] = 1023;
3685 ip[41] = 1024;
3686 ip[42] = 1025;
3687 ip[43] = 0;
3688 fp[44] = 1026.0f;
3689 }
3690 /* input 3, std430 */
3691 {
3692 in_data[3].resize(48 * 4);
3693 float *fp = reinterpret_cast<float *>(&in_data[3][0]);
3694 int *ip = reinterpret_cast<int *>(&in_data[3][0]);
3695 ip[0] = 10000;
3696 ip[1] = 0;
3697 ip[2] = 10001;
3698 ip[3] = 10002;
3699 ip[4] = 10003;
3700 ip[5] = 10004;
3701 fp[6] = 10005.0f;
3702 fp[7] = 0.0f;
3703 fp[8] = 10006.0f;
3704 fp[9] = 10007.0f;
3705 fp[10] = 0.0f;
3706 fp[11] = 0.0f;
3707 ip[12] = 10008;
3708 ip[13] = 10009;
3709 ip[14] = 10010;
3710 ip[15] = 0;
3711 fp[16] = 10011.0f;
3712 fp[17] = 10012.0f;
3713 fp[18] = 0.0f;
3714 fp[19] = 0.0f;
3715 ip[20] = 10013;
3716 ip[21] = 10014;
3717 ip[22] = 10015;
3718 ip[23] = 0;
3719 fp[24] = 10016.0f;
3720 fp[25] = 0.0f;
3721 fp[26] = 0.0f;
3722 fp[27] = 0.0f;
3723 ip[28] = 10017;
3724 ip[29] = 0;
3725 ip[30] = 10018;
3726 ip[31] = 10019;
3727 ip[32] = 10020;
3728 ip[33] = 0;
3729 ip[34] = 0;
3730 ip[35] = 0;
3731 fp[36] = 10021.0f;
3732 fp[37] = 10022.0f;
3733 fp[38] = 0.0f;
3734 fp[39] = 0.0f;
3735 ip[40] = 10023;
3736 ip[41] = 10024;
3737 ip[42] = 10025;
3738 ip[43] = 0;
3739 fp[44] = 10026.0f;
3740 }
3741 return NL
3742 "struct Struct0 {" NL " ivec2 data0;" NL "};" NL "struct Struct1 {" NL " vec2 data0;" NL " ivec3 data1;" NL
3743 "};" NL "struct Struct2 {" NL " int data0;" NL " Struct0 data1;" NL " int data2;" NL " Struct1 data3;" NL
3744 " float data4;" NL "};" NL "layout(std140, binding = 0) buffer Input01 {" NL " int data0;" NL
3745 " Struct0 data1[2];" NL " float data2;" NL " Struct1 data3[2];" NL " float data4;" NL " Struct2 data5;" NL
3746 "} g_input01[2];" NL "layout(std430, binding = 2) buffer Input23 {" NL " int data0;" NL
3747 " Struct0 data1[2];" NL " float data2;" NL " Struct1 data3[2];" NL " float data4;" NL " Struct2 data5;" NL
3748 "} g_input23[2];"
3749
3750 NL "layout(std140, binding = 4) buffer Output01 {" NL " int data0;" NL " Struct0 data1[2];" NL
3751 " float data2;" NL " Struct1 data3[2];" NL " float data4;" NL " Struct2 data5;" NL "} g_output01[2];" NL
3752 "layout(std430, binding = 6) buffer Output23 {" NL " int data0;" NL " Struct0 data1[2];" NL
3753 " float data2;" NL " Struct1 data3[2];" NL " float data4;" NL " Struct2 data5;" NL "} g_output23[2];" NL NL
3754 "void main() {" NL " for (int b = 0; b < g_input01.length(); ++b) {" NL
3755 " g_output01[b].data0 = g_input01[b].data0;" NL
3756 " for (int i = 0; i < g_input01[b].data1.length(); ++i) g_output01[b].data1[i] = g_input01[b].data1[i];" NL
3757 " g_output01[b].data2 = g_input01[b].data2;" NL " g_output01[b].data3[0] = g_input01[b].data3[0];" NL
3758 " g_output01[b].data3[1] = g_input01[b].data3[1];" NL " g_output01[b].data4 = g_input01[b].data4;" NL
3759 " }" NL " g_output01[0].data5 = g_input01[0].data5;" NL " g_output01[1].data5 = g_input01[1].data5;" NL NL
3760 " for (int b = 0; b < g_input23.length(); ++b) {" NL " g_output23[b].data0 = g_input23[b].data0;" NL
3761 " for (int i = 0; i < g_input23[b].data1.length(); ++i) g_output23[b].data1[i] = g_input23[b].data1[i];" NL
3762 " g_output23[b].data2 = g_input23[b].data2;" NL " g_output23[b].data3[0] = g_input23[b].data3[0];" NL
3763 " g_output23[b].data3[1] = g_input23[b].data3[1];" NL " g_output23[b].data4 = g_input23[b].data4;" NL
3764 " }" NL " g_output23[0].data5 = g_input23[0].data5;" NL " g_output23[1].data5 = g_input23[1].data5;" NL "}";
3765 }
3766
3767 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3768 {
GetInput(std::vector<GLubyte> in_data[4])3769 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3770 {
3771 return GetInputC4(in_data);
3772 }
3773 };
3774
3775 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3776 {
GetInput(std::vector<GLubyte> in_data[4])3777 virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3778 {
3779 return GetInputC4(in_data);
3780 }
3781 };
3782 //-----------------------------------------------------------------------------
3783 // 1.10.x BasicOperationsBase
3784 //-----------------------------------------------------------------------------
3785
3786 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3787 {
3788 GLuint m_program;
3789 GLuint m_buffer[2];
3790 GLuint m_vertex_array;
3791
3792 virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data) = 0;
3793
Setup()3794 virtual long Setup()
3795 {
3796 m_program = 0;
3797 memset(m_buffer, 0, sizeof(m_buffer));
3798 m_vertex_array = 0;
3799 return NO_ERROR;
3800 }
3801
Run()3802 virtual long Run()
3803 {
3804 if (!SupportedInVS(2))
3805 return NOT_SUPPORTED;
3806 std::vector<GLubyte> in_data;
3807 std::vector<GLubyte> expected_data;
3808 const char *glsl_vs = GetInput(in_data, expected_data);
3809
3810 m_program = CreateProgram(glsl_vs, "");
3811 glLinkProgram(m_program);
3812 if (!CheckProgram(m_program))
3813 return ERROR;
3814
3815 glGenBuffers(2, m_buffer);
3816
3817 /* output buffer */
3818 {
3819 std::vector<GLubyte> zero(expected_data.size());
3820 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3821 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3822 }
3823 // input buffer
3824 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3825 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3826
3827 glGenVertexArrays(1, &m_vertex_array);
3828 glEnable(GL_RASTERIZER_DISCARD);
3829
3830 glUseProgram(m_program);
3831 glBindVertexArray(m_vertex_array);
3832 glDrawArrays(GL_POINTS, 0, 1);
3833
3834 std::vector<GLubyte> out_data(expected_data.size());
3835 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3836 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3837 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)out_data.size(), &out_data[0]);
3838
3839 bool status = true;
3840 for (size_t i = 0; i < out_data.size(); ++i)
3841 {
3842 if (expected_data[i] != out_data[i])
3843 {
3844 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3845 << " is " << tcu::toHex(out_data[i]) << " should be "
3846 << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3847 status = false;
3848 }
3849 }
3850 if (!status)
3851 return ERROR;
3852 return NO_ERROR;
3853 }
3854
Cleanup()3855 virtual long Cleanup()
3856 {
3857 glDisable(GL_RASTERIZER_DISCARD);
3858 glUseProgram(0);
3859 glDeleteProgram(m_program);
3860 glDeleteBuffers(2, m_buffer);
3861 glDeleteVertexArrays(1, &m_vertex_array);
3862 return NO_ERROR;
3863 }
3864 };
3865
3866 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3867 {
3868 GLuint m_program;
3869 GLuint m_buffer[2];
3870
3871 virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data) = 0;
3872
Setup()3873 virtual long Setup()
3874 {
3875 m_program = 0;
3876 memset(m_buffer, 0, sizeof(m_buffer));
3877 return NO_ERROR;
3878 }
3879
Run()3880 virtual long Run()
3881 {
3882 std::vector<GLubyte> in_data;
3883 std::vector<GLubyte> expected_data;
3884
3885 std::stringstream ss;
3886 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data, expected_data);
3887 m_program = CreateProgramCS(ss.str());
3888 glLinkProgram(m_program);
3889 if (!CheckProgram(m_program))
3890 return ERROR;
3891
3892 glGenBuffers(2, m_buffer);
3893
3894 /* output buffer */
3895 {
3896 std::vector<GLubyte> zero(expected_data.size());
3897 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3898 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3899 }
3900 // input buffer
3901 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3902 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3903
3904 glUseProgram(m_program);
3905 glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3906 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3907 glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3908 glDispatchCompute(1, 1, 1);
3909
3910 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3911 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3912 GLubyte *out_data =
3913 (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3914 if (!out_data)
3915 return ERROR;
3916
3917 bool status = true;
3918 for (size_t i = 0; i < expected_data.size(); ++i)
3919 {
3920 if (expected_data[i] != out_data[i])
3921 {
3922 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3923 << " is " << tcu::toHex(out_data[i]) << " should be "
3924 << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3925 status = false;
3926 }
3927 }
3928 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3929 if (!status)
3930 return ERROR;
3931 return NO_ERROR;
3932 }
3933
Cleanup()3934 virtual long Cleanup()
3935 {
3936 glUseProgram(0);
3937 glDeleteProgram(m_program);
3938 glDeleteBuffers(2, m_buffer);
3939 return NO_ERROR;
3940 }
3941 };
3942
3943 //-----------------------------------------------------------------------------
3944 // 1.10.1 BasicOperationsCase1
3945 //-----------------------------------------------------------------------------
GetInputOp1(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3946 const char *GetInputOp1(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3947 {
3948 /* input */
3949 {
3950 in_data.resize(16 * 9);
3951 int *ip = reinterpret_cast<int *>(&in_data[0]);
3952 float *fp = reinterpret_cast<float *>(&in_data[0]);
3953 ip[0] = 1;
3954 ip[1] = 2;
3955 ip[2] = 3;
3956 ip[3] = 4;
3957 fp[4] = 1.0f;
3958 fp[5] = 2.0f;
3959 fp[6] = 3.0f;
3960 fp[7] = 0.0f;
3961 ip[8] = 1;
3962 ip[9] = 2;
3963 ip[10] = 3;
3964 ip[11] = 4;
3965 ip[12] = 1;
3966 ip[13] = -2;
3967 ip[14] = 3;
3968 ip[15] = 4;
3969 fp[16] = 1.0f;
3970 fp[17] = 2.0f;
3971 fp[18] = 3.0f;
3972 fp[19] = 4.0f;
3973 fp[20] = 1.0f;
3974 fp[21] = 2.0f;
3975 fp[22] = 3.0f;
3976 fp[23] = 4.0f;
3977 fp[24] = 1.0f;
3978 fp[25] = 2.0f;
3979 fp[26] = 3.0f;
3980 fp[27] = 4.0f;
3981 fp[28] = 1.0f;
3982 fp[29] = 2.0f;
3983 fp[30] = 3.0f;
3984 fp[31] = 4.0f;
3985 fp[32] = 1.0f;
3986 fp[33] = 0.0f;
3987 fp[34] = 0.0f;
3988 fp[35] = 4.0f;
3989 }
3990 /* expected output */
3991 {
3992 out_data.resize(16 * 9);
3993 int *ip = reinterpret_cast<int *>(&out_data[0]);
3994 float *fp = reinterpret_cast<float *>(&out_data[0]);
3995 ip[0] = 4;
3996 ip[1] = 3;
3997 ip[2] = 2;
3998 ip[3] = 1;
3999 fp[4] = 3.0f;
4000 fp[5] = 2.0f;
4001 fp[6] = 1.0f;
4002 fp[7] = 0.0f;
4003 ip[8] = 4;
4004 ip[9] = 1;
4005 ip[10] = 0;
4006 ip[11] = 3;
4007 ip[12] = 10;
4008 ip[13] = 4;
4009 ip[14] = -2;
4010 ip[15] = 20;
4011 fp[16] = 50.0f;
4012 fp[17] = 5.0f;
4013 fp[18] = 2.0f;
4014 fp[19] = 30.0f;
4015 fp[20] = 4.0f;
4016 fp[21] = 2.0f;
4017 fp[22] = 3.0f;
4018 fp[23] = 1.0f;
4019 fp[24] = 4.0f;
4020 fp[25] = 3.0f;
4021 fp[26] = 2.0f;
4022 fp[27] = 1.0f;
4023 fp[28] = 2.0f;
4024 fp[29] = 2.0f;
4025 fp[30] = 2.0f;
4026 fp[31] = 2.0f;
4027 fp[32] = 4.0f;
4028 fp[33] = 0.0f;
4029 fp[34] = 0.0f;
4030 fp[35] = 1.0f;
4031 }
4032 return NL "layout(std430, binding = 0) buffer Input {" NL " ivec4 data0;" NL " vec3 data1;" NL " uvec4 data2;" NL
4033 " ivec4 data3;" NL " vec4 data4;" NL " mat4 data5;" NL "} g_input;" NL
4034 "layout(std430, binding = 1) buffer Output {" NL " ivec4 data0;" NL " vec3 data1;" NL
4035 " uvec4 data2;" NL " ivec4 data3;" NL " vec4 data4;" NL " mat4 data5;" NL "} g_output;" NL
4036 "uniform vec3 g_value0 = vec3(10, 20, 30);" NL "uniform int g_index1 = 1;" NL "void main() {" NL
4037 " int index0 = 0;" NL " g_output.data0.wzyx = g_input.data0;" NL
4038 " g_output.data1 = g_input.data1.zyx;" NL " g_output.data2.xwy = g_input.data2.wzx;" NL
4039 " g_output.data3.xw = ivec2(10, 20);" NL " g_output.data3.zy = g_input.data3.yw;" NL
4040 " g_output.data4.wx = g_value0.xz;" NL " g_output.data4.wx += g_value0.yy;" NL
4041 " g_output.data4.yz = g_input.data4.xx + g_input.data4.wx;" NL
4042 " g_output.data5[g_index1 - 1].wyzx = vec4(1, 2, 3, 4);" NL
4043 " g_output.data5[g_index1 + index0] = g_input.data5[g_index1].wzyx;" NL
4044 " g_output.data5[1 + g_index1] = g_input.data5[g_index1 + 1].yyyy;" NL
4045 " g_output.data5[5 - g_index1 - 1].wx = g_input.data5[4 - g_index1].xw;" NL "}";
4046 }
4047
4048 class BasicOperationsCase1VS : public BasicOperationsBaseVS
4049 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4050 virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4051 {
4052 return GetInputOp1(in_data, out_data);
4053 }
4054 };
4055
4056 class BasicOperationsCase1CS : public BasicOperationsBaseCS
4057 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4058 virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4059 {
4060 return GetInputOp1(in_data, out_data);
4061 }
4062 };
4063 //-----------------------------------------------------------------------------
4064 // 1.10.2 BasicOperationsCase2
4065 //-----------------------------------------------------------------------------
GetInputOp2(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4066 const char *GetInputOp2(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4067 {
4068 /* input */
4069 {
4070 in_data.resize(16 * 8);
4071 float *fp = reinterpret_cast<float *>(&in_data[0]);
4072 fp[0] = 1.0f;
4073 fp[1] = 0.0f;
4074 fp[2] = 0.0f;
4075 fp[3] = 0.0f;
4076 fp[4] = 0.0f;
4077 fp[5] = 1.0f;
4078 fp[6] = 0.0f;
4079 fp[7] = 0.0f;
4080 fp[8] = 0.0f;
4081 fp[9] = 0.0f;
4082 fp[10] = 1.0f;
4083 fp[11] = 0.0f;
4084 fp[12] = 0.0f;
4085 fp[13] = 0.0f;
4086 fp[14] = 0.0f;
4087 fp[15] = 1.0f;
4088
4089 fp[16] = 2.0f;
4090 fp[17] = 0.0f;
4091 fp[18] = 0.0f;
4092 fp[19] = 0.0f;
4093 fp[20] = 0.0f;
4094 fp[21] = 3.0f;
4095 fp[22] = 0.0f;
4096 fp[23] = 0.0f;
4097 fp[24] = 0.0f;
4098 fp[25] = 0.0f;
4099 fp[26] = 4.0f;
4100 fp[27] = 0.0f;
4101 fp[28] = 0.0f;
4102 fp[29] = 0.0f;
4103 fp[30] = 0.0f;
4104 fp[31] = 5.0f;
4105 }
4106 /* expected output */
4107 {
4108 out_data.resize(16 * 5);
4109 float *fp = reinterpret_cast<float *>(&out_data[0]);
4110 fp[0] = 2.0f;
4111 fp[1] = 0.0f;
4112 fp[2] = 0.0f;
4113 fp[3] = 0.0f;
4114 fp[4] = 0.0f;
4115 fp[5] = 3.0f;
4116 fp[6] = 0.0f;
4117 fp[7] = 0.0f;
4118 fp[8] = 0.0f;
4119 fp[9] = 0.0f;
4120 fp[10] = 4.0f;
4121 fp[11] = 0.0f;
4122 fp[12] = 0.0f;
4123 fp[13] = 0.0f;
4124 fp[14] = 0.0f;
4125 fp[15] = 5.0f;
4126
4127 fp[16] = 0.0f;
4128 fp[17] = 1.0f;
4129 fp[18] = 4.0f;
4130 fp[19] = 0.0f;
4131 }
4132 return NL "layout(std430, binding = 0) buffer Input {" NL " mat4 data0;" NL " mat4 data1;" NL "} g_input;" NL
4133 "layout(std430, binding = 1) buffer Output {" NL " mat4 data0;" NL " vec4 data1;" NL "} g_output;" NL
4134 "uniform int g_index2 = 2;" NL "void main() {" NL
4135 " g_output.data0 = matrixCompMult(g_input.data0, g_input.data1);" NL
4136 " g_output.data1 = g_input.data0[1] + g_input.data1[g_index2];" NL "}";
4137 }
4138
4139 class BasicOperationsCase2VS : public BasicOperationsBaseVS
4140 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4141 virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4142 {
4143 return GetInputOp2(in_data, out_data);
4144 }
4145 };
4146
4147 class BasicOperationsCase2CS : public BasicOperationsBaseCS
4148 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4149 virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4150 {
4151 return GetInputOp2(in_data, out_data);
4152 }
4153 };
4154
4155 //-----------------------------------------------------------------------------
4156 // 1.11.x BasicStdLayoutBase3
4157 //-----------------------------------------------------------------------------
4158 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
4159 {
4160 GLuint m_program;
4161 GLuint m_buffer[4];
4162 GLuint m_vertex_array;
4163
4164 virtual const char *GetInput(std::vector<GLubyte> in_data[2]) = 0;
4165
Setup()4166 virtual long Setup()
4167 {
4168 m_program = 0;
4169 memset(m_buffer, 0, sizeof(m_buffer));
4170 m_vertex_array = 0;
4171 return NO_ERROR;
4172 }
4173
Run()4174 virtual long Run()
4175 {
4176 if (!SupportedInVS(2))
4177 return NOT_SUPPORTED;
4178 std::vector<GLubyte> in_data[2];
4179 const char *glsl_vs = GetInput(in_data);
4180
4181 m_program = CreateProgram(glsl_vs, "");
4182 glLinkProgram(m_program);
4183 if (!CheckProgram(m_program))
4184 return ERROR;
4185
4186 glGenBuffers(4, m_buffer);
4187
4188 // input buffers
4189 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4190 glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4191
4192 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4193 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4194
4195 /* output buffer 0 */
4196 {
4197 std::vector<GLubyte> out_data(in_data[0].size());
4198 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4199 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4200 }
4201 /* output buffer 1 */
4202 {
4203 std::vector<GLubyte> out_data(in_data[1].size());
4204 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4205 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4206 }
4207
4208 glGenVertexArrays(1, &m_vertex_array);
4209 glEnable(GL_RASTERIZER_DISCARD);
4210
4211 glUseProgram(m_program);
4212 glBindVertexArray(m_vertex_array);
4213 glDrawArrays(GL_POINTS, 0, 1);
4214
4215 bool status = true;
4216 for (int j = 0; j < 2; ++j)
4217 {
4218 std::vector<GLubyte> out_data(in_data[j].size());
4219 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4220 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4221 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), &out_data[0]);
4222
4223 for (size_t i = 0; i < in_data[j].size(); ++i)
4224 {
4225 if (in_data[j][i] != out_data[i])
4226 {
4227 m_context.getTestContext().getLog()
4228 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4229 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4230 << tcu::TestLog::EndMessage;
4231 status = false;
4232 }
4233 }
4234 }
4235 if (!status)
4236 return ERROR;
4237 return NO_ERROR;
4238 }
4239
Cleanup()4240 virtual long Cleanup()
4241 {
4242 glDisable(GL_RASTERIZER_DISCARD);
4243 glUseProgram(0);
4244 glDeleteProgram(m_program);
4245 glDeleteBuffers(4, m_buffer);
4246 glDeleteVertexArrays(1, &m_vertex_array);
4247 return NO_ERROR;
4248 }
4249 };
4250
4251 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4252 {
4253 GLuint m_program;
4254 GLuint m_buffer[4];
4255
4256 virtual const char *GetInput(std::vector<GLubyte> in_data[2]) = 0;
4257
Setup()4258 virtual long Setup()
4259 {
4260 m_program = 0;
4261 memset(m_buffer, 0, sizeof(m_buffer));
4262 return NO_ERROR;
4263 }
4264
Run()4265 virtual long Run()
4266 {
4267 std::vector<GLubyte> in_data[2];
4268
4269 std::stringstream ss;
4270 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
4271 m_program = CreateProgramCS(ss.str());
4272 glLinkProgram(m_program);
4273 if (!CheckProgram(m_program))
4274 return ERROR;
4275
4276 glGenBuffers(4, m_buffer);
4277
4278 // input buffers
4279 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4280 glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4281
4282 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4283 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4284
4285 /* output buffer 0 */
4286 {
4287 std::vector<GLubyte> out_data(in_data[0].size());
4288 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4289 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4290 }
4291 /* output buffer 1 */
4292 {
4293 std::vector<GLubyte> out_data(in_data[1].size());
4294 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4295 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4296 }
4297
4298 glUseProgram(m_program);
4299 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4300 glDispatchCompute(1, 1, 1);
4301
4302 bool status = true;
4303 for (int j = 0; j < 2; ++j)
4304 {
4305 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4306 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4307 GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
4308 GL_MAP_READ_BIT);
4309 if (!out_data)
4310 return ERROR;
4311
4312 for (size_t i = 0; i < in_data[j].size(); ++i)
4313 {
4314 if (in_data[j][i] != out_data[i])
4315 {
4316 m_context.getTestContext().getLog()
4317 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4318 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4319 << tcu::TestLog::EndMessage;
4320 status = false;
4321 }
4322 }
4323 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4324 }
4325 if (!status)
4326 return ERROR;
4327 return NO_ERROR;
4328 }
4329
Cleanup()4330 virtual long Cleanup()
4331 {
4332 glUseProgram(0);
4333 glDeleteProgram(m_program);
4334 glDeleteBuffers(4, m_buffer);
4335 return NO_ERROR;
4336 }
4337 };
4338 //-----------------------------------------------------------------------------
4339 // 1.11.1 Basic_UBO_SSBO_LayoutCase1
4340 //-----------------------------------------------------------------------------
GetInputUBO1(std::vector<GLubyte> in_data[2])4341 const char *GetInputUBO1(std::vector<GLubyte> in_data[2])
4342 {
4343 /* UBO */
4344 {
4345 in_data[0].resize(12 * 4);
4346 float *fp = reinterpret_cast<float *>(&in_data[0][0]);
4347 fp[0] = 1.0f;
4348 fp[1] = 0.0f;
4349 fp[2] = 0.0f;
4350 fp[3] = 0.0f;
4351 fp[4] = 2.0f;
4352 fp[5] = 0.0f;
4353 fp[6] = 0.0f;
4354 fp[7] = 0.0f;
4355 fp[8] = 3.0f;
4356 fp[9] = 0.0f;
4357 fp[10] = 0.0f;
4358 fp[11] = 0.0f;
4359 }
4360 /* SSBO */
4361 {
4362 in_data[1].resize(3 * 4);
4363 float *fp = reinterpret_cast<float *>(&in_data[1][0]);
4364 fp[0] = 1.0f;
4365 fp[1] = 2.0f;
4366 fp[2] = 3.0f;
4367 }
4368 return NL
4369 "layout(std140, binding = 0) uniform InputUBO {" NL " float data0;" NL " float data1[2];" NL
4370 "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL " float data0;" NL
4371 " float data1[2];" NL "} g_input_ssbo;" NL "layout(std140, binding = 1) buffer OutputUBO {" NL
4372 " float data0;" NL " float data1[2];" NL "} g_output_ubo;" NL
4373 "layout(std430, binding = 2) buffer OutputSSBO {" NL " float data0;" NL " float data1[2];" NL
4374 "} g_output_ssbo;" NL "void main() {" NL " g_output_ubo.data0 = g_input_ubo.data0;" NL
4375 " for (int i = 0; i < g_input_ubo.data1.length(); ++i) g_output_ubo.data1[i] = g_input_ubo.data1[i];" NL
4376 " g_output_ssbo.data0 = g_input_ssbo.data0;" NL
4377 " for (int i = 0; i < g_input_ssbo.data1.length(); ++i) g_output_ssbo.data1[i] = g_input_ssbo.data1[i];" NL
4378 "}";
4379 }
4380
4381 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4382 {
GetInput(std::vector<GLubyte> in_data[2])4383 virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4384 {
4385 return GetInputUBO1(in_data);
4386 }
4387 };
4388
4389 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4390 {
GetInput(std::vector<GLubyte> in_data[2])4391 virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4392 {
4393 return GetInputUBO1(in_data);
4394 }
4395 };
4396
4397 //-----------------------------------------------------------------------------
4398 // 1.11.2 Basic_UBO_SSBO_LayoutCase2
4399 //-----------------------------------------------------------------------------
GetInputUBO2(std::vector<GLubyte> in_data[2])4400 const char *GetInputUBO2(std::vector<GLubyte> in_data[2])
4401 {
4402 /* UBO */
4403 {
4404 in_data[0].resize(280 * 4);
4405 float *fp = reinterpret_cast<float *>(&in_data[0][0]);
4406 int *ip = reinterpret_cast<int *>(&in_data[0][0]);
4407 fp[0] = 1.0f;
4408 fp[1] = 2.0f;
4409 fp[2] = 3.0f;
4410 fp[3] = 4.0f;
4411 fp[4] = 5.0f;
4412 fp[5] = 6.0f;
4413 fp[6] = 7.0f;
4414 fp[8] = 9.0f;
4415 fp[12] = 10.0f;
4416 fp[16] = 11.0f;
4417 fp[20] = 12.0f;
4418 fp[24] = 13.0f;
4419
4420 ip[28] = 14;
4421 for (int i = 0; i < 20; ++i)
4422 {
4423 fp[32 + i * 4] = static_cast<float>(15 + i);
4424 }
4425 ip[112] = 140;
4426 for (int i = 0; i < 20; ++i)
4427 {
4428 fp[116 + i * 4] = static_cast<float>(150 + i);
4429 }
4430 ip[196] = 1400;
4431 for (int i = 0; i < 20; ++i)
4432 {
4433 fp[200 + i * 4] = static_cast<float>(1500 + i);
4434 }
4435 }
4436 /* SSBO */
4437 {
4438 in_data[1].resize(76 * 4);
4439 float *fp = reinterpret_cast<float *>(&in_data[1][0]);
4440 int *ip = reinterpret_cast<int *>(&in_data[1][0]);
4441 fp[0] = 1.0f;
4442 fp[1] = 2.0f;
4443 fp[2] = 3.0f;
4444 fp[3] = 4.0f;
4445 fp[4] = 5.0f;
4446 fp[5] = 6.0f;
4447 fp[6] = 7.0f;
4448 fp[7] = 8.0f;
4449 fp[8] = 9.0f;
4450 fp[9] = 10.0f;
4451 fp[10] = 11.0f;
4452 fp[11] = 12.0f;
4453 fp[12] = 13.0f;
4454 ip[13] = 14;
4455 fp[14] = 15.0f;
4456 fp[15] = 16.0f;
4457 fp[16] = 17.0f;
4458 fp[17] = 18.0f;
4459 fp[18] = 19.0f;
4460 fp[19] = 20.0f;
4461 fp[20] = 21.0f;
4462 fp[21] = 22.0f;
4463 fp[22] = 23.0f;
4464 fp[23] = 24.0f;
4465 fp[24] = 25.0f;
4466 fp[25] = 26.0f;
4467 fp[26] = 27.0f;
4468 fp[27] = 28.0f;
4469 fp[28] = 29.0f;
4470 fp[29] = 30.0f;
4471 fp[30] = 31.0f;
4472 fp[31] = 32.0f;
4473 fp[32] = 33.0f;
4474 fp[33] = 34.0f;
4475 ip[34] = 35;
4476 fp[35] = 36.0f;
4477 fp[36] = 37.0f;
4478 fp[37] = 38.0f;
4479 fp[38] = 39.0f;
4480 fp[39] = 40.0f;
4481 fp[40] = 41.0f;
4482 fp[41] = 42.0f;
4483 fp[42] = 43.0f;
4484 fp[43] = 44.0f;
4485 fp[44] = 45.0f;
4486 fp[45] = 46.0f;
4487 fp[46] = 47.0f;
4488 fp[47] = 48.0f;
4489 fp[48] = 49.0f;
4490 fp[49] = 50.0f;
4491 fp[50] = 51.0f;
4492 fp[51] = 52.0f;
4493 fp[52] = 53.0f;
4494 fp[53] = 54.0f;
4495 fp[54] = 55.0f;
4496 ip[55] = 56;
4497 fp[56] = 57.0f;
4498 fp[57] = 58.0f;
4499 fp[58] = 59.0f;
4500 fp[59] = 60.0f;
4501 fp[60] = 61.0f;
4502 fp[61] = 62.0f;
4503 fp[62] = 63.0f;
4504 fp[63] = 64.0f;
4505 fp[64] = 65.0f;
4506 fp[65] = 66.0f;
4507 fp[66] = 67.0f;
4508 fp[67] = 68.0f;
4509 fp[68] = 69.0f;
4510 fp[69] = 70.0f;
4511 fp[70] = 71.0f;
4512 fp[71] = 72.0f;
4513 fp[72] = 73.0f;
4514 fp[73] = 74.0f;
4515 fp[74] = 75.0f;
4516 fp[75] = 76.0f;
4517 }
4518 return NL
4519 "struct MM {" NL " float mm_a[5];" NL "};" NL "struct TT {" NL " int tt_a;" NL " MM tt_b[4];" NL "};" NL
4520 "layout(std140, binding = 0) uniform InputUBO {" NL " vec4 a;" NL " vec4 b;" NL " float c;" NL
4521 " float d[4];" NL " TT e[3];" NL "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL
4522 " vec4 a;" NL " vec4 b;" NL " float c;" NL " float d[4];" NL " TT e[3];" NL "} g_input_ssbo;" NL
4523 "layout(std140, binding = 1) buffer OutputUBO {" NL " vec4 a;" NL " vec4 b;" NL " float c;" NL
4524 " float d[4];" NL " TT e[3];" NL "} g_output_ubo;" NL "layout(std430, binding = 2) buffer OutputSSBO {" NL
4525 " vec4 a;" NL " vec4 b;" NL " float c;" NL " float d[4];" NL " TT e[3];" NL "} g_output_ssbo;" NL
4526 "uniform int g_index1 = 1;" NL "void main() {" NL " int index0 = 0;" NL NL
4527 " g_output_ubo.a = g_input_ubo.a;" NL " g_output_ubo.b = g_input_ubo.b;" NL
4528 " g_output_ubo.c = g_input_ubo.c;" NL
4529 " for (int i = 0; i < g_input_ubo.d.length(); ++i) g_output_ubo.d[i] = g_input_ubo.d[i];" NL
4530 " for (int j = 0; j < g_input_ubo.e.length(); ++j) {" NL
4531 " g_output_ubo.e[j].tt_a = g_input_ubo.e[j].tt_a;" NL
4532 " for (int i = 0; i < g_input_ubo.e[j].tt_b.length(); ++i) {" NL
4533 " g_output_ubo.e[j].tt_b[i].mm_a[0] = g_input_ubo.e[j].tt_b[i].mm_a[0];" NL
4534 " g_output_ubo.e[j].tt_b[index0 + i].mm_a[1] = g_input_ubo.e[j].tt_b[i].mm_a[1];" NL
4535 " g_output_ubo.e[j].tt_b[i].mm_a[2] = g_input_ubo.e[j].tt_b[i].mm_a[2 + index0];" NL
4536 " g_output_ubo.e[j + 1 - g_index1].tt_b[i].mm_a[4 - g_index1] = g_input_ubo.e[j].tt_b[i].mm_a[2 + "
4537 "g_index1];" NL " g_output_ubo.e[j].tt_b[i].mm_a[4] = g_input_ubo.e[j].tt_b[i - index0].mm_a[4];" NL
4538 " }" NL " }" NL NL " g_output_ssbo.a = g_input_ssbo.a;" NL " g_output_ssbo.b = g_input_ssbo.b;" NL
4539 " g_output_ssbo.c = g_input_ssbo.c;" NL
4540 " for (int i = 0; i < g_input_ssbo.d.length(); ++i) g_output_ssbo.d[i] = g_input_ssbo.d[i];" NL
4541 " for (int j = 0; j < g_input_ssbo.e.length(); ++j) {" NL
4542 " g_output_ssbo.e[j].tt_a = g_input_ssbo.e[j].tt_a;" NL
4543 " for (int i = 0; i < g_input_ssbo.e[j].tt_b.length(); ++i) {" NL
4544 " g_output_ssbo.e[j + index0].tt_b[i].mm_a[0] = g_input_ssbo.e[j].tt_b[i].mm_a[index0];" NL
4545 " g_output_ssbo.e[j].tt_b[i + index0].mm_a[1] = g_input_ssbo.e[j].tt_b[i].mm_a[g_index1];" NL
4546 " g_output_ssbo.e[j].tt_b[i].mm_a[2] = g_input_ssbo.e[j].tt_b[i].mm_a[1 + g_index1];" NL
4547 " g_output_ssbo.e[j - index0].tt_b[i].mm_a[g_index1 + 2] = g_input_ssbo.e[j].tt_b[i].mm_a[4 - "
4548 "g_index1];" NL " g_output_ssbo.e[j].tt_b[i].mm_a[4] = g_input_ssbo.e[j].tt_b[i].mm_a[4];" NL " }" NL
4549 " }" NL "}";
4550 }
4551
4552 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4553 {
GetInput(std::vector<GLubyte> in_data[2])4554 virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4555 {
4556 return GetInputUBO2(in_data);
4557 }
4558 };
4559
4560 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4561 {
GetInput(std::vector<GLubyte> in_data[2])4562 virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4563 {
4564 return GetInputUBO2(in_data);
4565 }
4566 };
4567
4568 //-----------------------------------------------------------------------------
4569 // 1.12.x BasicMatrixOperationsBase
4570 //-----------------------------------------------------------------------------
4571
4572 class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4573 {
4574 GLuint m_program;
4575 GLuint m_buffer[2];
4576 GLuint m_vertex_array;
4577
4578 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected) = 0;
4579
Equal(float a,float b)4580 static bool Equal(float a, float b)
4581 {
4582 return fabsf(a - b) < 0.001f;
4583 }
4584
Setup()4585 virtual long Setup()
4586 {
4587 m_program = 0;
4588 memset(m_buffer, 0, sizeof(m_buffer));
4589 m_vertex_array = 0;
4590 return NO_ERROR;
4591 }
4592
Run()4593 virtual long Run()
4594 {
4595 if (!SupportedInVS(2))
4596 return NOT_SUPPORTED;
4597 std::vector<float> in;
4598 std::vector<float> expected;
4599 const char *glsl_vs = GetInput(in, expected);
4600
4601 m_program = CreateProgram(glsl_vs, "");
4602 glLinkProgram(m_program);
4603 if (!CheckProgram(m_program))
4604 return ERROR;
4605
4606 glGenBuffers(2, m_buffer);
4607
4608 /* output buffer */
4609 {
4610 std::vector<float> zero(expected.size());
4611 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4612 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4613 GL_STATIC_DRAW);
4614 }
4615 // input buffer
4616 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4617 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4618
4619 glGenVertexArrays(1, &m_vertex_array);
4620 glEnable(GL_RASTERIZER_DISCARD);
4621
4622 glUseProgram(m_program);
4623 glBindVertexArray(m_vertex_array);
4624 glDrawArrays(GL_POINTS, 0, 1);
4625
4626 std::vector<float> out_data(expected.size());
4627 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4628 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4629 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)(out_data.size() * sizeof(float)), &out_data[0]);
4630
4631 bool status = true;
4632 for (size_t i = 0; i < out_data.size(); ++i)
4633 {
4634 if (!Equal(expected[i], out_data[i]))
4635 {
4636 m_context.getTestContext().getLog()
4637 << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4638 << " should be " << expected[i] << tcu::TestLog::EndMessage;
4639 status = false;
4640 }
4641 }
4642 if (!status)
4643 return ERROR;
4644 return NO_ERROR;
4645 }
4646
Cleanup()4647 virtual long Cleanup()
4648 {
4649 glDisable(GL_RASTERIZER_DISCARD);
4650 glUseProgram(0);
4651 glDeleteProgram(m_program);
4652 glDeleteBuffers(2, m_buffer);
4653 glDeleteVertexArrays(1, &m_vertex_array);
4654 return NO_ERROR;
4655 }
4656 };
4657
4658 class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4659 {
4660 GLuint m_program;
4661 GLuint m_buffer[2];
4662
4663 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected) = 0;
4664
Equal(float a,float b)4665 static bool Equal(float a, float b)
4666 {
4667 return fabsf(a - b) < 0.001f;
4668 }
4669
Setup()4670 virtual long Setup()
4671 {
4672 m_program = 0;
4673 memset(m_buffer, 0, sizeof(m_buffer));
4674 return NO_ERROR;
4675 }
4676
Run()4677 virtual long Run()
4678 {
4679 std::vector<float> in;
4680 std::vector<float> expected;
4681 std::stringstream ss;
4682 ss << "layout(local_size_x = 1) in;\n" << GetInput(in, expected);
4683 m_program = CreateProgramCS(ss.str());
4684 glLinkProgram(m_program);
4685 if (!CheckProgram(m_program))
4686 return ERROR;
4687
4688 glGenBuffers(2, m_buffer);
4689
4690 /* output buffer */
4691 {
4692 std::vector<float> zero(expected.size());
4693 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4694 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4695 GL_STATIC_DRAW);
4696 }
4697 // input buffer
4698 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4699 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4700
4701 glUseProgram(m_program);
4702 glDispatchCompute(1, 1, 1);
4703
4704 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4705 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4706 float *out_data = (float *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4707 (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4708 if (!out_data)
4709 return ERROR;
4710
4711 bool status = true;
4712 for (size_t i = 0; i < expected.size(); ++i)
4713 {
4714 if (!Equal(expected[i], out_data[i]))
4715 {
4716 m_context.getTestContext().getLog()
4717 << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4718 << " should be " << expected[i] << tcu::TestLog::EndMessage;
4719 status = false;
4720 }
4721 }
4722 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4723 if (!status)
4724 return ERROR;
4725 return NO_ERROR;
4726 }
4727
Cleanup()4728 virtual long Cleanup()
4729 {
4730 glUseProgram(0);
4731 glDeleteProgram(m_program);
4732 glDeleteBuffers(2, m_buffer);
4733 return NO_ERROR;
4734 }
4735 };
4736 //-----------------------------------------------------------------------------
4737 // 1.12.1 BasicMatrixOperationsCase1
4738 //-----------------------------------------------------------------------------
GetInputM1(std::vector<float> & in,std::vector<float> & expected)4739 const char *GetInputM1(std::vector<float> &in, std::vector<float> &expected)
4740 {
4741 in.resize(8);
4742 in[0] = 1.0f;
4743 in[2] = 3.0f;
4744 in[1] = 2.0f;
4745 in[3] = 4.0f;
4746 in[4] = 1.0f;
4747 in[6] = 3.0f;
4748 in[5] = 2.0f;
4749 in[7] = 4.0f;
4750 expected.resize(4);
4751 expected[0] = 7.0f;
4752 expected[2] = 15.0f;
4753 expected[1] = 10.0f;
4754 expected[3] = 22.0f;
4755
4756 return NL "layout(std430, binding = 0) buffer Input {" NL " mat2 m0;" NL " mat2 m1;" NL "} g_input;" NL
4757 "layout(std430, binding = 1) buffer Output {" NL " mat2 m;" NL "} g_output;" NL
4758 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4759 }
4760
4761 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4762 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4763 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4764 {
4765 return GetInputM1(in, expected);
4766 }
4767 };
4768
4769 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4770 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4771 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4772 {
4773 return GetInputM1(in, expected);
4774 }
4775 };
4776
4777 //-----------------------------------------------------------------------------
4778 // 1.12.2 BasicMatrixOperationsCase2
4779 //-----------------------------------------------------------------------------
GetInputM2(std::vector<float> & in,std::vector<float> & expected)4780 const char *GetInputM2(std::vector<float> &in, std::vector<float> &expected)
4781 {
4782 in.resize(16);
4783 expected.resize(4);
4784 // mat3x2
4785 in[0] = 1.0f;
4786 in[2] = 3.0f;
4787 in[4] = 5.0f;
4788 in[1] = 2.0f;
4789 in[3] = 4.0f;
4790 in[5] = 6.0f;
4791 // mat2x3
4792 in[8] = 1.0f;
4793 in[12] = 4.0f;
4794 in[9] = 2.0f;
4795 in[13] = 5.0f;
4796 in[10] = 3.0f;
4797 in[14] = 6.0f;
4798 // mat2
4799 expected[0] = 22.0f;
4800 expected[2] = 49.0f;
4801 expected[1] = 28.0f;
4802 expected[3] = 64.0f;
4803
4804 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat3x2 m0;" NL
4805 " layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4806 " layout(column_major) mat2 m;" NL "} g_output;" NL
4807 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4808 }
4809
4810 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4811 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4812 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4813 {
4814 return GetInputM2(in, expected);
4815 }
4816 };
4817
4818 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4819 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4820 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4821 {
4822 return GetInputM2(in, expected);
4823 }
4824 };
4825
4826 //-----------------------------------------------------------------------------
4827 // 1.12.3 BasicMatrixOperationsCase3
4828 //-----------------------------------------------------------------------------
GetInputM3(std::vector<float> & in,std::vector<float> & expected)4829 const char *GetInputM3(std::vector<float> &in, std::vector<float> &expected)
4830 {
4831 in.resize(16);
4832 expected.resize(4);
4833 // row major mat3x2
4834 in[0] = 1.0f;
4835 in[1] = 3.0f;
4836 in[2] = 5.0f;
4837 in[4] = 2.0f;
4838 in[5] = 4.0f;
4839 in[6] = 6.0f;
4840 // row major mat2x3
4841 in[8] = 1.0f;
4842 in[9] = 4.0f;
4843 in[10] = 2.0f;
4844 in[11] = 5.0f;
4845 in[12] = 3.0f;
4846 in[13] = 6.0f;
4847 // row major mat2
4848 expected[0] = 22.0f;
4849 expected[1] = 49.0f;
4850 expected[2] = 28.0f;
4851 expected[3] = 64.0f;
4852
4853 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(row_major) mat3x2 m0;" NL
4854 " layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4855 " layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4856 }
4857
4858 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4859 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4860 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4861 {
4862 return GetInputM3(in, expected);
4863 }
4864 };
4865
4866 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4867 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4868 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4869 {
4870 return GetInputM3(in, expected);
4871 }
4872 };
4873
4874 //-----------------------------------------------------------------------------
4875 // 1.12.4 BasicMatrixOperationsCase4
4876 //-----------------------------------------------------------------------------
GetInputM4(std::vector<float> & in,std::vector<float> & expected)4877 const char *GetInputM4(std::vector<float> &in, std::vector<float> &expected)
4878 {
4879 in.resize(16);
4880 expected.resize(4);
4881 // column major mat3x2
4882 in[0] = 1.0f;
4883 in[2] = 3.0f;
4884 in[4] = 5.0f;
4885 in[1] = 2.0f;
4886 in[3] = 4.0f;
4887 in[5] = 6.0f;
4888 // row major mat2x3
4889 in[8] = 1.0f;
4890 in[9] = 4.0f;
4891 in[10] = 2.0f;
4892 in[11] = 5.0f;
4893 in[12] = 3.0f;
4894 in[13] = 6.0f;
4895 // column major mat2
4896 expected[0] = 13.0f;
4897 expected[1] = 16.0f;
4898 expected[2] = 37.0f;
4899 expected[3] = 46.0f;
4900
4901 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat3x2 m0;" NL
4902 " layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4903 " layout(column_major) mat2 m;" NL "} g_output;" NL
4904 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4905 }
4906
4907 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4908 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4909 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4910 {
4911 return GetInputM4(in, expected);
4912 }
4913 };
4914
4915 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4916 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4917 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4918 {
4919 return GetInputM4(in, expected);
4920 }
4921 };
4922
4923 //-----------------------------------------------------------------------------
4924 // 1.12.5 BasicMatrixOperationsCase5
4925 //-----------------------------------------------------------------------------
GetInputM5(std::vector<float> & in,std::vector<float> & expected)4926 const char *GetInputM5(std::vector<float> &in, std::vector<float> &expected)
4927 {
4928 in.resize(16);
4929 expected.resize(4);
4930 // column major mat3x2
4931 in[0] = 1.0f;
4932 in[2] = 3.0f;
4933 in[4] = 5.0f;
4934 in[1] = 2.0f;
4935 in[3] = 4.0f;
4936 in[5] = 6.0f;
4937 // row major mat2x3
4938 in[8] = 1.0f;
4939 in[9] = 4.0f;
4940 in[10] = 2.0f;
4941 in[11] = 5.0f;
4942 in[12] = 3.0f;
4943 in[13] = 6.0f;
4944 // row major mat2
4945 expected[0] = 13.0f;
4946 expected[1] = 37.0f;
4947 expected[2] = 16.0f;
4948 expected[3] = 46.0f;
4949
4950 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat3x2 m0;" NL
4951 " layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4952 " layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4953 }
4954
4955 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4956 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4957 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4958 {
4959 return GetInputM5(in, expected);
4960 }
4961 };
4962
4963 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4964 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4965 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4966 {
4967 return GetInputM5(in, expected);
4968 }
4969 };
4970
4971 //-----------------------------------------------------------------------------
4972 // 1.12.6 BasicMatrixOperationsCase6
4973 //-----------------------------------------------------------------------------
GetInputM6(std::vector<float> & in,std::vector<float> & expected)4974 const char *GetInputM6(std::vector<float> &in, std::vector<float> &expected)
4975 {
4976 in.resize(20);
4977 expected.resize(4);
4978 // row major mat3x2
4979 in[0] = 1.0f;
4980 in[1] = 3.0f;
4981 in[2] = 5.0f;
4982 in[4] = 2.0f;
4983 in[5] = 4.0f;
4984 in[6] = 6.0f;
4985 // column major mat2x3
4986 in[8] = 1.0f;
4987 in[12] = 4.0f;
4988 in[9] = 2.0f;
4989 in[13] = 5.0f;
4990 in[10] = 3.0f;
4991 in[14] = 6.0f;
4992 // column major mat2
4993 expected[0] = 22.0f;
4994 expected[1] = 28.0f;
4995 expected[2] = 49.0f;
4996 expected[3] = 64.0f;
4997
4998 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(row_major) mat3x2 m0;" NL
4999 " layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
5000 " layout(column_major) mat2 m;" NL "} g_output;" NL
5001 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
5002 }
5003
5004 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
5005 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5006 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5007 {
5008 return GetInputM6(in, expected);
5009 }
5010 };
5011
5012 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
5013 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5014 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5015 {
5016 return GetInputM6(in, expected);
5017 }
5018 };
5019 //-----------------------------------------------------------------------------
5020 // 1.12.7 BasicMatrixOperationsCase7
5021 //-----------------------------------------------------------------------------
GetInputM7(std::vector<float> & in,std::vector<float> & expected)5022 const char *GetInputM7(std::vector<float> &in, std::vector<float> &expected)
5023 {
5024 in.resize(20);
5025 expected.resize(4);
5026 // row major mat3x2
5027 in[0] = 1.0f;
5028 in[1] = 3.0f;
5029 in[2] = 5.0f;
5030 in[4] = 2.0f;
5031 in[5] = 4.0f;
5032 in[6] = 6.0f;
5033 // column major mat2x3
5034 in[8] = 1.0f;
5035 in[12] = 4.0f;
5036 in[9] = 2.0f;
5037 in[13] = 5.0f;
5038 in[10] = 3.0f;
5039 in[14] = 6.0f;
5040 // row major mat2
5041 expected[0] = 22.0f;
5042 expected[1] = 49.0f;
5043 expected[2] = 28.0f;
5044 expected[3] = 64.0f;
5045
5046 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(row_major) mat3x2 m0;" NL
5047 " layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
5048 " layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
5049 }
5050
5051 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
5052 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5053 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5054 {
5055 return GetInputM7(in, expected);
5056 }
5057 };
5058
5059 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
5060 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5061 virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5062 {
5063 return GetInputM7(in, expected);
5064 }
5065 };
5066
5067 //-----------------------------------------------------------------------------
5068 // 1.13 BasicNoBindingLayout
5069 //-----------------------------------------------------------------------------
5070 class BasicNoBindingLayout : public ShaderStorageBufferObjectBase
5071 {
5072 GLuint m_vsp, m_ppo, m_ssbo, m_vao;
5073
Setup()5074 virtual long Setup()
5075 {
5076 m_vsp = 0;
5077 glGenProgramPipelines(1, &m_ppo);
5078 glGenBuffers(1, &m_ssbo);
5079 glGenVertexArrays(1, &m_vao);
5080 return NO_ERROR;
5081 }
5082
Cleanup()5083 virtual long Cleanup()
5084 {
5085 glDisable(GL_RASTERIZER_DISCARD);
5086 glDeleteProgram(m_vsp);
5087 glDeleteProgramPipelines(1, &m_ppo);
5088 glDeleteBuffers(1, &m_ssbo);
5089 glDeleteVertexArrays(1, &m_vao);
5090 return NO_ERROR;
5091 }
5092
Run()5093 virtual long Run()
5094 {
5095 if (!SupportedInVS(3))
5096 return NOT_SUPPORTED;
5097
5098 const char *const glsl_vs = "#version 430 core" NL "layout(std430) buffer Output0 { int data; } g_output0;" NL
5099 "layout(std430) buffer Output1 { int g_output1; };" NL
5100 "layout(std430) buffer Output2 { int data; } g_output2;" NL "void main() {" NL
5101 " g_output0.data = 1;" NL " g_output1 = 2;" NL " g_output2.data = 3;" NL "}";
5102 m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
5103 if (!CheckProgram(m_vsp))
5104 return ERROR;
5105 glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
5106
5107 glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output0"), 1);
5108 glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output1"), 5);
5109 glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output2"), 7);
5110
5111 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
5112 glBufferData(GL_SHADER_STORAGE_BUFFER, 1024, NULL, GL_DYNAMIC_DRAW);
5113 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, m_ssbo, 0, 4);
5114 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 5, m_ssbo, 256, 4);
5115 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_ssbo, 512, 4);
5116
5117 glEnable(GL_RASTERIZER_DISCARD);
5118 glBindProgramPipeline(m_ppo);
5119 glBindVertexArray(m_vao);
5120 glDrawArrays(GL_POINTS, 0, 1);
5121
5122 int data;
5123 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
5124 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5125 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 4, &data);
5126 if (data != 1)
5127 return ERROR;
5128 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 256, 4, &data);
5129 if (data != 2)
5130 return ERROR;
5131 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 512, 4, &data);
5132 if (data != 3)
5133 return ERROR;
5134
5135 return NO_ERROR;
5136 }
5137 };
5138
5139 //----------------------------------------------------------------------------
5140 // 1.14 BasicReadonlyWriteonly
5141 //-----------------------------------------------------------------------------
5142 class BasicReadonlyWriteonly : public ShaderStorageBufferObjectBase
5143 {
5144 GLuint m_program;
5145 GLuint m_storage_buffer[2];
5146
Setup()5147 virtual long Setup()
5148 {
5149 m_program = 0;
5150 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5151 return NO_ERROR;
5152 }
5153
Run()5154 virtual long Run()
5155 {
5156 const char *const glsl_cs =
5157 NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Input {" NL
5158 " readonly writeonly int g_in[];" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL
5159 " int count;" NL "} g_output;" NL "void main() {" NL " g_output.count = g_in.length();" NL "}";
5160
5161 m_program = CreateProgramCS(glsl_cs);
5162 glLinkProgram(m_program);
5163 if (!CheckProgram(m_program))
5164 return ERROR;
5165
5166 glGenBuffers(2, m_storage_buffer);
5167
5168 /* Input */
5169 int input_data[] = {1, 2, 3};
5170 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5171 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(input_data), input_data, GL_STATIC_DRAW);
5172
5173 /* Output */
5174 int output_data[] = {0};
5175 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5176 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(output_data), output_data, GL_DYNAMIC_COPY);
5177
5178 glUseProgram(m_program);
5179 glDispatchCompute(1, 1, 1);
5180 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5181
5182 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5183 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
5184 if (!data)
5185 return ERROR;
5186 if (*data != DE_LENGTH_OF_ARRAY(input_data))
5187 {
5188 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer data is " << *data << " should be "
5189 << sizeof(input_data) << tcu::TestLog::EndMessage;
5190 return ERROR;
5191 }
5192 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5193 return NO_ERROR;
5194 }
5195
Cleanup()5196 virtual long Cleanup()
5197 {
5198 glUseProgram(0);
5199 glDeleteProgram(m_program);
5200 glDeleteBuffers(2, m_storage_buffer);
5201 return NO_ERROR;
5202 }
5203 };
5204
5205 //----------------------------------------------------------------------------
5206 // 1.15 BasicNameMatch
5207 //-----------------------------------------------------------------------------
5208 class BasicNameMatch : public ShaderStorageBufferObjectBase
5209 {
Run()5210 virtual long Run()
5211 {
5212 GLint blocksVS, blocksFS;
5213 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
5214 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
5215 if ((blocksVS == 0) || (blocksFS == 0))
5216 return NOT_SUPPORTED;
5217
5218 // check if link error is generated when one of matched blocks has instance name and other doesn't
5219 std::string vs1("buffer Buf { float x; };\n"
5220 "void main() {\n"
5221 " gl_Position = vec4(x);\n"
5222 "}");
5223 std::string fs1("buffer Buf { float x; } b;\n"
5224 "out vec4 color;\n"
5225 "void main() {\n"
5226 " color = vec4(b.x);\n"
5227 "}");
5228 if (Link(vs1, fs1))
5229 {
5230 m_context.getTestContext().getLog()
5231 << tcu::TestLog::Message << "Linking should fail." << tcu::TestLog::EndMessage;
5232 return ERROR;
5233 }
5234
5235 // check if linking succeeds when both matched blocks are lacking an instance name
5236 std::string vs2("buffer Buf { float x; };\n"
5237 "void main() {\n"
5238 " gl_Position = vec4(x);\n"
5239 "}");
5240 std::string fs2("buffer Buf { float x; };\n"
5241 "out vec4 color;\n"
5242 "void main() {\n"
5243 " color = vec4(x);\n"
5244 "}");
5245 if (!Link(vs2, fs2))
5246 {
5247 m_context.getTestContext().getLog()
5248 << tcu::TestLog::Message << "Linking should succeed." << tcu::TestLog::EndMessage;
5249 return ERROR;
5250 }
5251
5252 // check if linking succeeds when both matched blocks have different instance names
5253 std::string vs3("buffer Buf { float x; } a;\n"
5254 "void main() {\n"
5255 " gl_Position = vec4(a.x);\n"
5256 "}");
5257 std::string fs3("buffer Buf { float x; } b;\n"
5258 "out vec4 color;\n"
5259 "void main() {\n"
5260 " color = vec4(b.x);\n"
5261 "}");
5262 if (!Link(vs3, fs3))
5263 {
5264 m_context.getTestContext().getLog()
5265 << tcu::TestLog::Message << "Linking should succeed." << tcu::TestLog::EndMessage;
5266 return ERROR;
5267 }
5268
5269 return NO_ERROR;
5270 }
5271
Link(const std::string & vs,const std::string & fs)5272 bool Link(const std::string &vs, const std::string &fs)
5273 {
5274 GLuint program = CreateProgram(vs, fs);
5275 glLinkProgram(program);
5276 GLint status;
5277 glGetProgramiv(program, GL_LINK_STATUS, &status);
5278 glDeleteProgram(program);
5279 return (status == GL_TRUE);
5280 }
5281 };
5282
5283 //-----------------------------------------------------------------------------
5284 // 2.1 AdvancedSwitchBuffers
5285 //-----------------------------------------------------------------------------
5286 class AdvancedSwitchBuffers : public ShaderStorageBufferObjectBase
5287 {
5288 GLuint m_program;
5289 GLuint m_storage_buffer[5];
5290 GLuint m_vertex_array;
5291 GLuint m_fbo, m_rt;
5292
Setup()5293 virtual long Setup()
5294 {
5295 m_program = 0;
5296 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5297 m_vertex_array = 0;
5298 glGenFramebuffers(1, &m_fbo);
5299 glGenTextures(1, &m_rt);
5300 return NO_ERROR;
5301 }
5302
Run()5303 virtual long Run()
5304 {
5305 if (!SupportedInVS(1))
5306 return NOT_SUPPORTED;
5307
5308 const char *const glsl_vs =
5309 NL "struct VertexData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL
5310 "layout(binding = 0, std430) buffer Input {" NL " VertexData vertex[];" NL "} g_vs_in;" NL
5311 "out StageData {" NL " vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5312 " gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5313 " g_vs_out.color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5314
5315 const char *const glsl_fs =
5316 NL "in StageData {" NL " vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5317 "void main() {" NL " g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5318 m_program = CreateProgram(glsl_vs, glsl_fs);
5319 glLinkProgram(m_program);
5320 if (!CheckProgram(m_program))
5321 return ERROR;
5322
5323 glGenBuffers(5, m_storage_buffer);
5324
5325 /* left, bottom, red quad */
5326 {
5327 const float data[] = {-0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5328 0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5329 -0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5330 0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
5331 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5332 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5333 }
5334 /* right, bottom, green quad */
5335 {
5336 const float data[] = {-0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5337 0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5338 -0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5339 0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
5340 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5341 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5342 }
5343 /* left, top, blue quad */
5344 {
5345 const float data[] = {-0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5346 0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5347 -0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5348 0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
5349 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5350 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5351 }
5352 /* right, top, yellow quad */
5353 {
5354 const float data[] = {-0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5355 0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5356 -0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5357 0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f};
5358 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5359 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5360 }
5361
5362 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5363 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
5364
5365 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5366 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(float) * 32);
5367 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5368 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 32, sizeof(float) * 32);
5369 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5370 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * sizeof(float) * 32,
5371 sizeof(float) * 32);
5372 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5373 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * sizeof(float) * 32,
5374 sizeof(float) * 32);
5375
5376 glBindTexture(GL_TEXTURE_2D, m_rt);
5377 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5378 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5379 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5380 glBindTexture(GL_TEXTURE_2D, 0);
5381 glViewport(0, 0, 100, 100);
5382 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5383 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5384
5385 glGenVertexArrays(1, &m_vertex_array);
5386
5387 glUseProgram(m_program);
5388 glBindVertexArray(m_vertex_array);
5389
5390 glClear(GL_COLOR_BUFFER_BIT);
5391 for (int i = 0; i < 4; ++i)
5392 {
5393 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5394 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5395 }
5396 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5397 {
5398 return ERROR;
5399 }
5400
5401 glClear(GL_COLOR_BUFFER_BIT);
5402 for (int i = 0; i < 4; ++i)
5403 {
5404 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * sizeof(float) * 32,
5405 sizeof(float) * 32);
5406 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
5407 }
5408 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5409 {
5410 return ERROR;
5411 }
5412
5413 return NO_ERROR;
5414 }
5415
Cleanup()5416 virtual long Cleanup()
5417 {
5418 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5419 glUseProgram(0);
5420 glDeleteProgram(m_program);
5421 glDeleteBuffers(5, m_storage_buffer);
5422 glDeleteVertexArrays(1, &m_vertex_array);
5423 glDeleteFramebuffers(1, &m_fbo);
5424 glDeleteTextures(1, &m_rt);
5425 return NO_ERROR;
5426 }
5427 };
5428
5429 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5430 {
5431 GLuint m_program;
5432 GLuint m_storage_buffer[6];
5433
Setup()5434 virtual long Setup()
5435 {
5436 m_program = 0;
5437 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5438 return NO_ERROR;
5439 }
5440
Run()5441 virtual long Run()
5442 {
5443 const char *const glsl_cs =
5444 NL "layout(local_size_x = 1) in;" NL "layout(binding = 0, std430) buffer Input {" NL " uint cookie[4];" NL
5445 "} g_in;" NL "layout(binding = 1, std430) buffer Output {" NL " uvec4 digest;" NL "} ;" NL
5446 "void main() {" NL " switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5447 " case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5448 " case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5449 " case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5450 " case 0xff000000u: digest.w = 0x000000ffu; break;" NL " }" NL "}";
5451 m_program = CreateProgramCS(glsl_cs);
5452 glLinkProgram(m_program);
5453 if (!CheckProgram(m_program))
5454 return ERROR;
5455
5456 glGenBuffers(6, m_storage_buffer);
5457
5458 const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22};
5459 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5460 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5461 const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0};
5462 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5463 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5464 const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0};
5465 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5466 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5467 const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0};
5468 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5469 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5470
5471 GLint alignment;
5472 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
5473 GLint offset = static_cast<GLint>(sizeof(data0) > (GLuint)alignment ? sizeof(data0) : alignment);
5474 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5475 glBufferData(GL_SHADER_STORAGE_BUFFER, offset * 4, NULL, GL_STATIC_DRAW);
5476
5477 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5478 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(data0));
5479 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5480 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, offset, sizeof(data0));
5481 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5482 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * offset, sizeof(data0));
5483 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5484 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * offset, sizeof(data0));
5485
5486 const GLubyte data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5487 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[5]);
5488 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5489
5490 glUseProgram(m_program);
5491 for (int i = 0; i < 4; ++i)
5492 {
5493 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5494 glDispatchCompute(1, 1, 1);
5495 }
5496 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5497 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5498 GLuint *out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5499 if (!out_data)
5500 return ERROR;
5501 GLuint expected[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
5502 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5503 out_data[3] != expected[3])
5504 {
5505 m_context.getTestContext().getLog()
5506 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5507 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5508 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5509 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5510 return ERROR;
5511 }
5512 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5513 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5514
5515 for (int i = 0; i < 4; ++i)
5516 {
5517 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5518 glDispatchCompute(1, 1, 1);
5519 }
5520 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5521 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5522 out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5523 if (!out_data)
5524 return ERROR;
5525 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5526 out_data[3] != expected[3])
5527 {
5528 m_context.getTestContext().getLog()
5529 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5530 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5531 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5532 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5533 return ERROR;
5534 }
5535
5536 return NO_ERROR;
5537 }
5538
Cleanup()5539 virtual long Cleanup()
5540 {
5541 glUseProgram(0);
5542 glDeleteProgram(m_program);
5543 glDeleteBuffers(6, m_storage_buffer);
5544 return NO_ERROR;
5545 }
5546 };
5547 //-----------------------------------------------------------------------------
5548 // 2.2 AdvancedSwitchPrograms
5549 //-----------------------------------------------------------------------------
5550
5551 class AdvancedSwitchPrograms : public ShaderStorageBufferObjectBase
5552 {
5553 GLuint m_program[4];
5554 GLuint m_storage_buffer[4];
5555 GLuint m_vertex_array;
5556 GLuint m_fbo, m_rt;
5557
GenSource(int binding)5558 std::string GenSource(int binding)
5559 {
5560 std::stringstream ss;
5561 ss << NL "struct VertexData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL "layout(binding = "
5562 << binding
5563 << ", std430) buffer Input {" NL " VertexData vertex[];" NL "} g_vs_in;" NL "out StageData {" NL
5564 " vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5565 " gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5566 " g_vs_out.color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5567 return ss.str();
5568 }
5569
Setup()5570 virtual long Setup()
5571 {
5572 memset(m_program, 0, sizeof(m_program));
5573 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5574 m_vertex_array = 0;
5575 glGenFramebuffers(1, &m_fbo);
5576 glGenTextures(1, &m_rt);
5577 return NO_ERROR;
5578 }
5579
Run()5580 virtual long Run()
5581 {
5582 if (!SupportedInVS(1))
5583 return NOT_SUPPORTED;
5584
5585 const char *const glsl_fs =
5586 NL "in StageData {" NL " vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5587 "void main() {" NL " g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5588 for (int i = 0; i < 4; ++i)
5589 {
5590 m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5591 glLinkProgram(m_program[i]);
5592 if (!CheckProgram(m_program[i]))
5593 return ERROR;
5594 }
5595
5596 glGenBuffers(4, m_storage_buffer);
5597
5598 /* left, bottom, red quad */
5599 {
5600 const float data[] = {-0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5601 0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5602 -0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5603 0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
5604 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5605 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5606 }
5607 /* right, bottom, green quad */
5608 {
5609 const float data[] = {-0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5610 0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5611 -0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5612 0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
5613 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5614 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5615 }
5616 /* left, top, blue quad */
5617 {
5618 const float data[] = {-0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5619 0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5620 -0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5621 0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
5622 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5623 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5624 }
5625 /* right, top, yellow quad */
5626 {
5627 const float data[] = {-0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5628 0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5629 -0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5630 0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f};
5631 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5632 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5633 }
5634
5635 glBindTexture(GL_TEXTURE_2D, m_rt);
5636 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5637 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5638 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5639 glBindTexture(GL_TEXTURE_2D, 0);
5640 glViewport(0, 0, 100, 100);
5641 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5642 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5643
5644 glGenVertexArrays(1, &m_vertex_array);
5645 glBindVertexArray(m_vertex_array);
5646
5647 glClear(GL_COLOR_BUFFER_BIT);
5648 for (int i = 0; i < 4; ++i)
5649 {
5650 glUseProgram(m_program[i]);
5651 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5652 }
5653 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5654 {
5655 return ERROR;
5656 }
5657
5658 glClear(GL_COLOR_BUFFER_BIT);
5659 glShaderStorageBlockBinding(m_program[0], 0, 3);
5660 glUseProgram(m_program[0]);
5661 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5662 if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(1, 1, 0), vec3(0)))
5663 {
5664 return ERROR;
5665 }
5666
5667 glClear(GL_COLOR_BUFFER_BIT);
5668 glShaderStorageBlockBinding(m_program[3], 0, 0);
5669 glUseProgram(m_program[3]);
5670 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5671 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0), vec3(0), vec3(0)))
5672 {
5673 return ERROR;
5674 }
5675
5676 return NO_ERROR;
5677 }
5678
Cleanup()5679 virtual long Cleanup()
5680 {
5681 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5682 glUseProgram(0);
5683 for (int i = 0; i < 4; ++i)
5684 glDeleteProgram(m_program[i]);
5685 glDeleteBuffers(4, m_storage_buffer);
5686 glDeleteVertexArrays(1, &m_vertex_array);
5687 glDeleteFramebuffers(1, &m_fbo);
5688 glDeleteTextures(1, &m_rt);
5689 return NO_ERROR;
5690 }
5691 };
5692
5693 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5694 {
5695 GLuint m_program[4];
5696 GLuint m_storage_buffer[5];
5697
Setup()5698 virtual long Setup()
5699 {
5700 memset(m_program, 0, sizeof(m_program));
5701 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5702 return NO_ERROR;
5703 }
5704
GenSource(int binding)5705 std::string GenSource(int binding)
5706 {
5707 std::stringstream ss;
5708 ss << NL "layout(local_size_x = 1) in;" NL "layout(binding = " << binding
5709 << ", std430) buffer Input {" NL " uint cookie[4];" NL "} g_in;" NL
5710 "layout(binding = 0, std430) buffer Output {" NL " uvec4 digest;" NL "} ;" NL "void main() {" NL
5711 " switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5712 " case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5713 " case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5714 " case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5715 " case 0xff000000u: digest.w = 0x000000ffu; break;" NL " }" NL "}";
5716 return ss.str();
5717 }
5718
Run()5719 virtual long Run()
5720 {
5721 for (int i = 0; i < 4; ++i)
5722 {
5723 m_program[i] = CreateProgramCS(GenSource(i + 1));
5724 glLinkProgram(m_program[i]);
5725 if (!CheckProgram(m_program[i]))
5726 return ERROR;
5727 }
5728
5729 glGenBuffers(5, m_storage_buffer);
5730
5731 const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22};
5732 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5733 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5734 const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0};
5735 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5736 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5737 const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0};
5738 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5739 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5740 const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0};
5741 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5742 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5743
5744 const GLubyte data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5745 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5746 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5747
5748 for (int i = 0; i < 4; ++i)
5749 {
5750 glUseProgram(m_program[i]);
5751 glDispatchCompute(1, 1, 1);
5752 }
5753 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5754 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5755 GLuint *out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5756 if (!out_data)
5757 return ERROR;
5758 GLuint expected[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
5759 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5760 out_data[3] != expected[3])
5761 {
5762 m_context.getTestContext().getLog()
5763 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5764 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5765 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5766 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5767 return ERROR;
5768 }
5769 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5770
5771 return NO_ERROR;
5772 }
5773
Cleanup()5774 virtual long Cleanup()
5775 {
5776 glUseProgram(0);
5777 for (int i = 0; i < 4; ++i)
5778 glDeleteProgram(m_program[i]);
5779 glDeleteBuffers(5, m_storage_buffer);
5780 return NO_ERROR;
5781 }
5782 };
5783 //-----------------------------------------------------------------------------
5784 // 2.3.1 AdvancedWriteFragment
5785 //-----------------------------------------------------------------------------
5786
5787 class AdvancedWriteFragment : public ShaderStorageBufferObjectBase
5788 {
5789 GLuint m_program[2];
5790 GLuint m_storage_buffer;
5791 GLuint m_counter_buffer;
5792 GLuint m_attribless_vertex_array;
5793 GLuint m_draw_vertex_array;
5794 GLuint m_fbo, m_rt;
5795
Setup()5796 virtual long Setup()
5797 {
5798 memset(m_program, 0, sizeof(m_program));
5799 m_storage_buffer = 0;
5800 m_counter_buffer = 0;
5801 m_attribless_vertex_array = 0;
5802 m_draw_vertex_array = 0;
5803 glGenFramebuffers(1, &m_fbo);
5804 glGenTextures(1, &m_rt);
5805 return NO_ERROR;
5806 }
5807
Run()5808 virtual long Run()
5809 {
5810 const char *const glsl_vs0 = NL
5811 "out StageData {" NL " vec2 position;" NL " vec3 color;" NL "} g_vs_out;" NL
5812 "const vec2 g_quad[4] = vec2[4](vec2(-0.4, -0.4), vec2(0.4, -0.4), vec2(-0.4, 0.4), vec2(0.4, 0.4));" NL
5813 "const vec2 g_offset[4] = vec2[4](vec2(-0.5, -0.5), vec2(0.5, -0.5), vec2(-0.5, 0.5), vec2(0.5, 0.5));" NL
5814 "const vec3 g_color[4] = vec3[4](vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0));" NL
5815 "void main() {" NL " vec2 pos = g_quad[gl_VertexID] + g_offset[gl_InstanceID];" NL
5816 " gl_Position = vec4(pos, 0, 1);" NL " g_vs_out.position = pos;" NL
5817 " g_vs_out.color = g_color[gl_InstanceID];" NL "}";
5818
5819 const char *const glsl_fs0 =
5820 NL "in StageData {" NL " vec2 position;" NL " vec3 color;" NL "} g_fs_in;" NL
5821 "layout(location = 0) out vec4 g_fs_out;" NL "struct FragmentData {" NL " vec2 position;" NL
5822 " vec3 color;" NL "};" NL "layout(std430, binding = 3) buffer Output {" NL
5823 " FragmentData g_fragment[];" NL "};" NL "uniform uint g_max_fragment_count = 100 * 100;" NL
5824 "layout(binding = 2, offset = 0) uniform atomic_uint g_fragment_counter;" NL "void main() {" NL
5825 " uint fragment_number = atomicCounterIncrement(g_fragment_counter);" NL
5826 " if (fragment_number < g_max_fragment_count) {" NL
5827 " g_fragment[fragment_number].position = g_fs_in.position;" NL
5828 " g_fragment[fragment_number].color = g_fs_in.color;" NL " }" NL
5829 " g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5830
5831 m_program[0] = CreateProgram(glsl_vs0, glsl_fs0);
5832 glLinkProgram(m_program[0]);
5833 if (!CheckProgram(m_program[0]))
5834 return ERROR;
5835
5836 const char *const glsl_vs1 =
5837 NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5838 "out StageData {" NL " vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5839 " gl_Position = vec4(g_in_position.xy, 0, 1);" NL " g_vs_out.color = g_in_color.rgb;" NL "}";
5840
5841 const char *const glsl_fs1 =
5842 NL "in StageData {" NL " vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5843 "void main() {" NL " g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5844
5845 m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5846 glLinkProgram(m_program[1]);
5847 if (!CheckProgram(m_program[1]))
5848 return ERROR;
5849
5850 // The first pass renders four squares on-screen, and writes a
5851 // record to the SSBO for each fragment processed. The rectangles
5852 // will be 40x40 when using a 100x100 viewport, so we expect 1600
5853 // pixels per rectangle or 6400 pixels total. Size the SSBO
5854 // accordingly, and render the second pass (sourcing the SSBO as a
5855 // vertex buffer) with an identical number of points. If we have
5856 // a larger buffer and draw more points on the second pass, those
5857 // may overwrite "real" points using garbage position/color.
5858 int expectedPixels = 6400;
5859
5860 glGenBuffers(1, &m_storage_buffer);
5861 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5862 glBufferData(GL_SHADER_STORAGE_BUFFER, expectedPixels * 32, NULL, GL_DYNAMIC_DRAW);
5863
5864 glGenBuffers(1, &m_counter_buffer);
5865 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
5866 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5867 uvec4 zero(0);
5868 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5869
5870 glBindTexture(GL_TEXTURE_2D, m_rt);
5871 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5872 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5873 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5874 glBindTexture(GL_TEXTURE_2D, 0);
5875 glViewport(0, 0, 100, 100);
5876 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5877 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5878
5879 glGenVertexArrays(1, &m_attribless_vertex_array);
5880
5881 glGenVertexArrays(1, &m_draw_vertex_array);
5882 glBindVertexArray(m_draw_vertex_array);
5883 glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5884 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5885 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(16));
5886 glBindBuffer(GL_ARRAY_BUFFER, 0);
5887 glEnableVertexAttribArray(0);
5888 glEnableVertexAttribArray(1);
5889 glBindVertexArray(0);
5890
5891 glClear(GL_COLOR_BUFFER_BIT);
5892 glUseProgram(m_program[0]);
5893 glUniform1ui(glGetUniformLocation(m_program[0], "g_max_fragment_count"), expectedPixels);
5894 glBindVertexArray(m_attribless_vertex_array);
5895 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5896
5897 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5898 {
5899 return ERROR;
5900 }
5901
5902 glClear(GL_COLOR_BUFFER_BIT);
5903 glUseProgram(m_program[1]);
5904 glBindVertexArray(m_draw_vertex_array);
5905 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5906 glDrawArrays(GL_POINTS, 0, expectedPixels);
5907 int bad_pixels;
5908
5909 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5910 bad_pixels > 2)
5911 {
5912 return ERROR;
5913 }
5914
5915 return NO_ERROR;
5916 }
5917
Cleanup()5918 virtual long Cleanup()
5919 {
5920 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5921 glUseProgram(0);
5922 for (int i = 0; i < 2; ++i)
5923 glDeleteProgram(m_program[i]);
5924 glDeleteBuffers(1, &m_storage_buffer);
5925 glDeleteBuffers(1, &m_counter_buffer);
5926 glDeleteVertexArrays(1, &m_attribless_vertex_array);
5927 glDeleteVertexArrays(1, &m_draw_vertex_array);
5928 glDeleteFramebuffers(1, &m_fbo);
5929 glDeleteTextures(1, &m_rt);
5930 return NO_ERROR;
5931 }
5932 };
5933
5934 //-----------------------------------------------------------------------------
5935 // 2.3.2 AdvancedWriteGeometry
5936 //-----------------------------------------------------------------------------
5937 class AdvancedWriteGeometry : public ShaderStorageBufferObjectBase
5938 {
5939 GLuint m_program[2];
5940 GLuint m_storage_buffer;
5941 GLuint m_vertex_array[2];
5942 GLuint m_vertex_buffer;
5943
Setup()5944 virtual long Setup()
5945 {
5946 memset(m_program, 0, sizeof(m_program));
5947 m_storage_buffer = 0;
5948 memset(m_vertex_array, 0, sizeof(m_vertex_array));
5949 m_vertex_buffer = 0;
5950 return NO_ERROR;
5951 }
5952
Run()5953 virtual long Run()
5954 {
5955 if (!SupportedInGS(1))
5956 return NOT_SUPPORTED;
5957
5958 const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
5959 " gl_Position = g_in_position;" NL "}";
5960
5961 const char *const glsl_gs =
5962 NL "layout(triangles) in;" NL "layout(triangle_strip, max_vertices = 3) out;" NL
5963 "layout(std430, binding = 1) buffer OutputBuffer {" NL " vec4 g_output_buffer[];" NL "};" NL
5964 "void main() {" NL " for (int i = 0; i < 3; ++i) {" NL
5965 " const int idx = gl_PrimitiveIDIn * 3 + i;" NL " g_output_buffer[idx] = gl_in[i].gl_Position;" NL
5966 " gl_Position = g_output_buffer[idx];" NL " EmitVertex();" NL " }" NL "}";
5967
5968 const char *const glsl_fs =
5969 NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL " g_fs_out = vec4(0, 1, 0, 1);" NL "}";
5970
5971 m_program[0] = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
5972 glLinkProgram(m_program[0]);
5973 if (!CheckProgram(m_program[0]))
5974 return ERROR;
5975
5976 m_program[1] = CreateProgram(glsl_vs, glsl_fs);
5977 glLinkProgram(m_program[1]);
5978 if (!CheckProgram(m_program[1]))
5979 return ERROR;
5980
5981 /* vertex buffer */
5982 {
5983 const float data[] = {-1, -1, 1, -1, -1, 1, 1, 1};
5984 glGenBuffers(1, &m_vertex_buffer);
5985 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5986 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5987 glBindBuffer(GL_ARRAY_BUFFER, 0);
5988 }
5989
5990 glGenBuffers(1, &m_storage_buffer);
5991 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer);
5992 glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
5993
5994 glGenVertexArrays(2, m_vertex_array);
5995
5996 glBindVertexArray(m_vertex_array[0]);
5997 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5998 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5999 glBindBuffer(GL_ARRAY_BUFFER, 0);
6000 glEnableVertexAttribArray(0);
6001 glBindVertexArray(0);
6002
6003 glBindVertexArray(m_vertex_array[1]);
6004 glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
6005 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
6006 glBindBuffer(GL_ARRAY_BUFFER, 0);
6007 glEnableVertexAttribArray(0);
6008 glBindVertexArray(0);
6009
6010 glClear(GL_COLOR_BUFFER_BIT);
6011 glUseProgram(m_program[0]);
6012 glBindVertexArray(m_vertex_array[0]);
6013 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6014 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6015 {
6016 return ERROR;
6017 }
6018
6019 glClear(GL_COLOR_BUFFER_BIT);
6020 glUseProgram(m_program[1]);
6021 glBindVertexArray(m_vertex_array[1]);
6022 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
6023 glDrawArrays(GL_TRIANGLES, 0, 6);
6024 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6025 {
6026 return ERROR;
6027 }
6028
6029 return NO_ERROR;
6030 }
6031
Cleanup()6032 virtual long Cleanup()
6033 {
6034 glUseProgram(0);
6035 for (int i = 0; i < 2; ++i)
6036 glDeleteProgram(m_program[i]);
6037 glDeleteBuffers(1, &m_storage_buffer);
6038 glDeleteBuffers(1, &m_vertex_buffer);
6039 glDeleteVertexArrays(2, m_vertex_array);
6040 return NO_ERROR;
6041 }
6042 };
6043 //-----------------------------------------------------------------------------
6044 // 2.3.3 AdvancedWriteTessellation
6045 //-----------------------------------------------------------------------------
6046
6047 class AdvancedWriteTessellation : public ShaderStorageBufferObjectBase
6048 {
6049 GLuint m_program;
6050 GLuint m_storage_buffer;
6051 GLuint m_counter_buffer;
6052 GLuint m_vertex_array;
6053 GLuint m_vertex_buffer;
6054
Setup()6055 virtual long Setup()
6056 {
6057 m_program = 0;
6058 m_storage_buffer = 0;
6059 m_counter_buffer = 0;
6060 m_vertex_array = 0;
6061 m_vertex_buffer = 0;
6062 return NO_ERROR;
6063 }
6064
Run()6065 virtual long Run()
6066 {
6067 if (!SupportedInTES(1))
6068 return NOT_SUPPORTED;
6069
6070 const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
6071 " gl_Position = g_in_position;" NL "}";
6072
6073 const char *const glsl_tes =
6074 NL "layout(quads) in;" NL "struct VertexData {" NL " int valid;" NL " vec4 position;" NL "};" NL
6075 "layout(std430, binding = 2) buffer VertexBuffer {" NL " VertexData g_vertex_buffer[];" NL "};" NL
6076 "layout(binding = 2, offset = 0) uniform atomic_uint g_vertex_counter;" NL "void main() {" NL
6077 " const uint idx = atomicCounterIncrement(g_vertex_counter);" NL
6078 " vec4 p0 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);" NL
6079 " vec4 p1 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);" NL
6080 " vec4 p = mix(p0, p1, gl_TessCoord.y);" NL " g_vertex_buffer[idx].position = p;" NL
6081 " g_vertex_buffer[idx].valid = 1;" NL " gl_Position = g_vertex_buffer[idx].position;" NL "}";
6082
6083 const char *const glsl_fs =
6084 NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL " g_fs_out = vec4(0, 1, 0, 1);" NL "}";
6085
6086 m_program = CreateProgram(glsl_vs, "", glsl_tes, "", glsl_fs);
6087 glLinkProgram(m_program);
6088 if (!CheckProgram(m_program))
6089 return ERROR;
6090
6091 /* vertex buffer */
6092 {
6093 const float data[] = {-1, -1, 1, -1, 1, 1, -1, 1};
6094 glGenBuffers(1, &m_vertex_buffer);
6095 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6096 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6097 glBindBuffer(GL_ARRAY_BUFFER, 0);
6098 }
6099
6100 glGenBuffers(1, &m_counter_buffer);
6101 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
6102 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
6103 uvec4 zero;
6104 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
6105
6106 struct
6107 {
6108 int valid;
6109 int pad[3];
6110 vec4 position;
6111 } data[6];
6112 deMemset((void *)data, 0, sizeof(data));
6113 glGenBuffers(1, &m_storage_buffer);
6114 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer);
6115 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6116
6117 glGenVertexArrays(1, &m_vertex_array);
6118 glBindVertexArray(m_vertex_array);
6119 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6120 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6121 glBindBuffer(GL_ARRAY_BUFFER, 0);
6122 glEnableVertexAttribArray(0);
6123 glBindVertexArray(0);
6124
6125 glClear(GL_COLOR_BUFFER_BIT);
6126 glUseProgram(m_program);
6127 glBindVertexArray(m_vertex_array);
6128 glPatchParameteri(GL_PATCH_VERTICES, 4);
6129 glDrawArrays(GL_PATCHES, 0, 4);
6130 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6131 {
6132 return ERROR;
6133 }
6134
6135 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6136 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6137 for (int i = 0; i < 4; ++i)
6138 {
6139 vec4 p = data[i].position;
6140 if (p[2] != 0.0f || p[3] != 1.0f)
6141 return ERROR;
6142 if (data[i].valid != 1)
6143 return ERROR;
6144 }
6145
6146 return NO_ERROR;
6147 }
6148
Cleanup()6149 virtual long Cleanup()
6150 {
6151 glPatchParameteri(GL_PATCH_VERTICES, 3);
6152 glUseProgram(0);
6153 glDeleteProgram(m_program);
6154 glDeleteBuffers(1, &m_storage_buffer);
6155 glDeleteBuffers(1, &m_counter_buffer);
6156 glDeleteBuffers(1, &m_vertex_buffer);
6157 glDeleteVertexArrays(1, &m_vertex_array);
6158 return NO_ERROR;
6159 }
6160 };
6161
6162 //-----------------------------------------------------------------------------
6163 // 2.4.1 AdvancedIndirectAddressingCase1
6164 //-----------------------------------------------------------------------------
6165 class AdvancedIndirectAddressingCase1 : public ShaderStorageBufferObjectBase
6166 {
6167 GLuint m_program;
6168 GLuint m_storage_buffer[4];
6169 GLuint m_vertex_array;
6170 GLuint m_vertex_buffer;
6171 GLuint m_fbo, m_rt;
6172
Setup()6173 virtual long Setup()
6174 {
6175 m_program = 0;
6176 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6177 m_vertex_array = 0;
6178 m_vertex_buffer = 0;
6179 glGenFramebuffers(1, &m_fbo);
6180 glGenTextures(1, &m_rt);
6181 return NO_ERROR;
6182 }
6183
Run()6184 virtual long Run()
6185 {
6186 if (!SupportedInVS(4))
6187 return NOT_SUPPORTED;
6188
6189 const char *const glsl_vs =
6190 NL "layout(location = 0) in vec2 g_in_position;" NL "struct Material {" NL " vec3 color;" NL "};" NL
6191 "layout(binding = 0, std430) buffer MaterialBuffer {" NL " Material g_material[4];" NL "};" NL
6192 "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL " uint g_material_id[4];" NL "};" NL
6193 "layout(binding = 2, std430) buffer TransformBuffer {" NL " vec2 translation[4];" NL "} g_transform;" NL
6194 "layout(binding = 3, std430) buffer TransformIDBuffer {" NL " uint g_transform_id[4];" NL "};" NL
6195 "out StageData {" NL " vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
6196 " const uint mid = g_material_id[gl_InstanceID];" NL " Material m = g_material[mid];" NL
6197 " const uint tid = g_transform_id[gl_InstanceID];" NL " vec2 t = g_transform.translation[tid];" NL
6198 " gl_Position = vec4(g_in_position + t, 0, 1);" NL " g_vs_out.color = m.color;" NL "}";
6199
6200 const char *const glsl_fs =
6201 NL "in StageData {" NL " vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
6202 "void main() {" NL " g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
6203
6204 m_program = CreateProgram(glsl_vs, glsl_fs);
6205 glLinkProgram(m_program);
6206 if (!CheckProgram(m_program))
6207 return ERROR;
6208
6209 glGenBuffers(4, m_storage_buffer);
6210
6211 /* material buffer */
6212 {
6213 const float data[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
6214 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
6215 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6216 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6217 }
6218 /* material id buffer */
6219 {
6220 const unsigned int data[] = {2, 3, 0, 2};
6221 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6222 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6223 }
6224 /* transform buffer */
6225 {
6226 const float data[] = {-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
6227 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6228 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6229 }
6230 /* transform id buffer */
6231 {
6232 const unsigned int data[] = {3, 1, 0, 2};
6233 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6234 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6235 }
6236
6237 /* vertex buffer */
6238 {
6239 const float data[] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
6240 glGenBuffers(1, &m_vertex_buffer);
6241 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6242 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6243 glBindBuffer(GL_ARRAY_BUFFER, 0);
6244 }
6245
6246 glBindTexture(GL_TEXTURE_2D, m_rt);
6247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6249 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6250 glBindTexture(GL_TEXTURE_2D, 0);
6251 glViewport(0, 0, 100, 100);
6252 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6253 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
6254
6255 glGenVertexArrays(1, &m_vertex_array);
6256 glBindVertexArray(m_vertex_array);
6257 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6258 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6259 glBindBuffer(GL_ARRAY_BUFFER, 0);
6260 glEnableVertexAttribArray(0);
6261 glBindVertexArray(0);
6262
6263 glClear(GL_COLOR_BUFFER_BIT);
6264 glUseProgram(m_program);
6265 glBindVertexArray(m_vertex_array);
6266 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
6267
6268 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 1)))
6269 {
6270 return ERROR;
6271 }
6272
6273 /* update material id buffer with BufferSubData */
6274 {
6275 const unsigned int data[] = {3, 2, 1, 0};
6276 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6277 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6278 }
6279
6280 /* update transform id buffer with BufferData */
6281 {
6282 const unsigned int data[] = {0, 1, 2, 3};
6283 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6284 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6285 }
6286
6287 glClear(GL_COLOR_BUFFER_BIT);
6288 glUseProgram(m_program);
6289 glBindVertexArray(m_vertex_array);
6290 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
6291 if (!ValidateWindow4Quads(vec3(1, 1, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0)))
6292 {
6293 return ERROR;
6294 }
6295
6296 return NO_ERROR;
6297 }
6298
Cleanup()6299 virtual long Cleanup()
6300 {
6301 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6302 glUseProgram(0);
6303 glDeleteProgram(m_program);
6304 glDeleteBuffers(4, m_storage_buffer);
6305 glDeleteBuffers(1, &m_vertex_buffer);
6306 glDeleteVertexArrays(1, &m_vertex_array);
6307 glDeleteFramebuffers(1, &m_fbo);
6308 glDeleteTextures(1, &m_rt);
6309 return NO_ERROR;
6310 }
6311 };
6312
6313 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
6314 {
6315 GLuint m_program;
6316 GLuint m_storage_buffer[5];
6317
Setup()6318 virtual long Setup()
6319 {
6320 m_program = 0;
6321 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6322 return NO_ERROR;
6323 }
6324
Run()6325 virtual long Run()
6326 {
6327 bool status = true;
6328
6329 const char *const glsl_cs =
6330 NL "layout(local_size_x = 2, local_size_y = 2) in;" NL "struct Material {" NL " vec3 color;" NL "};" NL
6331 "layout(binding = 0, std430) buffer MaterialBuffer {" NL " Material g_material[4];" NL "};" NL
6332 "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL " uint g_material_id[4];" NL "};" NL
6333 "layout(binding = 2, std430) buffer TransformBuffer {" NL " vec2 translation[4];" NL "} g_transform;" NL
6334 "layout(binding = 3, std430) buffer TransformIDBuffer {" NL " uint g_transform_id[4];" NL "};" NL
6335 "layout(binding = 4, std430) buffer OutputBuffer {" NL " vec3 color[16];" NL " vec2 pos[16];" NL
6336 "};" NL "vec2 g_in_position[4] = vec2[4](vec2(-0.4f, -0.4f), vec2(0.4f, -0.4f), vec2(-0.4f, 0.4f), "
6337 "vec2(0.4f, 0.4f));" NL "void main() {" NL " uint mid = g_material_id[gl_WorkGroupID.x];" NL
6338 " Material m = g_material[mid];" NL " uint tid = g_transform_id[gl_WorkGroupID.x];" NL
6339 " vec2 t = g_transform.translation[tid];" NL
6340 " pos[gl_LocalInvocationIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x * gl_WorkGroupSize.y] " NL
6341 " = g_in_position[gl_LocalInvocationIndex] + t;" NL " color[gl_LocalInvocationIndex + "
6342 "gl_WorkGroupID.x * gl_WorkGroupSize.x * "
6343 "gl_WorkGroupSize.y] = m.color;" NL "}";
6344
6345 m_program = CreateProgramCS(glsl_cs);
6346 glLinkProgram(m_program);
6347 if (!CheckProgram(m_program))
6348 return ERROR;
6349
6350 glGenBuffers(5, m_storage_buffer);
6351
6352 /* material buffer */
6353 {
6354 const float data[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
6355 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
6356 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6357 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6358 }
6359 /* material id buffer */
6360 {
6361 const unsigned int data[] = {2, 3, 0, 2};
6362 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6363 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6364 }
6365 /* transform buffer */
6366 {
6367 const float data[] = {-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
6368 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6369 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6370 }
6371 /* transform id buffer */
6372 {
6373 const unsigned int data[] = {3, 1, 0, 2};
6374 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6375 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6376 }
6377
6378 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6379 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * 4 * 4 + 16 * 2 * 4, 0, GL_STATIC_DRAW);
6380
6381 glUseProgram(m_program);
6382 glDispatchCompute(4, 1, 1);
6383 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6384 GLfloat *out_data =
6385 (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
6386 if (!out_data)
6387 return ERROR;
6388 GLfloat expected[16 * 4 + 16 * 2] = {
6389 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
6390 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
6391 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
6392 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
6393 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.1f, 0.1f, 0.9f, 0.1f, 0.1f, 0.9f,
6394 0.9f, 0.9f, 0.1f, -0.9f, 0.9f, -0.9f, 0.1f, -0.1f, 0.9f, -0.1f, -0.9f, -0.9f, -0.1f, -0.9f,
6395 -0.9f, -0.1f, -0.1f, -0.1f, -0.9f, 0.1f, -0.1f, 0.1f, -0.9f, 0.9f, -0.1f, 0.9f};
6396 for (int i = 0; i < 16; ++i)
6397 {
6398 if (out_data[i * 4 + 0] != expected[i * 4 + 0] || out_data[i * 4 + 1] != expected[i * 4 + 1] ||
6399 out_data[i * 4 + 2] != expected[i * 4 + 2])
6400 {
6401 m_context.getTestContext().getLog()
6402 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6403 << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
6404 << expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << tcu::TestLog::EndMessage;
6405 status = false;
6406 }
6407 }
6408 for (int i = 32; i < 32 + 16; ++i)
6409 {
6410 if (fabs(out_data[i * 2 + 0] - expected[i * 2 + 0]) > 1e-6 ||
6411 fabs(out_data[i * 2 + 1] - expected[i * 2 + 1]) > 1e-6)
6412 {
6413 m_context.getTestContext().getLog()
6414 << tcu::TestLog::Message << "Received: " << out_data[i * 2 + 0] << ", " << out_data[i * 2 + 1]
6415 << ", but expected: " << expected[i * 2 + 0] << ", " << expected[i * 2 + 1]
6416 << tcu::TestLog::EndMessage;
6417 status = false;
6418 }
6419 }
6420 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6421
6422 /* update material id buffer with BufferSubData */
6423 {
6424 const unsigned int data[] = {3, 2, 1, 0};
6425 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6426 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6427 }
6428
6429 /* update transform id buffer with BufferData */
6430 {
6431 const unsigned int data[] = {0, 1, 2, 3};
6432 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6433 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6434 }
6435
6436 glUseProgram(m_program);
6437 glDispatchCompute(4, 1, 1);
6438 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6439 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6440 GLfloat *out_data2 =
6441 (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
6442 if (!out_data2)
6443 return ERROR;
6444 GLfloat expected2[16 * 4 + 16 * 2] = {
6445 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
6446 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
6447 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
6448 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
6449 -0.9f, -0.9f, -0.1f, -0.9f, -0.9f, -0.1f, -0.1f, -0.1f, 0.1f, -0.9f, 0.9f, -0.9f, 0.1f, -0.1f, 0.9f, -0.1f,
6450 -0.9f, 0.1f, -0.1f, 0.1f, -0.9f, 0.9f, -0.1f, 0.9f, 0.1f, 0.1f, 0.9f, 0.1f, 0.1f, 0.9f, 0.9f, 0.9f};
6451 for (int i = 0; i < 16; ++i)
6452 {
6453 if (out_data2[i * 4 + 0] != expected2[i * 4 + 0] || out_data2[i * 4 + 1] != expected2[i * 4 + 1] ||
6454 out_data2[i * 4 + 2] != expected2[i * 4 + 2])
6455 {
6456 m_context.getTestContext().getLog()
6457 << tcu::TestLog::Message << "Received: " << out_data2[i * 4 + 0] << ", " << out_data2[i * 4 + 1]
6458 << ", " << out_data2[i * 4 + 2] << ", but expected: " << expected2[i * 4 + 0] << ", "
6459 << expected2[i * 4 + 1] << ", " << expected2[i * 4 + 2] << tcu::TestLog::EndMessage;
6460 status = false;
6461 }
6462 }
6463 for (int i = 32; i < 32 + 16; ++i)
6464 {
6465 if (fabs(out_data2[i * 2 + 0] - expected2[i * 2 + 0]) > 1e-6 ||
6466 fabs(out_data2[i * 2 + 1] - expected2[i * 2 + 1]) > 1e-6)
6467 {
6468 m_context.getTestContext().getLog()
6469 << tcu::TestLog::Message << "Received: " << out_data2[i * 2 + 0] << ", " << out_data2[i * 2 + 1]
6470 << ", but expected: " << expected2[i * 2 + 0] << ", " << expected2[i * 2 + 1]
6471 << tcu::TestLog::EndMessage;
6472 status = false;
6473 }
6474 }
6475
6476 if (status)
6477 return NO_ERROR;
6478 else
6479 return ERROR;
6480 }
6481
Cleanup()6482 virtual long Cleanup()
6483 {
6484 glUseProgram(0);
6485 glDeleteProgram(m_program);
6486 glDeleteBuffers(5, m_storage_buffer);
6487 return NO_ERROR;
6488 }
6489 };
6490 //-----------------------------------------------------------------------------
6491 // 2.4.2 AdvancedIndirectAddressingCase2
6492 //-----------------------------------------------------------------------------
6493
6494 class AdvancedIndirectAddressingCase2 : public ShaderStorageBufferObjectBase
6495 {
6496 GLuint m_program;
6497 GLuint m_storage_buffer[8];
6498 GLuint m_vertex_array;
6499 GLuint m_vertex_buffer;
6500 GLuint m_fbo, m_rt;
6501
Setup()6502 virtual long Setup()
6503 {
6504 m_program = 0;
6505 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6506 m_vertex_array = 0;
6507 m_vertex_buffer = 0;
6508 glGenFramebuffers(1, &m_fbo);
6509 glGenTextures(1, &m_rt);
6510 return NO_ERROR;
6511 }
6512
Run()6513 virtual long Run()
6514 {
6515 if (!SupportedInVS(4))
6516 return NOT_SUPPORTED;
6517
6518 const char *const glsl_vs =
6519 NL "layout(location = 1) in vec2 g_in_position;" NL "layout(binding = 0, std430) buffer Transform {" NL
6520 " vec2 translation;" NL "} g_transform[4];" NL "uniform uint g_transform_id = 2;" NL "void main() {" NL
6521 " gl_Position = vec4(g_in_position + g_transform[g_transform_id].translation, 0, 1);" NL "}";
6522
6523 const char *const glsl_fs =
6524 NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(binding = 4, std430) buffer Material {" NL
6525 " vec3 color;" NL "} g_material[4];" NL "uniform int g_material_id = 1;" NL "void main() {" NL
6526 " g_fs_out = vec4(g_material[g_material_id].color, 1);" NL "}";
6527 m_program = CreateProgram(glsl_vs, glsl_fs);
6528 glLinkProgram(m_program);
6529 if (!CheckProgram(m_program))
6530 return ERROR;
6531
6532 glGenBuffers(8, m_storage_buffer);
6533
6534 /* transform buffers */
6535 {
6536 const float data[4][2] = {{-0.5f, -0.5f}, {0.5f, -0.5f}, {-0.5f, 0.5f}, {0.5f, 0.5f}};
6537
6538 for (GLuint i = 0; i < 4; ++i)
6539 {
6540 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6541 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6542 }
6543 }
6544 /* material buffers */
6545 {
6546 const float data[4][4] = {
6547 {1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f, 0.0f}};
6548 for (GLuint i = 0; i < 4; ++i)
6549 {
6550 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_storage_buffer[i + 4]);
6551 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6552 }
6553 }
6554
6555 /* vertex buffer */
6556 {
6557 const float data[] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
6558 glGenBuffers(1, &m_vertex_buffer);
6559 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6560 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6561 glBindBuffer(GL_ARRAY_BUFFER, 0);
6562 }
6563
6564 glBindTexture(GL_TEXTURE_2D, m_rt);
6565 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6566 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6567 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6568 glBindTexture(GL_TEXTURE_2D, 0);
6569 glViewport(0, 0, 100, 100);
6570 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6571 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
6572
6573 glGenVertexArrays(1, &m_vertex_array);
6574 glBindVertexArray(m_vertex_array);
6575 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6576 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
6577 glBindBuffer(GL_ARRAY_BUFFER, 0);
6578 glEnableVertexAttribArray(1);
6579 glBindVertexArray(0);
6580
6581 glUseProgram(m_program);
6582 glBindVertexArray(m_vertex_array);
6583
6584 glClear(GL_COLOR_BUFFER_BIT);
6585 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6586 if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(0), vec3(0, 1, 0)))
6587 {
6588 return ERROR;
6589 }
6590
6591 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6592 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6593 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6594 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(0), vec3(0), vec3(0, 1, 0)))
6595 {
6596 return ERROR;
6597 }
6598
6599 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6600 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6601 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
6602 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(0), vec3(0, 1, 0)))
6603 {
6604 return ERROR;
6605 }
6606
6607 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6608 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6609 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6610 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 0, 0), vec3(0, 1, 0)))
6611 {
6612 return ERROR;
6613 }
6614
6615 // once again with only one validation at the end
6616 glClear(GL_COLOR_BUFFER_BIT);
6617 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6618 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6619 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6620
6621 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6622 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6623 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6624
6625 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6626 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6627 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6628
6629 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6630 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6631 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[7]);
6632 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6633
6634 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6635 {
6636 return ERROR;
6637 }
6638 return NO_ERROR;
6639 }
6640
Cleanup()6641 virtual long Cleanup()
6642 {
6643 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6644 glUseProgram(0);
6645 glDeleteProgram(m_program);
6646 glDeleteBuffers(8, m_storage_buffer);
6647 glDeleteBuffers(1, &m_vertex_buffer);
6648 glDeleteVertexArrays(1, &m_vertex_array);
6649 glDeleteFramebuffers(1, &m_fbo);
6650 glDeleteTextures(1, &m_rt);
6651 return NO_ERROR;
6652 }
6653 };
6654
6655 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6656 {
6657 GLuint m_program;
6658 GLuint m_storage_buffer[5];
6659
Setup()6660 virtual long Setup()
6661 {
6662 m_program = 0;
6663 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6664 return NO_ERROR;
6665 }
6666
Run()6667 virtual long Run()
6668 {
6669 GLint blocksC;
6670 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6671 if (blocksC < 8)
6672 return NOT_SUPPORTED;
6673 bool status = true;
6674
6675 const char *const glsl_cs =
6676 NL "layout(local_size_x = 4) in;" NL "layout(binding = 0, std430) buffer Material {" NL " vec3 color;" NL
6677 "} g_material[4];" NL "layout(binding = 4, std430) buffer OutputBuffer {" NL " vec3 color[4];" NL
6678 "};" NL "uniform int g_material_id;" NL "void main() {" NL
6679 " color[gl_LocalInvocationIndex] = vec3(g_material[g_material_id].color);" NL "}";
6680
6681 m_program = CreateProgramCS(glsl_cs);
6682 glLinkProgram(m_program);
6683 if (!CheckProgram(m_program))
6684 return ERROR;
6685
6686 glGenBuffers(5, m_storage_buffer);
6687
6688 /* material buffers */
6689 const float data[4][3] = {{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 0.0f}};
6690
6691 for (GLuint i = 0; i < 4; ++i)
6692 {
6693 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6694 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6695 }
6696
6697 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6698 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
6699
6700 glUseProgram(m_program);
6701 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6702 glDispatchCompute(1, 1, 1);
6703 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6704 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6705 GLfloat *out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6706 if (!out_data)
6707 return ERROR;
6708 const float *expected = &data[1][0];
6709
6710 for (int i = 0; i < 4; ++i)
6711 {
6712 if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6713 out_data[i * 4 + 2] != expected[2])
6714 {
6715 m_context.getTestContext().getLog()
6716 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6717 << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6718 << expected[2] << tcu::TestLog::EndMessage;
6719 status = false;
6720 }
6721 }
6722 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6723 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6724 glDispatchCompute(1, 1, 1);
6725 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6726 out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6727 if (!out_data)
6728 return ERROR;
6729 expected = &data[3][0];
6730
6731 for (int i = 0; i < 4; ++i)
6732 {
6733 if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6734 out_data[i * 4 + 2] != expected[2])
6735 {
6736 m_context.getTestContext().getLog()
6737 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6738 << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6739 << expected[2] << tcu::TestLog::EndMessage;
6740 status = false;
6741 }
6742 }
6743
6744 if (!status)
6745 {
6746 return ERROR;
6747 }
6748 return NO_ERROR;
6749 }
6750
Cleanup()6751 virtual long Cleanup()
6752 {
6753 glUseProgram(0);
6754 glDeleteProgram(m_program);
6755 glDeleteBuffers(5, m_storage_buffer);
6756 return NO_ERROR;
6757 }
6758 };
6759
6760 //-----------------------------------------------------------------------------
6761 // 2.5.1 AdvancedReadWriteCase1
6762 //-----------------------------------------------------------------------------
6763 class AdvancedReadWriteCase1 : public ShaderStorageBufferObjectBase
6764 {
6765 GLuint m_program;
6766 GLuint m_storage_buffer;
6767 GLuint m_vertex_array;
6768 GLuint m_vertex_buffer;
6769
Setup()6770 virtual long Setup()
6771 {
6772 m_program = 0;
6773 m_storage_buffer = 0;
6774 m_vertex_array = 0;
6775 m_vertex_buffer = 0;
6776 return NO_ERROR;
6777 }
6778
Run()6779 virtual long Run()
6780 {
6781 if (!SupportedInVS(1))
6782 return NOT_SUPPORTED;
6783
6784 const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "coherent buffer Buffer {" NL
6785 " vec4 in_color;" NL " vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL
6786 " if (gl_VertexID == 0) {" NL " g_buffer.out_color = g_buffer.in_color;" NL
6787 " memoryBarrier();" NL " }" NL " gl_Position = g_in_position;" NL "}";
6788
6789 const char *const glsl_fs =
6790 NL "layout(location = 0) out vec4 g_fs_out;" NL "coherent buffer Buffer {" NL " vec4 in_color;" NL
6791 " vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL " g_fs_out = g_buffer.out_color;" NL "}";
6792
6793 m_program = CreateProgram(glsl_vs, glsl_fs);
6794 glLinkProgram(m_program);
6795 if (!CheckProgram(m_program))
6796 return ERROR;
6797
6798 glGenBuffers(1, &m_storage_buffer);
6799 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6800 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
6801 float *ptr = reinterpret_cast<float *>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
6802 if (!ptr)
6803 return ERROR;
6804 *ptr++ = 0.0f;
6805 *ptr++ = 1.0f;
6806 *ptr++ = 0.0f;
6807 *ptr++ = 1.0f;
6808 *ptr++ = 0.0f;
6809 *ptr++ = 0.0f;
6810 *ptr++ = 0.0f;
6811 *ptr++ = 0.0f;
6812 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6813
6814 /* vertex buffer */
6815 {
6816 const float data[] = {-1, -1, 1, -1, -1, 1, 1, 1};
6817 glGenBuffers(1, &m_vertex_buffer);
6818 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6819 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6820 glBindBuffer(GL_ARRAY_BUFFER, 0);
6821 }
6822
6823 glGenVertexArrays(1, &m_vertex_array);
6824 glBindVertexArray(m_vertex_array);
6825 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6826 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6827 glBindBuffer(GL_ARRAY_BUFFER, 0);
6828 glEnableVertexAttribArray(0);
6829 glBindVertexArray(0);
6830
6831 glClear(GL_COLOR_BUFFER_BIT);
6832 glUseProgram(m_program);
6833 glBindVertexArray(m_vertex_array);
6834 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6835 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6836 {
6837 return ERROR;
6838 }
6839
6840 // update input color
6841 ptr = reinterpret_cast<float *>(
6842 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6843 if (!ptr)
6844 return ERROR;
6845 *ptr++ = 1.0f;
6846 *ptr++ = 0.0f;
6847 *ptr++ = 1.0f;
6848 *ptr++ = 1.0f;
6849 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6850
6851 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6852 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(1.0f, 0.0f, 1.0f)))
6853 {
6854 return ERROR;
6855 }
6856
6857 return NO_ERROR;
6858 }
6859
Cleanup()6860 virtual long Cleanup()
6861 {
6862 glUseProgram(0);
6863 glDeleteProgram(m_program);
6864 glDeleteBuffers(1, &m_storage_buffer);
6865 glDeleteBuffers(1, &m_vertex_buffer);
6866 glDeleteVertexArrays(1, &m_vertex_array);
6867 return NO_ERROR;
6868 }
6869 };
6870
6871 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6872 {
6873 GLuint m_program;
6874 GLuint m_storage_buffer;
6875
Setup()6876 virtual long Setup()
6877 {
6878 m_program = 0;
6879 m_storage_buffer = 0;
6880 return NO_ERROR;
6881 }
6882
Run()6883 virtual long Run()
6884 {
6885 bool status = true;
6886
6887 const char *const glsl_cs = NL
6888 "layout(local_size_x = 128) in;" NL "struct s {" NL " int ene;" NL " int due;" NL " int like;" NL
6889 " int fake;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL " s a[128];" NL "} g_buffer;" NL
6890 "void main() {" NL " g_buffer.a[gl_LocalInvocationIndex].due = g_buffer.a[gl_LocalInvocationIndex].ene;" NL
6891 " groupMemoryBarrier();" NL " barrier();" NL " g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].like = "
6892 "g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].due;" NL " groupMemoryBarrier();" NL " barrier();" NL
6893 " g_buffer.a[(gl_LocalInvocationIndex + 17u) % 128u].fake "
6894 "= g_buffer.a[(gl_LocalInvocationIndex + 17u) % "
6895 "128u].like;" NL "}";
6896 m_program = CreateProgramCS(glsl_cs);
6897 glLinkProgram(m_program);
6898 if (!CheckProgram(m_program))
6899 return ERROR;
6900
6901 glGenBuffers(1, &m_storage_buffer);
6902 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6903 GLint data[128 * 4];
6904 for (int i = 0; i < 128; ++i)
6905 {
6906 data[i * 4] = i + 256;
6907 data[i * 4 + 1] = 0;
6908 data[i * 4 + 2] = 0;
6909 data[i * 4 + 3] = 0;
6910 }
6911 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6912
6913 glUseProgram(m_program);
6914 glDispatchCompute(1, 1, 1);
6915 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6916 GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6917 if (!out_data)
6918 return ERROR;
6919 for (int i = 0; i < 128; ++i)
6920 {
6921 if (out_data[i * 4 + 3] != data[i * 4])
6922 {
6923 m_context.getTestContext().getLog()
6924 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", "
6925 << ", but expected: " << data[i * 4] << " -> " << out_data[i * 4 + 1] << " -> "
6926 << out_data[i * 4 + 2] << tcu::TestLog::EndMessage;
6927 status = false;
6928 }
6929 }
6930 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6931 for (int i = 0; i < 128; ++i)
6932 {
6933 data[i * 4] = i + 512;
6934 data[i * 4 + 1] = 0;
6935 data[i * 4 + 2] = 0;
6936 data[i * 4 + 3] = 0;
6937 }
6938 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6939
6940 glDispatchCompute(1, 1, 1);
6941 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6942 out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6943 if (!out_data)
6944 return ERROR;
6945 for (int i = 0; i < 128; ++i)
6946 {
6947 if (out_data[i * 4 + 3] != data[i * 4])
6948 {
6949 m_context.getTestContext().getLog()
6950 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", "
6951 << ", but expected: " << data[i * 4] << tcu::TestLog::EndMessage;
6952 status = false;
6953 }
6954 }
6955 if (status)
6956 return NO_ERROR;
6957 else
6958 return ERROR;
6959 }
6960
Cleanup()6961 virtual long Cleanup()
6962 {
6963 glUseProgram(0);
6964 glDeleteProgram(m_program);
6965 glDeleteBuffers(1, &m_storage_buffer);
6966 return NO_ERROR;
6967 }
6968 };
6969 //-----------------------------------------------------------------------------
6970 // 2.6.1 AdvancedUsageCase1
6971 //-----------------------------------------------------------------------------
6972
6973 class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6974 {
6975 GLuint m_program;
6976 GLuint m_storage_buffer[3];
6977 GLuint m_vertex_array;
6978 GLuint m_vertex_buffer;
6979 GLuint m_fbo, m_rt;
6980
Setup()6981 virtual long Setup()
6982 {
6983 m_program = 0;
6984 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6985 m_vertex_array = 0;
6986 m_vertex_buffer = 0;
6987 glGenFramebuffers(1, &m_fbo);
6988 glGenTextures(1, &m_rt);
6989 return NO_ERROR;
6990 }
6991
Run()6992 virtual long Run()
6993 {
6994 if (!SupportedInVS(1))
6995 return NOT_SUPPORTED;
6996
6997 const char *const glsl_vs =
6998 NL "layout(location = 0) in vec4 g_position;" NL "layout(location = 1) in int g_object_id;" NL
6999 "out StageData {" NL " flat int object_id;" NL "} g_vs_out;" NL
7000 "layout(binding = 0, std430) buffer TransformBuffer {" NL " mat4 g_transform[];" NL "};" NL
7001 "void main() {" NL " mat4 mvp = g_transform[g_object_id];" NL " gl_Position = mvp * g_position;" NL
7002 " g_vs_out.object_id = g_object_id;" NL "}";
7003
7004 const char *const glsl_fs = NL
7005 "in StageData {" NL " flat int object_id;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
7006 "struct Material {" NL " vec3 color;" NL "};" NL "layout(binding = 1, std430) buffer MaterialBuffer {" NL
7007 " Material g_material[4];" NL "};" NL "layout(binding = 2, std430) buffer MaterialIDBuffer {" NL
7008 " int g_material_id[4];" NL "};" NL "void main() {" NL " int mid = g_material_id[g_fs_in.object_id];" NL
7009 " Material m = g_material[mid];" NL " g_fs_out = vec4(m.color, 1);" NL "}";
7010
7011 m_program = CreateProgram(glsl_vs, glsl_fs);
7012 glLinkProgram(m_program);
7013 if (!CheckProgram(m_program))
7014 return ERROR;
7015
7016 glGenBuffers(3, m_storage_buffer);
7017
7018 /* transform buffer */
7019 {
7020 mat4 data[] = {Translation(-0.5f, -0.5f, 0.0f), Translation(0.5f, -0.5f, 0.0f),
7021 Translation(-0.5f, 0.5f, 0.0f), Translation(0.5f, 0.5f, 0.0f)};
7022 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7023 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7024 }
7025 /* material buffer */
7026 {
7027 vec4 data[] = {vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 0), vec4(1, 1, 0, 1)};
7028 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7029 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7030 }
7031 /* material id buffer */
7032 {
7033 int data[] = {0, 1, 2, 3};
7034 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7035 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7036 }
7037 /* vertex buffer */
7038 {
7039 struct
7040 {
7041 vec2 position;
7042 int object_id;
7043 } data[] = {{vec2(-0.4f, -0.4f), 0}, {vec2(0.4f, -0.4f), 0}, {vec2(-0.4f, 0.4f), 0}, {vec2(0.4f, 0.4f), 0},
7044 {vec2(-0.4f, -0.4f), 1}, {vec2(0.4f, -0.4f), 1}, {vec2(-0.4f, 0.4f), 1}, {vec2(0.4f, 0.4f), 1},
7045 {vec2(-0.4f, -0.4f), 2}, {vec2(0.4f, -0.4f), 2}, {vec2(-0.4f, 0.4f), 2}, {vec2(0.4f, 0.4f), 2},
7046 {vec2(-0.4f, -0.4f), 3}, {vec2(0.4f, -0.4f), 3}, {vec2(-0.4f, 0.4f), 3}, {vec2(0.4f, 0.4f), 3}};
7047 glGenBuffers(1, &m_vertex_buffer);
7048 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
7049 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7050 glBindBuffer(GL_ARRAY_BUFFER, 0);
7051 }
7052
7053 glBindTexture(GL_TEXTURE_2D, m_rt);
7054 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7055 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7056 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
7057 glBindTexture(GL_TEXTURE_2D, 0);
7058 glViewport(0, 0, 100, 100);
7059 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
7060 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
7061
7062 glGenVertexArrays(1, &m_vertex_array);
7063 glBindVertexArray(m_vertex_array);
7064 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
7065 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2) + sizeof(int), 0);
7066 glVertexAttribIPointer(1, 1, GL_INT, sizeof(vec2) + sizeof(int), reinterpret_cast<void *>(sizeof(vec2)));
7067 glBindBuffer(GL_ARRAY_BUFFER, 0);
7068 glEnableVertexAttribArray(0);
7069 glEnableVertexAttribArray(1);
7070 glBindVertexArray(0);
7071
7072 glClear(GL_COLOR_BUFFER_BIT);
7073 glUseProgram(m_program);
7074 glBindVertexArray(m_vertex_array);
7075 /* draw */
7076 {
7077 const GLint first[4] = {0, 4, 8, 12};
7078 const GLsizei count[4] = {4, 4, 4, 4};
7079 glMultiDrawArrays(GL_TRIANGLE_STRIP, first, count, 4);
7080 }
7081 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
7082 {
7083 return ERROR;
7084 }
7085 return NO_ERROR;
7086 }
7087
Cleanup()7088 virtual long Cleanup()
7089 {
7090 glViewport(0, 0, getWindowWidth(), getWindowHeight());
7091 glUseProgram(0);
7092 glDeleteProgram(m_program);
7093 glDeleteBuffers(3, m_storage_buffer);
7094 glDeleteBuffers(1, &m_vertex_buffer);
7095 glDeleteVertexArrays(1, &m_vertex_array);
7096 glDeleteFramebuffers(1, &m_fbo);
7097 glDeleteTextures(1, &m_rt);
7098 return NO_ERROR;
7099 }
7100 };
7101 //-----------------------------------------------------------------------------
7102 // 2.6.2 AdvancedUsageSync
7103 //-----------------------------------------------------------------------------
7104
7105 class AdvancedUsageSync : public ShaderStorageBufferObjectBase
7106 {
7107 GLuint m_program;
7108 GLuint m_storage_buffer[7];
7109 GLuint m_vertex_array;
7110
Setup()7111 virtual long Setup()
7112 {
7113 m_program = 0;
7114 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7115 m_vertex_array = 0;
7116 return NO_ERROR;
7117 }
7118
Run()7119 virtual long Run()
7120 {
7121 if (!SupportedInVS(3))
7122 return NOT_SUPPORTED;
7123
7124 const char *const glsl_vs =
7125 NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL " int g_data0, g_inc0;" NL
7126 " int g_data1, g_inc1;" NL "};" NL "layout(std430, binding = 1) buffer Buffer12 {" NL
7127 " int inc, data;" NL "} g_buffer12[2];" NL NL "void Modify(int path) {" NL " if (path == 0) {" NL
7128 " atomicAdd(g_data0, g_inc0);" NL " atomicAdd(g_data1, g_inc0);" NL " } else if (path == 1) {" NL
7129 " atomicAdd(g_data0, - g_inc0);" NL " atomicAdd(g_data1, - g_inc0);" NL
7130 " } else if (path == 2) {" NL " atomicAdd(g_data0, g_inc1);" NL " atomicAdd(g_data1, g_inc1);" NL
7131 " }" NL NL " if (path == 0) {" NL " g_buffer12[0].data += g_buffer12[1].inc;" NL
7132 " } else if (path == 1) {" NL " g_buffer12[1].data += g_buffer12[0].inc;" NL " }" NL "}" NL NL
7133 "void main() {" NL " Modify(gl_VertexID);" NL " gl_Position = vec4(0, 0, 0, 1);" NL "}";
7134
7135 const char *glsl_fs =
7136 NL "layout(binding = 3, std430) coherent buffer Buffer3 {" NL " int data;" NL "} g_buffer3;" NL
7137 "layout(std430, binding = 4) coherent buffer Buffer4 {" NL " int data0, inc0;" NL
7138 " int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
7139 " int inc, data;" NL "} g_buffer56[2];" NL NL "void ModifyFS(int path) {" NL " if (path == 0) {" NL
7140 " atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
7141 " } else if (path == 1) {" NL " atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
7142 " atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL " } else if (path == 2) {" NL
7143 " atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
7144 " }" NL NL " if (path == 0) {" NL " g_buffer56[0].data += g_buffer56[1].inc;" NL
7145 " } else if (path == 1) {" NL " g_buffer56[1].data += g_buffer56[0].inc;" NL " }" NL "}" NL
7146 "void main() {" NL " atomicAdd(g_buffer3.data, 1);" NL " ModifyFS(gl_PrimitiveID);" NL "}";
7147
7148 m_program = CreateProgram(glsl_vs, glsl_fs);
7149 glLinkProgram(m_program);
7150 if (!CheckProgram(m_program))
7151 return ERROR;
7152
7153 glGenVertexArrays(1, &m_vertex_array);
7154 glGenBuffers(7, m_storage_buffer);
7155
7156 /* Buffer0 */
7157 {
7158 int data[4] = {0, 1, 0, 2};
7159 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7160 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7161 }
7162 /* Buffer1 */
7163 {
7164 int data[2] = {3, 1};
7165 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7166 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7167 }
7168 /* Buffer2 */
7169 {
7170 int data[2] = {2, 4};
7171 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7172 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7173 }
7174 /* Buffer3 */
7175 {
7176 int data[1] = {0};
7177 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7178 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7179 }
7180 /* Buffer4 */
7181 {
7182 int data[4] = {0, 1, 0, 2};
7183 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7184 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7185 }
7186 /* Buffer5 */
7187 {
7188 int data[2] = {3, 1};
7189 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
7190 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7191 }
7192 /* Buffer6 */
7193 {
7194 int data[2] = {2, 4};
7195 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
7196 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7197 }
7198
7199 glUseProgram(m_program);
7200 glBindVertexArray(m_vertex_array);
7201
7202 glDrawArrays(GL_POINTS, 0, 3);
7203 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
7204 glDrawArrays(GL_POINTS, 0, 3);
7205
7206 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7207
7208 /* Buffer0 */
7209 {
7210 const int ref_data[4] = {4, 1, 4, 2};
7211 int data[4];
7212 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7213 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7214 for (int i = 0; i < 4; ++i)
7215 {
7216 if (data[i] != ref_data[i])
7217 {
7218 m_context.getTestContext().getLog()
7219 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7220 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7221 return ERROR;
7222 }
7223 }
7224 }
7225 /* Buffer1 */
7226 {
7227 const int ref_data[2] = {3, 5};
7228 int data[2];
7229 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7230 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7231 for (int i = 0; i < 2; ++i)
7232 {
7233 if (data[i] != ref_data[i])
7234 {
7235 m_context.getTestContext().getLog()
7236 << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7237 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7238 return ERROR;
7239 }
7240 }
7241 }
7242 /* Buffer2 */
7243 {
7244 const int ref_data[2] = {2, 10};
7245 int data[2];
7246 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
7247 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7248 for (int i = 0; i < 2; ++i)
7249 {
7250 if (data[i] != ref_data[i])
7251 {
7252 m_context.getTestContext().getLog()
7253 << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
7254 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7255 return ERROR;
7256 }
7257 }
7258 }
7259 /* Buffer3 */
7260 {
7261 const int ref_data[1] = {6};
7262 int data[1];
7263 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7264 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7265 for (int i = 0; i < 1; ++i)
7266 {
7267 if (data[i] != ref_data[i])
7268 {
7269 m_context.getTestContext().getLog()
7270 << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
7271 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7272 return ERROR;
7273 }
7274 }
7275 }
7276 /* Buffer4 */
7277 {
7278 const int ref_data[4] = {4, 1, 4, 2};
7279 int data[4];
7280 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7281 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7282 for (int i = 0; i < 4; ++i)
7283 {
7284 if (data[i] != ref_data[i])
7285 {
7286 m_context.getTestContext().getLog()
7287 << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
7288 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7289 return ERROR;
7290 }
7291 }
7292 }
7293 /* Buffer5 */
7294 {
7295 const int ref_data[2] = {3, 5};
7296 int data[2];
7297 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7298 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7299 for (int i = 0; i < 2; ++i)
7300 {
7301 if (data[i] != ref_data[i])
7302 {
7303 m_context.getTestContext().getLog()
7304 << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7305 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7306 return ERROR;
7307 }
7308 }
7309 }
7310 /* Buffer6 */
7311 {
7312 const int ref_data[2] = {2, 10};
7313 int data[2];
7314 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7315 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7316 for (int i = 0; i < 2; ++i)
7317 {
7318 if (data[i] != ref_data[i])
7319 {
7320 m_context.getTestContext().getLog()
7321 << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7322 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7323 return ERROR;
7324 }
7325 }
7326 }
7327
7328 return NO_ERROR;
7329 }
7330
Cleanup()7331 virtual long Cleanup()
7332 {
7333 glUseProgram(0);
7334 glDeleteProgram(m_program);
7335 glDeleteBuffers(7, m_storage_buffer);
7336 glDeleteVertexArrays(1, &m_vertex_array);
7337 return NO_ERROR;
7338 }
7339 };
7340
7341 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
7342 {
7343 GLuint m_program;
7344 GLuint m_storage_buffer[7];
7345
Setup()7346 virtual long Setup()
7347 {
7348 m_program = 0;
7349 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7350 return NO_ERROR;
7351 }
7352
Run()7353 virtual long Run()
7354 {
7355 const char *const glsl_cs =
7356 NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL
7357 " int g_data0, g_inc0;" NL " int g_data1, g_inc1;" NL "};" NL
7358 "layout(std430, binding = 1) buffer Buffer12 {" NL " int inc, data;" NL "} g_buffer12[2];" NL
7359 "layout(binding = 3, std430) coherent buffer Buffer3 {" NL " int data;" NL "} g_buffer3;" NL
7360 "layout(std430, binding = 4) coherent buffer Buffer4 {" NL " int data0, inc0;" NL
7361 " int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
7362 " int inc, data;" NL "} g_buffer56[2];" NL NL "void Modify1(int path) {" NL " if (path == 0) {" NL
7363 " atomicAdd(g_data0, g_inc0);" NL " atomicAdd(g_data1, g_inc0);" NL " } else if (path == 1) {" NL
7364 " atomicAdd(g_data0, - g_inc0);" NL " atomicAdd(g_data1, - g_inc0);" NL
7365 " } else if (path == 2) {" NL " atomicAdd(g_data0, g_inc1);" NL " atomicAdd(g_data1, g_inc1);" NL
7366 " }" NL " if (path == 0) {" NL " g_buffer12[0].data += g_buffer12[1].inc;" NL
7367 " } else if (path == 1) {" NL " g_buffer12[1].data += g_buffer12[0].inc;" NL " }" NL "}" NL NL
7368 "void Modify2(int path) {" NL " if (path == 0) {" NL
7369 " atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
7370 " } else if (path == 1) {" NL " atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
7371 " atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL " } else if (path == 2) {" NL
7372 " atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
7373 " }" NL " if (path == 0) {" NL " g_buffer56[0].data += g_buffer56[1].inc;" NL
7374 " } else if (path == 1) {" NL " g_buffer56[1].data += g_buffer56[0].inc;" NL " }" NL "}" NL NL
7375 "void main() {" NL " Modify1(int(gl_WorkGroupID.z));" NL " atomicAdd(g_buffer3.data, 1);" NL
7376 " Modify2(int(gl_WorkGroupID.z));" NL "}";
7377
7378 m_program = CreateProgramCS(glsl_cs);
7379 glLinkProgram(m_program);
7380 if (!CheckProgram(m_program))
7381 return ERROR;
7382
7383 glGenBuffers(7, m_storage_buffer);
7384
7385 /* Buffer0 */
7386 {
7387 int data[4] = {0, 1, 0, 2};
7388 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7389 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7390 }
7391 /* Buffer1 */
7392 {
7393 int data[2] = {3, 1};
7394 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7395 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7396 }
7397 /* Buffer2 */
7398 {
7399 int data[2] = {2, 4};
7400 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7401 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7402 }
7403 /* Buffer3 */
7404 {
7405 int data[1] = {0};
7406 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7407 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7408 }
7409 /* Buffer4 */
7410 {
7411 int data[4] = {0, 1, 0, 2};
7412 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7413 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7414 }
7415 /* Buffer5 */
7416 {
7417 int data[2] = {3, 1};
7418 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
7419 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7420 }
7421 /* Buffer6 */
7422 {
7423 int data[2] = {2, 4};
7424 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
7425 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7426 }
7427
7428 glUseProgram(m_program);
7429
7430 glDispatchCompute(1, 1, 3);
7431 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
7432 glDispatchCompute(1, 1, 3);
7433
7434 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7435
7436 /* Buffer0 */
7437 {
7438 const int ref_data[4] = {4, 1, 4, 2};
7439 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7440 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7441 if (!data)
7442 return ERROR;
7443 for (int i = 0; i < 4; ++i)
7444 {
7445 if (data[i] != ref_data[i])
7446 {
7447 m_context.getTestContext().getLog()
7448 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7449 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7450 return ERROR;
7451 }
7452 }
7453 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7454 }
7455 /* Buffer1 */
7456 {
7457 const int ref_data[2] = {3, 5};
7458 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7459 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7460 if (!data)
7461 return ERROR;
7462 for (int i = 0; i < 2; ++i)
7463 {
7464 if (data[i] != ref_data[i])
7465 {
7466 m_context.getTestContext().getLog()
7467 << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7468 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7469 return ERROR;
7470 }
7471 }
7472 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7473 }
7474 /* Buffer2 */
7475 {
7476 const int ref_data[2] = {2, 10};
7477 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
7478 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7479 if (!data)
7480 return ERROR;
7481 for (int i = 0; i < 2; ++i)
7482 {
7483 if (data[i] != ref_data[i])
7484 {
7485 m_context.getTestContext().getLog()
7486 << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
7487 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7488 return ERROR;
7489 }
7490 }
7491 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7492 }
7493 /* Buffer3 */
7494 {
7495 const int ref_data[1] = {6};
7496 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7497 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
7498 if (!data)
7499 return ERROR;
7500 for (int i = 0; i < 1; ++i)
7501 {
7502 if (data[i] != ref_data[i])
7503 {
7504 m_context.getTestContext().getLog()
7505 << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
7506 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7507 return ERROR;
7508 }
7509 }
7510 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7511 }
7512 /* Buffer4 */
7513 {
7514 const int ref_data[4] = {4, 1, 4, 2};
7515 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7516 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7517 if (!data)
7518 return ERROR;
7519 for (int i = 0; i < 4; ++i)
7520 {
7521 if (data[i] != ref_data[i])
7522 {
7523 m_context.getTestContext().getLog()
7524 << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
7525 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7526 return ERROR;
7527 }
7528 }
7529 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7530 }
7531 /* Buffer5 */
7532 {
7533 const int ref_data[2] = {3, 5};
7534 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7535 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7536 if (!data)
7537 return ERROR;
7538 for (int i = 0; i < 2; ++i)
7539 {
7540 if (data[i] != ref_data[i])
7541 {
7542 m_context.getTestContext().getLog()
7543 << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7544 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7545 return ERROR;
7546 }
7547 }
7548 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7549 }
7550 /* Buffer6 */
7551 {
7552 const int ref_data[2] = {2, 10};
7553 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7554 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7555 if (!data)
7556 return ERROR;
7557 for (int i = 0; i < 2; ++i)
7558 {
7559 if (data[i] != ref_data[i])
7560 {
7561 m_context.getTestContext().getLog()
7562 << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7563 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7564 return ERROR;
7565 }
7566 }
7567 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7568 }
7569
7570 return NO_ERROR;
7571 }
7572
Cleanup()7573 virtual long Cleanup()
7574 {
7575 glUseProgram(0);
7576 glDeleteProgram(m_program);
7577 glDeleteBuffers(7, m_storage_buffer);
7578 return NO_ERROR;
7579 }
7580 };
7581
7582 //-----------------------------------------------------------------------------
7583 // 2.6.3 AdvancedUsageOperators
7584 //-----------------------------------------------------------------------------
7585 class AdvancedUsageOperators : public ShaderStorageBufferObjectBase
7586 {
7587 GLuint m_program;
7588 GLuint m_storage_buffer[2];
7589 GLuint m_vertex_array;
7590
Setup()7591 virtual long Setup()
7592 {
7593 m_program = 0;
7594 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7595 m_vertex_array = 0;
7596 return NO_ERROR;
7597 }
7598
Run()7599 virtual long Run()
7600 {
7601 if (!SupportedInVS(2))
7602 return NOT_SUPPORTED;
7603
7604 const char *const glsl_vs =
7605 NL "layout(std430, binding = 0) buffer Buffer0 {" NL " readonly int g_i0;" NL " int g_o0;" NL "};" NL
7606 "layout(std430, binding = 1) buffer Buffer1 {" NL " int i0;" NL "} g_buffer1;" NL
7607 "uniform int g_values[] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL " g_o0 += g_i0;" NL
7608 " g_o0 <<= 1;" NL " g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL " g_o0 *= g_i0;" NL
7609 " g_o0 = --g_o0 + g_values[g_i0];" NL " g_o0++;" NL " ++g_o0;" NL " g_buffer1.i0 = 0xff2f;" NL
7610 " g_o0 &= g_buffer1.i0;" NL "}";
7611
7612 m_program = CreateProgram(glsl_vs, "");
7613 glLinkProgram(m_program);
7614 if (!CheckProgram(m_program))
7615 return ERROR;
7616
7617 glGenVertexArrays(1, &m_vertex_array);
7618 glGenBuffers(2, m_storage_buffer);
7619
7620 /* Buffer0 */
7621 {
7622 int data[4] = {3, 5};
7623 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7624 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7625 }
7626 /* Buffer1 */
7627 {
7628 int data[1] = {0};
7629 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7630 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7631 }
7632
7633 glEnable(GL_RASTERIZER_DISCARD);
7634 glUseProgram(m_program);
7635 glBindVertexArray(m_vertex_array);
7636 glDrawArrays(GL_POINTS, 0, 1);
7637 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7638
7639 /* Buffer0 */
7640 {
7641 const int ref_data[2] = {3, 37};
7642 int data[4];
7643 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7644 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7645 for (int i = 0; i < 2; ++i)
7646 {
7647 if (data[i] != ref_data[i])
7648 {
7649 m_context.getTestContext().getLog()
7650 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7651 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7652 return ERROR;
7653 }
7654 }
7655 }
7656 /* Buffer0 */
7657 {
7658 const int ref_data[1] = {0xff2f};
7659 int data[1];
7660 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7661 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7662 for (int i = 0; i < 1; ++i)
7663 {
7664 if (data[i] != ref_data[i])
7665 {
7666 m_context.getTestContext().getLog()
7667 << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7668 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7669 return ERROR;
7670 }
7671 }
7672 }
7673
7674 return NO_ERROR;
7675 }
7676
Cleanup()7677 virtual long Cleanup()
7678 {
7679 glDisable(GL_RASTERIZER_DISCARD);
7680 glUseProgram(0);
7681 glDeleteProgram(m_program);
7682 glDeleteBuffers(2, m_storage_buffer);
7683 glDeleteVertexArrays(1, &m_vertex_array);
7684 return NO_ERROR;
7685 }
7686 };
7687
7688 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7689 {
7690 GLuint m_program;
7691 GLuint m_storage_buffer[2];
7692
Setup()7693 virtual long Setup()
7694 {
7695 m_program = 0;
7696 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7697 return NO_ERROR;
7698 }
7699
Run()7700 virtual long Run()
7701 {
7702 const char *const glsl_cs =
7703 NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Buffer0 {" NL
7704 " readonly int g_i0;" NL " int g_o0;" NL "};" NL "layout(std430, binding = 1) buffer Buffer1 {" NL
7705 " int i0;" NL "} g_buffer1;" NL "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL
7706 " g_o0 += g_i0;" NL " g_o0 <<= 1;" NL " g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL " g_o0 *= g_i0;" NL
7707 " g_o0 = --g_o0 + g_values[g_i0];" NL " g_o0++;" NL " ++g_o0;" NL " g_buffer1.i0 = 0xff2f;" NL
7708 " g_o0 &= g_buffer1.i0;" NL "}";
7709
7710 m_program = CreateProgramCS(glsl_cs);
7711 glLinkProgram(m_program);
7712 if (!CheckProgram(m_program))
7713 return ERROR;
7714
7715 glGenBuffers(2, m_storage_buffer);
7716
7717 /* Buffer0 */
7718 {
7719 int data[4] = {3, 5};
7720 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7721 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7722 }
7723 /* Buffer1 */
7724 {
7725 int data[1] = {0};
7726 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7727 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7728 }
7729
7730 glUseProgram(m_program);
7731 glDispatchCompute(1, 1, 1);
7732 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7733
7734 /* Buffer0 */
7735 {
7736 const int ref_data[2] = {3, 37};
7737 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7738 int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7739 if (!data)
7740 return ERROR;
7741 for (int i = 0; i < 2; ++i)
7742 {
7743 if (data[i] != ref_data[i])
7744 {
7745 m_context.getTestContext().getLog()
7746 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7747 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7748 return ERROR;
7749 }
7750 }
7751 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7752 }
7753
7754 return NO_ERROR;
7755 }
7756
Cleanup()7757 virtual long Cleanup()
7758 {
7759 glUseProgram(0);
7760 glDeleteProgram(m_program);
7761 glDeleteBuffers(2, m_storage_buffer);
7762 return NO_ERROR;
7763 }
7764 };
7765
7766 //-----------------------------------------------------------------------------
7767 // 2.7 AdvancedUnsizedArrayLength
7768 //-----------------------------------------------------------------------------
7769 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7770 {
7771 GLuint m_program;
7772 GLuint m_storage_buffer[5];
7773 GLuint m_vertex_array;
7774
Setup()7775 virtual long Setup()
7776 {
7777 m_program = 0;
7778 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7779 m_vertex_array = 0;
7780 return NO_ERROR;
7781 }
7782
Run()7783 virtual long Run()
7784 {
7785 if (!SupportedInVS(5))
7786 return NOT_SUPPORTED;
7787
7788 const char *const glsl_vs =
7789 NL "layout(std430, binding = 0) readonly buffer Input0 {" NL " int g_input0[];" NL "};" NL
7790 "layout(std430, binding = 1) readonly buffer Input1 {" NL " int data[];" NL "} g_input1;" NL
7791 "layout(std430, binding = 2) readonly buffer Input23 {" NL " int data[];" NL "} g_input23[2];" NL
7792 "layout(std430, binding = 4) buffer Output {" NL " int g_length[4];" NL " int g_length2;" NL "};" NL
7793 "void main() {" NL " g_length[0] = g_input0.length();" NL " g_length[1] = g_input1.data.length();" NL
7794 " g_length[2] = g_input23[0].data.length();" NL " g_length[3] = g_input23[1].data.length();" NL
7795 " g_length2 = g_length.length();" NL "}";
7796
7797 m_program = CreateProgram(glsl_vs, "");
7798 glLinkProgram(m_program);
7799 if (!CheckProgram(m_program))
7800 return ERROR;
7801
7802 glGenVertexArrays(1, &m_vertex_array);
7803 glGenBuffers(5, m_storage_buffer);
7804
7805 /* input 0 */
7806 {
7807 int data[7] = {1, 2, 3, 4, 5, 6, 7};
7808 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7809 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7810 }
7811 /* input 1 */
7812 {
7813 int data[5] = {1, 2, 3, 4, 5};
7814 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7815 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7816 }
7817 /* input 2 */
7818 {
7819 int data[3] = {1, 2, 3};
7820 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7821 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7822 }
7823 /* input 3 */
7824 {
7825 int data[4] = {1, 2, 3, 4};
7826 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7827 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7828 }
7829 /* output */
7830 {
7831 int data[5] = {0};
7832 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7833 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7834 }
7835
7836 glEnable(GL_RASTERIZER_DISCARD);
7837 glUseProgram(m_program);
7838 glBindVertexArray(m_vertex_array);
7839 glDrawArrays(GL_POINTS, 0, 1);
7840
7841 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7842
7843 /* output */
7844 {
7845 int data[5];
7846 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7847 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7848 bool status = true;
7849 if (data[0] != 7)
7850 {
7851 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 0 length is " << data[0]
7852 << " should be 7." << tcu::TestLog::EndMessage;
7853 status = false;
7854 }
7855 if (data[1] != 5)
7856 {
7857 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 1 length is " << data[1]
7858 << " should be 5." << tcu::TestLog::EndMessage;
7859 status = false;
7860 }
7861 if (data[2] != 3)
7862 {
7863 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 2 length is " << data[2]
7864 << " should be 3." << tcu::TestLog::EndMessage;
7865 status = false;
7866 }
7867 if (data[3] != 4)
7868 {
7869 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 3 length is " << data[3]
7870 << " should be 4." << tcu::TestLog::EndMessage;
7871 status = false;
7872 }
7873 if (data[4] != 4)
7874 {
7875 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 length is " << data[4]
7876 << " should be 4." << tcu::TestLog::EndMessage;
7877 status = false;
7878 }
7879 if (!status)
7880 return ERROR;
7881 }
7882
7883 return NO_ERROR;
7884 }
7885
Cleanup()7886 virtual long Cleanup()
7887 {
7888 glDisable(GL_RASTERIZER_DISCARD);
7889 glUseProgram(0);
7890 glDeleteProgram(m_program);
7891 glDeleteBuffers(5, m_storage_buffer);
7892 glDeleteVertexArrays(1, &m_vertex_array);
7893 return NO_ERROR;
7894 }
7895 };
7896
7897 class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7898 {
7899 GLuint m_program;
7900 GLuint m_storage_buffer[8];
7901 GLuint m_vertex_array;
7902
7903 virtual void SetPath() = 0;
7904
Setup()7905 virtual long Setup()
7906 {
7907 m_program = 0;
7908 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7909 m_vertex_array = 0;
7910 return NO_ERROR;
7911 }
7912
Cleanup()7913 virtual long Cleanup()
7914 {
7915 glUseProgram(0);
7916 glDeleteProgram(m_program);
7917 glDeleteBuffers(8, m_storage_buffer);
7918 if (stage != compute)
7919 glDeleteVertexArrays(1, &m_vertex_array);
7920 return NO_ERROR;
7921 }
7922
BuildShaderPT(int stagept)7923 std::string BuildShaderPT(int stagept)
7924 {
7925 std::ostringstream os;
7926 if (stagept == vertex)
7927 {
7928 os << NL "void main() {" NL " gl_Position = vec4(0,0,0,1);";
7929 }
7930 if (stagept == fragment)
7931 {
7932 os << NL "void main() {";
7933 }
7934 os << NL "}";
7935 return os.str();
7936 }
7937
BuildShader()7938 std::string BuildShader()
7939 {
7940 std::ostringstream os;
7941 std::string e[4][7] = {{"bvec3", "vec4", "ivec3", "ivec3", "uvec2", "vec2", "uvec4"},
7942 {"mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2"},
7943 {"mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2"},
7944 {"S0", "S1", "S2", "S2", "S4", "S5", "S6"}};
7945
7946 std::string sd =
7947 NL "struct S0 {" NL " float f;" NL " int i;" NL " uint ui;" NL " bool b;" NL "};" NL "struct S1 {" NL
7948 " ivec3 iv;" NL " bvec2 bv;" NL " vec4 v;" NL " uvec2 uv;" NL "};" NL "struct S2 {" NL
7949 " mat2x2 m22;" NL " mat4x4 m44;" NL " mat2x3 m23;" NL " mat4x2 m42;" NL " mat3x4 m34;" NL "};" NL
7950 "struct S4 {" NL " float f[1];" NL " int i[2];" NL " uint ui[3];" NL " bool b[4];" NL
7951 " ivec3 iv[5];" NL " bvec2 bv[6];" NL " vec4 v[7];" NL " uvec2 uv[8];" NL "};" NL "struct S5 {" NL
7952 " S0 s0;" NL " S1 s1;" NL " S2 s2;" NL "};" NL "struct S6 {" NL " S4 s4[3];" NL "};";
7953
7954 std::string lo = "";
7955 std::string l[4] = {"std140", "std430", "shared", "packed"};
7956 lo += l[layout];
7957
7958 if (etype == matrix_rm)
7959 lo += ", row_major";
7960
7961 std::string decl = sd + NL "layout(" + lo + ") buffer;" NL "layout(binding = 0) readonly buffer Input0 {" +
7962 ((other_members) ? ("\n " + e[etype][0] + " pad0;") : "") + NL " " + e[etype][0] +
7963 " g_input0[];" NL "};" NL "layout(binding = 1) readonly buffer Input1 {" +
7964 ((other_members) ? ("\n " + e[etype][1] + " pad1;") : "") + NL " " + e[etype][1] +
7965 " data[];" NL "} g_input1;" NL "layout(binding = 2) readonly buffer Input23 {" +
7966 ((other_members) ? ("\n " + e[etype][2] + " pad2;") : "") + NL " " + e[etype][2] +
7967 " data[];" NL "} g_input23[2];" NL "layout(binding = 4) buffer Output0 {" +
7968 ((other_members) ? ("\n " + e[etype][4] + " pad4;") : "") + NL " " + e[etype][4] +
7969 " data[];" NL "} g_output0;" NL "layout(binding = 5) readonly buffer Input4 {" +
7970 ((other_members) ? ("\n " + e[etype][5] + " pad5;") : "") + NL " " + e[etype][5] +
7971 " data[];" NL "} g_input4;" NL "layout(binding = 6) buffer Output1 {" +
7972 ((other_members) ? ("\n " + e[etype][6] + " pad6;") : "") + NL " " + e[etype][6] +
7973 " data[];" NL "} g_output1;" NL "layout(std430, binding = 7) buffer Output {" NL
7974 " int g_length[];" NL "};";
7975
7976 std::string expr =
7977 NL " g_length[0] = g_input0.length();" NL " g_length[1] = g_input1.data.length();" NL
7978 " g_length[2] = g_input23[0].data.length();" NL " g_length[3] = g_input23[1].data.length();" NL
7979 " g_length[4] = g_output0.data.length();" NL " g_length[5] = g_input4.data.length();" NL
7980 " g_length[6] = g_output1.data.length();";
7981
7982 std::string lastelemexpr =
7983 NL " g_output0.data[g_output0.data.length()-2] += g_output0.data[g_output0.data.length()-1];" NL
7984 " g_output1.data[g_output1.data.length()-2] += g_output1.data[g_output1.data.length()-1];";
7985
7986 if (length_as_index)
7987 expr += lastelemexpr;
7988 if (stage == vertex)
7989 {
7990 os << decl << NL "void main() {" NL " gl_Position = vec4(0,0,0,1);" << expr;
7991 }
7992 if (stage == fragment)
7993 {
7994 os << NL << decl << NL "void main() {" << expr;
7995 }
7996 if (stage == compute)
7997 {
7998 os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7999 }
8000 os << NL "}";
8001 return os.str();
8002 }
8003
Run()8004 virtual long Run()
8005 {
8006 const int kSize = 100000;
8007 const int kBufs = 8;
8008 SetPath();
8009 if (stage == vertex && !SupportedInVS(8))
8010 return NOT_SUPPORTED;
8011 GLint blocksC;
8012 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
8013 GLint minA;
8014 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
8015 if (blocksC < kBufs)
8016 return NOT_SUPPORTED;
8017 if (stage == vertex)
8018 {
8019 std::string glsl_vs = BuildShader();
8020 std::string glsl_fs = BuildShaderPT(fragment);
8021 m_program = CreateProgram(glsl_vs, glsl_fs);
8022 }
8023 else if (stage == fragment)
8024 {
8025 std::string glsl_vs = BuildShaderPT(vertex);
8026 std::string glsl_fs = BuildShader();
8027 m_program = CreateProgram(glsl_vs, glsl_fs);
8028 }
8029 else
8030 { // compute
8031 std::string glsl_cs = BuildShader();
8032 m_program = CreateProgramCS(glsl_cs);
8033 }
8034 glLinkProgram(m_program);
8035 if (!CheckProgram(m_program))
8036 return ERROR;
8037 glUseProgram(m_program);
8038
8039 glGenBuffers(kBufs, m_storage_buffer);
8040 int sizes[kBufs] = {7, 5, 3, 4, 23, 123, 419, 8};
8041
8042 int columns[4][kBufs] = {{1, 1, 1, 1, 1, 1, 1, 1}, // vector: 1 col
8043 {2, 3, 4, 4, 2, 3, 4, 1}, // mat: # of cols
8044 {2, 3, 4, 4, 3, 2, 2, 1}, // RM mat: # of rows
8045 {1, 1, 1, 1, 1, 1, 1, 1}}; // structure: not used
8046
8047 int scalars[4][kBufs] = {{4, 4, 4, 4, 2, 2, 4, 1}, //vector: size
8048 {2, 4, 4, 4, 4, 2, 2, 1}, //matrix column_major: rows
8049 {2, 4, 4, 4, 2, 4, 4, 1}, //matrix row_major: columns
8050 {1, 1, 1, 1, 1, 1, 1, 1}}; //structure: not used
8051
8052 int mindw[4][kBufs] = {{3, 4, 3, 3, 2, 2, 4, 1}, // # of real 32bit items
8053 {4, 9, 16, 16, 6, 6, 8, 1},
8054 {4, 9, 16, 16, 6, 6, 8, 1},
8055 {4, 11, 35, 35, 81, 127, 381, 1}};
8056 int std430struct[kBufs] = {4, 16, 48, 48, 88, 68, 264, 1};
8057 int std140struct[kBufs] = {4, 16, 60, 60, 144, 80, 432, 1};
8058 int bufsize[kBufs][2] = {{0}};
8059
8060 std::vector<ivec4> data(kSize, ivec4(41));
8061 for (int i = 0; i < kBufs; ++i)
8062 {
8063 if (layout == std430)
8064 {
8065 bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
8066 if (etype == structure)
8067 {
8068 bufsize[i][1] = 4 * std430struct[i];
8069 }
8070 }
8071 else if (layout == std140)
8072 {
8073 bufsize[i][1] = 4 * columns[etype][i] * 4;
8074 if (etype == structure)
8075 {
8076 bufsize[i][1] = 4 * std140struct[i];
8077 }
8078 }
8079 else
8080 {
8081 bufsize[i][1] = 4 * mindw[etype][i];
8082 }
8083 bufsize[i][0] = sizes[i] * bufsize[i][1];
8084 if (i == kBufs - 1 || bind_seq == bindbasebefore)
8085 { // never trim feedback storage
8086 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
8087 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
8088 }
8089 else
8090 {
8091 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[i]);
8092 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
8093 if (bind_seq == bindbaseafter)
8094 {
8095 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
8096 }
8097 else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
8098 {
8099 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 2 * bufsize[i][1],
8100 bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
8101 }
8102 else
8103 { // bind_seq == bindrangesize || 2*bufsize[i][1] < minA
8104 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 0,
8105 bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
8106 }
8107 }
8108 }
8109
8110 if (stage != compute)
8111 {
8112 glGenVertexArrays(1, &m_vertex_array);
8113 glBindVertexArray(m_vertex_array);
8114 glDrawArrays(GL_POINTS, 0, 1);
8115 }
8116 else
8117 {
8118 glDispatchCompute(1, 1, 1);
8119 }
8120 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8121
8122 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[kBufs - 1]);
8123 int *dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
8124 if (!dataout)
8125 return ERROR;
8126 bool status = true;
8127 for (int i = 0; i < kBufs - 1; ++i)
8128 {
8129 if (other_members)
8130 sizes[i] -= 1; // space consumed by a pad
8131 if (bind_seq == bindrangesize || bind_seq == bindrangeoffset)
8132 sizes[i] -= 2; // space constrained by offset of range size
8133 if ((layout == std140 || layout == std430) && dataout[i] != sizes[i])
8134 {
8135 m_context.getTestContext().getLog()
8136 << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i] << " should be "
8137 << sizes[i] << tcu::TestLog::EndMessage;
8138 status = false;
8139 }
8140 if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
8141 {
8142 m_context.getTestContext().getLog()
8143 << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i]
8144 << " should be not greater that " << sizes[i] << tcu::TestLog::EndMessage;
8145 status = false;
8146 }
8147 }
8148 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8149
8150 if (length_as_index)
8151 {
8152 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
8153 dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[4][0], GL_MAP_READ_BIT);
8154 if (!dataout)
8155 return ERROR;
8156 int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
8157 if (dataout[i] != 82)
8158 {
8159 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 index " << i << " is "
8160 << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
8161 status = false;
8162 }
8163 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8164 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
8165 dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[6][0], GL_MAP_READ_BIT);
8166 if (!dataout)
8167 return ERROR;
8168 i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
8169 if (dataout[i] != 82)
8170 {
8171 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 6 index " << i << " is "
8172 << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
8173 status = false;
8174 }
8175 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8176 }
8177
8178 if (!status)
8179 return ERROR;
8180
8181 return NO_ERROR;
8182 }
8183
8184 public:
8185 int stage;
8186 int etype;
8187 int layout;
8188 bool other_members;
8189 int bind_seq;
8190 bool length_as_index;
8191
AdvancedUnsizedArrayLength2()8192 AdvancedUnsizedArrayLength2()
8193 : m_program(0)
8194 , m_vertex_array(0)
8195 , stage(compute)
8196 , etype(vector)
8197 , layout(std430)
8198 , other_members(false)
8199 , bind_seq(bindbasebefore)
8200 , length_as_index(false)
8201 {
8202 }
8203 };
8204
8205 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
8206 {
8207 public:
SetPath()8208 virtual void SetPath()
8209 {
8210 length_as_index = true;
8211 }
8212 };
8213
8214 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
8215 {
8216 public:
SetPath()8217 virtual void SetPath()
8218 {
8219 bind_seq = bindbaseafter;
8220 }
8221 };
8222
8223 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
8224 {
8225 public:
SetPath()8226 virtual void SetPath()
8227 {
8228 bind_seq = bindrangeoffset;
8229 }
8230 };
8231
8232 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
8233 {
8234 public:
SetPath()8235 virtual void SetPath()
8236 {
8237 bind_seq = bindrangesize;
8238 }
8239 };
8240
8241 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
8242 {
8243 public:
SetPath()8244 virtual void SetPath()
8245 {
8246 etype = vector;
8247 }
8248 };
8249
8250 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
8251 {
8252 public:
SetPath()8253 virtual void SetPath()
8254 {
8255 etype = matrix_cm;
8256 }
8257 };
8258
8259 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
8260 {
8261 public:
SetPath()8262 virtual void SetPath()
8263 {
8264 etype = matrix_rm;
8265 }
8266 };
8267
8268 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
8269 {
8270 public:
SetPath()8271 virtual void SetPath()
8272 {
8273 etype = structure;
8274 }
8275 };
8276
8277 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
8278 {
8279 public:
SetPath()8280 virtual void SetPath()
8281 {
8282 stage = compute;
8283 layout = std140;
8284 }
8285 };
8286
8287 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
8288 {
8289 public:
SetPath()8290 virtual void SetPath()
8291 {
8292 etype = matrix_cm;
8293 layout = std140;
8294 }
8295 };
8296
8297 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
8298 {
8299 public:
SetPath()8300 virtual void SetPath()
8301 {
8302 etype = matrix_rm;
8303 layout = std140;
8304 }
8305 };
8306
8307 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
8308 {
8309 public:
SetPath()8310 virtual void SetPath()
8311 {
8312 etype = structure;
8313 layout = std140;
8314 }
8315 };
8316
8317 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
8318 {
8319 public:
SetPath()8320 virtual void SetPath()
8321 {
8322 etype = vector;
8323 layout = packed;
8324 }
8325 };
8326
8327 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
8328 {
8329 public:
SetPath()8330 virtual void SetPath()
8331 {
8332 etype = matrix_cm;
8333 layout = packed;
8334 }
8335 };
8336
8337 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
8338 {
8339 public:
SetPath()8340 virtual void SetPath()
8341 {
8342 etype = matrix_rm;
8343 layout = shared;
8344 }
8345 };
8346
8347 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
8348 {
8349 public:
SetPath()8350 virtual void SetPath()
8351 {
8352 stage = fragment;
8353 etype = vector;
8354 layout = std430;
8355 }
8356 };
8357
8358 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
8359 {
8360 public:
SetPath()8361 virtual void SetPath()
8362 {
8363 stage = fragment;
8364 etype = matrix_cm;
8365 layout = std430;
8366 other_members = true;
8367 }
8368 };
8369
8370 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
8371 {
8372 public:
SetPath()8373 virtual void SetPath()
8374 {
8375 stage = fragment;
8376 etype = matrix_rm;
8377 layout = std140;
8378 }
8379 };
8380
8381 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
8382 {
8383 public:
SetPath()8384 virtual void SetPath()
8385 {
8386 stage = fragment;
8387 etype = structure;
8388 layout = std140;
8389 }
8390 };
8391
8392 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
8393 {
8394 public:
SetPath()8395 virtual void SetPath()
8396 {
8397 stage = vertex;
8398 etype = vector;
8399 layout = std430;
8400 other_members = true;
8401 }
8402 };
8403
8404 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
8405 {
8406 public:
SetPath()8407 virtual void SetPath()
8408 {
8409 stage = vertex;
8410 etype = matrix_cm;
8411 layout = std140;
8412 }
8413 };
8414
8415 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
8416 {
8417 public:
SetPath()8418 virtual void SetPath()
8419 {
8420 stage = vertex;
8421 etype = matrix_rm;
8422 layout = packed;
8423 }
8424 };
8425
8426 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
8427 {
8428 public:
SetPath()8429 virtual void SetPath()
8430 {
8431 stage = vertex;
8432 etype = structure;
8433 layout = std140;
8434 }
8435 };
8436
8437 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
8438 {
8439 public:
SetPath()8440 virtual void SetPath()
8441 {
8442 etype = vector;
8443 other_members = true;
8444 }
8445 };
8446
8447 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
8448 {
8449 public:
SetPath()8450 virtual void SetPath()
8451 {
8452 etype = matrix_cm;
8453 other_members = true;
8454 }
8455 };
8456
8457 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
8458 {
8459 public:
SetPath()8460 virtual void SetPath()
8461 {
8462 etype = matrix_rm;
8463 layout = std140;
8464 other_members = true;
8465 }
8466 };
8467
8468 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
8469 {
8470 public:
SetPath()8471 virtual void SetPath()
8472 {
8473 etype = structure;
8474 other_members = true;
8475 }
8476 };
8477
8478 //-----------------------------------------------------------------------------
8479 // 2.8 AdvancedMatrix
8480 //-----------------------------------------------------------------------------
8481
8482 class AdvancedMatrix : public ShaderStorageBufferObjectBase
8483 {
8484 GLuint m_program;
8485 GLuint m_storage_buffer[3];
8486 GLuint m_vertex_array;
8487 GLuint m_vertex_buffer;
8488 GLuint m_fbo, m_rt;
8489
Setup()8490 virtual long Setup()
8491 {
8492 m_program = 0;
8493 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
8494 m_vertex_array = 0;
8495 m_vertex_buffer = 0;
8496 glGenFramebuffers(1, &m_fbo);
8497 glGenTextures(1, &m_rt);
8498 return NO_ERROR;
8499 }
8500
Run()8501 virtual long Run()
8502 {
8503 if (!SupportedInVS(2))
8504 return NOT_SUPPORTED;
8505
8506 const char *const glsl_vs =
8507 NL "layout(location = 0) in vec4 g_position;" NL "out StageData {" NL " flat int instance_id;" NL
8508 "} vs_out;" NL "layout(binding = 0, std430) coherent buffer Buffer0 {" NL " mat3x4 g_transform[4];" NL
8509 " mat4x3 g_color;" NL " mat3 g_data0;" NL "};" NL
8510 "layout(binding = 1, std430) readonly buffer Buffer1 {" NL " mat4 color;" NL "} g_buffer1;" NL
8511 "uniform int g_index1 = 1;" NL "uniform int g_index2 = 2;" NL "void main() {" NL
8512 " gl_Position = vec4(transpose(g_transform[gl_InstanceID]) * g_position, 1);" NL
8513 " g_color[gl_InstanceID] = g_buffer1.color[gl_InstanceID].rgb;" NL
8514 " if (gl_VertexID == 0 && gl_InstanceID == 0) {" NL " g_data0[1][1] = 1.0;" NL
8515 " g_data0[g_index1][g_index2] += 3.0;" NL " }" NL " memoryBarrier();" NL
8516 " vs_out.instance_id = gl_InstanceID;" NL "}";
8517
8518 const char *const glsl_fs =
8519 NL "in StageData {" NL " flat int instance_id;" NL "} fs_in;" NL
8520 "layout(location = 0) out vec4 g_ocolor;" NL "layout(binding = 0, std430) coherent buffer Buffer0 {" NL
8521 " mat3x4 g_transform[4];" NL " mat4x3 g_color;" NL " mat3 g_data0;" NL "};" NL
8522 "uniform int g_index1 = 1;" NL "uniform int g_index2 = 2;" NL "void main() {" NL
8523 " if (g_data0[g_index1][g_index1] != 1.0) g_ocolor = vec4(0);" NL
8524 " else if (g_data0[g_index1][g_index2] != 3.0) g_ocolor = vec4(0);" NL
8525 " else g_ocolor = vec4(g_color[fs_in.instance_id], 1);" NL "}";
8526
8527 m_program = CreateProgram(glsl_vs, glsl_fs);
8528 glLinkProgram(m_program);
8529 if (!CheckProgram(m_program))
8530 return ERROR;
8531
8532 glGenBuffers(3, m_storage_buffer);
8533
8534 /* transform buffer */
8535 {
8536 float data[48 + 16 + 12 + 16] = {
8537 1.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f,
8538 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.5f,
8539 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
8540 };
8541 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
8542 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8543 }
8544 /* transform buffer */
8545 {
8546 float data[16] = {
8547 1.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f,
8548 };
8549 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
8550 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8551 }
8552 /* vertex buffer */
8553 {
8554 float data[8] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
8555 glGenBuffers(1, &m_vertex_buffer);
8556 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8557 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8558 glBindBuffer(GL_ARRAY_BUFFER, 0);
8559 }
8560
8561 glBindTexture(GL_TEXTURE_2D, m_rt);
8562 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8564 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
8565 glBindTexture(GL_TEXTURE_2D, 0);
8566 glViewport(0, 0, 100, 100);
8567 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
8568 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
8569
8570 glGenVertexArrays(1, &m_vertex_array);
8571 glBindVertexArray(m_vertex_array);
8572 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8573 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
8574 glBindBuffer(GL_ARRAY_BUFFER, 0);
8575 glEnableVertexAttribArray(0);
8576 glBindVertexArray(0);
8577
8578 glClear(GL_COLOR_BUFFER_BIT);
8579 glUseProgram(m_program);
8580 glBindVertexArray(m_vertex_array);
8581 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
8582
8583 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)))
8584 {
8585 return ERROR;
8586 }
8587 return NO_ERROR;
8588 }
8589
Cleanup()8590 virtual long Cleanup()
8591 {
8592 glViewport(0, 0, getWindowWidth(), getWindowHeight());
8593 glUseProgram(0);
8594 glDeleteProgram(m_program);
8595 glDeleteBuffers(3, m_storage_buffer);
8596 glDeleteBuffers(1, &m_vertex_buffer);
8597 glDeleteVertexArrays(1, &m_vertex_array);
8598 glDeleteFramebuffers(1, &m_fbo);
8599 glDeleteTextures(1, &m_rt);
8600 return NO_ERROR;
8601 }
8602 };
8603
8604 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8605 {
8606 GLuint m_program;
8607 GLuint m_storage_buffer;
8608
Setup()8609 virtual long Setup()
8610 {
8611 m_program = 0;
8612 m_storage_buffer = 0;
8613 return NO_ERROR;
8614 }
8615
Run()8616 virtual long Run()
8617 {
8618 bool status = true;
8619 const char *const glsl_cs =
8620 NL "layout(local_size_x = 1) in;" NL "layout(std430) buffer Buffer {" NL " mat4x3 dst4x3;" NL
8621 " mat4 dst4;" NL " mat4 src4;" NL "} b;" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8622 "void main() {" NL " b.dst4x3[gl_LocalInvocationIndex] = b.src4[gl_LocalInvocationIndex].rgb;" NL
8623 " b.dst4x3[gl_LocalInvocationIndex + 1u] = b.src4[gl_LocalInvocationIndex + 1u].aar;" NL
8624 " b.dst4[g_index2][g_index1] = 17.0;" NL " b.dst4[g_index2][g_index1] += 6.0;" NL
8625 " b.dst4[3][0] = b.src4[3][0] != 44.0 ? 3.0 : 7.0;" NL " b.dst4[3][1] = b.src4[3][1];" NL "}";
8626 m_program = CreateProgramCS(glsl_cs);
8627 glLinkProgram(m_program);
8628 if (!CheckProgram(m_program))
8629 return ERROR;
8630
8631 glGenBuffers(1, &m_storage_buffer);
8632 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
8633 GLfloat data[16 + 16 + 16];
8634 for (int i = 0; i < 32; ++i)
8635 data[i] = 0.0f;
8636 for (int i = 32; i < 48; ++i)
8637 data[i] = (GLfloat)i;
8638 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
8639
8640 glUseProgram(m_program);
8641 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8642 glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8643 glDispatchCompute(1, 1, 1);
8644 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8645 GLfloat *out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
8646 if (!out_data)
8647 return ERROR;
8648
8649 GLfloat expected[32] = {
8650 32.0f, 33.0f, 34.0f, 0.0f, 39.0f, 39.0f, 36.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
8651
8652 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 23.0f, 0.0f, 0.0f, 7.0f, 45.0f, 0.0f, 0.0f};
8653 for (int i = 0; i < 32; ++i)
8654 {
8655 if (out_data[i] != expected[i])
8656 {
8657 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i]
8658 << ", but expected: " << expected[i] << tcu::TestLog::EndMessage;
8659 status = false;
8660 }
8661 }
8662 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8663 if (status)
8664 return NO_ERROR;
8665 else
8666 return ERROR;
8667 }
8668
Cleanup()8669 virtual long Cleanup()
8670 {
8671 glUseProgram(0);
8672 glDeleteProgram(m_program);
8673 glDeleteBuffers(1, &m_storage_buffer);
8674 return NO_ERROR;
8675 }
8676 };
8677 //-----------------------------------------------------------------------------
8678 // 4.1.1 NegativeAPIBind
8679 //-----------------------------------------------------------------------------
8680
8681 class NegativeAPIBind : public ShaderStorageBufferObjectBase
8682 {
Run()8683 virtual long Run()
8684 {
8685 GLint bindings;
8686 GLint alignment;
8687 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8688 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
8689
8690 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8691 if (glGetError() != GL_INVALID_VALUE)
8692 {
8693 m_context.getTestContext().getLog()
8694 << tcu::TestLog::Message
8695 << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8696 "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8697 "MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8698 << tcu::TestLog::EndMessage;
8699 return ERROR;
8700 }
8701
8702 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8703 if (glGetError() != GL_INVALID_VALUE)
8704 {
8705 m_context.getTestContext().getLog()
8706 << tcu::TestLog::Message
8707 << "INVALID_VALUE is generated by BindBufferRange if <target> is\n"
8708 "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8709 "MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8710 << tcu::TestLog::EndMessage;
8711 return ERROR;
8712 }
8713
8714 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 0, alignment - 1, 0);
8715 if (glGetError() != GL_INVALID_VALUE)
8716 {
8717 m_context.getTestContext().getLog()
8718 << tcu::TestLog::Message
8719 << "INVALID_VALUE is generated by BindBufferRange if <target> is\n"
8720 "SHADER_STORAGE_BUFFER and <offset> is not a multiple of the value of\n"
8721 "SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."
8722 << tcu::TestLog::EndMessage;
8723 return ERROR;
8724 }
8725
8726 return NO_ERROR;
8727 }
8728 };
8729 //-----------------------------------------------------------------------------
8730 // 4.1.2 NegativeAPIBlockBinding
8731 //-----------------------------------------------------------------------------
8732
8733 class NegativeAPIBlockBinding : public ShaderStorageBufferObjectBase
8734 {
Run()8735 virtual long Run()
8736 {
8737 if (!SupportedInVS(1))
8738 return NOT_SUPPORTED;
8739 GLint bindings;
8740 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8741
8742 const char *const glsl_vs =
8743 "#version 430 core" NL "buffer Buffer {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}";
8744 const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8745 glShaderSource(sh, 1, &glsl_vs, NULL);
8746 glCompileShader(sh);
8747
8748 const GLuint p = glCreateProgram();
8749 glAttachShader(p, sh);
8750 glDeleteShader(sh);
8751 glLinkProgram(p);
8752
8753 glShaderStorageBlockBinding(p, 0, bindings);
8754 if (glGetError() != GL_INVALID_VALUE)
8755 {
8756 m_context.getTestContext().getLog()
8757 << tcu::TestLog::Message
8758 << "An INVALID_VALUE error is generated if storageBlockBinding is\n"
8759 "greater than or equal to the value of MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8760 << tcu::TestLog::EndMessage;
8761 glDeleteProgram(p);
8762 return ERROR;
8763 }
8764
8765 glShaderStorageBlockBinding(p, 1, 0);
8766 if (glGetError() != GL_INVALID_VALUE)
8767 {
8768 m_context.getTestContext().getLog()
8769 << tcu::TestLog::Message
8770 << "An INVALID_VALUE error is generated if storageBlockIndex is not an\n"
8771 "active shader storage block index in program."
8772 << tcu::TestLog::EndMessage;
8773 glDeleteProgram(p);
8774 return ERROR;
8775 }
8776
8777 glShaderStorageBlockBinding(0, 0, 0);
8778 if (glGetError() != GL_INVALID_VALUE)
8779 {
8780 m_context.getTestContext().getLog() << tcu::TestLog::Message
8781 << "An INVALID_VALUE error is generated if program is not the name of "
8782 "either a program or shader object."
8783 << tcu::TestLog::EndMessage;
8784 glDeleteProgram(p);
8785 return ERROR;
8786 }
8787
8788 glShaderStorageBlockBinding(sh, 0, 0);
8789 if (glGetError() != GL_INVALID_OPERATION)
8790 {
8791 m_context.getTestContext().getLog()
8792 << tcu::TestLog::Message
8793 << "An INVALID_OPERATION error is generated if program is the name of a shader object."
8794 << tcu::TestLog::EndMessage;
8795 glDeleteProgram(p);
8796 return ERROR;
8797 }
8798
8799 glDeleteProgram(p);
8800 return NO_ERROR;
8801 }
8802 };
8803 //-----------------------------------------------------------------------------
8804 // 4.2.1 NegativeGLSLCompileTime
8805 //-----------------------------------------------------------------------------
8806
8807 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8808 {
Shader1(int binding)8809 static std::string Shader1(int binding)
8810 {
8811 std::stringstream ss;
8812 ss << NL "layout(binding = " << binding
8813 << ") buffer Buffer {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}";
8814 return ss.str();
8815 }
8816
Shader2(int binding)8817 static std::string Shader2(int binding)
8818 {
8819 std::stringstream ss;
8820 ss << NL "layout(binding = " << binding
8821 << ") buffer Buffer {" NL " int x;" NL "} g_array[4];" NL "void main() {" NL " g_array[0].x = 0;" NL
8822 " g_array[1].x = 0;" NL " g_array[2].x = 0;" NL " g_array[3].x = 0;" NL "}";
8823 return ss.str();
8824 }
8825
Run()8826 virtual long Run()
8827 {
8828 GLint bindings;
8829 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8830
8831 // initialization of buffer block member 'x' not allowed
8832 if (!Compile(NL "buffer Buffer { int x = 10; };" NL "void main() {" NL " x = 0;" NL "}"))
8833 return ERROR;
8834
8835 // syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8836 if (!Compile(Shader1(-1)))
8837 return ERROR;
8838 // invalid value 96 for layout specifier 'binding'
8839 if (!Compile(Shader1(bindings)))
8840 return ERROR;
8841
8842 // invalid value 98 for layout specifier 'binding'
8843 if (!Compile(Shader2(bindings - 2)))
8844 return ERROR;
8845
8846 // OpenGL does not allow declaring buffer variable 'x' in the global scope. Use buffer blocks instead
8847 if (!Compile(NL "buffer int x;" NL "void main() {" NL " x = 0;" NL "}"))
8848 return ERROR;
8849
8850 // OpenGL requires buffer variables to be declared in a shader storage block in the global scope
8851 if (!Compile(NL "buffer Buffer { int y; };" NL "void main() {" NL " y = 0;" NL " buffer int x = 0;" NL "}"))
8852 return ERROR;
8853
8854 // OpenGL does not allow a parameter to be a buffer
8855 if (!Compile(NL "buffer Buffer { int y; };" NL "void Modify(buffer int a) {" NL " atomicAdd(a, 1);" NL "}" NL
8856 "void main() {" NL " Modify(y);" NL "}"))
8857 return ERROR;
8858
8859 // layout specifier 'std430', incompatible with 'uniform blocks'
8860 if (!Compile(NL "layout(std430) uniform UBO { int x; };" NL "buffer SSBO { int y; };" NL "void main() {" NL
8861 " y = x;" NL "}"))
8862 return ERROR;
8863
8864 // unknown layout specifier 'std430'
8865 if (!Compile(NL "buffer SSBO {" NL " layout(std430) int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}"))
8866 return ERROR;
8867
8868 // unknown layout specifier 'binding = 1'
8869 if (!Compile(NL "buffer SSBO {" NL " layout(binding = 1) int x;" NL "};" NL "void main() {" NL " x = 0;" NL
8870 "}"))
8871 return ERROR;
8872
8873 // OpenGL does not allow writing to readonly variable 'x'
8874 if (!Compile(NL "readonly buffer SSBO {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}"))
8875 return ERROR;
8876
8877 // OpenGL does not allow reading writeonly variable 'y'
8878 if (!Compile(NL "buffer SSBO {" NL " int x;" NL "};" NL "writeonly buffer SSBO2 {" NL " int y;" NL "};" NL
8879 "void main() {" NL " x = y;" NL "}"))
8880 return ERROR;
8881
8882 // OpenGL does not allow writing to readonly variable 'z'
8883 if (!Compile(NL "buffer SSBO {" NL " int x;" NL "};" NL "buffer SSBO2 {" NL " writeonly int y;" NL
8884 " readonly int z;" NL "};" NL "void main() {" NL " x = y;" NL " z = 0;" NL "}"))
8885 return ERROR;
8886
8887 // OpenGL does not allow having both readonly and writeonly qualifiers on a variable
8888 if (!Compile(NL "buffer SSBO {" NL " int x;" NL "};" NL "readonly buffer SSBO2 {" NL " writeonly int y;" NL
8889 "};" NL "void main() {" NL " x = y;" NL "}"))
8890 return ERROR;
8891
8892 // ["layout(binding = 1) buffer;" should cause compile-time error
8893 if (!Compile(NL "layout(binding = 1) buffer;" NL "buffer SSBO {" NL " int x;" NL "};" NL "void main() {" NL
8894 " x = 0;" NL "}"))
8895 return ERROR;
8896
8897 // [" atomicAdd(y, 2);" should cause compile-time error
8898 if (!Compile(NL "buffer Buffer { int x; };" NL "int y;" NL "void main() {" NL " atomicAdd(x, 1);" NL
8899 " atomicAdd(y, 2);" //
8900 NL "}"))
8901 return ERROR;
8902
8903 if (!Compile( // can't construct vector from an array
8904 NL "buffer b {" NL " vec4 x[10];" NL "};" NL "void main() {" NL " vec4 y = vec4(x);" NL "}"))
8905 return ERROR;
8906
8907 return NO_ERROR;
8908 }
8909
Compile(const std::string & source)8910 bool Compile(const std::string &source)
8911 {
8912 const char *const csVer = "#version 430 core";
8913 const char *const src[2] = {csVer, source.c_str()};
8914 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8915 glShaderSource(sh, 2, src, NULL);
8916 glCompileShader(sh);
8917
8918 GLchar log[1024];
8919 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8920 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
8921 << log << tcu::TestLog::EndMessage;
8922
8923 GLint status;
8924 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8925 glDeleteShader(sh);
8926
8927 if (status == GL_TRUE)
8928 {
8929 m_context.getTestContext().getLog()
8930 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
8931 return false;
8932 }
8933
8934 return true;
8935 }
8936 };
8937
8938 //-----------------------------------------------------------------------------
8939 // 4.2.2 NegativeGLSLLinkTime
8940 //-----------------------------------------------------------------------------
8941 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8942 {
Run()8943 virtual long Run()
8944 {
8945 // declaration of "x" conflicts with previous declaration at 0(4)
8946 // declaration of "Buffer" conflicts with previous declaration at 0(4)
8947 if (!Link("#version 430 core" NL "buffer Buffer { int x; };" NL "void Run();" NL "void main() {" NL
8948 " Run();" NL " x += 2;" NL "}",
8949 "#version 430 core" NL "buffer Buffer { uint x; };" NL "void Run() {" NL " x += 3;" NL "}"))
8950 return ERROR;
8951
8952 // declaration of "Buffer" conflicts with previous declaration at 0(4)
8953 if (!Link("#version 430 core" NL "buffer Buffer { int x; int y; };" NL "void Run();" NL "void main() {" NL
8954 " Run();" NL " x += 2;" NL "}",
8955 "#version 430 core" NL "buffer Buffer { int x; };" NL "void Run() {" NL " x += 3;" NL "}"))
8956 return ERROR;
8957
8958 // declaration of "Buffer" conflicts with previous declaration at 0(4)
8959 if (!Link("#version 430 core" NL "buffer Buffer { int y; };" NL "void Run();" NL "void main() {" NL
8960 " Run();" NL " y += 2;" NL "}",
8961 "#version 430 core" NL "buffer Buffer { int x; };" NL "void Run() {" NL " x += 3;" NL "}"))
8962 return ERROR;
8963
8964 // declaration of "g_buffer" conflicts with previous declaration at 0(4)
8965 // declaration of "Buffer" conflicts with previous declaration at 0(4)
8966 if (!Link("#version 430 core" NL "buffer Buffer { int x; } g_buffer[2];" NL "void Run();" NL "void main() {" NL
8967 " Run();" NL " g_buffer[0].x += 2;" NL "}",
8968 "#version 430 core" NL "buffer Buffer { int x; } g_buffer[3];" NL "void Run() {" NL
8969 " g_buffer[1].x += 3;" NL "}"))
8970 return ERROR;
8971
8972 return NO_ERROR;
8973 }
8974
Link(const std::string & cs0,const std::string & cs1)8975 bool Link(const std::string &cs0, const std::string &cs1)
8976 {
8977 const GLuint p = glCreateProgram();
8978
8979 /* shader 0 */
8980 {
8981 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8982 glAttachShader(p, sh);
8983 glDeleteShader(sh);
8984 const char *const src = cs0.c_str();
8985 glShaderSource(sh, 1, &src, NULL);
8986 glCompileShader(sh);
8987
8988 GLint status;
8989 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8990 if (status == GL_FALSE)
8991 {
8992 glDeleteProgram(p);
8993 m_context.getTestContext().getLog()
8994 << tcu::TestLog::Message << "VS0 compilation should be ok." << tcu::TestLog::EndMessage;
8995 return false;
8996 }
8997 }
8998 /* shader 1 */
8999 {
9000 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
9001 glAttachShader(p, sh);
9002 glDeleteShader(sh);
9003 const char *const src = cs1.c_str();
9004 glShaderSource(sh, 1, &src, NULL);
9005 glCompileShader(sh);
9006
9007 GLint status;
9008 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
9009 if (status == GL_FALSE)
9010 {
9011 glDeleteProgram(p);
9012 m_context.getTestContext().getLog()
9013 << tcu::TestLog::Message << "VS1 compilation should be ok." << tcu::TestLog::EndMessage;
9014 return false;
9015 }
9016 }
9017
9018 glLinkProgram(p);
9019
9020 GLchar log[1024];
9021 glGetProgramInfoLog(p, sizeof(log), NULL, log);
9022 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
9023 << log << tcu::TestLog::EndMessage;
9024
9025 GLint status;
9026 glGetProgramiv(p, GL_LINK_STATUS, &status);
9027 glDeleteProgram(p);
9028
9029 if (status == GL_TRUE)
9030 {
9031 m_context.getTestContext().getLog()
9032 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
9033 return false;
9034 }
9035
9036 return true;
9037 }
9038 };
9039
9040 } // anonymous namespace
9041
ShaderStorageBufferObjectTests(deqp::Context & context)9042 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context &context)
9043 : TestCaseGroup(context, "shader_storage_buffer_object", "")
9044 {
9045 }
9046
~ShaderStorageBufferObjectTests(void)9047 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
9048 {
9049 }
9050
init()9051 void ShaderStorageBufferObjectTests::init()
9052 {
9053 using namespace deqp;
9054
9055 addChild(new TestSubcase(m_context, "basic-basic", TestSubcase::Create<BasicBasic>));
9056 addChild(new TestSubcase(m_context, "basic-basic-cs", TestSubcase::Create<BasicBasicCS>));
9057 addChild(new TestSubcase(m_context, "basic-max", TestSubcase::Create<BasicMax>));
9058 addChild(new TestSubcase(m_context, "basic-binding", TestSubcase::Create<BasicBinding>));
9059 addChild(new TestSubcase(m_context, "basic-syntax", TestSubcase::Create<BasicSyntax>));
9060 addChild(new TestSubcase(m_context, "basic-syntaxSSO", TestSubcase::Create<BasicSyntaxSSO>));
9061 addChild(new TestSubcase(m_context, "basic-std430Layout-case1-vs", TestSubcase::Create<BasicStd430LayoutCase1VS>));
9062 addChild(new TestSubcase(m_context, "basic-std430Layout-case1-cs", TestSubcase::Create<BasicStd430LayoutCase1CS>));
9063 addChild(new TestSubcase(m_context, "basic-std430Layout-case2-vs", TestSubcase::Create<BasicStd430LayoutCase2VS>));
9064 addChild(new TestSubcase(m_context, "basic-std430Layout-case2-cs", TestSubcase::Create<BasicStd430LayoutCase2CS>));
9065 addChild(new TestSubcase(m_context, "basic-std430Layout-case3-vs", TestSubcase::Create<BasicStd430LayoutCase3VS>));
9066 addChild(new TestSubcase(m_context, "basic-std430Layout-case3-cs", TestSubcase::Create<BasicStd430LayoutCase3CS>));
9067 addChild(new TestSubcase(m_context, "basic-std430Layout-case4-vs", TestSubcase::Create<BasicStd430LayoutCase4VS>));
9068 addChild(new TestSubcase(m_context, "basic-std430Layout-case4-cs", TestSubcase::Create<BasicStd430LayoutCase4CS>));
9069 addChild(new TestSubcase(m_context, "basic-std430Layout-case5-vs", TestSubcase::Create<BasicStd430LayoutCase5VS>));
9070 addChild(new TestSubcase(m_context, "basic-std430Layout-case5-cs", TestSubcase::Create<BasicStd430LayoutCase5CS>));
9071 addChild(new TestSubcase(m_context, "basic-std430Layout-case6-vs", TestSubcase::Create<BasicStd430LayoutCase6VS>));
9072 addChild(new TestSubcase(m_context, "basic-std430Layout-case6-cs", TestSubcase::Create<BasicStd430LayoutCase6CS>));
9073 addChild(new TestSubcase(m_context, "basic-std430Layout-case7-vs", TestSubcase::Create<BasicStd430LayoutCase7VS>));
9074 addChild(new TestSubcase(m_context, "basic-std430Layout-case7-cs", TestSubcase::Create<BasicStd430LayoutCase7CS>));
9075 addChild(new TestSubcase(m_context, "basic-std140Layout-case1-vs", TestSubcase::Create<BasicStd140LayoutCase1VS>));
9076 addChild(new TestSubcase(m_context, "basic-std140Layout-case1-cs", TestSubcase::Create<BasicStd140LayoutCase1CS>));
9077 addChild(new TestSubcase(m_context, "basic-std140Layout-case2-vs", TestSubcase::Create<BasicStd140LayoutCase2VS>));
9078 addChild(new TestSubcase(m_context, "basic-std140Layout-case2-cs", TestSubcase::Create<BasicStd140LayoutCase2CS>));
9079 addChild(new TestSubcase(m_context, "basic-std140Layout-case3-vs", TestSubcase::Create<BasicStd140LayoutCase3VS>));
9080 addChild(new TestSubcase(m_context, "basic-std140Layout-case3-cs", TestSubcase::Create<BasicStd140LayoutCase3CS>));
9081 addChild(new TestSubcase(m_context, "basic-std140Layout-case4-vs", TestSubcase::Create<BasicStd140LayoutCase4VS>));
9082 addChild(new TestSubcase(m_context, "basic-std140Layout-case4-cs", TestSubcase::Create<BasicStd140LayoutCase4CS>));
9083 addChild(new TestSubcase(m_context, "basic-std140Layout-case5-vs", TestSubcase::Create<BasicStd140LayoutCase5VS>));
9084 addChild(new TestSubcase(m_context, "basic-std140Layout-case5-cs", TestSubcase::Create<BasicStd140LayoutCase5CS>));
9085 addChild(new TestSubcase(m_context, "basic-std140Layout-case6-vs", TestSubcase::Create<BasicStd140LayoutCase6VS>));
9086 addChild(new TestSubcase(m_context, "basic-std140Layout-case6-cs", TestSubcase::Create<BasicStd140LayoutCase6CS>));
9087 addChild(new TestSubcase(m_context, "basic-atomic-case1", TestSubcase::Create<BasicAtomicCase1>));
9088 addChild(new TestSubcase(m_context, "basic-atomic-case1-cs", TestSubcase::Create<BasicAtomicCase1CS>));
9089 addChild(new TestSubcase(m_context, "basic-atomic-case2", TestSubcase::Create<BasicAtomicCase2>));
9090 addChild(new TestSubcase(m_context, "basic-atomic-case3", TestSubcase::Create<BasicAtomicCase3>));
9091 addChild(new TestSubcase(m_context, "basic-atomic-case3-cs", TestSubcase::Create<BasicAtomicCase3CS>));
9092 addChild(new TestSubcase(m_context, "basic-atomic-case4", TestSubcase::Create<BasicAtomicCase4>));
9093 addChild(new TestSubcase(m_context, "basic-atomic-case4-cs", TestSubcase::Create<BasicAtomicCase4CS>));
9094 addChild(new TestSubcase(m_context, "basic-stdLayout-case1-vs", TestSubcase::Create<BasicStdLayoutCase1VS>));
9095 addChild(new TestSubcase(m_context, "basic-stdLayout-case1-cs", TestSubcase::Create<BasicStdLayoutCase1CS>));
9096 addChild(new TestSubcase(m_context, "basic-stdLayout-case2-vs", TestSubcase::Create<BasicStdLayoutCase2VS>));
9097 addChild(new TestSubcase(m_context, "basic-stdLayout-case2-cs", TestSubcase::Create<BasicStdLayoutCase2CS>));
9098 addChild(new TestSubcase(m_context, "basic-stdLayout-case3-vs", TestSubcase::Create<BasicStdLayoutCase3VS>));
9099 addChild(new TestSubcase(m_context, "basic-stdLayout-case3-cs", TestSubcase::Create<BasicStdLayoutCase3CS>));
9100 addChild(new TestSubcase(m_context, "basic-stdLayout-case4-vs", TestSubcase::Create<BasicStdLayoutCase4VS>));
9101 addChild(new TestSubcase(m_context, "basic-stdLayout-case4-cs", TestSubcase::Create<BasicStdLayoutCase4CS>));
9102 addChild(new TestSubcase(m_context, "basic-operations-case1-vs", TestSubcase::Create<BasicOperationsCase1VS>));
9103 addChild(new TestSubcase(m_context, "basic-operations-case1-cs", TestSubcase::Create<BasicOperationsCase1CS>));
9104 addChild(new TestSubcase(m_context, "basic-operations-case2-vs", TestSubcase::Create<BasicOperationsCase2VS>));
9105 addChild(new TestSubcase(m_context, "basic-operations-case2-cs", TestSubcase::Create<BasicOperationsCase2CS>));
9106 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-vs",
9107 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1VS>));
9108 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-cs",
9109 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1CS>));
9110 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-vs",
9111 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2VS>));
9112 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-cs",
9113 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2CS>));
9114 addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-vs",
9115 TestSubcase::Create<BasicMatrixOperationsCase1VS>));
9116 addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-cs",
9117 TestSubcase::Create<BasicMatrixOperationsCase1CS>));
9118 addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-vs",
9119 TestSubcase::Create<BasicMatrixOperationsCase2VS>));
9120 addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-cs",
9121 TestSubcase::Create<BasicMatrixOperationsCase2CS>));
9122 addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-vs",
9123 TestSubcase::Create<BasicMatrixOperationsCase3VS>));
9124 addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-cs",
9125 TestSubcase::Create<BasicMatrixOperationsCase3CS>));
9126 addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-vs",
9127 TestSubcase::Create<BasicMatrixOperationsCase4VS>));
9128 addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-cs",
9129 TestSubcase::Create<BasicMatrixOperationsCase4CS>));
9130 addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-vs",
9131 TestSubcase::Create<BasicMatrixOperationsCase5VS>));
9132 addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-cs",
9133 TestSubcase::Create<BasicMatrixOperationsCase5CS>));
9134 addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-vs",
9135 TestSubcase::Create<BasicMatrixOperationsCase6VS>));
9136 addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-cs",
9137 TestSubcase::Create<BasicMatrixOperationsCase6CS>));
9138 addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-vs",
9139 TestSubcase::Create<BasicMatrixOperationsCase7VS>));
9140 addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-cs",
9141 TestSubcase::Create<BasicMatrixOperationsCase7CS>));
9142 addChild(new TestSubcase(m_context, "basic-noBindingLayout", TestSubcase::Create<BasicNoBindingLayout>));
9143 addChild(new TestSubcase(m_context, "basic-readonly-writeonly", TestSubcase::Create<BasicReadonlyWriteonly>));
9144 addChild(new TestSubcase(m_context, "basic-name-match", TestSubcase::Create<BasicNameMatch>));
9145 addChild(new TestSubcase(m_context, "advanced-switchBuffers", TestSubcase::Create<AdvancedSwitchBuffers>));
9146 addChild(new TestSubcase(m_context, "advanced-switchBuffers-cs", TestSubcase::Create<AdvancedSwitchBuffersCS>));
9147 addChild(new TestSubcase(m_context, "advanced-switchPrograms", TestSubcase::Create<AdvancedSwitchPrograms>));
9148 addChild(new TestSubcase(m_context, "advanced-switchPrograms-cs", TestSubcase::Create<AdvancedSwitchProgramsCS>));
9149 addChild(new TestSubcase(m_context, "advanced-write-fragment", TestSubcase::Create<AdvancedWriteFragment>));
9150 addChild(new TestSubcase(m_context, "advanced-write-geometry", TestSubcase::Create<AdvancedWriteGeometry>));
9151 addChild(new TestSubcase(m_context, "advanced-write-tessellation", TestSubcase::Create<AdvancedWriteTessellation>));
9152 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1",
9153 TestSubcase::Create<AdvancedIndirectAddressingCase1>));
9154 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-cs",
9155 TestSubcase::Create<AdvancedIndirectAddressingCase1CS>));
9156 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2",
9157 TestSubcase::Create<AdvancedIndirectAddressingCase2>));
9158 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-cs",
9159 TestSubcase::Create<AdvancedIndirectAddressingCase2CS>));
9160 addChild(new TestSubcase(m_context, "advanced-readWrite-case1", TestSubcase::Create<AdvancedReadWriteCase1>));
9161 addChild(new TestSubcase(m_context, "advanced-readWrite-case1-cs", TestSubcase::Create<AdvancedReadWriteCase1CS>));
9162 addChild(new TestSubcase(m_context, "advanced-usage-case1", TestSubcase::Create<AdvancedUsageCase1>));
9163 addChild(new TestSubcase(m_context, "advanced-usage-sync", TestSubcase::Create<AdvancedUsageSync>));
9164 addChild(new TestSubcase(m_context, "advanced-usage-sync-cs", TestSubcase::Create<AdvancedUsageSyncCS>));
9165 addChild(new TestSubcase(m_context, "advanced-usage-operators", TestSubcase::Create<AdvancedUsageOperators>));
9166 addChild(new TestSubcase(m_context, "advanced-usage-operators-cs", TestSubcase::Create<AdvancedUsageOperatorsCS>));
9167 addChild(
9168 new TestSubcase(m_context, "advanced-unsizedArrayLength", TestSubcase::Create<AdvancedUnsizedArrayLength>));
9169 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec",
9170 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec>));
9171 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC",
9172 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC>));
9173 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matR",
9174 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matR>));
9175 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct",
9176 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct>));
9177 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-vec",
9178 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_vec>));
9179 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matC",
9180 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matC>));
9181 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR",
9182 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR>));
9183 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-struct",
9184 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_struct>));
9185 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-vec",
9186 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_vec>));
9187 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-matC",
9188 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_matC>));
9189 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-shared-matR",
9190 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_shared_matR>));
9191 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-vec",
9192 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_vec>));
9193 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-matC-pad",
9194 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_matC_pad>));
9195 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-matR",
9196 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_matR>));
9197 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-struct",
9198 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_struct>));
9199 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std430-vec",
9200 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std430_vec_pad>));
9201 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-matC",
9202 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_matC>));
9203 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-packed-matR",
9204 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_packed_matR>));
9205 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-struct",
9206 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_struct>));
9207 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-pad",
9208 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_pad>));
9209 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC-pad",
9210 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC_pad>));
9211 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR-pad",
9212 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR_pad>));
9213 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct-pad",
9214 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct_pad>));
9215
9216 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
9217 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
9218
9219 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
9220 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
9221
9222 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
9223 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
9224
9225 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
9226 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
9227
9228 addChild(new TestSubcase(m_context, "advanced-matrix", TestSubcase::Create<AdvancedMatrix>));
9229 addChild(new TestSubcase(m_context, "advanced-matrix-cs", TestSubcase::Create<AdvancedMatrixCS>));
9230 addChild(new TestSubcase(m_context, "negative-api-bind", TestSubcase::Create<NegativeAPIBind>));
9231 addChild(new TestSubcase(m_context, "negative-api-blockBinding", TestSubcase::Create<NegativeAPIBlockBinding>));
9232 addChild(new TestSubcase(m_context, "negative-glsl-compileTime", TestSubcase::Create<NegativeGLSLCompileTime>));
9233 addChild(new TestSubcase(m_context, "negative-glsl-linkTime", TestSubcase::Create<NegativeGLSLLinkTime>));
9234 }
9235
9236 } // namespace gl4cts
9237