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 "gl4cES31CompatibilityTests.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
35 namespace es31compatibility
36 {
37 using namespace glw;
38
39 namespace
40 {
41
42 typedef tcu::Vec2 vec2;
43 typedef tcu::Vec3 vec3;
44 typedef tcu::Vec4 vec4;
45 typedef tcu::IVec4 ivec4;
46 typedef tcu::UVec4 uvec4;
47 typedef tcu::Mat4 mat4;
48
49 enum ShaderStage
50 {
51 vertex,
52 fragment,
53 compute
54 };
55 enum BufferLayout
56 {
57 std140,
58 std430,
59 shared,
60 packed
61 };
62 enum ElementType
63 {
64 vector,
65 matrix_cm,
66 matrix_rm,
67 structure
68 };
69 enum BindingSeq
70 {
71 bindbasebefore,
72 bindbaseafter,
73 bindrangeoffset,
74 bindrangesize
75 };
76
77 const char* const kGLSLVer = "#version 310 es" NL "precision highp float;" NL "precision highp int;";
78
79 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
80 {
Title()81 virtual std::string Title()
82 {
83 return "";
84 }
85
Purpose()86 virtual std::string Purpose()
87 {
88 return "";
89 }
90
Method()91 virtual std::string Method()
92 {
93 return "";
94 }
95
PassCriteria()96 virtual std::string PassCriteria()
97 {
98 return "";
99 }
100
101 public:
IsVSFSAvailable(int requiredVS,int requiredFS)102 bool IsVSFSAvailable(int requiredVS, int requiredFS)
103 {
104 GLint blocksVS, blocksFS;
105 glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
106 glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
107 if (blocksVS >= requiredVS && blocksFS >= requiredFS)
108 return true;
109 else
110 {
111 std::ostringstream reason;
112 reason << "Required " << requiredVS << " VS storage blocks but only " << blocksVS << " available."
113 << std::endl
114 << "Required " << requiredFS << " FS storage blocks but only " << blocksFS << " available."
115 << std::endl;
116 OutputNotSupported(reason.str());
117 return false;
118 }
119 }
120
getWindowWidth()121 int getWindowWidth()
122 {
123 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
124 return renderTarget.getWidth();
125 }
126
getWindowHeight()127 int getWindowHeight()
128 {
129 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
130 return renderTarget.getHeight();
131 }
132
CheckProgram(GLuint program)133 bool CheckProgram(GLuint program)
134 {
135 GLint status;
136 glGetProgramiv(program, GL_LINK_STATUS, &status);
137
138 if (status == GL_FALSE)
139 {
140 GLint attached_shaders;
141 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
142
143 if (attached_shaders > 0)
144 {
145 std::vector<GLuint> shaders(attached_shaders);
146 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
147
148 for (GLint i = 0; i < attached_shaders; ++i)
149 {
150 GLenum type;
151 glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
152 switch (type)
153 {
154 case GL_VERTEX_SHADER:
155 m_context.getTestContext().getLog()
156 << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
157 break;
158 case GL_FRAGMENT_SHADER:
159 m_context.getTestContext().getLog()
160 << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
161 break;
162 case GL_COMPUTE_SHADER:
163 m_context.getTestContext().getLog()
164 << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
165 break;
166 default:
167 m_context.getTestContext().getLog()
168 << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
169 }
170 GLint length;
171 glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
172 if (length > 0)
173 {
174 std::vector<GLchar> source(length);
175 glGetShaderSource(shaders[i], length, NULL, &source[0]);
176 m_context.getTestContext().getLog()
177 << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
178 }
179 glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
180 if (length > 0)
181 {
182 std::vector<GLchar> log(length);
183 glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
184 m_context.getTestContext().getLog()
185 << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
186 }
187 }
188 }
189 GLint length;
190 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
191 if (length > 0)
192 {
193 std::vector<GLchar> log(length);
194 glGetProgramInfoLog(program, length, NULL, &log[0]);
195 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
196 }
197 }
198
199 return status == GL_TRUE ? true : false;
200 }
201
CreateProgram(const std::string & vs,const std::string & fs)202 GLuint CreateProgram(const std::string& vs, const std::string& fs)
203 {
204 const GLuint p = glCreateProgram();
205
206 if (!vs.empty())
207 {
208 const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
209 glAttachShader(p, sh);
210 glDeleteShader(sh);
211 const char* const src[2] = { kGLSLVer, vs.c_str() };
212 glShaderSource(sh, 2, src, NULL);
213 glCompileShader(sh);
214 }
215 if (!fs.empty())
216 {
217 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
218 glAttachShader(p, sh);
219 glDeleteShader(sh);
220 const char* const src[2] = { kGLSLVer, fs.c_str() };
221 glShaderSource(sh, 2, src, NULL);
222 glCompileShader(sh);
223 }
224
225 return p;
226 }
CreateProgramCS(const std::string & cs)227 GLuint CreateProgramCS(const std::string& cs)
228 {
229 const GLuint p = glCreateProgram();
230
231 if (!cs.empty())
232 {
233 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
234 glAttachShader(p, sh);
235 glDeleteShader(sh);
236 const char* const src[2] = { kGLSLVer, cs.c_str() };
237 glShaderSource(sh, 2, src, NULL);
238 glCompileShader(sh);
239 }
240 return p;
241 }
242
BuildShaderProgram(GLenum type,const std::string & source)243 GLuint BuildShaderProgram(GLenum type, const std::string& source)
244 {
245 const char* const src[2] = { kGLSLVer, source.c_str() };
246 return glCreateShaderProgramv(type, 2, src);
247 }
248
ColorEqual(int x,int y,const vec3 & c0,const vec3 & expected,const vec3 & epsilon,const vec3 & color_max)249 bool ColorEqual(int x, int y, const vec3& c0, const vec3& expected, const vec3& epsilon, const vec3& color_max)
250 {
251 bool status = true;
252 if (fabs(c0[0] / color_max[0] - expected[0]) > epsilon[0])
253 status = false;
254 if (fabs(c0[1] / color_max[1] - expected[1]) > epsilon[1])
255 status = false;
256 if (fabs(c0[2] / color_max[2] - expected[2]) > epsilon[2])
257 status = false;
258
259 if (!status)
260 m_context.getTestContext().getLog()
261 << tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << " " << y << "). Color is ("
262 << c0[0] / color_max[0] << " " << c0[1] / color_max[1] << " " << c0[2] / color_max[2]
263 << "). Color should be (" << expected[0] << " " << expected[1] << " " << expected[2] << ")."
264 << tcu::TestLog::EndMessage;
265 return status;
266 }
267
CheckFB(vec3 expected)268 bool CheckFB(vec3 expected)
269 {
270 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
271 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
272 vec3 g_color_eps = vec3(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
273 1.f / (float)(1 << pixelFormat.blueBits));
274 vec3 g_color_max = vec3(255);
275 std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4);
276 int fb_w = getWindowWidth();
277 int fb_h = getWindowHeight();
278 glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
279 for (GLint i = 0, y = 0; y < fb_h; ++y)
280 for (GLint x = 0; x < fb_w; ++x, i += 4)
281 {
282 if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] ||
283 fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] ||
284 fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2])
285 {
286 m_context.getTestContext().getLog()
287 << tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << " " << y
288 << "). Color is (" << fb[i + 0] / g_color_max[0] << " " << fb[i + 1] / g_color_max[1] << " "
289 << fb[i + 2] / g_color_max[2] << "). Color should be (" << expected[0] << " " << expected[1]
290 << " " << expected[2] << ")." << tcu::TestLog::EndMessage;
291 return false;
292 }
293 }
294 return true;
295 }
296
ValidateWindow4Quads(const vec3 & lb,const vec3 & rb,const vec3 & rt,const vec3 & lt,int * bad_pixels=NULL)297 bool ValidateWindow4Quads(const vec3& lb, const vec3& rb, const vec3& rt, const vec3& lt, int* bad_pixels = NULL)
298 {
299 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
300 const tcu::PixelFormat& pixelFormat = renderTarget.getPixelFormat();
301 vec3 g_color_eps = vec3(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
302 1.f / (float)(1 << pixelFormat.blueBits));
303 vec3 g_color_max = vec3(255);
304
305 const int width = 100;
306 const int height = 100;
307 std::vector<GLubyte> fb(width * height * 4);
308 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
309
310 bool status = true;
311 int bad = 0;
312
313 // left-bottom quad
314 for (int y = 10, i = (100 * 10 + 10) * 4; y < height / 2 - 10; ++y, i += 70 * 4)
315 {
316 for (int x = 10; x < width / 2 - 10; ++x, i += 4)
317 {
318 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
319 if (!ColorEqual(x, y, c, lb, g_color_eps, g_color_max))
320 {
321 status = false;
322 bad++;
323 }
324 }
325 }
326 if (!status)
327 {
328 m_context.getTestContext().getLog()
329 << tcu::TestLog::Message << "Left-bottom quad checking failed. Bad pixels: " << bad
330 << tcu::TestLog::EndMessage;
331 //return status;
332 }
333 // right-bottom quad
334 for (int y = 10, i = (100 * 10 + 60) * 4; y < height / 2 - 10; ++y, i += 70 * 4)
335 {
336 for (int x = width / 2 + 10; x < width - 10; ++x, i += 4)
337 {
338 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
339 if (!ColorEqual(x, y, c, rb, g_color_eps, g_color_max))
340 {
341 status = false;
342 bad++;
343 }
344 }
345 }
346 if (!status)
347 {
348 m_context.getTestContext().getLog()
349 << tcu::TestLog::Message << "right-bottom quad checking failed. Bad pixels: " << bad
350 << tcu::TestLog::EndMessage;
351 //return status;
352 }
353 // right-top quad
354 for (int y = height / 2 + 10, i = (100 * 60 + 60) * 4; y < height - 10; ++y, i += 70 * 4)
355 {
356 for (int x = width / 2 + 10; x < width - 10; ++x, i += 4)
357 {
358 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
359 if (!ColorEqual(x, y, c, rt, g_color_eps, g_color_max))
360 {
361 status = false;
362 bad++;
363 }
364 }
365 }
366 if (!status)
367 {
368 m_context.getTestContext().getLog()
369 << tcu::TestLog::Message << "right-top quad checking failed. Bad pixels: " << bad
370 << tcu::TestLog::EndMessage;
371 //return status;
372 }
373 // left-top quad
374 for (int y = height / 2 + 10, i = (100 * 60 + 10) * 4; y < height - 10; ++y, i += 70 * 4)
375 {
376 for (int x = 10; x < width / 2 - 10; ++x, i += 4)
377 {
378 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
379 if (!ColorEqual(x, y, c, lt, g_color_eps, g_color_max))
380 {
381 status = false;
382 bad++;
383 }
384 }
385 }
386 if (!status)
387 {
388 m_context.getTestContext().getLog()
389 << tcu::TestLog::Message << "left-top quad checking failed. Bad pixels: " << bad
390 << tcu::TestLog::EndMessage;
391 //return status;
392 }
393 // middle horizontal line should be black
394 for (int y = height / 2 - 2, i = (100 * 48) * 4; y < height / 2 + 2; ++y)
395 {
396 for (int x = 0; x < width; ++x, i += 4)
397 {
398 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
399 if (!ColorEqual(x, y, c, vec3(0), g_color_eps, g_color_max))
400 {
401 status = false;
402 bad++;
403 }
404 }
405 }
406 if (!status)
407 {
408 m_context.getTestContext().getLog()
409 << tcu::TestLog::Message << "middle horizontal line checking failed. Bad pixels: " << bad
410 << tcu::TestLog::EndMessage;
411 //return status;
412 }
413 // middle vertical line should be black
414 for (int y = 0, i = 48 * 4; y < height; ++y, i += 96 * 4)
415 {
416 for (int x = width / 2 - 2; x < width / 2 + 2; ++x, i += 4)
417 {
418 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
419 if (!ColorEqual(x, y, c, vec3(0), g_color_eps, g_color_max))
420 {
421 status = false;
422 bad++;
423 }
424 }
425 }
426 if (!status)
427 {
428 m_context.getTestContext().getLog()
429 << tcu::TestLog::Message << "middle vertical line checking failed. Bad pixels: " << bad
430 << tcu::TestLog::EndMessage;
431 //return status;
432 }
433
434 if (bad_pixels)
435 *bad_pixels = bad;
436 m_context.getTestContext().getLog()
437 << tcu::TestLog::Message << "Bad pixels: " << (bad_pixels == NULL ? 0 : *bad_pixels)
438 << ", counted bad: " << bad << tcu::TestLog::EndMessage;
439 return status;
440 }
441
Translation(float tx,float ty,float tz)442 const mat4 Translation(float tx, float ty, float tz)
443 {
444 float d[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, tx, ty, tz, 1.0f };
445 return mat4(d);
446 }
447
GLenumToString(GLenum e)448 const char* GLenumToString(GLenum e)
449 {
450 switch (e)
451 {
452 case GL_SHADER_STORAGE_BUFFER_BINDING:
453 return "GL_SHADER_STORAGE_BUFFER_BINDING";
454 case GL_SHADER_STORAGE_BUFFER_START:
455 return "GL_SHADER_STORAGE_BUFFER_START";
456 case GL_SHADER_STORAGE_BUFFER_SIZE:
457 return "GL_SHADER_STORAGE_BUFFER_SIZE";
458 case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
459 return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS";
460 case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
461 return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
462 case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
463 return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS";
464 case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
465 return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
466 case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
467 return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE";
468 case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
469 return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS";
470 case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
471 return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES";
472 case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
473 return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
474
475 default:
476 assert(0);
477 break;
478 }
479 return NULL;
480 }
481 };
482
483 //-----------------------------------------------------------------------------
484 // 1.1 BasicBasic
485 //-----------------------------------------------------------------------------
486 class BasicBasicVS : public ShaderStorageBufferObjectBase
487 {
488 GLuint m_program;
489 GLuint m_buffer;
490 GLuint m_vertex_array;
491
Setup()492 virtual long Setup()
493 {
494 m_program = 0;
495 m_buffer = 0;
496 m_vertex_array = 0;
497 return NO_ERROR;
498 }
499
Run()500 virtual long Run()
501 {
502 if (!IsVSFSAvailable(1, 0))
503 return NOT_SUPPORTED;
504
505 const char* const glsl_vs =
506 NL "layout(std430, binding = 1) buffer InputBuffer {" NL " vec4 position[3];" NL "} g_input_buffer;" NL
507 "void main() {" NL " gl_Position = g_input_buffer.position[gl_VertexID];" NL "}";
508 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
509 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
510 m_program = CreateProgram(glsl_vs, glsl_fs);
511 glLinkProgram(m_program);
512 if (!CheckProgram(m_program))
513 return ERROR;
514
515 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 };
516 glGenBuffers(1, &m_buffer);
517 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
518 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
519 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
520
521 glGenVertexArrays(1, &m_vertex_array);
522 glBindVertexArray(m_vertex_array);
523
524 glUseProgram(m_program);
525 glClear(GL_COLOR_BUFFER_BIT);
526 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer);
527 glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1);
528 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
529
530 if (!CheckFB(vec3(0, 1, 0)))
531 return ERROR;
532 else
533 return NO_ERROR;
534 }
535
Cleanup()536 virtual long Cleanup()
537 {
538 glUseProgram(0);
539 glDeleteProgram(m_program);
540 glDeleteBuffers(1, &m_buffer);
541 glDeleteVertexArrays(1, &m_vertex_array);
542 return NO_ERROR;
543 }
544 };
545
546 class BasicBasicCS : public ShaderStorageBufferObjectBase
547 {
548 GLuint m_program;
549 GLuint m_buffer;
550
Setup()551 virtual long Setup()
552 {
553 m_program = 0;
554 m_buffer = 0;
555 return NO_ERROR;
556 }
557
Run()558 virtual long Run()
559 {
560 const char* const glsl_cs = NL "layout(local_size_x = 1) in;" NL "buffer Buffer {" NL " int result;" NL "};" NL
561 "void main() {" NL " result = 7;" NL "}";
562 m_program = CreateProgramCS(glsl_cs);
563 glLinkProgram(m_program);
564 if (!CheckProgram(m_program))
565 return ERROR;
566
567 glGenBuffers(1, &m_buffer);
568 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
569 glBufferData(GL_SHADER_STORAGE_BUFFER, 4, 0, GL_STATIC_READ);
570 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
571
572 glUseProgram(m_program);
573 glDispatchCompute(1, 1, 1);
574 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
575
576 GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
577 if (!out_data)
578 return ERROR;
579 if (*out_data == 7)
580 return NO_ERROR;
581 else
582 return ERROR;
583 }
584
Cleanup()585 virtual long Cleanup()
586 {
587 glUseProgram(0);
588 glDeleteProgram(m_program);
589 glDeleteBuffers(1, &m_buffer);
590 return NO_ERROR;
591 }
592 };
593
594 //-----------------------------------------------------------------------------
595 // 1.2 BasicMax
596 //-----------------------------------------------------------------------------
597 class BasicMax : public ShaderStorageBufferObjectBase
598 {
Check(GLenum e,GLint64 value,bool max_value)599 bool Check(GLenum e, GLint64 value, bool max_value)
600 {
601 GLint i;
602 GLint64 i64;
603 GLfloat f;
604 GLboolean b;
605
606 glGetIntegerv(e, &i);
607 glGetInteger64v(e, &i64);
608 glGetFloatv(e, &f);
609 glGetBooleanv(e, &b);
610
611 bool status = true;
612 if (max_value)
613 {
614 if (static_cast<GLint64>(i) < value)
615 status = false;
616 if (i64 < value)
617 status = false;
618 if (static_cast<GLint64>(f) < value)
619 status = false;
620
621 if (!status)
622 {
623 m_context.getTestContext().getLog()
624 << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at least "
625 << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
626 }
627 }
628 else
629 {
630 if (static_cast<GLint64>(i) > value)
631 status = false;
632 if (i64 > value)
633 status = false;
634 if (static_cast<GLint64>(f) > value)
635 status = false;
636
637 if (!status)
638 {
639 m_context.getTestContext().getLog()
640 << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at most "
641 << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
642 }
643 }
644 return status;
645 }
646
Run()647 virtual long Run()
648 {
649 if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
650 return ERROR;
651 if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 0, true))
652 return ERROR;
653 if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 4, true))
654 return ERROR;
655 if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 4, true))
656 return ERROR;
657 if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 134217728 /* 2^27 */, true))
658 return ERROR;
659 if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 4, true))
660 return ERROR;
661 if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4, true))
662 return ERROR;
663 if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
664 return ERROR;
665 return NO_ERROR;
666 }
667 };
668 //-----------------------------------------------------------------------------
669 // 1.3 BasicBinding
670 //-----------------------------------------------------------------------------
671 class BasicBinding : public ShaderStorageBufferObjectBase
672 {
673 GLuint m_buffer[4];
674
Check(GLenum e,GLuint expected)675 bool Check(GLenum e, GLuint expected)
676 {
677 GLint i;
678 GLint64 i64;
679 GLfloat f;
680 GLboolean b;
681
682 GLfloat expectedFloat = static_cast<GLfloat>(expected);
683
684 glGetIntegerv(e, &i);
685 glGetInteger64v(e, &i64);
686 glGetFloatv(e, &f);
687 glGetBooleanv(e, &b);
688
689 bool status = true;
690 if (static_cast<GLuint>(i) != expected)
691 status = false;
692 if (static_cast<GLuint>(i64) != expected)
693 status = false;
694 if (static_cast<GLuint>(f) != expectedFloat)
695 status = false;
696 if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
697 status = false;
698
699 if (!status)
700 {
701 m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " is " << i
702 << " should be " << expected << tcu::TestLog::EndMessage;
703 }
704 return status;
705 }
706
CheckIndexed(GLenum e,GLuint index,GLuint expected)707 bool CheckIndexed(GLenum e, GLuint index, GLuint expected)
708 {
709 GLint i;
710 GLint64 i64;
711
712 glGetIntegeri_v(e, index, &i);
713 glGetInteger64i_v(e, index, &i64);
714
715 bool status = true;
716 if (static_cast<GLuint>(i) != expected)
717 status = false;
718 if (static_cast<GLuint>(i64) != expected)
719 status = false;
720
721 if (!status)
722 {
723 m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " at index " << index
724 << " is " << i << " should be " << expected << tcu::TestLog::EndMessage;
725 }
726 return status;
727 }
728
Setup()729 virtual long Setup()
730 {
731 memset(m_buffer, 0, sizeof(m_buffer));
732 return NO_ERROR;
733 }
734
Run()735 virtual long Run()
736 {
737 GLint maxShaderStorageBufferBindings = 0;
738 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
739
740 // check default state
741 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
742 return ERROR;
743 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
744 {
745 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
746 return ERROR;
747 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
748 return ERROR;
749 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
750 return ERROR;
751 }
752
753 glGenBuffers(4, m_buffer);
754 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
755 {
756 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0]);
757
758 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
759 return ERROR;
760 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
761 return ERROR;
762 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
763 return ERROR;
764 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
765 return ERROR;
766
767 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
768
769 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
770 return ERROR;
771 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
772 return ERROR;
773 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
774 return ERROR;
775 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
776 return ERROR;
777 }
778
779 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
780 {
781 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0], 256, 512);
782
783 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
784 return ERROR;
785 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
786 return ERROR;
787 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 256))
788 return ERROR;
789 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 512))
790 return ERROR;
791
792 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 512, 128);
793
794 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
795 return ERROR;
796 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
797 return ERROR;
798 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
799 return ERROR;
800 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
801 return ERROR;
802
803 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 0, 0);
804
805 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
806 return ERROR;
807 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
808 return ERROR;
809 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
810 return ERROR;
811 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
812 return ERROR;
813 }
814
815 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[2]);
816 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[2]))
817 return ERROR;
818 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 0, m_buffer[2]))
819 return ERROR;
820 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 0, 0))
821 return ERROR;
822 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 0, 0))
823 return ERROR;
824
825 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_buffer[3]);
826 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[3]))
827 return ERROR;
828 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 5, m_buffer[3]))
829 return ERROR;
830 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 5, 0))
831 return ERROR;
832 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 5, 0))
833 return ERROR;
834
835 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_buffer[1], 2048, 1000);
836 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[1]))
837 return ERROR;
838 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 7, m_buffer[1]))
839 return ERROR;
840 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 7, 2048))
841 return ERROR;
842 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 7, 1000))
843 return ERROR;
844
845 glDeleteBuffers(4, m_buffer);
846 memset(m_buffer, 0, sizeof(m_buffer));
847
848 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
849 return ERROR;
850 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
851 {
852 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
853 return ERROR;
854 }
855
856 return NO_ERROR;
857 }
858
Cleanup()859 virtual long Cleanup()
860 {
861 glDeleteBuffers(4, m_buffer);
862 return NO_ERROR;
863 }
864 };
865
866 //-----------------------------------------------------------------------------
867 // 1.4 BasicSyntax
868 //-----------------------------------------------------------------------------
869 class BasicSyntaxVS : public ShaderStorageBufferObjectBase
870 {
871 GLuint m_program;
872 GLuint m_buffer;
873 GLuint m_vertex_array;
874
RunIteration(const char * vs,const char * fs)875 bool RunIteration(const char* vs, const char* fs)
876 {
877 if (m_program != 0)
878 glDeleteProgram(m_program);
879 m_program = CreateProgram(vs, fs);
880 glLinkProgram(m_program);
881 if (!CheckProgram(m_program))
882 return false;
883
884 glClear(GL_COLOR_BUFFER_BIT);
885 glUseProgram(m_program);
886 glDrawArrays(GL_TRIANGLES, 0, 3);
887
888 return CheckFB(vec3(0, 1, 0));
889 }
890
Setup()891 virtual long Setup()
892 {
893 m_program = 0;
894 m_buffer = 0;
895 m_vertex_array = 0;
896 return NO_ERROR;
897 }
898
Run()899 virtual long Run()
900 {
901 if (!IsVSFSAvailable(1, 0))
902 return NOT_SUPPORTED;
903 const int kCount = 8;
904 const char* const glsl_vs[kCount] = {
905 NL "layout(std430) buffer Buffer {" NL " vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
906 " gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
907 NL "coherent buffer Buffer {" NL " buffer vec4 position0;" NL " coherent vec4 position1;" NL
908 " restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
909 " if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
910 " if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
911 " if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
912 NL "layout(std140, binding = 0) readonly buffer Buffer {" NL " readonly vec4 position[];" NL "};" NL
913 "void main() {" NL " gl_Position = position[gl_VertexID];" NL "}",
914 NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
915 "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
916 " restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
917 " gl_Position = g_buffer.position[gl_VertexID];" NL "}",
918 NL "buffer Buffer {" NL " vec4 position[3];" //
919 NL "} g_buffer[1];" NL "void main() {" NL " gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
920 NL "layout(shared) coherent buffer Buffer {" NL " restrict volatile vec4 position0;" NL
921 " buffer readonly vec4 position1;" NL " vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
922 " if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
923 " else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
924 " else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
925 NL "layout(packed) coherent buffer Buffer {" NL " vec4 position01[2];" NL " vec4 position2;" NL
926 "} g_buffer;" NL "void main() {" NL " if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
927 " else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
928 " else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
929 NL "layout(std430) coherent buffer Buffer {" NL " coherent vec4 position01[2];" NL " vec4 position2[];" NL
930 "} g_buffer;" NL "void main() {" NL " switch (gl_VertexID) {" NL
931 " case 0: gl_Position = g_buffer.position01[0]; break;" NL
932 " case 1: gl_Position = g_buffer.position01[1]; break;" NL
933 " case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL " }" NL "}",
934 };
935 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
936 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
937
938 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 };
939 glGenBuffers(1, &m_buffer);
940 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
941 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
942
943 glGenVertexArrays(1, &m_vertex_array);
944 glBindVertexArray(m_vertex_array);
945
946 for (int i = 0; i < kCount; ++i)
947 {
948 if (!RunIteration(glsl_vs[i], glsl_fs))
949 return ERROR;
950 }
951
952 return NO_ERROR;
953 }
954
Cleanup()955 virtual long Cleanup()
956 {
957 glUseProgram(0);
958 glDeleteProgram(m_program);
959 glDeleteBuffers(1, &m_buffer);
960 glDeleteVertexArrays(1, &m_vertex_array);
961 return NO_ERROR;
962 }
963 };
964
965 class BasicSyntaxCS : public ShaderStorageBufferObjectBase
966 {
967 GLuint m_program;
968 GLuint m_buffer[2];
969
RunIteration(const char * cs)970 bool RunIteration(const char* cs)
971 {
972 std::stringstream ss;
973 ss << "layout(local_size_x = 3) in;" NL "layout (std430) buffer Result {" NL " int result[3];" NL "};" << cs;
974
975 if (m_program != 0)
976 glDeleteProgram(m_program);
977 m_program = CreateProgramCS(ss.str());
978 glLinkProgram(m_program);
979 if (!CheckProgram(m_program))
980 return false;
981
982 glUseProgram(m_program);
983 glDispatchCompute(1, 1, 1);
984 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
985
986 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[0]);
987 GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 3, GL_MAP_READ_BIT);
988 if (!out_data)
989 return false;
990 bool result = out_data[0] == 7 && out_data[1] == 17 && out_data[2] == 23;
991 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
992 GLint data[3] = { 0 };
993 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 3, data, GL_STATIC_READ);
994
995 return result;
996 }
997
Setup()998 virtual long Setup()
999 {
1000 m_program = 0;
1001 memset(m_buffer, 0, sizeof(m_buffer));
1002 return NO_ERROR;
1003 }
1004
Run()1005 virtual long Run()
1006 {
1007 const int kCount = 8;
1008 const char* const glsl_cs[kCount] = {
1009 NL "layout(std430, binding = 1) buffer Buffer {" NL " vec4 indata[3];" NL "} g_input_buffer;" NL
1010 "void main() {" NL
1011 " result[gl_LocalInvocationIndex] = int(g_input_buffer.indata[gl_LocalInvocationID.x].z);" NL "}",
1012
1013 NL "layout(binding = 1) coherent buffer Buffer {" NL " buffer vec4 indata0;" NL
1014 " coherent vec4 indata1;" NL " restrict readonly vec4 indata2;" NL "} g_input_buffer;" NL
1015 "void main() {" NL
1016 " if (gl_LocalInvocationID.x == 0u) result[gl_LocalInvocationIndex] = int(g_input_buffer.indata0.z);" NL
1017 " if (gl_LocalInvocationID.x == 1u) result[gl_LocalInvocationIndex] = int(g_input_buffer.indata1.z);" NL
1018 " if (gl_LocalInvocationID.x == 2u) result[gl_LocalInvocationIndex] = int(g_input_buffer.indata2.z);" NL
1019 "}",
1020
1021 NL "layout(std140, binding = 1) readonly buffer Buffer {" NL " readonly vec4 indata[];" NL "};" NL
1022 "void main() {" NL " result[gl_LocalInvocationIndex] = int(indata[gl_LocalInvocationID.x].z);" NL "}",
1023
1024 NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1025 "layout(std430) buffer;" NL "layout(binding = 1) coherent restrict volatile buffer Buffer {" NL
1026 " restrict coherent vec4 indata[];" NL "} g_buffer;" NL "void main() {" NL
1027 " result[gl_LocalInvocationIndex] = int(g_buffer.indata[gl_LocalInvocationID.x].z);" NL "}",
1028
1029 NL "layout(binding = 1) buffer Buffer {" NL " vec4 indata[3];" //
1030 NL "} g_buffer[1];" NL "void main() {" NL
1031 " result[gl_LocalInvocationIndex] = int(g_buffer[0].indata[gl_LocalInvocationID.x].z);" NL "}",
1032
1033 NL
1034 "layout(shared, binding = 1) coherent buffer Buffer {" NL " restrict volatile vec4 indata0;" NL
1035 " buffer readonly vec4 indata1;" NL " vec4 indata2;" NL "} g_buffer[1];" NL "void main() {" NL
1036 " if (gl_LocalInvocationID.x == 0u) result[gl_LocalInvocationIndex] = int(g_buffer[0].indata0.z);" NL
1037 " else if (gl_LocalInvocationID.x == 1u) result[gl_LocalInvocationIndex] = int(g_buffer[0].indata1.z);" NL
1038 " else if (gl_LocalInvocationID.x == 2u) result[gl_LocalInvocationIndex] = int(g_buffer[0].indata2.z);" NL
1039 "}",
1040
1041 NL
1042 "layout(packed, binding = 1) coherent buffer Buffer {" NL " vec4 indata01[2];" NL " vec4 indata2;" NL
1043 "} g_buffer;" NL "void main() {" NL
1044 " if (gl_LocalInvocationID.x == 0u) result[gl_LocalInvocationIndex] = int(g_buffer.indata01[0].z);" NL
1045 " else if (gl_LocalInvocationID.x == 1u) result[gl_LocalInvocationIndex] = int(g_buffer.indata01[1].z);" NL
1046 " else if (gl_LocalInvocationID.x == 2u) result[gl_LocalInvocationIndex] = int(g_buffer.indata2.z);" NL
1047 "}",
1048
1049 NL "layout(std430, binding = 1) coherent buffer Buffer {" NL " coherent vec4 indata01[2];" NL
1050 " vec4 indata2[];" NL "} g_buffer;" NL "void main() {" NL " switch (gl_LocalInvocationID.x) {" NL
1051 " case 0u: result[gl_LocalInvocationIndex] = int(g_buffer.indata01[0].z); break;" NL
1052 " case 1u: result[gl_LocalInvocationIndex] = int(g_buffer.indata01[1].z); break;" NL
1053 " case 2u: result[gl_LocalInvocationIndex] = int(g_buffer.indata2[gl_LocalInvocationIndex-2u].z); "
1054 "break;" NL " }" NL "}",
1055 };
1056
1057 glGenBuffers(2, m_buffer);
1058 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1059 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 3, 0, GL_STATIC_READ);
1060 const float data[12] = { -1.0f, -1.0f, 7.0f, 1.0f, 3.0f, -1.0f, 17.0f, 1.0f, -1.0f, 3.0f, 23.0f, 1.0f };
1061 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1062 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1063 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1064
1065 for (int i = 0; i < kCount; ++i)
1066 {
1067 if (!RunIteration(glsl_cs[i]))
1068 return ERROR;
1069 }
1070
1071 return NO_ERROR;
1072 }
1073
Cleanup()1074 virtual long Cleanup()
1075 {
1076 glUseProgram(0);
1077 glDeleteProgram(m_program);
1078 glDeleteBuffers(2, m_buffer);
1079 return NO_ERROR;
1080 }
1081 };
1082 //-----------------------------------------------------------------------------
1083 // 1.5 BasicSyntaxSSO
1084 //-----------------------------------------------------------------------------
1085 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1086 {
1087 GLuint m_pipeline;
1088 GLuint m_vsp, m_fsp;
1089 GLuint m_buffer;
1090 GLuint m_vertex_array;
1091
RunIteration(const char * vs)1092 bool RunIteration(const char* vs)
1093 {
1094 if (m_vsp != 0)
1095 glDeleteProgram(m_vsp);
1096 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, vs);
1097 if (!CheckProgram(m_vsp))
1098 return false;
1099
1100 glClear(GL_COLOR_BUFFER_BIT);
1101 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
1102 glDrawArrays(GL_TRIANGLES, 0, 3);
1103
1104 return CheckFB(vec3(0, 1, 0));
1105 }
1106
Setup()1107 virtual long Setup()
1108 {
1109 m_pipeline = 0;
1110 m_vsp = m_fsp = 0;
1111 m_buffer = 0;
1112 m_vertex_array = 0;
1113 return NO_ERROR;
1114 }
1115
Run()1116 virtual long Run()
1117 {
1118 if (!IsVSFSAvailable(1, 0))
1119 return NOT_SUPPORTED;
1120 const int kCount = 8;
1121
1122 const char* const glsl_vs[kCount] = {
1123 NL "layout(std430) buffer Buffer {" NL " vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1124 " gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1125 NL "coherent buffer Buffer {" NL " vec4 position0;" NL " coherent vec4 position1;" NL
1126 " restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
1127 " if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1128 " if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1129 " if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1130 NL "layout(std140, binding = 0) readonly buffer Buffer {" NL " readonly vec4 position[];" NL "};" NL
1131 "void main() {" NL " gl_Position = position[gl_VertexID];" NL "}",
1132 NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1133 "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1134 " restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1135 " gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1136 NL "buffer Buffer {" NL " vec4 position[3];" //
1137 NL "} g_buffer[1];" NL "void main() {" NL " gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1138 NL "layout(shared) coherent buffer Buffer {" NL " restrict volatile vec4 position0;" NL
1139 " readonly vec4 position1;" NL " vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
1140 " if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1141 " else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1142 " else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1143 NL "layout(packed) coherent buffer Buffer {" NL " vec4 position01[2];" NL " vec4 position2;" NL
1144 "} g_buffer;" NL "void main() {" NL " if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1145 " else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1146 " else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1147 NL "layout(std430) coherent buffer Buffer {" NL " coherent vec4 position01[2];" NL " vec4 position2[];" NL
1148 "} g_buffer;" NL "void main() {" NL " switch (gl_VertexID) {" NL
1149 " case 0: gl_Position = g_buffer.position01[0]; break;" NL
1150 " case 1: gl_Position = g_buffer.position01[1]; break;" NL
1151 " case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL " }" NL "}",
1152 };
1153 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1154 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1155 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
1156 if (!CheckProgram(m_fsp))
1157 return ERROR;
1158
1159 glGenProgramPipelines(1, &m_pipeline);
1160 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
1161
1162 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 };
1163 glGenBuffers(1, &m_buffer);
1164 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1165 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1166
1167 glBindProgramPipeline(m_pipeline);
1168
1169 glGenVertexArrays(1, &m_vertex_array);
1170 glBindVertexArray(m_vertex_array);
1171
1172 for (int i = 0; i < kCount; ++i)
1173 {
1174 if (!RunIteration(glsl_vs[i]))
1175 return ERROR;
1176 }
1177
1178 return NO_ERROR;
1179 }
1180
Cleanup()1181 virtual long Cleanup()
1182 {
1183 glDeleteProgramPipelines(1, &m_pipeline);
1184 glDeleteProgram(m_vsp);
1185 glDeleteProgram(m_fsp);
1186 glDeleteBuffers(1, &m_buffer);
1187 glDeleteVertexArrays(1, &m_vertex_array);
1188 return NO_ERROR;
1189 }
1190 };
1191
1192 //-----------------------------------------------------------------------------
1193 // 1.6.x BasicStdLayoutBase
1194 //-----------------------------------------------------------------------------
1195 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1196 {
1197 GLuint m_program;
1198 GLuint m_buffer[2];
1199 GLuint m_vertex_array;
1200
1201 virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1202
Setup()1203 virtual long Setup()
1204 {
1205 m_program = 0;
1206 memset(m_buffer, 0, sizeof(m_buffer));
1207 m_vertex_array = 0;
1208 return NO_ERROR;
1209 }
1210
Run()1211 virtual long Run()
1212 {
1213 if (!IsVSFSAvailable(2, 0))
1214 return NOT_SUPPORTED;
1215 std::vector<GLubyte> in_data;
1216 const char* glsl_vs = GetInput(in_data);
1217 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1218 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1219
1220 m_program = CreateProgram(glsl_vs, glsl_fs);
1221 glLinkProgram(m_program);
1222 if (!CheckProgram(m_program))
1223 return ERROR;
1224
1225 glGenBuffers(2, m_buffer);
1226
1227 std::vector<GLubyte> out_d(in_data.size());
1228 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1229 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &out_d[0], GL_STATIC_DRAW);
1230
1231 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1232 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1233
1234 glGenVertexArrays(1, &m_vertex_array);
1235 glEnable(GL_RASTERIZER_DISCARD);
1236
1237 glUseProgram(m_program);
1238 glBindVertexArray(m_vertex_array);
1239 glDrawArrays(GL_POINTS, 0, 1);
1240
1241 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
1242 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1243 GLubyte* out_data =
1244 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1245 if (!out_data)
1246 return ERROR;
1247
1248 bool status = true;
1249 for (size_t i = 0; i < in_data.size(); ++i)
1250 {
1251 if (in_data[i] != out_data[i])
1252 {
1253 m_context.getTestContext().getLog()
1254 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1255 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1256 status = false;
1257 }
1258 }
1259 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1260 if (!status)
1261 return ERROR;
1262 return NO_ERROR;
1263 }
1264
Cleanup()1265 virtual long Cleanup()
1266 {
1267 glDisable(GL_RASTERIZER_DISCARD);
1268 glUseProgram(0);
1269 glDeleteProgram(m_program);
1270 glDeleteBuffers(2, m_buffer);
1271 glDeleteVertexArrays(1, &m_vertex_array);
1272 return NO_ERROR;
1273 }
1274 };
1275
1276 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1277 {
1278 GLuint m_program;
1279 GLuint m_buffer[2];
1280
1281 virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1282
Setup()1283 virtual long Setup()
1284 {
1285 m_program = 0;
1286 memset(m_buffer, 0, sizeof(m_buffer));
1287 return NO_ERROR;
1288 }
1289
Run()1290 virtual long Run()
1291 {
1292 std::vector<GLubyte> in_data;
1293 std::stringstream ss;
1294 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
1295
1296 m_program = CreateProgramCS(ss.str());
1297 glLinkProgram(m_program);
1298 if (!CheckProgram(m_program))
1299 return ERROR;
1300
1301 glGenBuffers(2, m_buffer);
1302
1303 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1304 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1305 std::vector<GLubyte> out_d(in_data.size());
1306 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1307 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)out_d.size(), &out_d[0], GL_STATIC_DRAW);
1308
1309 glUseProgram(m_program);
1310 glDispatchCompute(1, 1, 1);
1311
1312 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1313 GLubyte* out_data =
1314 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1315 if (!out_data)
1316 return ERROR;
1317
1318 bool status = true;
1319
1320 for (size_t i = 0; i < in_data.size(); ++i)
1321 {
1322 if (in_data[i] != out_data[i])
1323 {
1324 m_context.getTestContext().getLog()
1325 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1326 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1327 status = false;
1328 }
1329 else
1330 {
1331 }
1332 }
1333 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1334 if (!status)
1335 return ERROR;
1336 return NO_ERROR;
1337 }
1338
Cleanup()1339 virtual long Cleanup()
1340 {
1341 glUseProgram(0);
1342 glDeleteProgram(m_program);
1343 glDeleteBuffers(2, m_buffer);
1344 return NO_ERROR;
1345 }
1346 };
1347
1348 //-----------------------------------------------------------------------------
1349 // 1.6.1 BasicStd430LayoutCase1
1350 //-----------------------------------------------------------------------------
GetInput430c1(std::vector<GLubyte> & in_data)1351 const char* GetInput430c1(std::vector<GLubyte>& in_data)
1352 {
1353 in_data.resize(6 * 4);
1354 float* fp = reinterpret_cast<float*>(&in_data[0]);
1355 int* ip = reinterpret_cast<int*>(&in_data[0]);
1356 fp[0] = 1.0f;
1357 fp[1] = 2.0f;
1358 fp[2] = 3.0f;
1359 fp[3] = 4.0f;
1360 ip[4] = 5;
1361 ip[5] = 6;
1362 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1363 " ivec2 data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL " float data0;" NL
1364 " float data1[3];" NL " ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1365 " g_output.data0 = g_input.data0;" NL
1366 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1367 " g_output.data2 = g_input.data2;" NL "}";
1368 }
1369
1370 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1371 {
GetInput(std::vector<GLubyte> & in_data)1372 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1373 {
1374 return GetInput430c1(in_data);
1375 }
1376 };
1377
1378 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1379 {
GetInput(std::vector<GLubyte> & in_data)1380 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1381 {
1382 return GetInput430c1(in_data);
1383 }
1384 };
1385
1386 //-----------------------------------------------------------------------------
1387 // 1.6.2 BasicStd430LayoutCase2
1388 //-----------------------------------------------------------------------------
GetInput430c2(std::vector<GLubyte> & in_data)1389 const char* GetInput430c2(std::vector<GLubyte>& in_data)
1390 {
1391 in_data.resize(17 * 4);
1392 float* fp = reinterpret_cast<float*>(&in_data[0]);
1393 fp[0] = 1.0f;
1394 fp[1] = 2.0f;
1395 fp[2] = 3.0f;
1396 fp[3] = 4.0f;
1397 fp[4] = 5.0f;
1398 fp[5] = 6.0f;
1399 fp[8] = 7.0f;
1400 fp[9] = 8.0f;
1401 fp[10] = 9.0f;
1402 fp[12] = 10.0f;
1403 fp[13] = 11.0f;
1404 fp[14] = 12.0f;
1405 fp[16] = 13.0f;
1406 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1407 " vec2 data2;" NL " readonly vec3 data3[2];" NL " float data4;" NL "} g_input;" NL
1408 "layout(std430, binding = 1) buffer Output {" NL " float data0;" NL " float data1[3];" NL
1409 " vec2 data2;" NL " vec3 data3[2];" NL " float data4;" NL "} g_output;" NL "void main() {" NL
1410 " g_output.data0 = g_input.data0;" NL
1411 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1412 " g_output.data2 = g_input.data2;" NL
1413 " for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1414 " g_output.data4 = g_input.data4;" NL "}";
1415 }
1416
1417 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1418 {
GetInput(std::vector<GLubyte> & in_data)1419 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1420 {
1421 return GetInput430c2(in_data);
1422 }
1423 };
1424
1425 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1426 {
GetInput(std::vector<GLubyte> & in_data)1427 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1428 {
1429 return GetInput430c2(in_data);
1430 }
1431 };
1432
1433 //-----------------------------------------------------------------------------
1434 // 1.6.3 BasicStd430LayoutCase3
1435 //-----------------------------------------------------------------------------
GetInput430c3(std::vector<GLubyte> & in_data)1436 const char* GetInput430c3(std::vector<GLubyte>& in_data)
1437 {
1438 in_data.resize(16 * 4);
1439 float* fp = reinterpret_cast<float*>(&in_data[0]);
1440 fp[0] = 1.0f;
1441 fp[1] = 2.0f;
1442 fp[2] = 3.0f;
1443 fp[3] = 0.0f;
1444 fp[4] = 4.0f;
1445 fp[5] = 5.0f;
1446 fp[6] = 6.0f;
1447 fp[7] = 0.0f;
1448 fp[8] = 7.0f;
1449 fp[9] = 8.0f;
1450 fp[10] = 9.0f;
1451 fp[11] = 10.0f;
1452 fp[12] = 11.0f;
1453 fp[13] = 12.0f;
1454 fp[14] = 13.0f;
1455 fp[15] = 14.0f;
1456 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat2x3 data0;" NL
1457 " layout(row_major) mat4x2 data1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
1458 " layout(column_major) mat2x3 data0;" NL " layout(row_major) mat4x2 data1;" NL "} g_output;" NL
1459 "void main() {" NL " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL "}";
1460 }
1461
1462 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1463 {
GetInput(std::vector<GLubyte> & in_data)1464 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1465 {
1466 return GetInput430c3(in_data);
1467 }
1468 };
1469
1470 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1471 {
GetInput(std::vector<GLubyte> & in_data)1472 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1473 {
1474 return GetInput430c3(in_data);
1475 }
1476 };
1477
1478 //-----------------------------------------------------------------------------
1479 // 1.6.4 BasicStd430LayoutCase4
1480 //-----------------------------------------------------------------------------
GetInput430c4(std::vector<GLubyte> & in_data)1481 const char* GetInput430c4(std::vector<GLubyte>& in_data)
1482 {
1483 in_data.resize(17 * 4);
1484 float* fp = reinterpret_cast<float*>(&in_data[0]);
1485 fp[0] = 1.0f;
1486 fp[1] = 2.0f;
1487 fp[2] = 3.0f;
1488 fp[3] = 4.0f;
1489 fp[4] = 5.0f;
1490 fp[5] = 6.0f;
1491 fp[6] = 7.0f;
1492 fp[7] = 8.0f;
1493 fp[8] = 9.0f;
1494 fp[9] = 10.0f;
1495 fp[10] = 11.0f;
1496 fp[12] = 12.0f;
1497 fp[13] = 13.0f;
1498 fp[14] = 14.0f;
1499 fp[16] = 15.0f;
1500
1501 return NL "layout(std430, binding = 0) buffer Input {" NL " mat4x2 data0;" NL " mat2x3 data1;" NL
1502 " float data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL " mat4x2 data0;" NL
1503 " mat2x3 data1;" NL " float data2;" NL "} g_output;" NL "void main() {" NL
1504 " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL
1505 " g_output.data2 = g_input.data2;" NL "}";
1506 }
1507
1508 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1509 {
GetInput(std::vector<GLubyte> & in_data)1510 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1511 {
1512 return GetInput430c4(in_data);
1513 }
1514 };
1515
1516 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1517 {
GetInput(std::vector<GLubyte> & in_data)1518 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1519 {
1520 return GetInput430c4(in_data);
1521 }
1522 };
1523 //-----------------------------------------------------------------------------
1524 // 1.6.5 BasicStd430LayoutCase5
1525 //-----------------------------------------------------------------------------
GetInput430c5(std::vector<GLubyte> & in_data)1526 const char* GetInput430c5(std::vector<GLubyte>& in_data)
1527 {
1528 in_data.resize(8 * 4);
1529 float* fp = reinterpret_cast<float*>(&in_data[0]);
1530 fp[0] = 1.0f;
1531 fp[1] = 3.0f;
1532 fp[2] = 5.0f;
1533 fp[3] = 7.0f;
1534 fp[4] = 2.0f;
1535 fp[5] = 4.0f;
1536 fp[6] = 6.0f;
1537 fp[7] = 8.0f;
1538
1539 return NL "layout(std430, binding = 0, row_major) buffer Input {" NL " mat4x2 data0;" NL "} g_input;" NL
1540 "layout(std430, binding = 1, row_major) buffer Output {" NL " mat4x2 data0;" NL "} g_output;" NL
1541 "void main() {" NL " g_output.data0 = g_input.data0;" NL "}";
1542 }
1543
1544 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1545 {
GetInput(std::vector<GLubyte> & in_data)1546 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1547 {
1548 return GetInput430c5(in_data);
1549 }
1550 };
1551
1552 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1553 {
GetInput(std::vector<GLubyte> & in_data)1554 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1555 {
1556 return GetInput430c5(in_data);
1557 }
1558 };
1559
1560 //-----------------------------------------------------------------------------
1561 // 1.6.6 BasicStd430LayoutCase6
1562 //-----------------------------------------------------------------------------
GetInput430c6(std::vector<GLubyte> & in_data)1563 const char* GetInput430c6(std::vector<GLubyte>& in_data)
1564 {
1565 in_data.resize(92 * 4);
1566 float* fp = reinterpret_cast<float*>(&in_data[0]);
1567 fp[0] = 1.0f;
1568 fp[1] = 2.0f;
1569 fp[2] = 3.0f;
1570 fp[3] = 4.0f;
1571 fp[4] = 5.0f;
1572 fp[5] = 0.0f;
1573 fp[6] = 6.0f;
1574 fp[7] = 7.0f;
1575 fp[8] = 8.0f;
1576 fp[9] = 9.0f;
1577 fp[10] = 10.0f;
1578 fp[11] = 11.0f;
1579 fp[12] = 12.0f;
1580 fp[13] = 0.0f;
1581 fp[14] = 0.0f;
1582 fp[15] = 0.0f;
1583 fp[16] = 13.0f;
1584 fp[17] = 14.0f;
1585 fp[18] = 15.0f;
1586 fp[19] = 0.0f;
1587 fp[20] = 16.0f;
1588 fp[21] = 17.0f;
1589 fp[22] = 18.0f;
1590 fp[23] = 0.0f;
1591 fp[24] = 19.0f;
1592 fp[25] = 20.0f;
1593 fp[26] = 21.0f;
1594 fp[27] = 22.0f;
1595 fp[28] = 23.0f;
1596 fp[29] = 24.0f;
1597 fp[30] = 25.0f;
1598 fp[31] = 26.0f;
1599 fp[32] = 27.0f;
1600 fp[33] = 28.0f;
1601 fp[34] = 0.0f;
1602 fp[35] = 0.0f;
1603 fp[36] = 29.0f;
1604 fp[37] = 30.0f;
1605 fp[38] = 31.0f;
1606 fp[39] = 0.0f;
1607 fp[40] = 32.0f;
1608 fp[41] = 33.0f;
1609 fp[42] = 34.0f;
1610 fp[43] = 0.0f;
1611 fp[44] = 35.0f;
1612 fp[45] = 36.0f;
1613 fp[46] = 37.0f;
1614 fp[47] = 0.0f;
1615 fp[48] = 38.0f;
1616 fp[49] = 39.0f;
1617 fp[50] = 40.0f;
1618 fp[51] = 0.0f;
1619 fp[52] = 41.0f;
1620 fp[53] = 42.0f;
1621 fp[54] = 43.0f;
1622 fp[55] = 0.0f;
1623 fp[56] = 44.0f;
1624 fp[57] = 45.0f;
1625 fp[58] = 46.0f;
1626 fp[59] = 0.0f;
1627 fp[60] = 47.0f;
1628 fp[61] = 48.0f;
1629 fp[62] = 49.0f;
1630 fp[63] = 50.0f;
1631 fp[64] = 51.0f;
1632 fp[65] = 52.0f;
1633 fp[66] = 53.0f;
1634 fp[67] = 54.0f;
1635 fp[68] = 55.0f;
1636 fp[69] = 56.0f;
1637 fp[70] = 57.0f;
1638 fp[71] = 58.0f;
1639 fp[72] = 59.0f;
1640 fp[73] = 60.0f;
1641 fp[74] = 61.0f;
1642 fp[75] = 62.0f;
1643 fp[76] = 63.0f;
1644 fp[77] = 64.0f;
1645 fp[78] = 65.0f;
1646 fp[79] = 66.0f;
1647 fp[80] = 67.0f;
1648 fp[81] = 68.0f;
1649 fp[82] = 69.0f;
1650 fp[83] = 70.0f;
1651 fp[84] = 71.0f;
1652 fp[85] = 72.0f;
1653 fp[86] = 73.0f;
1654 fp[87] = 74.0f;
1655 fp[88] = 75.0f;
1656 fp[89] = 76.0f;
1657 fp[90] = 77.0f;
1658 fp[91] = 78.0f;
1659
1660 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0[2];" NL " float data1[3];" NL
1661 " vec2 data2;" NL " float data3[5];" NL " vec3 data4[2];" NL " float data5[2];" NL
1662 " mat2 data6[2];" NL " mat3 data7[2];" NL " mat4 data8[2];" NL "} g_input;" NL
1663 "layout(std430, binding = 1) buffer Output {" NL " float data0[2];" NL " float data1[3];" NL
1664 " vec2 data2;" NL " float data3[5];" NL " vec3 data4[2];" NL " float data5[2];" NL
1665 " mat2 data6[2];" NL " mat3 data7[2];" NL " mat4 data8[2];" NL "} g_output;" NL "void main() {" NL
1666 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
1667 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1668 " g_output.data2 = g_input.data2;" NL
1669 " for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1670 " for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
1671 " for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
1672 " for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL
1673 " for (int i = 0; i < g_input.data7.length(); ++i) g_output.data7[i] = g_input.data7[i];" NL
1674 " for (int i = 0; i < g_input.data8.length(); ++i) g_output.data8[i] = g_input.data8[i];" NL "}";
1675 }
1676
1677 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1678 {
GetInput(std::vector<GLubyte> & in_data)1679 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1680 {
1681 return GetInput430c6(in_data);
1682 }
1683 };
1684
1685 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1686 {
GetInput(std::vector<GLubyte> & in_data)1687 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1688 {
1689 return GetInput430c6(in_data);
1690 }
1691 };
1692
1693 //-----------------------------------------------------------------------------
1694 // 1.6.7 BasicStd430LayoutCase7
1695 //-----------------------------------------------------------------------------
GetInput430c7(std::vector<GLubyte> & in_data)1696 const char* GetInput430c7(std::vector<GLubyte>& in_data)
1697 {
1698 in_data.resize(36 * 4);
1699 int* ip = reinterpret_cast<int*>(&in_data[0]);
1700 float* fp = reinterpret_cast<float*>(&in_data[0]);
1701 ip[0] = 1;
1702 ip[1] = 0;
1703 ip[2] = 2;
1704 ip[3] = 3;
1705 fp[4] = 4.0f;
1706 fp[5] = 0.0f;
1707 fp[6] = 0.0f;
1708 fp[7] = 0.0f;
1709 fp[8] = 5.0f;
1710 fp[9] = 6.0f;
1711 fp[10] = 7.0f;
1712 fp[11] = 0.0f;
1713 fp[12] = 8.0f;
1714 fp[13] = 0.0f;
1715 fp[14] = 0.0f;
1716 fp[15] = 0.0f;
1717 fp[16] = 9.0f;
1718 fp[17] = 10.0f;
1719 fp[18] = 11.0f;
1720 fp[19] = 0.0f;
1721 ip[20] = 12;
1722 ip[21] = 13;
1723 ip[22] = 14;
1724 ip[23] = 15;
1725 fp[24] = 16.0f;
1726 fp[25] = 0.0f;
1727 fp[26] = 0.0f;
1728 fp[27] = 0.0f;
1729 fp[28] = 17.0f;
1730 fp[29] = 18.0f;
1731 fp[30] = 19.0f;
1732 fp[31] = 0.0f;
1733 ip[32] = 20;
1734 ip[33] = 21;
1735 ip[34] = 22;
1736 ip[35] = 23;
1737
1738 return NL "struct Struct0 {" NL " ivec2 m0;" NL "};" NL "struct Struct1 {" NL " vec3 m0;" NL "};" NL
1739 "struct Struct3 {" NL " int m0;" NL "};" NL "struct Struct2 {" NL " float m0;" // offset = 0
1740 NL " Struct1 m1;" // offset = 16
1741 NL " Struct0 m2;" // offset = 32
1742 NL " int m3;" // offset = 40
1743 NL " Struct3 m4;" // offset = 44
1744 NL "};" NL "layout(std430, binding = 0) buffer Input {" NL " int data0;" // offset = 0
1745 NL " Struct0 data1;" // offset = 8
1746 NL " float data2;" // offset = 16
1747 NL " Struct1 data3;" // offset = 32
1748 NL " Struct2 data4[2];" // offset = 48
1749 NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL " int data0;" NL " Struct0 data1;" NL
1750 " float data2;" NL " Struct1 data3;" NL " Struct2 data4[2];" NL "} g_output;" NL "void main() {" NL
1751 " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL
1752 " g_output.data2 = g_input.data2;" NL " g_output.data3 = g_input.data3;" NL
1753 " for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL "}";
1754 }
1755
1756 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1757 {
GetInput(std::vector<GLubyte> & in_data)1758 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1759 {
1760 return GetInput430c7(in_data);
1761 }
1762 };
1763
1764 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1765 {
GetInput(std::vector<GLubyte> & in_data)1766 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1767 {
1768 return GetInput430c7(in_data);
1769 }
1770 };
1771
1772 //-----------------------------------------------------------------------------
1773 // 1.7.1 BasicStd140LayoutCase1
1774 //-----------------------------------------------------------------------------
GetInput140c1(std::vector<GLubyte> & in_data)1775 const char* GetInput140c1(std::vector<GLubyte>& in_data)
1776 {
1777 in_data.resize(5 * 4);
1778 float* fp = reinterpret_cast<float*>(&in_data[0]);
1779 fp[0] = 1.0f;
1780 fp[1] = 0.0f;
1781 fp[2] = 0.0f;
1782 fp[3] = 0.0f;
1783 fp[4] = 2.0f;
1784
1785 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0[2];" NL "} g_input;" NL
1786 "layout(std140, binding = 1) buffer Output {" NL " float data0[2];" NL "} g_output;" NL
1787 "void main() {" NL
1788 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1789 }
1790
1791 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1792 {
GetInput(std::vector<GLubyte> & in_data)1793 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1794 {
1795 return GetInput140c1(in_data);
1796 }
1797 };
1798
1799 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1800 {
GetInput(std::vector<GLubyte> & in_data)1801 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1802 {
1803 return GetInput140c1(in_data);
1804 }
1805 };
1806
1807 //-----------------------------------------------------------------------------
1808 // 1.7.2 BasicStd140LayoutCase2
1809 //-----------------------------------------------------------------------------
GetInput140c2(std::vector<GLubyte> & in_data)1810 const char* GetInput140c2(std::vector<GLubyte>& in_data)
1811 {
1812 in_data.resize(18 * 4);
1813 float* fp = reinterpret_cast<float*>(&in_data[0]);
1814 int* ip = reinterpret_cast<int*>(&in_data[0]);
1815 fp[0] = 1.0f;
1816 fp[1] = 0.0f;
1817 fp[2] = 0.0f;
1818 fp[3] = 0.0f;
1819 fp[4] = 2.0f;
1820 fp[5] = 0.0f;
1821 fp[6] = 0.0f;
1822 fp[7] = 0.0f;
1823 fp[8] = 3.0f;
1824 fp[9] = 0.0f;
1825 fp[10] = 0.0f;
1826 fp[11] = 0.0f;
1827 fp[12] = 4.0f;
1828 fp[13] = 0.0f;
1829 fp[14] = 0.0f;
1830 fp[15] = 0.0f;
1831 ip[16] = 5;
1832 ip[17] = 6;
1833
1834 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1835 " ivec2 data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL " float data0;" NL
1836 " float data1[3];" NL " ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1837 " g_output.data0 = g_input.data0;" NL
1838 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1839 " g_output.data2 = g_input.data2;" NL "}";
1840 }
1841
1842 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1843 {
GetInput(std::vector<GLubyte> & in_data)1844 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1845 {
1846 return GetInput140c2(in_data);
1847 }
1848 };
1849
1850 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1851 {
GetInput(std::vector<GLubyte> & in_data)1852 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1853 {
1854 return GetInput140c2(in_data);
1855 }
1856 };
1857
1858 //-----------------------------------------------------------------------------
1859 // 1.7.3 BasicStd140LayoutCase3
1860 //-----------------------------------------------------------------------------
GetInput140c3(std::vector<GLubyte> & in_data)1861 const char* GetInput140c3(std::vector<GLubyte>& in_data)
1862 {
1863 in_data.resize(29 * 4);
1864 float* fp = reinterpret_cast<float*>(&in_data[0]);
1865 fp[0] = 1.0f;
1866 fp[1] = 0.0f;
1867 fp[2] = 0.0f;
1868 fp[3] = 0.0f;
1869 fp[4] = 2.0f;
1870 fp[5] = 0.0f;
1871 fp[6] = 0.0f;
1872 fp[7] = 0.0f;
1873 fp[8] = 3.0f;
1874 fp[9] = 0.0f;
1875 fp[10] = 0.0f;
1876 fp[11] = 0.0f;
1877 fp[12] = 4.0f;
1878 fp[13] = 0.0f;
1879 fp[14] = 0.0f;
1880 fp[15] = 0.0f;
1881 fp[16] = 5.0f;
1882 fp[17] = 6.0f;
1883 fp[18] = 0.0f;
1884 fp[19] = 0.0f;
1885 fp[20] = 7.0f;
1886 fp[21] = 8.0f;
1887 fp[22] = 9.0f;
1888 fp[23] = 0.0f;
1889 fp[24] = 10.0f;
1890 fp[25] = 11.0f;
1891 fp[26] = 12.0f;
1892 fp[27] = 0.0f;
1893 fp[28] = 13.0f;
1894 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0;" NL " float data1[3];" NL
1895 " vec2 data2;" NL " readonly vec3 data3[2];" NL " float data4;" NL "} g_input;" NL
1896 "layout(std140, binding = 1) buffer Output {" NL " float data0;" NL " float data1[3];" NL
1897 " vec2 data2;" NL " vec3 data3[2];" NL " float data4;" NL "} g_output;" NL "void main() {" NL
1898 " g_output.data0 = g_input.data0;" NL
1899 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1900 " g_output.data2 = g_input.data2;" NL
1901 " for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1902 " g_output.data4 = g_input.data4;" NL "}";
1903 }
1904
1905 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1906 {
GetInput(std::vector<GLubyte> & in_data)1907 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1908 {
1909 return GetInput140c3(in_data);
1910 }
1911 };
1912
1913 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1914 {
GetInput(std::vector<GLubyte> & in_data)1915 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1916 {
1917 return GetInput140c3(in_data);
1918 }
1919 };
1920
1921 //-----------------------------------------------------------------------------
1922 // 1.7.4 BasicStd140LayoutCase4
1923 //-----------------------------------------------------------------------------
GetInput140c4(std::vector<GLubyte> & in_data)1924 const char* GetInput140c4(std::vector<GLubyte>& in_data)
1925 {
1926 in_data.resize(25 * 4);
1927 float* fp = reinterpret_cast<float*>(&in_data[0]);
1928 fp[0] = 1.0f;
1929 fp[1] = 2.0f;
1930 fp[2] = 0.0f;
1931 fp[3] = 0.0f;
1932 fp[4] = 3.0f;
1933 fp[5] = 4.0f;
1934 fp[6] = 0.0f;
1935 fp[7] = 0.0f;
1936 fp[8] = 5.0f;
1937 fp[9] = 6.0f;
1938 fp[10] = 0.0f;
1939 fp[11] = 0.0f;
1940 fp[12] = 7.0f;
1941 fp[13] = 8.0f;
1942 fp[14] = 0.0f;
1943 fp[15] = 0.0f;
1944 fp[16] = 9.0f;
1945 fp[17] = 10.0f;
1946 fp[18] = 11.0f;
1947 fp[19] = 0.0f;
1948 fp[20] = 12.0f;
1949 fp[21] = 13.0f;
1950 fp[22] = 14.0f;
1951 fp[23] = 0.0f;
1952 fp[24] = 15.0f;
1953
1954 return NL "layout(std140, binding = 0) buffer Input {" NL " mat4x2 data0;" NL " mat2x3 data1;" NL
1955 " float data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL " mat4x2 data0;" NL
1956 " mat2x3 data1;" NL " float data2;" NL "} g_output;" NL "void main() {" NL
1957 " g_output.data0 = g_input.data0;" NL " g_output.data1 = g_input.data1;" NL
1958 " g_output.data2 = g_input.data2;" NL "}";
1959 }
1960
1961 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
1962 {
GetInput(std::vector<GLubyte> & in_data)1963 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1964 {
1965 return GetInput140c4(in_data);
1966 }
1967 };
1968
1969 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
1970 {
GetInput(std::vector<GLubyte> & in_data)1971 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1972 {
1973 return GetInput140c4(in_data);
1974 }
1975 };
1976
1977 //-----------------------------------------------------------------------------
1978 // 1.7.5 BasicStd140LayoutCase5
1979 //-----------------------------------------------------------------------------
GetInput140c5(std::vector<GLubyte> & in_data)1980 const char* GetInput140c5(std::vector<GLubyte>& in_data)
1981 {
1982 in_data.resize(8 * 4);
1983 float* fp = reinterpret_cast<float*>(&in_data[0]);
1984 fp[0] = 1.0f;
1985 fp[1] = 2.0f;
1986 fp[2] = 3.0f;
1987 fp[3] = 4.0f;
1988 fp[4] = 5.0f;
1989 fp[5] = 6.0f;
1990 fp[6] = 7.0f;
1991 fp[7] = 8.0f;
1992 return NL "layout(std140, binding = 0, row_major) buffer Input {" NL " mat4x2 data0;" NL "} g_input;" NL
1993 "layout(std140, binding = 1, row_major) buffer Output {" NL " mat4x2 data0;" NL "} g_output;" NL
1994 "void main() {" NL " g_output.data0 = g_input.data0;" NL "}";
1995 }
1996
1997 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
1998 {
GetInput(std::vector<GLubyte> & in_data)1999 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2000 {
2001 return GetInput140c5(in_data);
2002 }
2003 };
2004
2005 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2006 {
GetInput(std::vector<GLubyte> & in_data)2007 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2008 {
2009 return GetInput140c5(in_data);
2010 }
2011 };
2012
2013 //-----------------------------------------------------------------------------
2014 // 1.7.6 BasicStd140LayoutCase6
2015 //-----------------------------------------------------------------------------
GetInput140c6(std::vector<GLubyte> & in_data)2016 const char* GetInput140c6(std::vector<GLubyte>& in_data)
2017 {
2018 in_data.resize(96 * 4);
2019 float* fp = reinterpret_cast<float*>(&in_data[0]);
2020 fp[0] = 1.0f;
2021 fp[1] = 0.0f;
2022 fp[2] = 0.0f;
2023 fp[3] = 0.0f;
2024 fp[4] = 2.0f;
2025 fp[5] = 0.0f;
2026 fp[6] = 0.0f;
2027 fp[7] = 0.0f;
2028 fp[8] = 3.0f;
2029 fp[9] = 0.0f;
2030 fp[10] = 0.0f;
2031 fp[11] = 0.0f;
2032 fp[12] = 4.0f;
2033 fp[13] = 0.0f;
2034 fp[14] = 0.0f;
2035 fp[15] = 0.0f;
2036 fp[16] = 5.0f;
2037 fp[17] = 0.0f;
2038 fp[18] = 0.0f;
2039 fp[19] = 0.0f;
2040 fp[20] = 6.0f;
2041 fp[21] = 7.0f;
2042 fp[22] = 8.0f;
2043 fp[23] = 9.0f;
2044 fp[24] = 10.0f;
2045 fp[25] = 11.0f;
2046 fp[26] = 0.0f;
2047 fp[27] = 0.0f;
2048 fp[28] = 12.0f;
2049 fp[29] = 13.0f;
2050 fp[30] = 0.0f;
2051 fp[31] = 0.0f;
2052 fp[32] = 14.0f;
2053 fp[33] = 15.0f;
2054 fp[34] = 0.0f;
2055 fp[35] = 0.0f;
2056 fp[36] = 16.0f;
2057 fp[37] = 17.0f;
2058 fp[38] = 0.0f;
2059 fp[39] = 0.0f;
2060 fp[40] = 18.0f;
2061 fp[41] = 19.0f;
2062 fp[42] = 20.0f;
2063 fp[43] = 0.0f;
2064 fp[44] = 21.0f;
2065 fp[45] = 22.0f;
2066 fp[46] = 23.0f;
2067 fp[47] = 0.0f;
2068 fp[48] = 24.0f;
2069 fp[49] = 25.0f;
2070 fp[50] = 26.0f;
2071 fp[51] = 0.0f;
2072 fp[52] = 27.0f;
2073 fp[53] = 28.0f;
2074 fp[54] = 29.0f;
2075 fp[55] = 0.0f;
2076 fp[56] = 30.0f;
2077 fp[57] = 31.0f;
2078 fp[58] = 32.0f;
2079 fp[59] = 0.0f;
2080 fp[60] = 33.0f;
2081 fp[61] = 34.0f;
2082 fp[62] = 35.0f;
2083 fp[63] = 0.0f;
2084 fp[64] = 36.0f;
2085 fp[65] = 37.0f;
2086 fp[66] = 38.0f;
2087 fp[67] = 39.0f;
2088 fp[68] = 40.0f;
2089 fp[69] = 41.0f;
2090 fp[70] = 42.0f;
2091 fp[71] = 43.0f;
2092 fp[72] = 44.0f;
2093 fp[73] = 45.0f;
2094 fp[74] = 46.0f;
2095 fp[75] = 47.0f;
2096 fp[76] = 48.0f;
2097 fp[77] = 49.0f;
2098 fp[78] = 50.0f;
2099 fp[79] = 51.0f;
2100 fp[80] = 52.0f;
2101 fp[81] = 68.0f;
2102 fp[82] = 69.0f;
2103 fp[83] = 70.0f;
2104 fp[84] = 56.0f;
2105 fp[85] = 72.0f;
2106 fp[86] = 73.0f;
2107 fp[87] = 74.0f;
2108 fp[88] = 60.0f;
2109 fp[89] = 76.0f;
2110 fp[90] = 77.0f;
2111 fp[91] = 78.0f;
2112 fp[92] = 64.0f;
2113 fp[93] = 80.0f;
2114 fp[94] = 81.0f;
2115 fp[95] = 82.0f;
2116
2117 return NL "layout(std140, binding = 0) buffer Input {" NL " float data0[2];" NL " float data1[3];" NL
2118 " vec2 data2;" NL " vec2 data3;" NL " mat2 data4[2];" NL " mat3 data5[2];" NL " mat4 data6[2];" NL
2119 "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL " float data0[2];" NL
2120 " float data1[3];" NL " vec2 data2;" NL " vec2 data3;" NL " mat2 data4[2];" NL " mat3 data5[2];" NL
2121 " mat4 data6[2];" NL "} g_output;" NL "void main() {" NL
2122 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
2123 " for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
2124 " g_output.data2 = g_input.data2;" NL " g_output.data3 = g_input.data3;" NL
2125 " for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
2126 " for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
2127 " for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL "}";
2128 }
2129
2130 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2131 {
GetInput(std::vector<GLubyte> & in_data)2132 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2133 {
2134 return GetInput140c6(in_data);
2135 }
2136 };
2137
2138 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2139 {
GetInput(std::vector<GLubyte> & in_data)2140 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2141 {
2142 return GetInput140c6(in_data);
2143 }
2144 };
2145
2146 //-----------------------------------------------------------------------------
2147 // 1.8.1 BasicAtomicCase1
2148 //-----------------------------------------------------------------------------
2149 class BasicAtomicCase1VSFS : public ShaderStorageBufferObjectBase
2150 {
2151 GLuint m_program;
2152 GLuint m_storage_buffer[4];
2153 GLuint m_vertex_array;
2154 GLuint m_vertex_buffer;
2155
Setup()2156 virtual long Setup()
2157 {
2158 m_program = 0;
2159 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2160 m_vertex_array = 0;
2161 m_vertex_buffer = 0;
2162 return NO_ERROR;
2163 }
2164
Run()2165 virtual long Run()
2166 {
2167 if (!IsVSFSAvailable(2, 2))
2168 return NOT_SUPPORTED;
2169
2170 const char* const glsl_vs = NL
2171 "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) coherent buffer VSuint {" NL
2172 " uint g_uint_out[4];" NL "};" NL "layout(std430, binding = 1) coherent buffer VSint {" NL
2173 " int data[4];" NL "} g_int_out;" NL "uniform uint g_uint_value[8];" NL "flat out int vertexid;" NL
2174 "void main() {" NL " gl_Position = g_in_position;" NL " vertexid = gl_VertexID;" NL "#ifdef GL_ES" NL
2175 " gl_PointSize = 1.0f;" NL "#endif" NL NL
2176 " // 0 is the initial value of g_uint_out while 7 is the value at the end shader execution." NL
2177 " // Since vertex shader can be executed multiple times due to implementation dependent reasons," NL
2178 " // initial validation should consider both value as possibility." NL
2179 " uint ret = atomicExchange(g_uint_out[gl_VertexID], g_uint_value[1]);" NL
2180 " if ((ret != 0u) && (ret != 7u)) return;" NL
2181 " if (atomicAdd(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2182 " if (atomicMin(g_uint_out[gl_VertexID], g_uint_value[1]) != 3u) return;" NL
2183 " if (atomicMax(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2184 " if (atomicAnd(g_uint_out[gl_VertexID], g_uint_value[3]) != 2u) return;" NL
2185 " if (atomicOr(g_uint_out[gl_VertexID], g_uint_value[4]) != 0u) return;" NL
2186 " if (g_uint_value[0] > 0u) {" NL
2187 " if (atomicXor(g_uint_out[gl_VertexID], g_uint_value[5]) != 3u) return;" NL " }" NL
2188 " if (atomicCompSwap(g_uint_out[gl_VertexID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2189 " g_uint_out[gl_VertexID] = 1u;" NL " return;" NL " }" NL NL
2190 " int ret2 = atomicExchange(g_int_out.data[gl_VertexID], 1);" NL
2191 " if ((ret2 != 0) && (ret2 != 7)) return;" NL
2192 " if (atomicAdd(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2193 " if (atomicMin(g_int_out.data[gl_VertexID], 1) != 3) return;" NL
2194 " if (atomicMax(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2195 " if (atomicAnd(g_int_out.data[gl_VertexID], 0x1) != 2) return;" NL
2196 " if (atomicOr(g_int_out.data[gl_VertexID], 0x3) != 0) return;" NL
2197 " if (atomicXor(g_int_out.data[gl_VertexID], 0x1) != 3) return;" NL
2198 " if (atomicCompSwap(g_int_out.data[gl_VertexID], 0x2, 0x7) != 2) {" NL
2199 " g_int_out.data[gl_VertexID] = 1;" NL " return;" NL " }" NL "}";
2200
2201 const char* const glsl_fs = NL
2202 "flat in int vertexid;" NL "layout(location = 0) out vec4 g_fs_out;" NL
2203 "layout(std430, binding = 2) coherent buffer FSuint {" NL " uint data[4];" NL "} g_uint_fs;" NL
2204 "layout(std430, binding = 3) coherent buffer FSint {" NL " int data[4];" NL "} g_int_fs;" NL
2205 "uniform uint g_uint_value[8];" NL "void main() {" NL " g_fs_out = vec4(0, 1, 0, 1);" NL NL
2206 " if (atomicExchange(g_uint_fs.data[vertexid], g_uint_value[1]) != 0u) return;" // 0, 1
2207 NL " if (atomicAdd(g_uint_fs.data[vertexid], g_uint_value[2]) != 1u) return;" // 1, 2
2208 NL " if (atomicMin(g_uint_fs.data[vertexid], g_uint_value[1]) != 3u) return;" // 3, 1
2209 NL " if (atomicMax(g_uint_fs.data[vertexid], g_uint_value[2]) != 1u) return;" // 1, 2
2210 NL " if (atomicAnd(g_uint_fs.data[vertexid], g_uint_value[3]) != 2u) return;" // 2, 0x1
2211 NL " if (atomicOr(g_uint_fs.data[vertexid], g_uint_value[4]) != 0u) return;" // 0, 0x3
2212 NL " if (g_uint_value[0] > 0u) {" NL
2213 " if (atomicXor(g_uint_fs.data[vertexid], g_uint_value[5]) != 3u) return;" // 0x3, 0x1
2214 NL " }" NL
2215 " if (atomicCompSwap(g_uint_fs.data[vertexid], g_uint_value[6], g_uint_value[7]) != 2u) {" // 2, 0x2, 0x7
2216 NL " g_uint_fs.data[vertexid] = 1u;" NL " return;" NL " }" NL NL
2217 " if (atomicExchange(g_int_fs.data[vertexid], 1) != 0) return;" NL
2218 " if (atomicAdd(g_int_fs.data[vertexid], 2) != 1) return;" NL
2219 " if (atomicMin(g_int_fs.data[vertexid], 1) != 3) return;" NL
2220 " if (atomicMax(g_int_fs.data[vertexid], 2) != 1) return;" NL
2221 " if (atomicAnd(g_int_fs.data[vertexid], 0x1) != 2) return;" NL
2222 " if (atomicOr(g_int_fs.data[vertexid], 0x3) != 0) return;" NL
2223 " if (atomicXor(g_int_fs.data[vertexid], 0x1) != 3) return;" NL
2224 " if (atomicCompSwap(g_int_fs.data[vertexid], 0x2, 0x7) != 2) {" NL " g_int_fs.data[vertexid] = 1;" NL
2225 " return;" NL " }" NL "}";
2226 m_program = CreateProgram(glsl_vs, glsl_fs);
2227 glLinkProgram(m_program);
2228 if (!CheckProgram(m_program))
2229 return ERROR;
2230
2231 glGenBuffers(4, m_storage_buffer);
2232 for (GLuint i = 0; i < 4; ++i)
2233 {
2234 const int data[4] = { 0 };
2235 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2236 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2237 }
2238
2239 /* vertex buffer */
2240 {
2241 const float data[] = { -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f };
2242 glGenBuffers(1, &m_vertex_buffer);
2243 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2244 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2245 glBindBuffer(GL_ARRAY_BUFFER, 0);
2246 }
2247
2248 glGenVertexArrays(1, &m_vertex_array);
2249 glBindVertexArray(m_vertex_array);
2250 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2251 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2252 glBindBuffer(GL_ARRAY_BUFFER, 0);
2253 glEnableVertexAttribArray(0);
2254 glBindVertexArray(0);
2255
2256 glClear(GL_COLOR_BUFFER_BIT);
2257 glUseProgram(m_program);
2258 GLuint unif[8] = { 3, 1, 2, 1, 3, 1, 2, 7 };
2259 glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2260
2261 glBindVertexArray(m_vertex_array);
2262 glDrawArrays(GL_POINTS, 0, 4);
2263 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2264
2265 for (int ii = 0; ii < 2; ++ii)
2266 {
2267 /* uint data */
2268 {
2269 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2270 GLuint* data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2271 if (!data)
2272 return ERROR;
2273 for (GLuint i = 0; i < 4; ++i)
2274 {
2275 if (data[i] != 7)
2276 {
2277 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2278 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2279 return ERROR;
2280 }
2281 }
2282 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2283 }
2284 /* int data */
2285 {
2286 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2287 GLint* data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2288 if (!data)
2289 return ERROR;
2290 for (GLint i = 0; i < 4; ++i)
2291 {
2292 if (data[i] != 7)
2293 {
2294 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2295 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2296 return ERROR;
2297 }
2298 }
2299 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2300 }
2301 }
2302 return NO_ERROR;
2303 }
2304
Cleanup()2305 virtual long Cleanup()
2306 {
2307 glUseProgram(0);
2308 glDeleteProgram(m_program);
2309 glDeleteBuffers(4, m_storage_buffer);
2310 glDeleteBuffers(1, &m_vertex_buffer);
2311 glDeleteVertexArrays(1, &m_vertex_array);
2312 return NO_ERROR;
2313 }
2314 };
2315 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2316 {
2317 GLuint m_program;
2318 GLuint m_storage_buffer[2];
2319
Setup()2320 virtual long Setup()
2321 {
2322 m_program = 0;
2323 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2324 return NO_ERROR;
2325 }
2326
Run()2327 virtual long Run()
2328 {
2329 const char* const glsl_cs =
2330 NL "layout(local_size_x = 4) in;" NL "layout(std430, binding = 2) coherent buffer FSuint {" NL
2331 " uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 3) coherent buffer FSint {" NL
2332 " int data[4];" NL "} g_int_fs;" NL "uniform uint g_uint_value[8];" NL "void main() {" NL
2333 " if (atomicExchange(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 0u) return;" // 0, 1
2334 NL " if (atomicAdd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" // 1, 2
2335 NL " if (atomicMin(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 3u) return;" // 3, 1
2336 NL " if (atomicMax(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" // 1, 2
2337 NL " if (atomicAnd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[3]) != 2u) return;" // 2, 0x1
2338 NL " if (atomicOr(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[4]) != 0u) return;" // 0, 0x3
2339 NL " if (g_uint_value[0] > 0u) {" NL
2340 " if (atomicXor(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[5]) != 3u) return;" // 0x3, 0x1
2341 NL " }" NL " if (atomicCompSwap(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[6], "
2342 "g_uint_value[7]) != 2u) {" // 2, 0x2, 0x7
2343 NL " g_uint_fs.data[gl_LocalInvocationIndex] = 1u;" NL " return;" NL " }" NL
2344 " if (atomicExchange(g_int_fs.data[gl_LocalInvocationIndex], 1) != 0) return;" NL
2345 " if (atomicAdd(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2346 " if (atomicMin(g_int_fs.data[gl_LocalInvocationIndex], 1) != 3) return;" NL
2347 " if (atomicMax(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2348 " if (atomicAnd(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 2) return;" NL
2349 " if (atomicOr(g_int_fs.data[gl_LocalInvocationIndex], 0x3) != 0) return;" NL
2350 " if (atomicXor(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 3) return;" NL
2351 " if (atomicCompSwap(g_int_fs.data[gl_LocalInvocationIndex], 0x2, 0x7) != 2) {" NL
2352 " g_int_fs.data[gl_LocalInvocationIndex] = 1;" NL " return;" NL " }" NL "}";
2353 m_program = CreateProgramCS(glsl_cs);
2354 glLinkProgram(m_program);
2355 if (!CheckProgram(m_program))
2356 return ERROR;
2357
2358 glGenBuffers(2, m_storage_buffer);
2359 for (GLuint i = 0; i < 2; ++i)
2360 {
2361 const int data[4] = { 0 };
2362 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 2, m_storage_buffer[i]);
2363 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2364 }
2365
2366 glUseProgram(m_program);
2367 GLuint unif[8] = { 3, 1, 2, 1, 3, 1, 2, 7 };
2368 glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2369 glDispatchCompute(1, 1, 1);
2370 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2371
2372 /* uint data */
2373 {
2374 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
2375 GLuint* data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2376 if (!data)
2377 return ERROR;
2378 for (GLuint i = 0; i < 4; ++i)
2379 {
2380 if (data[i] != 7)
2381 {
2382 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2383 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2384 return ERROR;
2385 }
2386 }
2387 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2388 }
2389 /* int data */
2390 {
2391 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
2392 GLint* data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2393 if (!data)
2394 return ERROR;
2395 for (GLint i = 0; i < 4; ++i)
2396 {
2397 if (data[i] != 7)
2398 {
2399 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2400 << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2401 return ERROR;
2402 }
2403 }
2404 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2405 }
2406 return NO_ERROR;
2407 }
2408
Cleanup()2409 virtual long Cleanup()
2410 {
2411 glUseProgram(0);
2412 glDeleteProgram(m_program);
2413 glDeleteBuffers(2, m_storage_buffer);
2414 return NO_ERROR;
2415 }
2416 };
2417 //-----------------------------------------------------------------------------
2418 // 1.8.3 BasicAtomicCase3
2419 //-----------------------------------------------------------------------------
2420 class BasicAtomicCase3VSFS : public ShaderStorageBufferObjectBase
2421 {
2422 GLuint m_program;
2423 GLuint m_storage_buffer;
2424 GLuint m_vertex_array;
2425 GLuint m_vertex_buffer;
2426
Setup()2427 virtual long Setup()
2428 {
2429 m_program = 0;
2430 m_storage_buffer = 0;
2431 m_vertex_array = 0;
2432 m_vertex_buffer = 0;
2433 return NO_ERROR;
2434 }
2435
Run()2436 virtual long Run()
2437 {
2438 if (!IsVSFSAvailable(1, 1))
2439 return NOT_SUPPORTED;
2440 const char* const glsl_vs = NL
2441 "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) coherent buffer Buffer {" NL
2442 " uvec4 u[4];" NL " ivec3 i[4];" NL "} g_vs_buffer;" NL "flat out int vertexid;" NL "void main() {" NL
2443 " vertexid = gl_VertexID;" NL " gl_Position = g_in_position;" NL "#ifdef GL_ES" NL
2444 " gl_PointSize = 1.0f;" NL "#endif" NL " atomicAdd(g_vs_buffer.u[0].x, g_vs_buffer.u[gl_VertexID][1]);" NL
2445 " atomicAdd(g_vs_buffer.u[0][0], g_vs_buffer.u[gl_VertexID].z);" NL
2446 " atomicAdd(g_vs_buffer.i[0].x, g_vs_buffer.i[gl_VertexID][1]);" NL
2447 " atomicAdd(g_vs_buffer.i[0][0], g_vs_buffer.i[gl_VertexID].z);" NL "}";
2448 const char* const glsl_fs =
2449 NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) coherent buffer Buffer {" NL
2450 " uvec4 u[4];" NL " ivec3 i[4];" NL "} g_fs_buffer;" NL "flat in int vertexid;" NL "void main() {" NL
2451 " g_fs_out = vec4(0, 1, 0, 1);" NL " atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[vertexid][1]);" NL
2452 " atomicAdd(g_fs_buffer.i[0].x, g_fs_buffer.i[vertexid][1]);" NL "}";
2453 m_program = CreateProgram(glsl_vs, glsl_fs);
2454 glLinkProgram(m_program);
2455 if (!CheckProgram(m_program))
2456 return ERROR;
2457
2458 /* init storage buffer */
2459 {
2460 glGenBuffers(1, &m_storage_buffer);
2461 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2462 glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2463 ivec4* ptr = reinterpret_cast<ivec4*>(
2464 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2465 if (!ptr)
2466 return ERROR;
2467 for (int i = 0; i < 4; ++i)
2468 {
2469 ptr[i * 2] = ivec4(0, 1, 2, 0);
2470 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2471 }
2472 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2473 }
2474
2475 /* init vertex buffer */
2476 {
2477 const float data[] = { -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f };
2478 glGenBuffers(1, &m_vertex_buffer);
2479 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2480 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2481 glBindBuffer(GL_ARRAY_BUFFER, 0);
2482 }
2483
2484 glGenVertexArrays(1, &m_vertex_array);
2485 glBindVertexArray(m_vertex_array);
2486 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2487 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2488 glBindBuffer(GL_ARRAY_BUFFER, 0);
2489 glEnableVertexAttribArray(0);
2490 glBindVertexArray(0);
2491
2492 glClear(GL_COLOR_BUFFER_BIT);
2493 glUseProgram(m_program);
2494 glBindVertexArray(m_vertex_array);
2495 glDrawArrays(GL_POINTS, 0, 4);
2496 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2497
2498 GLuint* u = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2499 if (!u)
2500 return ERROR;
2501 if (*u != 16)
2502 {
2503 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2504 << " should be 16." << tcu::TestLog::EndMessage;
2505 return ERROR;
2506 }
2507 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2508 GLint* i = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2509 if (!i)
2510 return ERROR;
2511 if (*i != 16)
2512 {
2513 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2514 << " should be 16." << tcu::TestLog::EndMessage;
2515 return ERROR;
2516 }
2517 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2518
2519 return NO_ERROR;
2520 }
2521
Cleanup()2522 virtual long Cleanup()
2523 {
2524 glUseProgram(0);
2525 glDeleteProgram(m_program);
2526 glDeleteBuffers(1, &m_storage_buffer);
2527 glDeleteBuffers(1, &m_vertex_buffer);
2528 glDeleteVertexArrays(1, &m_vertex_array);
2529 return NO_ERROR;
2530 }
2531 };
2532 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2533 {
2534 GLuint m_program;
2535 GLuint m_storage_buffer;
2536
Setup()2537 virtual long Setup()
2538 {
2539 m_program = 0;
2540 m_storage_buffer = 0;
2541 return NO_ERROR;
2542 }
2543
Run()2544 virtual long Run()
2545 {
2546 const char* const glsl_cs =
2547 NL "layout(local_size_y = 4) in;" NL "layout(std430) coherent buffer Buffer {" NL " uvec4 u[4];" NL
2548 " ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2549 " atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y][2]);" NL
2550 " atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y][1]);" NL
2551 " atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y].z);" NL
2552 " atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y].y);" NL "}";
2553 m_program = CreateProgramCS(glsl_cs);
2554 glLinkProgram(m_program);
2555 if (!CheckProgram(m_program))
2556 return ERROR;
2557
2558 /* init storage buffer */
2559 {
2560 glGenBuffers(1, &m_storage_buffer);
2561 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2562 glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2563 ivec4* ptr = reinterpret_cast<ivec4*>(
2564 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2565 if (!ptr)
2566 return ERROR;
2567 for (int i = 0; i < 4; ++i)
2568 {
2569 ptr[i * 2] = ivec4(0, 1, 2, 0);
2570 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2571 }
2572 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2573 }
2574
2575 glUseProgram(m_program);
2576 glDispatchCompute(1, 1, 1);
2577 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2578
2579 GLuint* u = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2580 if (!u)
2581 return ERROR;
2582 if (*u != 16)
2583 {
2584 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2585 << " should be 16." << tcu::TestLog::EndMessage;
2586 return ERROR;
2587 }
2588 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2589 GLint* i = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2590 if (!i)
2591 return ERROR;
2592 if (*i != 16)
2593 {
2594 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2595 << " should be 16." << tcu::TestLog::EndMessage;
2596 return ERROR;
2597 }
2598 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2599
2600 return NO_ERROR;
2601 }
2602
Cleanup()2603 virtual long Cleanup()
2604 {
2605 glUseProgram(0);
2606 glDeleteProgram(m_program);
2607 glDeleteBuffers(1, &m_storage_buffer);
2608 return NO_ERROR;
2609 }
2610 };
2611
2612 //-----------------------------------------------------------------------------
2613 // 1.8.4 BasicAtomicCase4
2614 //-----------------------------------------------------------------------------
2615 class BasicAtomicCase4VSFS : public ShaderStorageBufferObjectBase
2616 {
2617 GLuint m_program;
2618 GLuint m_storage_buffer[2];
2619 GLuint m_vertex_array;
2620 GLuint m_vertex_buffer;
2621
Setup()2622 virtual long Setup()
2623 {
2624 m_program = 0;
2625 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2626 m_vertex_array = 0;
2627 m_vertex_buffer = 0;
2628 return NO_ERROR;
2629 }
2630
Run()2631 virtual long Run()
2632 {
2633 if (!IsVSFSAvailable(2, 2))
2634 return NOT_SUPPORTED;
2635 const char* const glsl_vs =
2636 NL "layout(location = 0) in vec4 g_in_position;" NL
2637 "layout(std430, binding = 0) coherent buffer Counters {" NL " uint g_uint_counter;" NL
2638 " int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL " uint udata[8];" NL
2639 " int idata[8];" NL "} g_output;" NL "void main() {" NL " gl_Position = g_in_position;" NL
2640 "#ifdef GL_ES" NL " gl_PointSize = 1.0f;" NL "#endif" NL
2641 " uint uidx = atomicAdd(g_uint_counter, 1u);" NL " int iidx = atomicAdd(g_int_counter, -1);" NL
2642 " g_output.udata[uidx] = uidx;" NL " g_output.idata[iidx] = iidx;" NL "}";
2643 const char* const glsl_fs =
2644 NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) coherent buffer Counters {" NL
2645 " uint g_uint_counter;" NL " int g_int_counter;" NL "};" NL
2646 "layout(std430, binding = 1) buffer Output {" NL " uint udata[8];" NL " int idata[8];" NL
2647 "} g_output;" NL "void main() {" NL " g_fs_out = vec4(0, 1, 0, 1);" NL
2648 " uint uidx = atomicAdd(g_uint_counter, 1u);" NL " int iidx = atomicAdd(g_int_counter, -1);" NL
2649 " g_output.udata[uidx] = uidx;" NL " g_output.idata[iidx] = iidx;" NL "}";
2650 m_program = CreateProgram(glsl_vs, glsl_fs);
2651 glLinkProgram(m_program);
2652 if (!CheckProgram(m_program))
2653 return ERROR;
2654
2655 glGenBuffers(2, m_storage_buffer);
2656 /* counter buffer */
2657 {
2658 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2659 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2660 int* ptr = reinterpret_cast<int*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
2661 if (!ptr)
2662 return ERROR;
2663 *ptr++ = 0;
2664 *ptr++ = 7;
2665 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2666 }
2667 /* output buffer */
2668 {
2669 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2670 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2671 }
2672 /* vertex buffer */
2673 {
2674 const float data[] = { -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f };
2675 glGenBuffers(1, &m_vertex_buffer);
2676 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2677 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2678 glBindBuffer(GL_ARRAY_BUFFER, 0);
2679 }
2680
2681 glGenVertexArrays(1, &m_vertex_array);
2682 glBindVertexArray(m_vertex_array);
2683 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2684 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2685 glBindBuffer(GL_ARRAY_BUFFER, 0);
2686 glEnableVertexAttribArray(0);
2687 glBindVertexArray(0);
2688
2689 glClear(GL_COLOR_BUFFER_BIT);
2690 glUseProgram(m_program);
2691 glBindVertexArray(m_vertex_array);
2692 glDrawArrays(GL_POINTS, 0, 4);
2693 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2694
2695 GLuint* udata = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
2696 if (!udata)
2697 return ERROR;
2698 for (GLuint i = 0; i < 8; ++i)
2699 {
2700 if (udata[i] != i)
2701 {
2702 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2703 << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2704 return ERROR;
2705 }
2706 }
2707 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2708 GLint* idata = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
2709 if (!idata)
2710 return ERROR;
2711 for (GLint i = 0; i < 8; ++i)
2712 {
2713 if (idata[i] != i)
2714 {
2715 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2716 << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2717 return ERROR;
2718 }
2719 }
2720 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2721 return NO_ERROR;
2722 }
2723
Cleanup()2724 virtual long Cleanup()
2725 {
2726 glUseProgram(0);
2727 glDeleteProgram(m_program);
2728 glDeleteBuffers(2, m_storage_buffer);
2729 glDeleteBuffers(1, &m_vertex_buffer);
2730 glDeleteVertexArrays(1, &m_vertex_array);
2731 return NO_ERROR;
2732 }
2733 };
2734
2735 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2736 {
2737 GLuint m_program;
2738 GLuint m_storage_buffer[2];
2739
Setup()2740 virtual long Setup()
2741 {
2742 m_program = 0;
2743 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2744 return NO_ERROR;
2745 }
2746
Run()2747 virtual long Run()
2748 {
2749 const char* const glsl_cs =
2750 NL "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;" NL
2751 "layout(std430, binding = 0) coherent buffer Counters {" NL " uint g_uint_counter;" NL
2752 " int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL " uint udata[8];" NL
2753 " int idata[8];" NL "} g_output;" NL "void main() {" NL
2754 " uint uidx = atomicAdd(g_uint_counter, 1u);" NL " int iidx = atomicAdd(g_int_counter, -1);" NL
2755 " g_output.udata[uidx] = uidx;" NL " g_output.idata[iidx] = iidx;" NL "}";
2756 m_program = CreateProgramCS(glsl_cs);
2757 glLinkProgram(m_program);
2758 if (!CheckProgram(m_program))
2759 return ERROR;
2760
2761 glGenBuffers(2, m_storage_buffer);
2762 /* counter buffer */
2763 {
2764 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2765 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2766 int* ptr = reinterpret_cast<int*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
2767 if (!ptr)
2768 return ERROR;
2769 *ptr++ = 0;
2770 *ptr++ = 7;
2771 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2772 }
2773 /* output buffer */
2774 {
2775 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2776 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2777 }
2778 glUseProgram(m_program);
2779 glDispatchCompute(1, 1, 1);
2780 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2781
2782 GLuint* udata = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
2783 if (!udata)
2784 return ERROR;
2785 for (GLuint i = 0; i < 8; ++i)
2786 {
2787 if (udata[i] != i)
2788 {
2789 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2790 << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2791 return ERROR;
2792 }
2793 }
2794 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2795 GLint* idata = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
2796 if (!idata)
2797 return ERROR;
2798 for (GLint i = 0; i < 8; ++i)
2799 {
2800 if (idata[i] != i)
2801 {
2802 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2803 << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2804 return ERROR;
2805 }
2806 }
2807 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2808 return NO_ERROR;
2809 }
2810
Cleanup()2811 virtual long Cleanup()
2812 {
2813 glUseProgram(0);
2814 glDeleteProgram(m_program);
2815 glDeleteBuffers(2, m_storage_buffer);
2816 return NO_ERROR;
2817 }
2818 };
2819 //-----------------------------------------------------------------------------
2820 // 1.9.x BasicStdLayoutBase2
2821 //-----------------------------------------------------------------------------
2822 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
2823 {
2824 GLuint m_program;
2825 GLuint m_buffer[8];
2826 GLuint m_vertex_array;
2827
2828 virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
2829
Setup()2830 virtual long Setup()
2831 {
2832 m_program = 0;
2833 memset(m_buffer, 0, sizeof(m_buffer));
2834 m_vertex_array = 0;
2835 return NO_ERROR;
2836 }
2837
Run()2838 virtual long Run()
2839 {
2840 if (!IsVSFSAvailable(8, 0))
2841 return NOT_SUPPORTED;
2842 std::vector<GLubyte> in_data[4];
2843 const char* glsl_vs = GetInput(in_data);
2844 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
2845 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
2846
2847 m_program = CreateProgram(glsl_vs, glsl_fs);
2848 glLinkProgram(m_program);
2849 if (!CheckProgram(m_program))
2850 return ERROR;
2851
2852 glGenBuffers(8, m_buffer);
2853
2854 for (GLuint i = 0; i < 4; ++i)
2855 {
2856 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
2857 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
2858
2859 std::vector<GLubyte> out_data(in_data[i].size());
2860 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
2861 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
2862 }
2863
2864 glGenVertexArrays(1, &m_vertex_array);
2865 glEnable(GL_RASTERIZER_DISCARD);
2866
2867 glUseProgram(m_program);
2868 glBindVertexArray(m_vertex_array);
2869 glDrawArrays(GL_POINTS, 0, 1);
2870
2871 bool status = true;
2872 for (int j = 0; j < 4; ++j)
2873 {
2874 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
2875 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2876 GLubyte* out_data =
2877 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
2878 if (!out_data)
2879 return ERROR;
2880
2881 for (size_t i = 0; i < in_data[j].size(); ++i)
2882 {
2883 if (in_data[j][i] != out_data[i])
2884 {
2885 m_context.getTestContext().getLog()
2886 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
2887 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
2888 << tcu::TestLog::EndMessage;
2889 status = false;
2890 }
2891 }
2892 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2893 }
2894 if (!status)
2895 return ERROR;
2896 return NO_ERROR;
2897 }
2898
Cleanup()2899 virtual long Cleanup()
2900 {
2901 glDisable(GL_RASTERIZER_DISCARD);
2902 glUseProgram(0);
2903 glDeleteProgram(m_program);
2904 glDeleteBuffers(8, m_buffer);
2905 glDeleteVertexArrays(1, &m_vertex_array);
2906 return NO_ERROR;
2907 }
2908 };
2909
2910 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
2911 {
2912 GLuint m_program;
2913 GLuint m_buffer[8];
2914
2915 virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
2916
Setup()2917 virtual long Setup()
2918 {
2919 m_program = 0;
2920 memset(m_buffer, 0, sizeof(m_buffer));
2921 return NO_ERROR;
2922 }
2923
Run()2924 virtual long Run()
2925 {
2926 std::vector<GLubyte> in_data[4];
2927 std::stringstream ss;
2928 GLint blocksCS;
2929 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksCS);
2930 if (blocksCS < 8)
2931 return NO_ERROR;
2932 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
2933 m_program = CreateProgramCS(ss.str());
2934 glLinkProgram(m_program);
2935 if (!CheckProgram(m_program))
2936 return ERROR;
2937
2938 glGenBuffers(8, m_buffer);
2939
2940 for (GLuint i = 0; i < 4; ++i)
2941 {
2942 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
2943 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
2944
2945 std::vector<GLubyte> out_data(in_data[i].size());
2946 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
2947 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
2948 }
2949
2950 glUseProgram(m_program);
2951 glDispatchCompute(1, 1, 1);
2952 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2953
2954 bool status = true;
2955 for (int j = 0; j < 4; ++j)
2956 {
2957 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
2958 GLubyte* out_data =
2959 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
2960 if (!out_data)
2961 return ERROR;
2962
2963 for (size_t i = 0; i < in_data[j].size(); ++i)
2964 {
2965 if (in_data[j][i] != out_data[i])
2966 {
2967 m_context.getTestContext().getLog()
2968 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
2969 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
2970 << tcu::TestLog::EndMessage;
2971 status = false;
2972 }
2973 }
2974 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2975 }
2976 if (!status)
2977 return ERROR;
2978 return NO_ERROR;
2979 }
2980
Cleanup()2981 virtual long Cleanup()
2982 {
2983 glUseProgram(0);
2984 glDeleteProgram(m_program);
2985 glDeleteBuffers(8, m_buffer);
2986 return NO_ERROR;
2987 }
2988 };
2989
2990 //-----------------------------------------------------------------------------
2991 // 1.9.1 BasicStdLayoutCase1
2992 //-----------------------------------------------------------------------------
GetInputC1(std::vector<GLubyte> in_data[4])2993 const char* GetInputC1(std::vector<GLubyte> in_data[4])
2994 {
2995 for (int i = 0; i < 4; ++i)
2996 {
2997 in_data[i].resize(1 * 4);
2998 float* fp = reinterpret_cast<float*>(&in_data[i][0]);
2999 fp[0] = (float)(i + 1) * 1.0f;
3000 }
3001 return NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL "} g_input[4];" NL
3002 "layout(std430, binding = 4) buffer Output {" NL " float data0;" NL "} g_output[4];" NL
3003 "void main() {" NL " g_output[0].data0 = g_input[0].data0;" NL
3004 " g_output[1].data0 = g_input[1].data0;" NL " g_output[2].data0 = g_input[2].data0;" NL
3005 " g_output[3].data0 = g_input[3].data0;" NL "}";
3006 }
3007
3008 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3009 {
GetInput(std::vector<GLubyte> in_data[4])3010 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3011 {
3012 return GetInputC1(in_data);
3013 }
3014 };
3015
3016 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
3017 {
GetInput(std::vector<GLubyte> in_data[4])3018 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3019 {
3020 return GetInputC1(in_data);
3021 }
3022 };
3023
3024 //-----------------------------------------------------------------------------
3025 // 1.9.2 BasicStdLayoutCase2
3026 //-----------------------------------------------------------------------------
GetInputC2(std::vector<GLubyte> in_data[4])3027 const char* GetInputC2(std::vector<GLubyte> in_data[4])
3028 {
3029 /* input 0, std140 */
3030 {
3031 in_data[0].resize(12 * 4);
3032 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3033 fp[0] = 1.0f;
3034 fp[1] = 0.0f;
3035 fp[2] = 0.0f;
3036 fp[3] = 0.0f;
3037 fp[4] = 2.0f;
3038 fp[5] = 0.0f;
3039 fp[6] = 0.0f;
3040 fp[7] = 0.0f;
3041 fp[8] = 3.0f;
3042 fp[9] = 0.0f;
3043 fp[10] = 0.0f;
3044 fp[11] = 0.0f;
3045 }
3046 /* input 1, std430 */
3047 {
3048 in_data[1].resize(3 * 4);
3049 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3050 fp[0] = 4.0f;
3051 fp[1] = 5.0f;
3052 fp[2] = 6.0f;
3053 }
3054 /* input 2, std140 */
3055 {
3056 in_data[2].resize(12 * 4);
3057 float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3058 fp[0] = 7.0f;
3059 fp[1] = 0.0f;
3060 fp[2] = 0.0f;
3061 fp[3] = 0.0f;
3062 fp[4] = 8.0f;
3063 fp[5] = 0.0f;
3064 fp[6] = 0.0f;
3065 fp[7] = 0.0f;
3066 fp[8] = 9.0f;
3067 fp[9] = 0.0f;
3068 fp[10] = 0.0f;
3069 fp[11] = 0.0f;
3070 }
3071 /* input 3, std430 */
3072 {
3073 in_data[3].resize(3 * 4);
3074 float* fp = reinterpret_cast<float*>(&in_data[3][0]);
3075 fp[0] = 10.0f;
3076 fp[1] = 11.0f;
3077 fp[2] = 12.0f;
3078 }
3079 return NL "layout(std140, binding = 0) buffer Input0 {" NL " float data0[3];" NL "} g_input0;" NL
3080 "layout(std430, binding = 1) buffer Input1 {" NL " float data0[3];" NL "} g_input1;" NL
3081 "layout(std140, binding = 2) buffer Input2 {" NL " float data0[3];" NL "} g_input2;" NL
3082 "layout(std430, binding = 3) buffer Input3 {" NL " float data0[3];" NL "} g_input3;" NL
3083 "layout(std140, binding = 4) buffer Output0 {" NL " float data0[3];" NL "} g_output0;" NL
3084 "layout(std430, binding = 5) buffer Output1 {" NL " float data0[3];" NL "} g_output1;" NL
3085 "layout(std140, binding = 6) buffer Output2 {" NL " float data0[3];" NL "} g_output2;" NL
3086 "layout(std430, binding = 7) buffer Output3 {" NL " float data0[3];" NL "} g_output3;" NL
3087 "void main() {" NL
3088 " for (int i = 0; i < g_input0.data0.length(); ++i) g_output0.data0[i] = g_input0.data0[i];" NL
3089 " for (int i = 0; i < g_input1.data0.length(); ++i) g_output1.data0[i] = g_input1.data0[i];" NL
3090 " for (int i = 0; i < g_input2.data0.length(); ++i) g_output2.data0[i] = g_input2.data0[i];" NL
3091 " for (int i = 0; i < g_input3.data0.length(); ++i) g_output3.data0[i] = g_input3.data0[i];" NL "}";
3092 }
3093
3094 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3095 {
GetInput(std::vector<GLubyte> in_data[4])3096 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3097 {
3098 return GetInputC2(in_data);
3099 }
3100 };
3101
3102 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3103 {
GetInput(std::vector<GLubyte> in_data[4])3104 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3105 {
3106 return GetInputC2(in_data);
3107 }
3108 };
3109
3110 //-----------------------------------------------------------------------------
3111 // 1.9.3 BasicStdLayoutCase3
3112 //-----------------------------------------------------------------------------
GetInputC3(std::vector<GLubyte> in_data[4])3113 const char* GetInputC3(std::vector<GLubyte> in_data[4])
3114 {
3115 /* input 0, std140 */
3116 {
3117 in_data[0].resize(62 * 4);
3118 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3119 int* ip = reinterpret_cast<int*>(&in_data[0][0]);
3120 ip[0] = 1;
3121 ip[1] = 0;
3122 ip[2] = 0;
3123 ip[3] = 0;
3124 fp[4] = 2.0f;
3125 fp[5] = 0.0f;
3126 fp[6] = 0.0f;
3127 fp[7] = 0.0f;
3128 fp[8] = 3.0f;
3129 fp[9] = 0.0f;
3130 fp[10] = 0.0f;
3131 fp[11] = 0.0f;
3132 fp[12] = 4.0f;
3133 fp[13] = 0.0f;
3134 fp[14] = 0.0f;
3135 fp[15] = 0.0f;
3136 fp[16] = 5.0f;
3137 fp[17] = 0.0f;
3138 fp[18] = 0.0f;
3139 fp[19] = 0.0f;
3140 fp[20] = 6.0f;
3141 fp[21] = 0.0f;
3142 fp[22] = 0.0f;
3143 fp[23] = 0.0f;
3144 fp[24] = 7.0f;
3145 fp[25] = 8.0f;
3146 fp[26] = 0.0f;
3147 fp[27] = 0.0f;
3148 fp[28] = 9.0f;
3149 fp[29] = 10.0f;
3150 fp[30] = 0.0f;
3151 fp[31] = 0.0f;
3152 fp[32] = 11.0f;
3153 fp[33] = 12.0f;
3154 fp[34] = 0.0f;
3155 fp[35] = 0.0f;
3156 fp[36] = 13.0f;
3157 fp[37] = 0.0f;
3158 fp[38] = 0.0f;
3159 fp[39] = 0.0f;
3160 fp[40] = 14.0f;
3161 fp[41] = 0.0f;
3162 fp[42] = 0.0f;
3163 fp[43] = 0.0f;
3164 fp[44] = 15.0f;
3165 fp[45] = 0.0f;
3166 fp[46] = 0.0f;
3167 fp[47] = 0.0f;
3168 ip[48] = 16;
3169 ip[49] = 0;
3170 ip[50] = 0;
3171 ip[51] = 0;
3172 ip[52] = 17;
3173 ip[53] = 18;
3174 ip[54] = 19;
3175 ip[55] = 0;
3176 }
3177 /* input 1, std430 */
3178 {
3179 in_data[1].resize(30 * 4);
3180 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3181 int* ip = reinterpret_cast<int*>(&in_data[1][0]);
3182 ip[0] = 1;
3183 fp[1] = 2.0f;
3184 fp[2] = 3.0f;
3185 fp[3] = 4.0f;
3186 fp[4] = 5.0f;
3187 fp[5] = 6.0f;
3188 fp[6] = 7.0f;
3189 fp[7] = 8.0f;
3190 fp[8] = 9.0f;
3191 fp[9] = 10.0f;
3192 fp[10] = 11.0f;
3193 fp[11] = 12.0f;
3194 fp[12] = 13.0f;
3195 fp[13] = 14.0f;
3196 fp[14] = 15.0f;
3197 ip[15] = 16;
3198 ip[16] = 17;
3199 ip[17] = 18;
3200 ip[18] = 19;
3201 }
3202 /* input 2, std140 */
3203 {
3204 in_data[2].resize(5 * 4);
3205 int* ip = reinterpret_cast<int*>(&in_data[2][0]);
3206 ip[0] = 1;
3207 ip[1] = 0;
3208 ip[2] = 0;
3209 ip[3] = 0;
3210 ip[4] = 2;
3211 }
3212 /* input 3, std430 */
3213 {
3214 in_data[3].resize(2 * 4);
3215 int* ip = reinterpret_cast<int*>(&in_data[3][0]);
3216 ip[0] = 1;
3217 ip[1] = 2;
3218 }
3219 return NL "layout(std140, binding = 0) buffer Input0 {" NL " int data0;" //BA=4, OF=[0]0, next=4
3220 NL " float data1[5];" //BA=16, OF=[4]16, next=96
3221 NL " mat3x2 data2;" //BA=16, OF=[24]96, next=144
3222 NL " float data3;" //BA=4, OF=[36]144,next=148
3223 NL " float data4[2];" //BA=16, OF=[40]160,next=192
3224 NL " int data5;" //BA=4, OF=[48]192,next=196
3225 NL " ivec3 data6;" //BA=16, OF=[52]208
3226 NL "} g_input0;" NL "layout(std430, binding = 1) buffer Input1 {" NL " int data0;" //BA=4, OF=[0], next=[1]
3227 NL " float data1[5];" //BA=4, OF=[1], next=[6]
3228 NL " mat3x2 data2;" //BA=8, OF=[6], next=[12]
3229 NL " float data3;" //BA=4, OF=[12], next=[13]
3230 NL " float data4[2];" //BA=4, OF=[13], next=[15]
3231 NL " int data5;" //BA=4, OF=[15], next=[16]
3232 NL " ivec3 data6;" //BA=16,OF=[16]
3233 NL "} g_input1;" NL "struct Struct0 {" NL " int data0;" NL "};" NL
3234 "layout(std140, binding = 2) buffer Input2 {" NL " int data0;" // offset 0
3235 NL " Struct0 data1;" // offset 16, struct should be aligned to a multiple of 16 bytes
3236 NL "} g_input2;" NL "layout(std430, binding = 3) buffer Input3 {" NL " int data0;" // offset 0
3237 NL " Struct0 data1;" // offset 4
3238 NL "} g_input3;"
3239
3240 NL "layout(std140, binding = 4) buffer Output0 {" NL " int data0;" NL " float data1[5];" NL
3241 " mat3x2 data2;" NL " float data3;" NL " float data4[2];" NL " int data5;" NL " ivec3 data6;" NL
3242 "} g_output0;" NL "layout(std430, binding = 5) buffer Output1 {" NL " int data0;" NL
3243 " float data1[5];" NL " mat3x2 data2;" NL " float data3;" NL " float data4[2];" NL " int data5;" NL
3244 " ivec3 data6;" NL "} g_output1;" NL "layout(std140, binding = 6) buffer Output2 {" NL " int data0;" NL
3245 " Struct0 data1;" NL "} g_output2;" NL "layout(std430, binding = 7) buffer Output3 {" NL
3246 " int data0;" NL " Struct0 data1;" NL "} g_output3;" NL "void main() {" NL
3247 " g_output0.data0 = g_input0.data0;" NL
3248 " for (int i = 0; i < g_input0.data1.length(); ++i) g_output0.data1[i] = g_input0.data1[i];" NL
3249 " g_output0.data2 = g_input0.data2;" NL " g_output0.data3 = g_input0.data3;" NL
3250 " for (int i = 0; i < g_input0.data4.length(); ++i) g_output0.data4[i] = g_input0.data4[i];" NL
3251 " g_output0.data5 = g_input0.data5;" NL " g_output0.data6 = g_input0.data6;"
3252
3253 NL " g_output1.data0 = g_input1.data0;" NL
3254 " for (int i = 0; i < g_input1.data1.length(); ++i) g_output1.data1[i] = g_input1.data1[i];" NL
3255 " g_output1.data2 = g_input1.data2;" NL " g_output1.data3 = g_input1.data3;" NL
3256 " for (int i = 0; i < g_input1.data4.length(); ++i) g_output1.data4[i] = g_input1.data4[i];" NL
3257 " g_output1.data5 = g_input1.data5;" NL " g_output1.data6 = g_input1.data6;"
3258
3259 NL " g_output2.data0 = g_input2.data0;" NL " g_output2.data1 = g_input2.data1;"
3260
3261 NL " g_output3.data0 = g_input3.data0;" NL " g_output3.data1 = g_input3.data1;" NL "}";
3262 }
3263
3264 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3265 {
GetInput(std::vector<GLubyte> in_data[4])3266 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3267 {
3268 return GetInputC3(in_data);
3269 }
3270 };
3271
3272 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3273 {
GetInput(std::vector<GLubyte> in_data[4])3274 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3275 {
3276 return GetInputC3(in_data);
3277 }
3278 };
3279
3280 //-----------------------------------------------------------------------------
3281 // 1.9.4 BasicStdLayoutCase4
3282 //-----------------------------------------------------------------------------
GetInputC4(std::vector<GLubyte> in_data[4])3283 const char* GetInputC4(std::vector<GLubyte> in_data[4])
3284 {
3285 /* input 0, std140 */
3286 {
3287 in_data[0].resize(57 * 4);
3288 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3289 int* ip = reinterpret_cast<int*>(&in_data[0][0]);
3290 ip[0] = 1;
3291 ip[1] = 0;
3292 ip[2] = 0;
3293 ip[3] = 0;
3294 ip[4] = 2;
3295 ip[5] = 3;
3296 ip[6] = 0;
3297 ip[7] = 0;
3298 ip[8] = 4;
3299 ip[9] = 5;
3300 ip[10] = 0;
3301 ip[11] = 0;
3302 fp[12] = 6.0f;
3303 fp[13] = 0.0f;
3304 fp[14] = 0.0f;
3305 fp[15] = 0.0f;
3306 fp[16] = 7.0f;
3307 fp[17] = 8.0f;
3308 fp[18] = 0.0f;
3309 fp[19] = 0.0f;
3310 ip[20] = 9;
3311 ip[21] = 10;
3312 ip[22] = 11;
3313 ip[23] = 0;
3314 fp[24] = 12.0f;
3315 fp[25] = 13.0f;
3316 fp[26] = 0.0f;
3317 fp[27] = 0.0f;
3318 ip[28] = 14;
3319 ip[29] = 15;
3320 ip[30] = 16;
3321 ip[31] = 0;
3322 fp[32] = 17.0f;
3323 fp[33] = 0.0f;
3324 fp[34] = 0.0f;
3325 fp[35] = 0.0f;
3326 ip[36] = 18;
3327 ip[37] = 0;
3328 ip[38] = 0;
3329 ip[39] = 0;
3330 ip[40] = 19;
3331 ip[41] = 20;
3332 ip[42] = 0;
3333 ip[43] = 0;
3334 ip[44] = 21;
3335 ip[45] = 0;
3336 ip[45] = 0;
3337 ip[45] = 0;
3338 fp[48] = 22.0f;
3339 fp[49] = 23.0f;
3340 fp[50] = 0.0f;
3341 fp[51] = 0.0f;
3342 ip[52] = 24;
3343 ip[53] = 25;
3344 ip[54] = 26;
3345 ip[55] = 0;
3346 fp[56] = 27.0f;
3347 }
3348 /* input 1, std140 */
3349 {
3350 in_data[1].resize(57 * 4);
3351 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3352 int* ip = reinterpret_cast<int*>(&in_data[1][0]);
3353 ip[0] = 101;
3354 ip[1] = 0;
3355 ip[2] = 0;
3356 ip[3] = 0;
3357 ip[4] = 102;
3358 ip[5] = 103;
3359 ip[6] = 0;
3360 ip[7] = 0;
3361 ip[8] = 104;
3362 ip[9] = 105;
3363 ip[10] = 0;
3364 ip[11] = 0;
3365 fp[12] = 106.0f;
3366 fp[13] = 0.0f;
3367 fp[14] = 0.0f;
3368 fp[15] = 0.0f;
3369 fp[16] = 107.0f;
3370 fp[17] = 108.0f;
3371 fp[18] = 0.0f;
3372 fp[19] = 0.0f;
3373 ip[20] = 109;
3374 ip[21] = 110;
3375 ip[22] = 111;
3376 ip[23] = 0;
3377 fp[24] = 112.0f;
3378 fp[25] = 113.0f;
3379 fp[26] = 0.0f;
3380 fp[27] = 0.0f;
3381 ip[28] = 114;
3382 ip[29] = 115;
3383 ip[30] = 116;
3384 ip[31] = 0;
3385 fp[32] = 117.0f;
3386 fp[33] = 0.0f;
3387 fp[34] = 0.0f;
3388 fp[35] = 0.0f;
3389 ip[36] = 118;
3390 ip[37] = 0;
3391 ip[38] = 0;
3392 ip[39] = 0;
3393 ip[40] = 119;
3394 ip[41] = 120;
3395 ip[42] = 0;
3396 ip[43] = 0;
3397 ip[44] = 121;
3398 ip[45] = 0;
3399 ip[45] = 0;
3400 ip[45] = 0;
3401 fp[48] = 122.0f;
3402 fp[49] = 123.0f;
3403 fp[50] = 0.0f;
3404 fp[51] = 0.0f;
3405 ip[52] = 124;
3406 ip[53] = 125;
3407 ip[54] = 126;
3408 ip[55] = 0;
3409 fp[56] = 127.0f;
3410 }
3411 /* input 2, std430 */
3412 {
3413 in_data[2].resize(45 * 4);
3414 float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3415 int* ip = reinterpret_cast<int*>(&in_data[2][0]);
3416 ip[0] = 1000;
3417 ip[1] = 0;
3418 ip[2] = 1001;
3419 ip[3] = 1002;
3420 ip[4] = 1003;
3421 ip[5] = 1004;
3422 fp[6] = 1005.0f;
3423 fp[7] = 0.0f;
3424 fp[8] = 1006.0f;
3425 fp[9] = 1007.0f;
3426 fp[10] = 0.0f;
3427 fp[11] = 0.0f;
3428 ip[12] = 1008;
3429 ip[13] = 1009;
3430 ip[14] = 1010;
3431 ip[15] = 0;
3432 fp[16] = 1011.0f;
3433 fp[17] = 1012.0f;
3434 fp[18] = 0.0f;
3435 fp[19] = 0.0f;
3436 ip[20] = 1013;
3437 ip[21] = 1014;
3438 ip[22] = 1015;
3439 ip[23] = 0;
3440 fp[24] = 1016.0f;
3441 fp[25] = 0.0f;
3442 fp[26] = 0.0f;
3443 fp[27] = 0.0f;
3444 ip[28] = 1017;
3445 ip[29] = 0;
3446 ip[30] = 1018;
3447 ip[31] = 1019;
3448 ip[32] = 1020;
3449 ip[33] = 0;
3450 ip[34] = 0;
3451 ip[35] = 0;
3452 fp[36] = 1021.0f;
3453 fp[37] = 1022.0f;
3454 fp[38] = 0.0f;
3455 fp[39] = 0.0f;
3456 ip[40] = 1023;
3457 ip[41] = 1024;
3458 ip[42] = 1025;
3459 ip[43] = 0;
3460 fp[44] = 1026.0f;
3461 }
3462 /* input 3, std430 */
3463 {
3464 in_data[3].resize(45 * 4);
3465 float* fp = reinterpret_cast<float*>(&in_data[3][0]);
3466 int* ip = reinterpret_cast<int*>(&in_data[3][0]);
3467 ip[0] = 10000;
3468 ip[1] = 0;
3469 ip[2] = 10001;
3470 ip[3] = 10002;
3471 ip[4] = 10003;
3472 ip[5] = 10004;
3473 fp[6] = 10005.0f;
3474 fp[7] = 0.0f;
3475 fp[8] = 10006.0f;
3476 fp[9] = 10007.0f;
3477 fp[10] = 0.0f;
3478 fp[11] = 0.0f;
3479 ip[12] = 10008;
3480 ip[13] = 10009;
3481 ip[14] = 10010;
3482 ip[15] = 0;
3483 fp[16] = 10011.0f;
3484 fp[17] = 10012.0f;
3485 fp[18] = 0.0f;
3486 fp[19] = 0.0f;
3487 ip[20] = 10013;
3488 ip[21] = 10014;
3489 ip[22] = 10015;
3490 ip[23] = 0;
3491 fp[24] = 10016.0f;
3492 fp[25] = 0.0f;
3493 fp[26] = 0.0f;
3494 fp[27] = 0.0f;
3495 ip[28] = 10017;
3496 ip[29] = 0;
3497 ip[30] = 10018;
3498 ip[31] = 10019;
3499 ip[32] = 10020;
3500 ip[33] = 0;
3501 ip[34] = 0;
3502 ip[35] = 0;
3503 fp[36] = 10021.0f;
3504 fp[37] = 10022.0f;
3505 fp[38] = 0.0f;
3506 fp[39] = 0.0f;
3507 ip[40] = 10023;
3508 ip[41] = 10024;
3509 ip[42] = 10025;
3510 ip[43] = 0;
3511 fp[44] = 10026.0f;
3512 }
3513
3514 return NL
3515 "struct Struct0 {" NL " ivec2 data0;" NL "};" NL "struct Struct1 {" NL " vec2 data0;" // offset 0
3516 NL " ivec3 data1;" // offset 16
3517 NL "};" NL "struct Struct2 {" NL " int data0;" // offset 0
3518 NL " Struct0 data1;" // offset std430 8, std140 16
3519 NL " int data2;" // offset std430 16, std140 32
3520 NL " Struct1 data3;" // offset std430 32, std140 48
3521 NL " float data4;" // offset std430 64, std140 80
3522 NL "};" NL "layout(std140, binding = 0) buffer Input01 {" NL " int data0;" // offset 0
3523 NL " Struct0 data1[2];" // offset 16
3524 NL " float data2;" // offset 48
3525 NL " Struct1 data3[2];" // offset 64
3526 NL " float data4;" // offset 128
3527 NL " Struct2 data5;" // offset 144
3528 NL "} g_input01[2];" NL "layout(std430, binding = 2) buffer Input23 {" NL " int data0;" // offset 0
3529 NL " Struct0 data1[2];" // offset 8
3530 NL " float data2;" // offset 24
3531 NL " Struct1 data3[2];" // offset 32
3532 NL " float data4;" // offset 96
3533 NL " Struct2 data5;" // offset 112
3534 NL "} g_input23[2];"
3535
3536 NL "layout(std140, binding = 4) buffer Output01 {" NL " int data0;" NL " Struct0 data1[2];" NL
3537 " float data2;" NL " Struct1 data3[2];" NL " float data4;" NL " Struct2 data5;" NL "} g_output01[2];" NL
3538 "layout(std430, binding = 6) buffer Output23 {" NL " int data0;" NL " Struct0 data1[2];" NL
3539 " float data2;" NL " Struct1 data3[2];" NL " float data4;" NL " Struct2 data5;" NL "} g_output23[2];" NL NL
3540 "void main() {" NL " g_output01[0].data0 = g_input01[0].data0;" NL
3541 " for (int i = 0; i < g_input01[0].data1.length(); ++i) g_output01[0].data1[i] = g_input01[0].data1[i];" NL
3542 " g_output01[0].data2 = g_input01[0].data2;" NL " g_output01[0].data3[0] = g_input01[0].data3[0];" NL
3543 " g_output01[0].data3[1] = g_input01[0].data3[1];" NL " g_output01[0].data4 = g_input01[0].data4;" NL
3544 " g_output01[1].data0 = g_input01[1].data0;" NL
3545 " for (int i = 0; i < g_input01[1].data1.length(); ++i) g_output01[1].data1[i] = g_input01[1].data1[i];" NL
3546 " g_output01[1].data2 = g_input01[1].data2;" NL " g_output01[1].data3[0] = g_input01[1].data3[0];" NL
3547 " g_output01[1].data3[1] = g_input01[1].data3[1];" NL " g_output01[1].data4 = g_input01[1].data4;" NL
3548 " g_output01[0].data5 = g_input01[0].data5;" NL " g_output01[1].data5 = g_input01[1].data5;" NL NL
3549 " g_output23[0].data0 = g_input23[0].data0;" NL
3550 " for (int i = 0; i < g_input23[0].data1.length(); ++i) g_output23[0].data1[i] = g_input23[0].data1[i];" NL
3551 " g_output23[0].data2 = g_input23[0].data2;" NL " g_output23[0].data3[0] = g_input23[0].data3[0];" NL
3552 " g_output23[0].data3[1] = g_input23[0].data3[1];" NL " g_output23[0].data4 = g_input23[0].data4;" NL
3553 " g_output23[1].data0 = g_input23[1].data0;" NL
3554 " for (int i = 0; i < g_input23[1].data1.length(); ++i) g_output23[1].data1[i] = g_input23[1].data1[i];" NL
3555 " g_output23[1].data2 = g_input23[1].data2;" NL " g_output23[1].data3[0] = g_input23[1].data3[0];" NL
3556 " g_output23[1].data3[1] = g_input23[1].data3[1];" NL " g_output23[1].data4 = g_input23[1].data4;" NL
3557 " g_output23[0].data5 = g_input23[0].data5;" NL " g_output23[1].data5 = g_input23[1].data5;" NL "}";
3558 }
3559
3560 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3561 {
GetInput(std::vector<GLubyte> in_data[4])3562 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3563 {
3564 return GetInputC4(in_data);
3565 }
3566 };
3567
3568 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3569 {
GetInput(std::vector<GLubyte> in_data[4])3570 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3571 {
3572 return GetInputC4(in_data);
3573 }
3574 };
3575
3576 //-----------------------------------------------------------------------------
3577 // 1.10.x BasicOperationsBase
3578 //-----------------------------------------------------------------------------
3579 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3580 {
3581 GLuint m_program;
3582 GLuint m_buffer[2];
3583 GLuint m_vertex_array;
3584
3585 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3586
Setup()3587 virtual long Setup()
3588 {
3589 m_program = 0;
3590 memset(m_buffer, 0, sizeof(m_buffer));
3591 m_vertex_array = 0;
3592 return NO_ERROR;
3593 }
3594
Run()3595 virtual long Run()
3596 {
3597 if (!IsVSFSAvailable(2, 0))
3598 return NOT_SUPPORTED;
3599 std::vector<GLubyte> in_data;
3600 std::vector<GLubyte> expected_data;
3601 const char* glsl_vs = GetInput(in_data, expected_data);
3602 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
3603 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
3604
3605 m_program = CreateProgram(glsl_vs, glsl_fs);
3606 glLinkProgram(m_program);
3607 if (!CheckProgram(m_program))
3608 return ERROR;
3609
3610 glGenBuffers(2, m_buffer);
3611
3612 /* output buffer */
3613 {
3614 std::vector<GLubyte> zero(expected_data.size());
3615 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3616 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3617 }
3618 // input buffer
3619 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3620 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3621
3622 glGenVertexArrays(1, &m_vertex_array);
3623 glEnable(GL_RASTERIZER_DISCARD);
3624
3625 glUseProgram(m_program);
3626 glBindVertexArray(m_vertex_array);
3627
3628 glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3629 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3630 glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3631
3632 glDrawArrays(GL_POINTS, 0, 1);
3633
3634 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3635 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3636 GLubyte* out_data =
3637 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3638 if (!out_data)
3639 return ERROR;
3640
3641 bool status = true;
3642 for (size_t i = 0; i < expected_data.size(); ++i)
3643 {
3644 if (expected_data[i] != out_data[i])
3645 {
3646 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3647 << " is " << tcu::toHex(out_data[i]) << " should be "
3648 << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3649 status = false;
3650 }
3651 }
3652 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3653 if (!status)
3654 return ERROR;
3655 return NO_ERROR;
3656 }
3657
Cleanup()3658 virtual long Cleanup()
3659 {
3660 glDisable(GL_RASTERIZER_DISCARD);
3661 glUseProgram(0);
3662 glDeleteProgram(m_program);
3663 glDeleteBuffers(2, m_buffer);
3664 glDeleteVertexArrays(1, &m_vertex_array);
3665 return NO_ERROR;
3666 }
3667 };
3668
3669 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3670 {
3671 GLuint m_program;
3672 GLuint m_buffer[2];
3673
3674 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3675
Setup()3676 virtual long Setup()
3677 {
3678 m_program = 0;
3679 memset(m_buffer, 0, sizeof(m_buffer));
3680 return NO_ERROR;
3681 }
3682
Run()3683 virtual long Run()
3684 {
3685 std::vector<GLubyte> in_data;
3686 std::vector<GLubyte> expected_data;
3687
3688 std::stringstream ss;
3689 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data, expected_data);
3690 m_program = CreateProgramCS(ss.str());
3691 glLinkProgram(m_program);
3692 if (!CheckProgram(m_program))
3693 return ERROR;
3694
3695 glGenBuffers(2, m_buffer);
3696
3697 /* output buffer */
3698 {
3699 std::vector<GLubyte> zero(expected_data.size());
3700 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3701 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3702 }
3703 // input buffer
3704 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3705 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3706
3707 glUseProgram(m_program);
3708 glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3709 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3710 glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3711 glDispatchCompute(1, 1, 1);
3712
3713 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3714 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3715 GLubyte* out_data =
3716 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3717 if (!out_data)
3718 return ERROR;
3719
3720 bool status = true;
3721 for (size_t i = 0; i < expected_data.size(); ++i)
3722 {
3723 if (expected_data[i] != out_data[i])
3724 {
3725 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3726 << " is " << tcu::toHex(out_data[i]) << " should be "
3727 << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3728 status = false;
3729 }
3730 }
3731 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3732 if (!status)
3733 return ERROR;
3734 return NO_ERROR;
3735 }
3736
Cleanup()3737 virtual long Cleanup()
3738 {
3739 glUseProgram(0);
3740 glDeleteProgram(m_program);
3741 glDeleteBuffers(2, m_buffer);
3742 return NO_ERROR;
3743 }
3744 };
3745
3746 //-----------------------------------------------------------------------------
3747 // 1.10.1 BasicOperationsCase1
3748 //-----------------------------------------------------------------------------
GetInputOp1(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3749 const char* GetInputOp1(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3750 {
3751 /* input */
3752 {
3753 in_data.resize(16 * 9);
3754 int* ip = reinterpret_cast<int*>(&in_data[0]);
3755 float* fp = reinterpret_cast<float*>(&in_data[0]);
3756 ip[0] = 1;
3757 ip[1] = 2;
3758 ip[2] = 3;
3759 ip[3] = 4; // data0
3760 fp[4] = 1.0f;
3761 fp[5] = 2.0f;
3762 fp[6] = 3.0f;
3763 fp[7] = 0.0f; // data1
3764 ip[8] = 1;
3765 ip[9] = 2;
3766 ip[10] = 3;
3767 ip[11] = 4; // data2
3768 ip[12] = 1;
3769 ip[13] = -2;
3770 ip[14] = 3;
3771 ip[15] = 4; // data3
3772 fp[16] = 1.0f;
3773 fp[17] = 2.0f;
3774 fp[18] = 3.0f;
3775 fp[19] = 4.0f; // data4
3776 fp[20] = 1.0f;
3777 fp[21] = 2.0f;
3778 fp[22] = 3.0f;
3779 fp[23] = 4.0f; // data5
3780 fp[24] = 1.0f;
3781 fp[25] = 2.0f;
3782 fp[26] = 3.0f;
3783 fp[27] = 4.0f; // data5
3784 fp[28] = 1.0f;
3785 fp[29] = 2.0f;
3786 fp[30] = 3.0f;
3787 fp[31] = 4.0f; // data5
3788 fp[32] = 1.0f;
3789 fp[33] = 0.0f;
3790 fp[34] = 0.0f;
3791 fp[35] = 4.0f; // data5
3792 }
3793 /* expected output */
3794 {
3795 out_data.resize(16 * 9);
3796 int* ip = reinterpret_cast<int*>(&out_data[0]);
3797 float* fp = reinterpret_cast<float*>(&out_data[0]);
3798 ip[0] = 4;
3799 ip[1] = 3;
3800 ip[2] = 2;
3801 ip[3] = 1;
3802 fp[4] = 3.0f;
3803 fp[5] = 2.0f;
3804 fp[6] = 1.0f;
3805 fp[7] = 0.0f;
3806 ip[8] = 4;
3807 ip[9] = 1;
3808 ip[10] = 0;
3809 ip[11] = 3;
3810 ip[12] = 10;
3811 ip[13] = 4;
3812 ip[14] = -2;
3813 ip[15] = 20;
3814 fp[16] = 50.0f;
3815 fp[17] = 5.0f;
3816 fp[18] = 2.0f;
3817 fp[19] = 30.0f;
3818 fp[20] = 4.0f;
3819 fp[21] = 2.0f;
3820 fp[22] = 3.0f;
3821 fp[23] = 1.0f; // data5
3822 fp[24] = 4.0f;
3823 fp[25] = 3.0f;
3824 fp[26] = 2.0f;
3825 fp[27] = 1.0f; // data5
3826 fp[28] = 2.0f;
3827 fp[29] = 2.0f;
3828 fp[30] = 2.0f;
3829 fp[31] = 2.0f; // data5
3830 fp[32] = 4.0f;
3831 fp[33] = 0.0f;
3832 fp[34] = 0.0f;
3833 fp[35] = 1.0f; // data5
3834 }
3835
3836 return NL "layout(std430, binding = 0) buffer Input {" NL " ivec4 data0;" NL " vec3 data1;" NL " uvec4 data2;" NL
3837 " ivec4 data3;" NL " vec4 data4;" NL " mat4 data5;" NL "} g_input;" NL
3838 "layout(std430, binding = 1) buffer Output {" NL " ivec4 data0;" NL " vec3 data1;" NL
3839 " uvec4 data2;" NL " ivec4 data3;" NL " vec4 data4;" NL " mat4 data5;" NL "} g_output;" NL
3840 "uniform vec3 g_value0;" NL "uniform int g_index1;" NL "void main() {" NL " int index0 = 0;" NL
3841 " g_output.data0.wzyx = g_input.data0;" NL " g_output.data1 = g_input.data1.zyx;" NL
3842 " g_output.data2.xwy = g_input.data2.wzx;" NL " g_output.data3.xw = ivec2(10, 20);" NL
3843 " g_output.data3.zy = g_input.data3.yw;" NL " g_output.data4.wx = g_value0.xz;" // w == 10.0, x == 30.0
3844 NL " g_output.data4.wx += g_value0.yy;" // w == 30.0, x == 50.0
3845 NL " g_output.data4.yz = g_input.data4.xx + g_input.data4.wx;" // y == 5.0, z == 2.0
3846 NL " g_output.data5[g_index1 - 1].wyzx = vec4(1, 2, 3, 4);" NL
3847 " g_output.data5[g_index1 + index0] = g_input.data5[g_index1].wzyx;" NL
3848 " g_output.data5[1 + g_index1] = g_input.data5[g_index1 + 1].yyyy;" NL
3849 " g_output.data5[5 - g_index1 - 1].wx = g_input.data5[4 - g_index1].xw;" NL "}";
3850 }
3851
3852 class BasicOperationsCase1VS : public BasicOperationsBaseVS
3853 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3854 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3855 {
3856 return GetInputOp1(in_data, out_data);
3857 }
3858 };
3859
3860 class BasicOperationsCase1CS : public BasicOperationsBaseCS
3861 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3862 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3863 {
3864 return GetInputOp1(in_data, out_data);
3865 }
3866 };
3867
3868 //-----------------------------------------------------------------------------
3869 // 1.10.2 BasicOperationsCase2
3870 //-----------------------------------------------------------------------------
GetInputOp2(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3871 const char* GetInputOp2(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3872 {
3873 /* input */
3874 {
3875 in_data.resize(16 * 8);
3876 float* fp = reinterpret_cast<float*>(&in_data[0]);
3877 fp[0] = 1.0f;
3878 fp[1] = 0.0f;
3879 fp[2] = 0.0f;
3880 fp[3] = 0.0f;
3881 fp[4] = 0.0f;
3882 fp[5] = 1.0f;
3883 fp[6] = 0.0f;
3884 fp[7] = 0.0f;
3885 fp[8] = 0.0f;
3886 fp[9] = 0.0f;
3887 fp[10] = 1.0f;
3888 fp[11] = 0.0f;
3889 fp[12] = 0.0f;
3890 fp[13] = 0.0f;
3891 fp[14] = 0.0f;
3892 fp[15] = 1.0f;
3893
3894 fp[16] = 2.0f;
3895 fp[17] = 0.0f;
3896 fp[18] = 0.0f;
3897 fp[19] = 0.0f;
3898 fp[20] = 0.0f;
3899 fp[21] = 3.0f;
3900 fp[22] = 0.0f;
3901 fp[23] = 0.0f;
3902 fp[24] = 0.0f;
3903 fp[25] = 0.0f;
3904 fp[26] = 4.0f;
3905 fp[27] = 0.0f;
3906 fp[28] = 0.0f;
3907 fp[29] = 0.0f;
3908 fp[30] = 0.0f;
3909 fp[31] = 5.0f;
3910 }
3911 /* expected output */
3912 {
3913 out_data.resize(16 * 5);
3914 float* fp = reinterpret_cast<float*>(&out_data[0]);
3915 fp[0] = 2.0f;
3916 fp[1] = 0.0f;
3917 fp[2] = 0.0f;
3918 fp[3] = 0.0f;
3919 fp[4] = 0.0f;
3920 fp[5] = 3.0f;
3921 fp[6] = 0.0f;
3922 fp[7] = 0.0f;
3923 fp[8] = 0.0f;
3924 fp[9] = 0.0f;
3925 fp[10] = 4.0f;
3926 fp[11] = 0.0f;
3927 fp[12] = 0.0f;
3928 fp[13] = 0.0f;
3929 fp[14] = 0.0f;
3930 fp[15] = 5.0f;
3931
3932 fp[16] = 0.0f;
3933 fp[17] = 1.0f;
3934 fp[18] = 4.0f;
3935 fp[19] = 0.0f;
3936 }
3937 return NL "layout(std430, binding = 0) buffer Input {" NL " mat4 data0;" NL " mat4 data1;" NL "} g_input;" NL
3938 "layout(std430, binding = 1) buffer Output {" NL " mat4 data0;" NL " vec4 data1;" NL "} g_output;" NL
3939 "uniform int g_index2;" NL "void main() {" NL
3940 " g_output.data0 = matrixCompMult(g_input.data0, g_input.data1);" NL
3941 " g_output.data1 = g_input.data0[1] + g_input.data1[g_index2];" NL "}";
3942 }
3943
3944 class BasicOperationsCase2VS : public BasicOperationsBaseVS
3945 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3946 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3947 {
3948 return GetInputOp2(in_data, out_data);
3949 }
3950 };
3951
3952 class BasicOperationsCase2CS : public BasicOperationsBaseCS
3953 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3954 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3955 {
3956 return GetInputOp2(in_data, out_data);
3957 }
3958 };
3959
3960 //-----------------------------------------------------------------------------
3961 // 1.11.x BasicStdLayoutBase3
3962 //-----------------------------------------------------------------------------
3963 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
3964 {
3965 GLuint m_program;
3966 GLuint m_buffer[4];
3967 GLuint m_vertex_array;
3968
3969 virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
3970
Setup()3971 virtual long Setup()
3972 {
3973 m_program = 0;
3974 memset(m_buffer, 0, sizeof(m_buffer));
3975 m_vertex_array = 0;
3976 return NO_ERROR;
3977 }
3978
Run()3979 virtual long Run()
3980 {
3981 if (!IsVSFSAvailable(4, 0))
3982 return NOT_SUPPORTED;
3983 std::vector<GLubyte> in_data[2];
3984 const char* glsl_vs = GetInput(in_data);
3985 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
3986 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
3987
3988 m_program = CreateProgram(glsl_vs, glsl_fs);
3989 glLinkProgram(m_program);
3990 if (!CheckProgram(m_program))
3991 return ERROR;
3992
3993 glGenBuffers(4, m_buffer);
3994
3995 // input buffers
3996 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
3997 glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
3998
3999 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4000 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4001
4002 /* output buffer 0 */
4003 {
4004 std::vector<GLubyte> out_data(in_data[0].size());
4005 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4006 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4007 }
4008 /* output buffer 1 */
4009 {
4010 std::vector<GLubyte> out_data(in_data[1].size());
4011 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4012 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4013 }
4014
4015 glGenVertexArrays(1, &m_vertex_array);
4016 glEnable(GL_RASTERIZER_DISCARD);
4017
4018 glUseProgram(m_program);
4019 glBindVertexArray(m_vertex_array);
4020
4021 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4022
4023 glDrawArrays(GL_POINTS, 0, 1);
4024
4025 bool status = true;
4026 for (int j = 0; j < 2; ++j)
4027 {
4028 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4029 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4030 GLubyte* out_data =
4031 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
4032 if (!out_data)
4033 return ERROR;
4034
4035 for (size_t i = 0; i < in_data[j].size(); ++i)
4036 {
4037 if (in_data[j][i] != out_data[i])
4038 {
4039 m_context.getTestContext().getLog()
4040 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4041 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4042 << tcu::TestLog::EndMessage;
4043 status = false;
4044 }
4045 }
4046 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4047 }
4048 if (!status)
4049 return ERROR;
4050 return NO_ERROR;
4051 }
4052
Cleanup()4053 virtual long Cleanup()
4054 {
4055 glDisable(GL_RASTERIZER_DISCARD);
4056 glUseProgram(0);
4057 glDeleteProgram(m_program);
4058 glDeleteBuffers(4, m_buffer);
4059 glDeleteVertexArrays(1, &m_vertex_array);
4060 return NO_ERROR;
4061 }
4062 };
4063
4064 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4065 {
4066 GLuint m_program;
4067 GLuint m_buffer[4];
4068
4069 virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
4070
Setup()4071 virtual long Setup()
4072 {
4073 m_program = 0;
4074 memset(m_buffer, 0, sizeof(m_buffer));
4075 return NO_ERROR;
4076 }
4077
Run()4078 virtual long Run()
4079 {
4080 std::vector<GLubyte> in_data[2];
4081
4082 std::stringstream ss;
4083 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
4084 m_program = CreateProgramCS(ss.str());
4085 glLinkProgram(m_program);
4086 if (!CheckProgram(m_program))
4087 return ERROR;
4088
4089 glGenBuffers(4, m_buffer);
4090
4091 // input buffers
4092 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4093 glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4094
4095 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4096 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4097
4098 /* output buffer 0 */
4099 {
4100 std::vector<GLubyte> out_data(in_data[0].size());
4101 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4102 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4103 }
4104 /* output buffer 1 */
4105 {
4106 std::vector<GLubyte> out_data(in_data[1].size());
4107 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4108 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4109 }
4110
4111 glUseProgram(m_program);
4112 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4113 glDispatchCompute(1, 1, 1);
4114
4115 bool status = true;
4116 for (int j = 0; j < 2; ++j)
4117 {
4118 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4119 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4120 GLubyte* out_data =
4121 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
4122 if (!out_data)
4123 return ERROR;
4124
4125 for (size_t i = 0; i < in_data[j].size(); ++i)
4126 {
4127 if (in_data[j][i] != out_data[i])
4128 {
4129 m_context.getTestContext().getLog()
4130 << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4131 << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4132 << tcu::TestLog::EndMessage;
4133 status = false;
4134 }
4135 }
4136 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4137 }
4138 if (!status)
4139 return ERROR;
4140 return NO_ERROR;
4141 }
4142
Cleanup()4143 virtual long Cleanup()
4144 {
4145 glUseProgram(0);
4146 glDeleteProgram(m_program);
4147 glDeleteBuffers(4, m_buffer);
4148 return NO_ERROR;
4149 }
4150 };
4151
4152 //-----------------------------------------------------------------------------
4153 // 1.11.1 Basic_UBO_SSBO_LayoutCase1
4154 //-----------------------------------------------------------------------------
GetInputUBO1(std::vector<GLubyte> in_data[2])4155 const char* GetInputUBO1(std::vector<GLubyte> in_data[2])
4156 {
4157 /* UBO */
4158 {
4159 in_data[0].resize(12 * 4);
4160 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4161 fp[0] = 1.0f;
4162 fp[1] = 0.0f;
4163 fp[2] = 0.0f;
4164 fp[3] = 0.0f;
4165 fp[4] = 2.0f;
4166 fp[5] = 0.0f;
4167 fp[6] = 0.0f;
4168 fp[7] = 0.0f;
4169 fp[8] = 3.0f;
4170 fp[9] = 0.0f;
4171 fp[10] = 0.0f;
4172 fp[11] = 0.0f;
4173 }
4174 /* SSBO */
4175 {
4176 in_data[1].resize(3 * 4);
4177 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
4178 fp[0] = 1.0f;
4179 fp[1] = 2.0f;
4180 fp[2] = 3.0f;
4181 }
4182
4183 return NL
4184 "layout(std140, binding = 0) uniform InputUBO {" NL " float data0;" NL " float data1[2];" NL
4185 "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL " float data0;" NL
4186 " float data1[2];" NL "} g_input_ssbo;" NL "layout(std140, binding = 1) buffer OutputUBO {" NL
4187 " float data0;" NL " float data1[2];" NL "} g_output_ubo;" NL
4188 "layout(std430, binding = 2) buffer OutputSSBO {" NL " float data0;" NL " float data1[2];" NL
4189 "} g_output_ssbo;" NL "void main() {" NL " g_output_ubo.data0 = g_input_ubo.data0;" NL
4190 " for (int i = 0; i < g_input_ubo.data1.length(); ++i) g_output_ubo.data1[i] = g_input_ubo.data1[i];" NL
4191 " g_output_ssbo.data0 = g_input_ssbo.data0;" NL
4192 " for (int i = 0; i < g_input_ssbo.data1.length(); ++i) g_output_ssbo.data1[i] = g_input_ssbo.data1[i];" NL
4193 "}";
4194 }
4195
4196 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4197 {
GetInput(std::vector<GLubyte> in_data[2])4198 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4199 {
4200 return GetInputUBO1(in_data);
4201 }
4202 };
4203
4204 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4205 {
GetInput(std::vector<GLubyte> in_data[2])4206 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4207 {
4208 return GetInputUBO1(in_data);
4209 }
4210 };
4211
4212 //-----------------------------------------------------------------------------
4213 // 1.11.2 Basic_UBO_SSBO_LayoutCase2
4214 //-----------------------------------------------------------------------------
GetInputUBO2(std::vector<GLubyte> in_data[2])4215 const char* GetInputUBO2(std::vector<GLubyte> in_data[2])
4216 {
4217 /* UBO */
4218 {
4219 in_data[0].resize(280 * 4);
4220 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4221 int* ip = reinterpret_cast<int*>(&in_data[0][0]);
4222 fp[0] = 1.0f;
4223 fp[1] = 2.0f;
4224 fp[2] = 3.0f;
4225 fp[3] = 4.0f;
4226 fp[4] = 5.0f;
4227 fp[5] = 6.0f;
4228 fp[6] = 7.0f;
4229 fp[8] = 9.0f;
4230 fp[12] = 10.0f;
4231 fp[16] = 11.0f;
4232 fp[20] = 12.0f;
4233 fp[24] = 13.0f;
4234
4235 ip[28] = 14;
4236 for (int i = 0; i < 20; ++i)
4237 {
4238 fp[32 + i * 4] = static_cast<float>(15 + i);
4239 }
4240 ip[112] = 140;
4241 for (int i = 0; i < 20; ++i)
4242 {
4243 fp[116 + i * 4] = static_cast<float>(150 + i);
4244 }
4245 ip[196] = 1400;
4246 for (int i = 0; i < 20; ++i)
4247 {
4248 fp[200 + i * 4] = static_cast<float>(1500 + i);
4249 }
4250 }
4251 /* SSBO */
4252 {
4253 in_data[1].resize(76 * 4);
4254 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
4255 int* ip = reinterpret_cast<int*>(&in_data[1][0]);
4256 fp[0] = 1.0f;
4257 fp[1] = 2.0f;
4258 fp[2] = 3.0f;
4259 fp[3] = 4.0f;
4260 fp[4] = 5.0f;
4261 fp[5] = 6.0f;
4262 fp[6] = 7.0f;
4263 fp[7] = 8.0f;
4264 fp[8] = 9.0f;
4265 fp[9] = 10.0f;
4266 fp[10] = 11.0f;
4267 fp[11] = 12.0f;
4268 fp[12] = 13.0f;
4269 ip[13] = 14;
4270 fp[14] = 15.0f;
4271 fp[15] = 16.0f;
4272 fp[16] = 17.0f;
4273 fp[17] = 18.0f;
4274 fp[18] = 19.0f;
4275 fp[19] = 20.0f;
4276 fp[20] = 21.0f;
4277 fp[21] = 22.0f;
4278 fp[22] = 23.0f;
4279 fp[23] = 24.0f;
4280 fp[24] = 25.0f;
4281 fp[25] = 26.0f;
4282 fp[26] = 27.0f;
4283 fp[27] = 28.0f;
4284 fp[28] = 29.0f;
4285 fp[29] = 30.0f;
4286 fp[30] = 31.0f;
4287 fp[31] = 32.0f;
4288 fp[32] = 33.0f;
4289 fp[33] = 34.0f;
4290 ip[34] = 35;
4291 fp[35] = 36.0f;
4292 fp[36] = 37.0f;
4293 fp[37] = 38.0f;
4294 fp[38] = 39.0f;
4295 fp[39] = 40.0f;
4296 fp[40] = 41.0f;
4297 fp[41] = 42.0f;
4298 fp[42] = 43.0f;
4299 fp[43] = 44.0f;
4300 fp[44] = 45.0f;
4301 fp[45] = 46.0f;
4302 fp[46] = 47.0f;
4303 fp[47] = 48.0f;
4304 fp[48] = 49.0f;
4305 fp[49] = 50.0f;
4306 fp[50] = 51.0f;
4307 fp[51] = 52.0f;
4308 fp[52] = 53.0f;
4309 fp[53] = 54.0f;
4310 fp[54] = 55.0f;
4311 ip[55] = 56;
4312 fp[56] = 57.0f;
4313 fp[57] = 58.0f;
4314 fp[58] = 59.0f;
4315 fp[59] = 60.0f;
4316 fp[60] = 61.0f;
4317 fp[61] = 62.0f;
4318 fp[62] = 63.0f;
4319 fp[63] = 64.0f;
4320 fp[64] = 65.0f;
4321 fp[65] = 66.0f;
4322 fp[66] = 67.0f;
4323 fp[67] = 68.0f;
4324 fp[68] = 69.0f;
4325 fp[69] = 70.0f;
4326 fp[70] = 71.0f;
4327 fp[71] = 72.0f;
4328 fp[72] = 73.0f;
4329 fp[73] = 74.0f;
4330 fp[74] = 75.0f;
4331 fp[75] = 76.0f;
4332 }
4333 return NL
4334 "struct MM {" NL " float mm_a[5];" NL "};" NL "struct TT {" NL " int tt_a;" NL " MM tt_b[4];" NL "};" NL
4335 "layout(std140, binding = 0) uniform InputUBO {" NL " vec4 a;" NL " vec4 b;" NL " float c;" NL
4336 " float d[4];" NL " TT e[3];" NL "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL
4337 " vec4 a;" NL " vec4 b;" NL " float c;" NL " float d[4];" NL " TT e[3];" NL "} g_input_ssbo;" NL
4338 "layout(std140, binding = 1) buffer OutputUBO {" NL " vec4 a;" NL " vec4 b;" NL " float c;" NL
4339 " float d[4];" NL " TT e[3];" NL "} g_output_ubo;" NL "layout(std430, binding = 2) buffer OutputSSBO {" NL
4340 " vec4 a;" NL " vec4 b;" NL " float c;" NL " float d[4];" NL " TT e[3];" NL "} g_output_ssbo;" NL
4341 "uniform int g_index1;" NL "void main() {" NL " int index0 = 0;" NL NL " g_output_ubo.a = g_input_ubo.a;" NL
4342 " g_output_ubo.b = g_input_ubo.b;" NL " g_output_ubo.c = g_input_ubo.c;" NL
4343 " for (int i = 0; i < g_input_ubo.d.length(); ++i) g_output_ubo.d[i] = g_input_ubo.d[i];" NL
4344 " for (int j = 0; j < g_input_ubo.e.length(); ++j) {" NL
4345 " g_output_ubo.e[j].tt_a = g_input_ubo.e[j].tt_a;" NL
4346 " for (int i = 0; i < g_input_ubo.e[j].tt_b.length(); ++i) {" NL
4347 " g_output_ubo.e[j].tt_b[i].mm_a[0] = g_input_ubo.e[j].tt_b[i].mm_a[0];" NL
4348 " g_output_ubo.e[j].tt_b[index0 + i].mm_a[1] = g_input_ubo.e[j].tt_b[i].mm_a[1];" NL
4349 " g_output_ubo.e[j].tt_b[i].mm_a[2] = g_input_ubo.e[j].tt_b[i].mm_a[2 + index0];" NL
4350 " 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 + "
4351 "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
4352 " }" NL " }" NL NL " g_output_ssbo.a = g_input_ssbo.a;" NL " g_output_ssbo.b = g_input_ssbo.b;" NL
4353 " g_output_ssbo.c = g_input_ssbo.c;" NL
4354 " for (int i = 0; i < g_input_ssbo.d.length(); ++i) g_output_ssbo.d[i] = g_input_ssbo.d[i];" NL
4355 " for (int j = 0; j < g_input_ssbo.e.length(); ++j) {" NL
4356 " g_output_ssbo.e[j].tt_a = g_input_ssbo.e[j].tt_a;" NL
4357 " for (int i = 0; i < g_input_ssbo.e[j].tt_b.length(); ++i) {" NL
4358 " g_output_ssbo.e[j + index0].tt_b[i].mm_a[0] = g_input_ssbo.e[j].tt_b[i].mm_a[index0];" NL
4359 " 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
4360 " 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
4361 " 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 - "
4362 "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
4363 " }" NL "}";
4364 }
4365
4366 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4367 {
GetInput(std::vector<GLubyte> in_data[2])4368 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4369 {
4370 return GetInputUBO2(in_data);
4371 }
4372 };
4373
4374 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4375 {
GetInput(std::vector<GLubyte> in_data[2])4376 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4377 {
4378 return GetInputUBO2(in_data);
4379 }
4380 };
4381
4382 //-----------------------------------------------------------------------------
4383 // 1.12.x BasicMatrixOperationsBase
4384 //-----------------------------------------------------------------------------
4385 class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4386 {
4387 GLuint m_program;
4388 GLuint m_buffer[2];
4389 GLuint m_vertex_array;
4390
4391 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4392
Equal(float a,float b)4393 static bool Equal(float a, float b)
4394 {
4395 return fabsf(a - b) < 0.001f;
4396 }
4397
Setup()4398 virtual long Setup()
4399 {
4400 m_program = 0;
4401 memset(m_buffer, 0, sizeof(m_buffer));
4402 m_vertex_array = 0;
4403 return NO_ERROR;
4404 }
4405
Run()4406 virtual long Run()
4407 {
4408 if (!IsVSFSAvailable(2, 0))
4409 return NOT_SUPPORTED;
4410 std::vector<float> in;
4411 std::vector<float> expected;
4412 const char* glsl_vs = GetInput(in, expected);
4413 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
4414 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
4415
4416 m_program = CreateProgram(glsl_vs, glsl_fs);
4417 glLinkProgram(m_program);
4418 if (!CheckProgram(m_program))
4419 return ERROR;
4420
4421 glGenBuffers(2, m_buffer);
4422
4423 /* output buffer */
4424 {
4425 std::vector<float> zero(expected.size());
4426 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4427 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4428 GL_STATIC_DRAW);
4429 }
4430 // input buffer
4431 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4432 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4433
4434 glGenVertexArrays(1, &m_vertex_array);
4435 glEnable(GL_RASTERIZER_DISCARD);
4436
4437 glUseProgram(m_program);
4438 glBindVertexArray(m_vertex_array);
4439 glDrawArrays(GL_POINTS, 0, 1);
4440
4441 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4442 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4443 float* out_data = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4444 (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4445 if (!out_data)
4446 return ERROR;
4447
4448 bool status = true;
4449 for (size_t i = 0; i < expected.size(); ++i)
4450 {
4451 if (!Equal(expected[i], out_data[i]))
4452 {
4453 m_context.getTestContext().getLog()
4454 << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4455 << " should be " << expected[i] << tcu::TestLog::EndMessage;
4456 status = false;
4457 }
4458 }
4459 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4460 if (!status)
4461 return ERROR;
4462 return NO_ERROR;
4463 }
4464
Cleanup()4465 virtual long Cleanup()
4466 {
4467 glDisable(GL_RASTERIZER_DISCARD);
4468 glUseProgram(0);
4469 glDeleteProgram(m_program);
4470 glDeleteBuffers(2, m_buffer);
4471 glDeleteVertexArrays(1, &m_vertex_array);
4472 return NO_ERROR;
4473 }
4474 };
4475
4476 class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4477 {
4478 GLuint m_program;
4479 GLuint m_buffer[2];
4480
4481 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4482
Equal(float a,float b)4483 static bool Equal(float a, float b)
4484 {
4485 return fabsf(a - b) < 0.001f;
4486 }
4487
Setup()4488 virtual long Setup()
4489 {
4490 m_program = 0;
4491 memset(m_buffer, 0, sizeof(m_buffer));
4492 return NO_ERROR;
4493 }
4494
Run()4495 virtual long Run()
4496 {
4497 std::vector<float> in;
4498 std::vector<float> expected;
4499 std::stringstream ss;
4500 ss << "layout(local_size_x = 1) in;\n" << GetInput(in, expected);
4501 m_program = CreateProgramCS(ss.str());
4502 glLinkProgram(m_program);
4503 if (!CheckProgram(m_program))
4504 return ERROR;
4505
4506 glGenBuffers(2, m_buffer);
4507
4508 /* output buffer */
4509 {
4510 std::vector<float> zero(expected.size());
4511 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4512 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4513 GL_STATIC_DRAW);
4514 }
4515 // input buffer
4516 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4517 glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4518
4519 glUseProgram(m_program);
4520 glDispatchCompute(1, 1, 1);
4521
4522 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4523 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4524 float* out_data = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4525 (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4526 if (!out_data)
4527 return ERROR;
4528
4529 bool status = true;
4530 for (size_t i = 0; i < expected.size(); ++i)
4531 {
4532 if (!Equal(expected[i], out_data[i]))
4533 {
4534 m_context.getTestContext().getLog()
4535 << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4536 << " should be " << expected[i] << tcu::TestLog::EndMessage;
4537 status = false;
4538 }
4539 }
4540 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4541 if (!status)
4542 return ERROR;
4543 return NO_ERROR;
4544 }
4545
Cleanup()4546 virtual long Cleanup()
4547 {
4548 glUseProgram(0);
4549 glDeleteProgram(m_program);
4550 glDeleteBuffers(2, m_buffer);
4551 return NO_ERROR;
4552 }
4553 };
4554
4555 //-----------------------------------------------------------------------------
4556 // 1.12.1 BasicMatrixOperationsCase1
4557 //-----------------------------------------------------------------------------
GetInputM1(std::vector<float> & in,std::vector<float> & expected)4558 const char* GetInputM1(std::vector<float>& in, std::vector<float>& expected)
4559 {
4560 in.resize(8);
4561 in[0] = 1.0f;
4562 in[2] = 3.0f;
4563 in[1] = 2.0f;
4564 in[3] = 4.0f;
4565 in[4] = 1.0f;
4566 in[6] = 3.0f;
4567 in[5] = 2.0f;
4568 in[7] = 4.0f;
4569 expected.resize(4);
4570 expected[0] = 7.0f;
4571 expected[2] = 15.0f;
4572 expected[1] = 10.0f;
4573 expected[3] = 22.0f;
4574 return NL "layout(std430, binding = 0) buffer Input {" NL " mat2 m0;" NL " mat2 m1;" NL "} g_input;" NL
4575 "layout(std430, binding = 1) buffer Output {" NL " mat2 m;" NL "} g_output;" NL
4576 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4577 }
4578
4579 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4580 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4581 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4582 {
4583 return GetInputM1(in, expected);
4584 }
4585 };
4586
4587 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4588 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4589 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4590 {
4591 return GetInputM1(in, expected);
4592 }
4593 };
4594
4595 //-----------------------------------------------------------------------------
4596 // 1.12.2 BasicMatrixOperationsCase2
4597 //-----------------------------------------------------------------------------
GetInputM2(std::vector<float> & in,std::vector<float> & expected)4598 const char* GetInputM2(std::vector<float>& in, std::vector<float>& expected)
4599 {
4600 in.resize(15);
4601 expected.resize(4);
4602 // mat3x2
4603 in[0] = 1.0f;
4604 in[2] = 3.0f;
4605 in[4] = 5.0f;
4606 in[1] = 2.0f;
4607 in[3] = 4.0f;
4608 in[5] = 6.0f;
4609 // mat2x3
4610 in[8] = 1.0f;
4611 in[12] = 4.0f;
4612 in[9] = 2.0f;
4613 in[13] = 5.0f;
4614 in[10] = 3.0f;
4615 in[14] = 6.0f;
4616 // mat2
4617 expected[0] = 22.0f;
4618 expected[2] = 49.0f;
4619 expected[1] = 28.0f;
4620 expected[3] = 64.0f;
4621 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat3x2 m0;" NL
4622 " layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4623 " layout(column_major) mat2 m;" NL "} g_output;" NL
4624 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4625 }
4626
4627 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4628 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4629 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4630 {
4631 return GetInputM2(in, expected);
4632 }
4633 };
4634
4635 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4636 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4637 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4638 {
4639 return GetInputM2(in, expected);
4640 }
4641 };
4642
4643 //-----------------------------------------------------------------------------
4644 // 1.12.3 BasicMatrixOperationsCase3
4645 //-----------------------------------------------------------------------------
GetInputM3(std::vector<float> & in,std::vector<float> & expected)4646 const char* GetInputM3(std::vector<float>& in, std::vector<float>& expected)
4647 {
4648 in.resize(15);
4649 expected.resize(4);
4650 // row major mat3x2
4651 in[0] = 1.0f;
4652 in[1] = 3.0f;
4653 in[2] = 5.0f;
4654 in[4] = 2.0f;
4655 in[5] = 4.0f;
4656 in[6] = 6.0f;
4657 // row major mat2x3
4658 in[8] = 1.0f;
4659 in[9] = 4.0f;
4660 in[10] = 2.0f;
4661 in[11] = 5.0f;
4662 in[12] = 3.0f;
4663 in[13] = 6.0f;
4664 // row major mat2
4665 expected[0] = 22.0f;
4666 expected[1] = 49.0f;
4667 expected[2] = 28.0f;
4668 expected[3] = 64.0f;
4669
4670 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(row_major) mat3x2 m0;" NL
4671 " layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4672 " layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4673 }
4674
4675 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4676 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4677 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4678 {
4679 return GetInputM3(in, expected);
4680 }
4681 };
4682
4683 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4684 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4685 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4686 {
4687 return GetInputM3(in, expected);
4688 }
4689 };
4690
4691 //-----------------------------------------------------------------------------
4692 // 1.12.4 BasicMatrixOperationsCase4
4693 //-----------------------------------------------------------------------------
GetInputM4(std::vector<float> & in,std::vector<float> & expected)4694 const char* GetInputM4(std::vector<float>& in, std::vector<float>& expected)
4695 {
4696 in.resize(15);
4697 expected.resize(4);
4698 // column major mat3x2
4699 in[0] = 1.0f;
4700 in[2] = 3.0f;
4701 in[4] = 5.0f;
4702 in[1] = 2.0f;
4703 in[3] = 4.0f;
4704 in[5] = 6.0f;
4705 // row major mat2x3
4706 in[8] = 1.0f;
4707 in[9] = 4.0f;
4708 in[10] = 2.0f;
4709 in[11] = 5.0f;
4710 in[12] = 3.0f;
4711 in[13] = 6.0f;
4712 // column major mat2
4713 expected[0] = 13.0f;
4714 expected[1] = 16.0f;
4715 expected[2] = 37.0f;
4716 expected[3] = 46.0f;
4717 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat3x2 m0;" NL
4718 " layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4719 " layout(column_major) mat2 m;" NL "} g_output;" NL
4720 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4721 }
4722
4723 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4724 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4725 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4726 {
4727 return GetInputM4(in, expected);
4728 }
4729 };
4730
4731 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4732 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4733 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4734 {
4735 return GetInputM4(in, expected);
4736 }
4737 };
4738
4739 //-----------------------------------------------------------------------------
4740 // 1.12.5 BasicMatrixOperationsCase5
4741 //-----------------------------------------------------------------------------
GetInputM5(std::vector<float> & in,std::vector<float> & expected)4742 const char* GetInputM5(std::vector<float>& in, std::vector<float>& expected)
4743 {
4744 in.resize(15);
4745 expected.resize(4);
4746 // column major mat3x2
4747 in[0] = 1.0f;
4748 in[2] = 3.0f;
4749 in[4] = 5.0f;
4750 in[1] = 2.0f;
4751 in[3] = 4.0f;
4752 in[5] = 6.0f;
4753 // row major mat2x3
4754 in[8] = 1.0f;
4755 in[9] = 4.0f;
4756 in[10] = 2.0f;
4757 in[11] = 5.0f;
4758 in[12] = 3.0f;
4759 in[13] = 6.0f;
4760 // row major mat2
4761 expected[0] = 13.0f;
4762 expected[1] = 37.0f;
4763 expected[2] = 16.0f;
4764 expected[3] = 46.0f;
4765 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(column_major) mat3x2 m0;" NL
4766 " layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4767 " layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4768 }
4769
4770 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4771 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4772 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4773 {
4774 return GetInputM5(in, expected);
4775 }
4776 };
4777
4778 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4779 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4780 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4781 {
4782 return GetInputM5(in, expected);
4783 }
4784 };
4785
4786 //-----------------------------------------------------------------------------
4787 // 1.12.6 BasicMatrixOperationsCase6
4788 //-----------------------------------------------------------------------------
GetInputM6(std::vector<float> & in,std::vector<float> & expected)4789 const char* GetInputM6(std::vector<float>& in, std::vector<float>& expected)
4790 {
4791 in.resize(20);
4792 expected.resize(4);
4793 // row major mat3x2
4794 in[0] = 1.0f;
4795 in[1] = 3.0f;
4796 in[2] = 5.0f;
4797 in[4] = 2.0f;
4798 in[5] = 4.0f;
4799 in[6] = 6.0f;
4800 // column major mat2x3
4801 in[8] = 1.0f;
4802 in[12] = 4.0f;
4803 in[9] = 2.0f;
4804 in[13] = 5.0f;
4805 in[10] = 3.0f;
4806 in[14] = 6.0f;
4807 // column major mat2
4808 expected[0] = 22.0f;
4809 expected[1] = 28.0f;
4810 expected[2] = 49.0f;
4811 expected[3] = 64.0f;
4812 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(row_major) mat3x2 m0;" NL
4813 " layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4814 " layout(column_major) mat2 m;" NL "} g_output;" NL
4815 "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4816 }
4817
4818 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
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 GetInputM6(in, expected);
4823 }
4824 };
4825
4826 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
4827 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4828 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4829 {
4830 return GetInputM6(in, expected);
4831 }
4832 };
4833
4834 //-----------------------------------------------------------------------------
4835 // 1.12.7 BasicMatrixOperationsCase7
4836 //-----------------------------------------------------------------------------
GetInputM7(std::vector<float> & in,std::vector<float> & expected)4837 const char* GetInputM7(std::vector<float>& in, std::vector<float>& expected)
4838 {
4839 in.resize(20);
4840 expected.resize(4);
4841 // row major mat3x2
4842 in[0] = 1.0f;
4843 in[1] = 3.0f;
4844 in[2] = 5.0f;
4845 in[4] = 2.0f;
4846 in[5] = 4.0f;
4847 in[6] = 6.0f;
4848 // column major mat2x3
4849 in[8] = 1.0f;
4850 in[12] = 4.0f;
4851 in[9] = 2.0f;
4852 in[13] = 5.0f;
4853 in[10] = 3.0f;
4854 in[14] = 6.0f;
4855 // row major mat2
4856 expected[0] = 22.0f;
4857 expected[1] = 49.0f;
4858 expected[2] = 28.0f;
4859 expected[3] = 64.0f;
4860 return NL "layout(std430, binding = 0) buffer Input {" NL " layout(row_major) mat3x2 m0;" NL
4861 " layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4862 " layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4863 }
4864
4865 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
4866 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4867 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4868 {
4869 return GetInputM7(in, expected);
4870 }
4871 };
4872
4873 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
4874 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4875 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4876 {
4877 return GetInputM7(in, expected);
4878 }
4879 };
4880
4881 //-----------------------------------------------------------------------------
4882 // 2.1 AdvancedSwitchBuffers
4883 //-----------------------------------------------------------------------------
4884 class AdvancedSwitchBuffersVS : public ShaderStorageBufferObjectBase
4885 {
PassCriteria()4886 virtual std::string PassCriteria()
4887 {
4888 return NL "Everything works as expected.";
4889 }
4890
4891 GLuint m_program;
4892 GLuint m_storage_buffer[5];
4893 GLuint m_vertex_array;
4894 GLuint m_fbo, m_rt;
4895
Setup()4896 virtual long Setup()
4897 {
4898 m_program = 0;
4899 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
4900 m_vertex_array = 0;
4901 glGenFramebuffers(1, &m_fbo);
4902 glGenTextures(1, &m_rt);
4903 return NO_ERROR;
4904 }
4905
Run()4906 virtual long Run()
4907 {
4908 if (!IsVSFSAvailable(1, 0))
4909 return NOT_SUPPORTED;
4910 const char* const glsl_vs = NL "struct VertexData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL
4911 "layout(binding = 0, std430) buffer Input {" NL " VertexData vertex[4];" NL
4912 "} g_vs_in;" NL "out vec3 StageData_color;" NL "void main() {" NL
4913 " gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
4914 " StageData_color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
4915 const char* const glsl_fs = NL "in vec3 StageData_color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
4916 "void main() {" NL " g_fs_out = vec4(StageData_color, 1);" NL "}";
4917 m_program = CreateProgram(glsl_vs, glsl_fs);
4918 glLinkProgram(m_program);
4919 if (!CheckProgram(m_program))
4920 return ERROR;
4921
4922 glGenBuffers(5, m_storage_buffer);
4923
4924 /* left, bottom, red quad */
4925 {
4926 const float data[] = { -0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4927 0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4928 -0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4929 0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
4930 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
4931 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4932 }
4933 /* right, bottom, green quad */
4934 {
4935 const float data[] = { -0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4936 0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4937 -0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4938 0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
4939 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
4940 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4941 }
4942 /* left, top, blue quad */
4943 {
4944 const float data[] = { -0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4945 0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4946 -0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4947 0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f };
4948 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
4949 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4950 }
4951 /* right, top, yellow quad */
4952 {
4953 const float data[] = { -0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4954 0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4955 -0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4956 0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f };
4957 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
4958 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4959 }
4960
4961 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
4962 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
4963
4964 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
4965 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(float) * 32);
4966 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
4967 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 32, sizeof(float) * 32);
4968 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
4969 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * sizeof(float) * 32,
4970 sizeof(float) * 32);
4971 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
4972 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * sizeof(float) * 32,
4973 sizeof(float) * 32);
4974
4975 glBindTexture(GL_TEXTURE_2D, m_rt);
4976 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4977 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4978 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
4979 glBindTexture(GL_TEXTURE_2D, 0);
4980 glViewport(0, 0, 100, 100);
4981 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
4982 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
4983
4984 glGenVertexArrays(1, &m_vertex_array);
4985
4986 glUseProgram(m_program);
4987 glBindVertexArray(m_vertex_array);
4988
4989 glClear(GL_COLOR_BUFFER_BIT);
4990 for (int i = 0; i < 4; ++i)
4991 {
4992 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
4993 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4994 }
4995 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
4996 {
4997 return ERROR;
4998 }
4999
5000 glClear(GL_COLOR_BUFFER_BIT);
5001 for (int i = 0; i < 4; ++i)
5002 {
5003 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * sizeof(float) * 32,
5004 sizeof(float) * 32);
5005 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
5006 }
5007 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5008 {
5009 return ERROR;
5010 }
5011
5012 return NO_ERROR;
5013 }
5014
Cleanup()5015 virtual long Cleanup()
5016 {
5017 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5018 glUseProgram(0);
5019 glDeleteProgram(m_program);
5020 glDeleteBuffers(5, m_storage_buffer);
5021 glDeleteVertexArrays(1, &m_vertex_array);
5022 glDeleteFramebuffers(1, &m_fbo);
5023 glDeleteTextures(1, &m_rt);
5024 return NO_ERROR;
5025 }
5026 };
5027 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5028 {
5029 GLuint m_program;
5030 GLuint m_storage_buffer[6];
5031
Setup()5032 virtual long Setup()
5033 {
5034 m_program = 0;
5035 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5036 return NO_ERROR;
5037 }
5038
Run()5039 virtual long Run()
5040 {
5041 const char* const glsl_cs =
5042 NL "layout(local_size_x = 1) in;" NL "layout(binding = 0, std430) buffer Input {" NL " uint cookie[4];" NL
5043 "} g_in;" NL "layout(binding = 1, std430) buffer Output {" NL " uvec4 digest;" NL "} ;" NL
5044 "void main() {" NL " switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5045 " case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5046 " case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5047 " case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5048 " case 0xff000000u: digest.w = 0x000000ffu; break;" NL " }" NL "}";
5049 m_program = CreateProgramCS(glsl_cs);
5050 glLinkProgram(m_program);
5051 if (!CheckProgram(m_program))
5052 return ERROR;
5053
5054 glGenBuffers(6, m_storage_buffer);
5055
5056 const GLubyte data0[] = { 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22 };
5057 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5058 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5059 const GLubyte data1[] = { 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0 };
5060 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5061 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5062 const GLubyte data2[] = { 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0 };
5063 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5064 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5065 const GLubyte data3[] = { 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0 };
5066 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5067 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5068
5069 GLint alignment;
5070 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
5071 GLint offset = static_cast<GLint>(sizeof(data0) > (GLuint)alignment ? sizeof(data0) : alignment);
5072 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5073 glBufferData(GL_SHADER_STORAGE_BUFFER, offset * 4, NULL, GL_STATIC_DRAW);
5074
5075 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5076 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(data0));
5077 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5078 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, offset, sizeof(data0));
5079 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5080 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * offset, sizeof(data0));
5081 glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5082 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * offset, sizeof(data0));
5083
5084 const GLubyte data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5085 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[5]);
5086 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5087
5088 glUseProgram(m_program);
5089 for (int i = 0; i < 4; ++i)
5090 {
5091 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5092 glDispatchCompute(1, 1, 1);
5093 }
5094 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5095 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5096 GLuint* out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5097 if (!out_data)
5098 return ERROR;
5099 GLuint expected[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
5100 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5101 out_data[3] != expected[3])
5102 {
5103 m_context.getTestContext().getLog()
5104 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5105 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5106 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5107 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5108 return ERROR;
5109 }
5110 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5111 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5112
5113 for (int i = 0; i < 4; ++i)
5114 {
5115 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5116 glDispatchCompute(1, 1, 1);
5117 }
5118 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5119 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5120 out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5121 if (!out_data)
5122 return ERROR;
5123 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5124 out_data[3] != expected[3])
5125 {
5126 m_context.getTestContext().getLog()
5127 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5128 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5129 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5130 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5131 return ERROR;
5132 }
5133
5134 return NO_ERROR;
5135 }
5136
Cleanup()5137 virtual long Cleanup()
5138 {
5139 glUseProgram(0);
5140 glDeleteProgram(m_program);
5141 glDeleteBuffers(6, m_storage_buffer);
5142 return NO_ERROR;
5143 }
5144 };
5145 //-----------------------------------------------------------------------------
5146 // 2.2 AdvancedSwitchPrograms
5147 //-----------------------------------------------------------------------------
5148 class AdvancedSwitchProgramsVS : public ShaderStorageBufferObjectBase
5149 {
5150 GLuint m_program[4];
5151 GLuint m_storage_buffer[4];
5152 GLuint m_vertex_array;
5153 GLuint m_fbo, m_rt;
5154
GenSource(int binding)5155 std::string GenSource(int binding)
5156 {
5157 std::stringstream ss;
5158 ss << NL "struct VertexData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL "layout(binding = "
5159 << binding
5160 << ", std430) buffer Input {" NL " VertexData vertex[4];" NL "} g_vs_in;" NL "out vec3 StageData_color;" NL
5161 "void main() {" NL " gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5162 " StageData_color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5163 return ss.str();
5164 }
5165
Setup()5166 virtual long Setup()
5167 {
5168 memset(m_program, 0, sizeof(m_program));
5169 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5170 m_vertex_array = 0;
5171 glGenFramebuffers(1, &m_fbo);
5172 glGenTextures(1, &m_rt);
5173 return NO_ERROR;
5174 }
5175
Run()5176 virtual long Run()
5177 {
5178 if (!IsVSFSAvailable(1, 0))
5179 return NOT_SUPPORTED;
5180 const char* const glsl_fs = NL "in vec3 StageData_color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5181 "void main() {" NL " g_fs_out = vec4(StageData_color, 1);" NL "}";
5182 for (int i = 0; i < 4; ++i)
5183 {
5184 m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5185 glLinkProgram(m_program[i]);
5186 if (!CheckProgram(m_program[i]))
5187 return ERROR;
5188 }
5189
5190 glGenBuffers(4, m_storage_buffer);
5191
5192 /* left, bottom, red quad */
5193 {
5194 const float data[] = { -0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5195 0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5196 -0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5197 0.4f - 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
5198 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5199 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5200 }
5201 /* right, bottom, green quad */
5202 {
5203 const float data[] = { -0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5204 0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5205 -0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5206 0.4f + 0.5f, 0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
5207 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5208 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5209 }
5210 /* left, top, blue quad */
5211 {
5212 const float data[] = { -0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5213 0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5214 -0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5215 0.4f - 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f };
5216 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5217 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5218 }
5219 /* right, top, yellow quad */
5220 {
5221 const float data[] = { -0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5222 0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5223 -0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5224 0.4f + 0.5f, 0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f };
5225 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5226 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5227 }
5228
5229 glBindTexture(GL_TEXTURE_2D, m_rt);
5230 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5231 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5232 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5233 glBindTexture(GL_TEXTURE_2D, 0);
5234 glViewport(0, 0, 100, 100);
5235 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5236 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5237
5238 glGenVertexArrays(1, &m_vertex_array);
5239 glBindVertexArray(m_vertex_array);
5240
5241 glClear(GL_COLOR_BUFFER_BIT);
5242 for (int i = 0; i < 4; ++i)
5243 {
5244 glUseProgram(m_program[i]);
5245 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5246 }
5247 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5248 {
5249 return ERROR;
5250 }
5251
5252 return NO_ERROR;
5253 }
5254
Cleanup()5255 virtual long Cleanup()
5256 {
5257 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5258 glUseProgram(0);
5259 for (int i = 0; i < 4; ++i)
5260 glDeleteProgram(m_program[i]);
5261 glDeleteBuffers(4, m_storage_buffer);
5262 glDeleteVertexArrays(1, &m_vertex_array);
5263 glDeleteFramebuffers(1, &m_fbo);
5264 glDeleteTextures(1, &m_rt);
5265 return NO_ERROR;
5266 }
5267 };
5268 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5269 {
5270 GLuint m_program[4];
5271 GLuint m_storage_buffer[5];
5272
Setup()5273 virtual long Setup()
5274 {
5275 memset(m_program, 0, sizeof(m_program));
5276 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5277 return NO_ERROR;
5278 }
5279
GenSource(int binding)5280 std::string GenSource(int binding)
5281 {
5282 std::stringstream ss;
5283 ss << NL "layout(local_size_x = 1) in;" NL "layout(binding = " << binding
5284 << ", std430) buffer Input {" NL " uint cookie[4];" NL "} g_in;" NL
5285 "layout(binding = 0, std430) buffer Output {" NL " uvec4 digest;" NL "} ;" NL "void main() {" NL
5286 " switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5287 " case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5288 " case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5289 " case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5290 " case 0xff000000u: digest.w = 0x000000ffu; break;" NL " }" NL "}";
5291 return ss.str();
5292 }
5293
Run()5294 virtual long Run()
5295 {
5296 for (int i = 0; i < 4; ++i)
5297 {
5298 m_program[i] = CreateProgramCS(GenSource(i + 1));
5299 glLinkProgram(m_program[i]);
5300 if (!CheckProgram(m_program[i]))
5301 return ERROR;
5302 }
5303
5304 glGenBuffers(5, m_storage_buffer);
5305
5306 const GLubyte data0[] = { 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22 };
5307 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5308 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5309 const GLubyte data1[] = { 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0 };
5310 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5311 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5312 const GLubyte data2[] = { 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0 };
5313 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5314 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5315 const GLubyte data3[] = { 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0 };
5316 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5317 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5318
5319 const GLubyte data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5320 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5321 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5322
5323 for (int i = 0; i < 4; ++i)
5324 {
5325 glUseProgram(m_program[i]);
5326 glDispatchCompute(1, 1, 1);
5327 }
5328 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5329 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5330 GLuint* out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5331 if (!out_data)
5332 return ERROR;
5333 GLuint expected[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
5334 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5335 out_data[3] != expected[3])
5336 {
5337 m_context.getTestContext().getLog()
5338 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5339 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5340 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5341 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5342 return ERROR;
5343 }
5344 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5345
5346 return NO_ERROR;
5347 }
5348
Cleanup()5349 virtual long Cleanup()
5350 {
5351 glUseProgram(0);
5352 for (int i = 0; i < 4; ++i)
5353 glDeleteProgram(m_program[i]);
5354 glDeleteBuffers(5, m_storage_buffer);
5355 return NO_ERROR;
5356 }
5357 };
5358
5359 //-----------------------------------------------------------------------------
5360 // 2.3.1 AdvancedWriteFragment
5361 //-----------------------------------------------------------------------------
5362 class AdvancedWriteFragmentFS : public ShaderStorageBufferObjectBase
5363 {
5364 GLuint m_program[2];
5365 GLuint m_storage_buffer;
5366 GLuint m_counter_buffer;
5367 GLuint m_attribless_vertex_array;
5368 GLuint m_draw_vertex_array;
5369 GLuint m_fbo, m_rt;
5370
Setup()5371 virtual long Setup()
5372 {
5373 memset(m_program, 0, sizeof(m_program));
5374 m_storage_buffer = 0;
5375 m_counter_buffer = 0;
5376 m_attribless_vertex_array = 0;
5377 m_draw_vertex_array = 0;
5378 glGenFramebuffers(1, &m_fbo);
5379 glGenTextures(1, &m_rt);
5380 return NO_ERROR;
5381 }
5382
Run()5383 virtual long Run()
5384 {
5385 if (!IsVSFSAvailable(0, 1))
5386 return NOT_SUPPORTED;
5387 const char* const glsl_vs0 =
5388 NL "out vec2 position;" NL "out vec3 color;" NL
5389 "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
5390 "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
5391 "vec3 g_color[4] = vec3[4](vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0));" NL
5392 "void main() {" NL " vec2 pos = g_quad[gl_VertexID] + g_offset[gl_InstanceID];" NL
5393 " gl_Position = vec4(pos, 0, 1);" NL " position = pos;" NL " color = g_color[gl_InstanceID];" NL "}";
5394 const char* const glsl_fs0 =
5395 NL "in vec2 position;" NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5396 "struct FragmentData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL
5397 "layout(std430, binding = 3) buffer Output {" NL " FragmentData g_fragment[6400];" NL "};" NL
5398 "uniform uint g_max_fragment_count;" NL
5399 "layout(binding = 2, offset = 0) uniform atomic_uint g_fragment_counter;" NL "void main() {" NL
5400 " uint fragment_number = atomicCounterIncrement(g_fragment_counter);" NL
5401 " if (fragment_number < g_max_fragment_count) {" NL
5402 " g_fragment[fragment_number].position = position;" NL
5403 " g_fragment[fragment_number].color = color;" NL " }" NL " g_fs_out = vec4(color, 1);" NL "}";
5404 m_program[0] = CreateProgram(glsl_vs0, glsl_fs0);
5405 glLinkProgram(m_program[0]);
5406 if (!CheckProgram(m_program[0]))
5407 return ERROR;
5408
5409 const char* const glsl_vs1 =
5410 NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5411 "out vec3 color;" NL "void main() {" NL " gl_Position = vec4(g_in_position.xy, 0, 1);" NL
5412 "#ifdef GL_ES" NL " gl_PointSize = 1.0f;" NL "#endif" NL " color = g_in_color.rgb;" NL "}";
5413 const char* const glsl_fs1 = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5414 "void main() {" NL " g_fs_out = vec4(color, 1);" NL "}";
5415 m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5416 glLinkProgram(m_program[1]);
5417 if (!CheckProgram(m_program[1]))
5418 return ERROR;
5419
5420 // The first pass renders four squares on-screen, and writes a
5421 // record to the SSBO for each fragment processed. The rectangles
5422 // will be 40x40 when using a 100x100 viewport, so we expect 1600
5423 // pixels per rectangle or 6400 pixels total. Size the SSBO
5424 // accordingly, and render the second pass (sourcing the SSBO as a
5425 // vertex buffer) with an identical number of points. If we have
5426 // a larger buffer and draw more points on the second pass, those
5427 // may overwrite "real" points using garbage position/color.
5428 int expectedPixels = 6400;
5429
5430 glGenBuffers(1, &m_storage_buffer);
5431 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5432 glBufferData(GL_SHADER_STORAGE_BUFFER, expectedPixels * 32, NULL, GL_DYNAMIC_DRAW);
5433
5434 glGenBuffers(1, &m_counter_buffer);
5435 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
5436 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5437 uvec4 zero(0);
5438 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5439
5440 glBindTexture(GL_TEXTURE_2D, m_rt);
5441 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5442 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5443 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5444 glBindTexture(GL_TEXTURE_2D, 0);
5445 glViewport(0, 0, 100, 100);
5446 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5447 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5448
5449 glGenVertexArrays(1, &m_attribless_vertex_array);
5450
5451 glGenVertexArrays(1, &m_draw_vertex_array);
5452 glBindVertexArray(m_draw_vertex_array);
5453 glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5454 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5455 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void*>(16));
5456 glBindBuffer(GL_ARRAY_BUFFER, 0);
5457 glEnableVertexAttribArray(0);
5458 glEnableVertexAttribArray(1);
5459 glBindVertexArray(0);
5460
5461 glClear(GL_COLOR_BUFFER_BIT);
5462 glUseProgram(m_program[0]);
5463 glUniform1ui(glGetUniformLocation(m_program[0], "g_max_fragment_count"), expectedPixels);
5464 glBindVertexArray(m_attribless_vertex_array);
5465 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5466 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5467 {
5468 return ERROR;
5469 }
5470
5471 glClear(GL_COLOR_BUFFER_BIT);
5472 glUseProgram(m_program[1]);
5473 glBindVertexArray(m_draw_vertex_array);
5474 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5475 glDrawArrays(GL_POINTS, 0, expectedPixels);
5476 int bad_pixels;
5477 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5478 bad_pixels > 2)
5479 {
5480 return ERROR;
5481 }
5482
5483 return NO_ERROR;
5484 }
5485
Cleanup()5486 virtual long Cleanup()
5487 {
5488 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5489 glUseProgram(0);
5490 for (int i = 0; i < 2; ++i)
5491 glDeleteProgram(m_program[i]);
5492 glDeleteBuffers(1, &m_storage_buffer);
5493 glDeleteBuffers(1, &m_counter_buffer);
5494 glDeleteVertexArrays(1, &m_attribless_vertex_array);
5495 glDeleteVertexArrays(1, &m_draw_vertex_array);
5496 glDeleteFramebuffers(1, &m_fbo);
5497 glDeleteTextures(1, &m_rt);
5498 return NO_ERROR;
5499 }
5500 };
5501
5502 class AdvancedWriteFragmentCS : public ShaderStorageBufferObjectBase
5503 {
5504 GLuint m_program[2];
5505 GLuint m_storage_buffer;
5506 GLuint m_counter_buffer;
5507 GLuint m_draw_vertex_array;
5508 GLuint m_fbo, m_rt;
5509
Setup()5510 virtual long Setup()
5511 {
5512 memset(m_program, 0, sizeof(m_program));
5513 m_storage_buffer = 0;
5514 m_counter_buffer = 0;
5515 m_draw_vertex_array = 0;
5516 glGenFramebuffers(1, &m_fbo);
5517 glGenTextures(1, &m_rt);
5518 return NO_ERROR;
5519 }
5520
Run()5521 virtual long Run()
5522 {
5523 const char* const glsl_cs = NL
5524 "layout(local_size_x = 10, local_size_y = 10) in;" NL "uniform uint g_max_point_count;" NL
5525 "uniform uint g_brick;" NL
5526 "vec3 g_color[5] = vec3[5](vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 0));" NL
5527 "struct PointData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL
5528 "layout(std430, binding = 3) buffer Output {" NL " PointData g_point[];" NL "};" NL
5529 "layout(binding = 0, offset = 0) uniform atomic_uint g_point_counter;" NL "void main() {" NL
5530 " uint g_offset[4] = uint[4](g_brick, 9u*g_brick, 11u*g_brick, 19u*g_brick);" NL
5531 " uint point_number = atomicCounterIncrement(g_point_counter);" NL
5532 " uint giidx = gl_GlobalInvocationID.x;" NL " uint giidy = gl_GlobalInvocationID.y;" NL
5533 " g_point[point_number].position = vec2(gl_GlobalInvocationID.xy * 2u) / 100.0 - 1.0;" NL
5534 " g_point[point_number].color = g_color[4];" NL " if (point_number < g_max_point_count) {" NL
5535 " if (giidx > g_offset[0] && giidx < g_offset[1] && giidy > g_offset[0] && giidy < g_offset[1]) {" NL
5536 " g_point[point_number].color = g_color[0];" NL " }" NL
5537 " if (giidx > g_offset[2] && giidx < g_offset[3] && giidy > g_offset[0] && giidy < g_offset[1]) {" NL
5538 " g_point[point_number].color = g_color[1];" NL " }" NL
5539 " if (giidx > g_offset[2] && giidx < g_offset[3] && giidy > g_offset[2] && giidy < g_offset[3]) {" NL
5540 " g_point[point_number].color = g_color[2];" NL " }" NL
5541 " if (giidx > g_offset[0] && giidx < g_offset[1] && giidy > g_offset[2] && giidy < g_offset[3]) {" NL
5542 " g_point[point_number].color = g_color[3];" NL " }" NL " }" NL "}";
5543 m_program[0] = CreateProgramCS(glsl_cs);
5544 glLinkProgram(m_program[0]);
5545 if (!CheckProgram(m_program[0]))
5546 return ERROR;
5547
5548 const char* const glsl_vs1 =
5549 NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5550 "out vec3 color;" NL "void main() {" NL " gl_Position = vec4(g_in_position.xy, 0, 1);" NL
5551 "#ifdef GL_ES" NL " gl_PointSize = 1.0f;" NL "#endif" NL " color = g_in_color.rgb;" NL "}";
5552 const char* const glsl_fs1 = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5553 "void main() {" NL " g_fs_out = vec4(color, 1);" NL "}";
5554 m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5555 glLinkProgram(m_program[1]);
5556 if (!CheckProgram(m_program[1]))
5557 return ERROR;
5558
5559 glGenBuffers(1, &m_storage_buffer);
5560 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5561 glBufferData(GL_SHADER_STORAGE_BUFFER, 100 * 100 * 32, NULL, GL_DYNAMIC_DRAW);
5562
5563 glGenBuffers(1, &m_counter_buffer);
5564 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
5565 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5566 uvec4 zero(0);
5567 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5568
5569 glGenVertexArrays(1, &m_draw_vertex_array);
5570 glBindVertexArray(m_draw_vertex_array);
5571 glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5572 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5573 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void*>(16));
5574 glBindBuffer(GL_ARRAY_BUFFER, 0);
5575 glEnableVertexAttribArray(0);
5576 glEnableVertexAttribArray(1);
5577 glBindVertexArray(0);
5578
5579 glUseProgram(m_program[0]);
5580 glUniform1ui(glGetUniformLocation(m_program[0], "g_max_point_count"), 100 * 100);
5581 glUniform1ui(glGetUniformLocation(m_program[0], "g_brick"), 5);
5582 glDispatchCompute(10, 10, 1);
5583
5584 glBindTexture(GL_TEXTURE_2D, m_rt);
5585 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5586 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5587 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5588 glBindTexture(GL_TEXTURE_2D, 0);
5589 glViewport(0, 0, 100, 100);
5590 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5591 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5592
5593 glClear(GL_COLOR_BUFFER_BIT);
5594 glUseProgram(m_program[1]);
5595 glBindVertexArray(m_draw_vertex_array);
5596 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5597 glDrawArrays(GL_POINTS, 0, 100 * 100);
5598 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5599 {
5600 return ERROR;
5601 }
5602
5603 return NO_ERROR;
5604 }
5605
Cleanup()5606 virtual long Cleanup()
5607 {
5608 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5609 glUseProgram(0);
5610 for (int i = 0; i < 2; ++i)
5611 glDeleteProgram(m_program[i]);
5612 glDeleteBuffers(1, &m_storage_buffer);
5613 glDeleteBuffers(1, &m_counter_buffer);
5614 glDeleteVertexArrays(1, &m_draw_vertex_array);
5615 glDeleteFramebuffers(1, &m_fbo);
5616 glDeleteTextures(1, &m_rt);
5617 return NO_ERROR;
5618 }
5619 };
5620
5621 //-----------------------------------------------------------------------------
5622 // 2.4.1 AdvancedIndirectAddressingCase1
5623 //-----------------------------------------------------------------------------
5624 class AdvancedIndirectAddressingCase1VS : public ShaderStorageBufferObjectBase
5625 {
5626 GLuint m_program;
5627 GLuint m_storage_buffer[4];
5628 GLuint m_vertex_array;
5629 GLuint m_vertex_buffer;
5630 GLuint m_fbo, m_rt;
5631
Setup()5632 virtual long Setup()
5633 {
5634 m_program = 0;
5635 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5636 m_vertex_array = 0;
5637 m_vertex_buffer = 0;
5638 glGenFramebuffers(1, &m_fbo);
5639 glGenTextures(1, &m_rt);
5640 return NO_ERROR;
5641 }
5642
Run()5643 virtual long Run()
5644 {
5645 if (!IsVSFSAvailable(4, 0))
5646 return NOT_SUPPORTED;
5647 const char* const glsl_vs =
5648 NL "layout(location = 0) in vec2 g_in_position;" NL "struct Material {" NL " vec3 color;" NL "};" NL
5649 "layout(binding = 0, std430) buffer MaterialBuffer {" NL " Material g_material[4];" NL "};" NL
5650 "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL " uint g_material_id[4];" NL "};" NL
5651 "layout(binding = 2, std430) buffer TransformBuffer {" NL " vec2 translation[4];" NL "} g_transform;" NL
5652 "layout(binding = 3, std430) buffer TransformIDBuffer {" NL " uint g_transform_id[4];" NL "};" NL
5653 "out vec3 color;" NL "void main() {" NL " uint mid = g_material_id[gl_InstanceID];" NL
5654 " Material m = g_material[mid];" NL " uint tid = g_transform_id[gl_InstanceID];" NL
5655 " vec2 t = g_transform.translation[tid];" NL " gl_Position = vec4(g_in_position + t, 0, 1);" NL
5656 " color = m.color;" NL "}";
5657 const char* const glsl_fs = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5658 "void main() {" NL " g_fs_out = vec4(color, 1);" NL "}";
5659 m_program = CreateProgram(glsl_vs, glsl_fs);
5660 glLinkProgram(m_program);
5661 if (!CheckProgram(m_program))
5662 return ERROR;
5663
5664 glGenBuffers(4, m_storage_buffer);
5665
5666 /* material buffer */
5667 {
5668 const float data[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
5669 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
5670 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5671 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5672 }
5673 /* material id buffer */
5674 {
5675 const unsigned int data[] = { 2, 3, 0, 2 };
5676 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5677 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5678 }
5679 /* transform buffer */
5680 {
5681 const float data[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
5682 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5683 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5684 }
5685 /* transform id buffer */
5686 {
5687 const unsigned int data[] = { 3, 1, 0, 2 };
5688 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5689 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5690 }
5691
5692 /* vertex buffer */
5693 {
5694 const float data[] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
5695 glGenBuffers(1, &m_vertex_buffer);
5696 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5697 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5698 glBindBuffer(GL_ARRAY_BUFFER, 0);
5699 }
5700
5701 glBindTexture(GL_TEXTURE_2D, m_rt);
5702 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5703 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5704 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5705 glBindTexture(GL_TEXTURE_2D, 0);
5706 glViewport(0, 0, 100, 100);
5707 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5708 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5709
5710 glGenVertexArrays(1, &m_vertex_array);
5711 glBindVertexArray(m_vertex_array);
5712 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5713 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5714 glBindBuffer(GL_ARRAY_BUFFER, 0);
5715 glEnableVertexAttribArray(0);
5716 glBindVertexArray(0);
5717
5718 glClear(GL_COLOR_BUFFER_BIT);
5719 glUseProgram(m_program);
5720 glBindVertexArray(m_vertex_array);
5721 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5722 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 1)))
5723 {
5724 return ERROR;
5725 }
5726
5727 /* update material id buffer with BufferSubData */
5728 {
5729 const unsigned int data[] = { 3, 2, 1, 0 };
5730 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5731 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
5732 }
5733
5734 /* update transform id buffer with BufferData */
5735 {
5736 const unsigned int data[] = { 0, 1, 2, 3 };
5737 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5738 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5739 }
5740
5741 glClear(GL_COLOR_BUFFER_BIT);
5742 glUseProgram(m_program);
5743 glBindVertexArray(m_vertex_array);
5744 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5745 if (!ValidateWindow4Quads(vec3(1, 1, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0)))
5746 {
5747 return ERROR;
5748 }
5749
5750 return NO_ERROR;
5751 }
5752
Cleanup()5753 virtual long Cleanup()
5754 {
5755 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5756 glUseProgram(0);
5757 glDeleteProgram(m_program);
5758 glDeleteBuffers(4, m_storage_buffer);
5759 glDeleteBuffers(1, &m_vertex_buffer);
5760 glDeleteVertexArrays(1, &m_vertex_array);
5761 glDeleteFramebuffers(1, &m_fbo);
5762 glDeleteTextures(1, &m_rt);
5763 return NO_ERROR;
5764 }
5765 };
5766
5767 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
5768 {
5769 GLuint m_program;
5770 GLuint m_storage_buffer[5];
5771
Setup()5772 virtual long Setup()
5773 {
5774 m_program = 0;
5775 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5776 return NO_ERROR;
5777 }
5778
Run()5779 virtual long Run()
5780 {
5781 bool status = true;
5782 const char* const glsl_cs =
5783 NL "layout(local_size_x = 2, local_size_y = 2) in;" NL "struct Material {" NL " vec3 color;" NL "};" NL
5784 "layout(binding = 0, std430) buffer MaterialBuffer {" NL " Material g_material[4];" NL "};" NL
5785 "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL " uint g_material_id[4];" NL "};" NL
5786 "layout(binding = 2, std430) buffer TransformBuffer {" NL " vec2 translation[4];" NL "} g_transform;" NL
5787 "layout(binding = 3, std430) buffer TransformIDBuffer {" NL " uint g_transform_id[4];" NL "};" NL
5788 "layout(binding = 4, std430) buffer OutputBuffer {" NL " vec3 color[16];" NL " vec2 pos[16];" NL
5789 "};" NL "vec2 g_in_position[4] = vec2[4](vec2(-0.4f, -0.4f), vec2(0.4f, -0.4f), vec2(-0.4f, 0.4f), "
5790 "vec2(0.4f, 0.4f));" NL "void main() {" NL " uint mid = g_material_id[gl_WorkGroupID.x];" NL
5791 " Material m = g_material[mid];" NL " uint tid = g_transform_id[gl_WorkGroupID.x];" NL
5792 " vec2 t = g_transform.translation[tid];" NL
5793 " pos[gl_LocalInvocationIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x * gl_WorkGroupSize.y] " NL
5794 " = g_in_position[gl_LocalInvocationIndex] + t;" NL " color[gl_LocalInvocationIndex + "
5795 "gl_WorkGroupID.x * gl_WorkGroupSize.x * "
5796 "gl_WorkGroupSize.y] = m.color;" NL "}";
5797 m_program = CreateProgramCS(glsl_cs);
5798 glLinkProgram(m_program);
5799 if (!CheckProgram(m_program))
5800 return ERROR;
5801
5802 glGenBuffers(5, m_storage_buffer);
5803
5804 /* material buffer */
5805 {
5806 const float data[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
5807 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
5808 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5809 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5810 }
5811 /* material id buffer */
5812 {
5813 const unsigned int data[] = { 2, 3, 0, 2 };
5814 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5815 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5816 }
5817 /* transform buffer */
5818 {
5819 const float data[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
5820 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5821 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5822 }
5823 /* transform id buffer */
5824 {
5825 const unsigned int data[] = { 3, 1, 0, 2 };
5826 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5827 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5828 }
5829
5830 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5831 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * 4 * 4 + 16 * 2 * 4, 0, GL_STATIC_DRAW);
5832
5833 glUseProgram(m_program);
5834 glDispatchCompute(4, 1, 1);
5835 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5836 GLfloat* out_data =
5837 (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
5838 if (!out_data)
5839 return ERROR;
5840
5841 GLfloat expected[16 * 4 + 16 * 2] = {
5842 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,
5843 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,
5844 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,
5845 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,
5846 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,
5847 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,
5848 -0.9f, -0.1f, -0.1f, -0.1f, -0.9f, 0.1f, -0.1f, 0.1f, -0.9f, 0.9f, -0.1f, 0.9f
5849 };
5850 for (int i = 0; i < 16; ++i)
5851 {
5852 if (out_data[i * 4 + 0] != expected[i * 4 + 0] || out_data[i * 4 + 1] != expected[i * 4 + 1] ||
5853 out_data[i * 4 + 2] != expected[i * 4 + 2])
5854 {
5855 m_context.getTestContext().getLog()
5856 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
5857 << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
5858 << expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
5859 status = false;
5860 }
5861 }
5862 for (int i = 32; i < 32 + 16; ++i)
5863 {
5864 if (fabs(out_data[i * 2 + 0] - expected[i * 2 + 0]) > 1e-6 ||
5865 fabs(out_data[i * 2 + 1] - expected[i * 2 + 1]) > 1e-6)
5866 {
5867 m_context.getTestContext().getLog()
5868 << tcu::TestLog::Message << "Received: " << out_data[i * 2 + 0] << ", " << out_data[i * 2 + 1]
5869 << ", but expected: " << expected[i * 2 + 0] << ", " << expected[i * 2 + 1] << ", "
5870 << tcu::TestLog::EndMessage;
5871 status = false;
5872 }
5873 }
5874 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5875
5876 /* update material id buffer with BufferSubData */
5877 {
5878 const unsigned int data[] = { 3, 2, 1, 0 };
5879 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5880 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
5881 }
5882
5883 /* update transform id buffer with BufferData */
5884 {
5885 const unsigned int data[] = { 0, 1, 2, 3 };
5886 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5887 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5888 }
5889
5890 glUseProgram(m_program);
5891 glDispatchCompute(4, 1, 1);
5892 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5893 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5894 GLfloat* out_data2 =
5895 (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
5896 if (!out_data2)
5897 return ERROR;
5898
5899 GLfloat expected2[16 * 4 + 16 * 2] = {
5900 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,
5901 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,
5902 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,
5903 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,
5904 -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,
5905 -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
5906 };
5907 for (int i = 0; i < 16; ++i)
5908 {
5909 if (out_data2[i * 4 + 0] != expected2[i * 4 + 0] || out_data2[i * 4 + 1] != expected2[i * 4 + 1] ||
5910 out_data2[i * 4 + 2] != expected2[i * 4 + 2])
5911 {
5912 m_context.getTestContext().getLog()
5913 << tcu::TestLog::Message << "Received: " << out_data2[i * 4 + 0] << ", " << out_data2[i * 4 + 1]
5914 << ", " << out_data2[i * 4 + 2] << ", but expected: " << expected2[i * 4 + 0] << ", "
5915 << expected2[i * 4 + 1] << ", " << expected2[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
5916 status = false;
5917 }
5918 }
5919 for (int i = 32; i < 32 + 16; ++i)
5920 {
5921 if (fabs(out_data2[i * 2 + 0] - expected2[i * 2 + 0]) > 1e-6 ||
5922 fabs(out_data2[i * 2 + 1] - expected2[i * 2 + 1]) > 1e-6)
5923 {
5924 m_context.getTestContext().getLog()
5925 << tcu::TestLog::Message << "Received: " << out_data2[i * 2 + 0] << ", " << out_data2[i * 2 + 1]
5926 << ", but expected: " << expected2[i * 2 + 0] << ", " << expected2[i * 2 + 1] << ", "
5927 << tcu::TestLog::EndMessage;
5928 status = false;
5929 }
5930 }
5931
5932 if (status)
5933 return NO_ERROR;
5934 else
5935 return ERROR;
5936 }
5937
Cleanup()5938 virtual long Cleanup()
5939 {
5940 glUseProgram(0);
5941 glDeleteProgram(m_program);
5942 glDeleteBuffers(5, m_storage_buffer);
5943 return NO_ERROR;
5944 }
5945 };
5946 //-----------------------------------------------------------------------------
5947 // 2.4.2 AdvancedIndirectAddressingCase2
5948 //-----------------------------------------------------------------------------
5949 class AdvancedIndirectAddressingCase2VSFS : public ShaderStorageBufferObjectBase
5950 {
5951 GLuint m_program;
5952 GLuint m_storage_buffer[8];
5953 GLuint m_vertex_array;
5954 GLuint m_vertex_buffer;
5955 GLuint m_fbo, m_rt;
5956
Setup()5957 virtual long Setup()
5958 {
5959 m_program = 0;
5960 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5961 m_vertex_array = 0;
5962 m_vertex_buffer = 0;
5963 glGenFramebuffers(1, &m_fbo);
5964 glGenTextures(1, &m_rt);
5965 return NO_ERROR;
5966 }
5967
Run()5968 virtual long Run()
5969 {
5970 if (!IsVSFSAvailable(4, 4))
5971 return NOT_SUPPORTED;
5972 GLint blocksC;
5973 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
5974 if (blocksC < 8)
5975 return NOT_SUPPORTED;
5976 const char* const glsl_vs =
5977 NL "layout(location = 1) in vec2 g_in_position;" NL "layout(binding = 0, std430) buffer Transform {" NL
5978 " vec2 translation;" NL "} g_transform[4];" NL "uniform uint g_transform_id;" NL "void main() {" NL
5979 " vec2 translation = vec2(0);" NL " switch (g_transform_id) {" NL " case 0u:" NL
5980 " translation = g_transform[0].translation;" NL " break;" NL " case 1u:" NL
5981 " translation = g_transform[1].translation;" NL " break;" NL " case 2u:" NL
5982 " translation = g_transform[2].translation;" NL " break;" NL " case 3u:" NL
5983 " translation = g_transform[3].translation;" NL " break;" NL " }" NL
5984 " gl_Position = vec4(g_in_position + translation, 0, 1);" NL "}";
5985 const char* const glsl_fs = NL
5986 "layout(location = 0) out vec4 g_fs_out;" NL "layout(binding = 4, std430) buffer Material {" NL
5987 " vec3 color;" NL "} g_material[4];" NL "uniform int g_material_id;" NL "void main() {" NL
5988 " vec3 color = vec3(0);" NL " switch (g_material_id) {" NL " case 0:" NL
5989 " color = g_material[0].color;" NL " break;" NL " case 1:" NL " color = g_material[1].color;" NL
5990 " break;" NL " case 2:" NL " color = g_material[2].color;" NL " break;" NL " case 3:" NL
5991 " color = g_material[3].color;" NL " break;" NL " }" NL " g_fs_out = vec4(color, 1);" NL "}";
5992 m_program = CreateProgram(glsl_vs, glsl_fs);
5993 glLinkProgram(m_program);
5994 if (!CheckProgram(m_program))
5995 return ERROR;
5996
5997 glGenBuffers(8, m_storage_buffer);
5998
5999 /* transform buffers */
6000 {
6001 const float data[4][2] = { { -0.5f, -0.5f }, { 0.5f, -0.5f }, { -0.5f, 0.5f }, { 0.5f, 0.5f } };
6002 for (GLuint i = 0; i < 4; ++i)
6003 {
6004 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6005 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6006 }
6007 }
6008 /* material buffers */
6009 {
6010 const float data[4][3] = {
6011 { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }
6012 };
6013 for (GLuint i = 0; i < 4; ++i)
6014 {
6015 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_storage_buffer[i + 4]);
6016 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6017 }
6018 }
6019
6020 /* vertex buffer */
6021 {
6022 const float data[] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
6023 glGenBuffers(1, &m_vertex_buffer);
6024 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6025 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6026 glBindBuffer(GL_ARRAY_BUFFER, 0);
6027 }
6028
6029 glBindTexture(GL_TEXTURE_2D, m_rt);
6030 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6031 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6032 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6033 glBindTexture(GL_TEXTURE_2D, 0);
6034 glViewport(0, 0, 100, 100);
6035 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6036 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
6037
6038 glGenVertexArrays(1, &m_vertex_array);
6039 glBindVertexArray(m_vertex_array);
6040 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6041 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
6042 glBindBuffer(GL_ARRAY_BUFFER, 0);
6043 glEnableVertexAttribArray(1);
6044 glBindVertexArray(0);
6045
6046 glUseProgram(m_program);
6047 glBindVertexArray(m_vertex_array);
6048
6049 glClear(GL_COLOR_BUFFER_BIT);
6050 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6051 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6052 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6053 if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(0), vec3(0, 1, 0)))
6054 {
6055 return ERROR;
6056 }
6057
6058 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6059 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6060 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6061 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(0), vec3(0), vec3(0, 1, 0)))
6062 {
6063 return ERROR;
6064 }
6065
6066 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6067 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6068 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
6069 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(0), vec3(0, 1, 0)))
6070 {
6071 return ERROR;
6072 }
6073
6074 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6075 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6076 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6077 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 0, 0), vec3(0, 1, 0)))
6078 {
6079 return ERROR;
6080 }
6081
6082 // once again with only one validation at the end
6083 glClear(GL_COLOR_BUFFER_BIT);
6084 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6085 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6086 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6087
6088 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6089 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6090 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6091
6092 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6093 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6094 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6095
6096 glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6097 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6098 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[7]);
6099 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6100
6101 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6102 {
6103 return ERROR;
6104 }
6105 return NO_ERROR;
6106 }
6107
Cleanup()6108 virtual long Cleanup()
6109 {
6110 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6111 glUseProgram(0);
6112 glDeleteProgram(m_program);
6113 glDeleteBuffers(8, m_storage_buffer);
6114 glDeleteBuffers(1, &m_vertex_buffer);
6115 glDeleteVertexArrays(1, &m_vertex_array);
6116 glDeleteFramebuffers(1, &m_fbo);
6117 glDeleteTextures(1, &m_rt);
6118 return NO_ERROR;
6119 }
6120 };
6121
6122 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6123 {
6124 GLuint m_program;
6125 GLuint m_storage_buffer[5];
6126
Setup()6127 virtual long Setup()
6128 {
6129 m_program = 0;
6130 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6131 return NO_ERROR;
6132 }
6133
Run()6134 virtual long Run()
6135 {
6136 GLint blocksC;
6137 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6138 if (blocksC < 8)
6139 return NOT_SUPPORTED;
6140 bool status = true;
6141 const char* const glsl_cs =
6142 NL "layout(local_size_x = 4) in;" NL "layout(binding = 0, std430) buffer Material {" NL " vec3 color;" NL
6143 "} g_material[4];" NL "layout(binding = 4, std430) buffer OutputBuffer {" NL " vec3 color[4];" NL
6144 "};" NL "uniform int g_material_id;" NL "void main() {" NL
6145 " if (g_material_id == 0) color[gl_LocalInvocationIndex] = g_material[0].color;" NL
6146 " else if (g_material_id == 1) color[gl_LocalInvocationIndex] = g_material[1].color;" NL
6147 " else if (g_material_id == 2) color[gl_LocalInvocationIndex] = g_material[2].color;" NL
6148 " else if (g_material_id == 3) color[gl_LocalInvocationIndex] = g_material[3].color;" NL "}";
6149 m_program = CreateProgramCS(glsl_cs);
6150 glLinkProgram(m_program);
6151 if (!CheckProgram(m_program))
6152 return ERROR;
6153
6154 glGenBuffers(5, m_storage_buffer);
6155
6156 /* material buffers */
6157 const float data[4][3] = {
6158 { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }
6159 };
6160 for (GLuint i = 0; i < 4; ++i)
6161 {
6162 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6163 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6164 }
6165
6166 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6167 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
6168
6169 glUseProgram(m_program);
6170 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6171 glDispatchCompute(1, 1, 1);
6172 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6173 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6174 GLfloat* out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6175 if (!out_data)
6176 return ERROR;
6177 const float* expected = &data[1][0];
6178 for (int i = 0; i < 4; ++i)
6179 {
6180 if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6181 out_data[i * 4 + 2] != expected[2])
6182 {
6183 m_context.getTestContext().getLog()
6184 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6185 << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
6186 << expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
6187 status = false;
6188 }
6189 }
6190 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6191 glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6192 glDispatchCompute(1, 1, 1);
6193 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6194 out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6195 if (!out_data)
6196 return ERROR;
6197 expected = &data[3][0];
6198 for (int i = 0; i < 4; ++i)
6199 {
6200 if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6201 out_data[i * 4 + 2] != expected[2])
6202 {
6203 m_context.getTestContext().getLog()
6204 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6205 << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6206 << expected[2] << ", " << tcu::TestLog::EndMessage;
6207 status = false;
6208 }
6209 }
6210
6211 if (!status)
6212 {
6213 return ERROR;
6214 }
6215 return NO_ERROR;
6216 }
6217
Cleanup()6218 virtual long Cleanup()
6219 {
6220 glUseProgram(0);
6221 glDeleteProgram(m_program);
6222 glDeleteBuffers(5, m_storage_buffer);
6223 return NO_ERROR;
6224 }
6225 };
6226
6227 //-----------------------------------------------------------------------------
6228 // 2.5.1 AdvancedReadWriteCase1
6229 //-----------------------------------------------------------------------------
6230 class AdvancedReadWriteCase1VSFS : public ShaderStorageBufferObjectBase
6231 {
6232 GLuint m_program;
6233 GLuint m_storage_buffer;
6234 GLuint m_vertex_array;
6235 GLuint m_vertex_buffer;
6236
Setup()6237 virtual long Setup()
6238 {
6239 m_program = 0;
6240 m_storage_buffer = 0;
6241 m_vertex_array = 0;
6242 m_vertex_buffer = 0;
6243 return NO_ERROR;
6244 }
6245
Run()6246 virtual long Run()
6247 {
6248 if (!IsVSFSAvailable(1, 1))
6249 return NOT_SUPPORTED;
6250 const char* const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "coherent buffer Buffer {" NL
6251 " vec4 in_color;" NL " vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL
6252 " if (gl_VertexID == 0) {" NL " g_buffer.out_color = g_buffer.in_color;" NL
6253 " memoryBarrier();" NL " }" NL " gl_Position = g_in_position;" NL "}";
6254 const char* const glsl_fs =
6255 NL "layout(location = 0) out vec4 g_fs_out;" NL "coherent buffer Buffer {" NL " vec4 in_color;" NL
6256 " vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL " g_fs_out = g_buffer.out_color;" NL "}";
6257 m_program = CreateProgram(glsl_vs, glsl_fs);
6258 glLinkProgram(m_program);
6259 if (!CheckProgram(m_program))
6260 return ERROR;
6261
6262 glGenBuffers(1, &m_storage_buffer);
6263 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6264 glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
6265 float* ptr = reinterpret_cast<float*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_WRITE_BIT));
6266 if (!ptr)
6267 return ERROR;
6268 *ptr++ = 0.0f;
6269 *ptr++ = 1.0f;
6270 *ptr++ = 0.0f;
6271 *ptr++ = 1.0f;
6272 *ptr++ = 0.0f;
6273 *ptr++ = 0.0f;
6274 *ptr++ = 0.0f;
6275 *ptr++ = 0.0f;
6276 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6277
6278 /* vertex buffer */
6279 {
6280 const float data[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
6281 glGenBuffers(1, &m_vertex_buffer);
6282 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6283 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6284 glBindBuffer(GL_ARRAY_BUFFER, 0);
6285 }
6286
6287 glGenVertexArrays(1, &m_vertex_array);
6288 glBindVertexArray(m_vertex_array);
6289 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6290 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6291 glBindBuffer(GL_ARRAY_BUFFER, 0);
6292 glEnableVertexAttribArray(0);
6293 glBindVertexArray(0);
6294
6295 glClear(GL_COLOR_BUFFER_BIT);
6296 glUseProgram(m_program);
6297 glBindVertexArray(m_vertex_array);
6298 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6299 if (!CheckFB(vec3(0, 1, 0)))
6300 {
6301 return ERROR;
6302 }
6303
6304 ptr = reinterpret_cast<float*>(
6305 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6306 if (!ptr)
6307 return ERROR;
6308 *ptr++ = 1.0f;
6309 *ptr++ = 0.0f;
6310 *ptr++ = 1.0f;
6311 *ptr++ = 1.0f;
6312 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6313
6314 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6315 if (!CheckFB(vec3(1, 0, 1)))
6316 {
6317 return ERROR;
6318 }
6319
6320 return NO_ERROR;
6321 }
6322
Cleanup()6323 virtual long Cleanup()
6324 {
6325 glUseProgram(0);
6326 glDeleteProgram(m_program);
6327 glDeleteBuffers(1, &m_storage_buffer);
6328 glDeleteBuffers(1, &m_vertex_buffer);
6329 glDeleteVertexArrays(1, &m_vertex_array);
6330 return NO_ERROR;
6331 }
6332 };
6333 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6334 {
6335 GLuint m_program;
6336 GLuint m_storage_buffer;
6337
Setup()6338 virtual long Setup()
6339 {
6340 m_program = 0;
6341 m_storage_buffer = 0;
6342 return NO_ERROR;
6343 }
6344
Run()6345 virtual long Run()
6346 {
6347 bool status = true;
6348 const char* const glsl_cs = NL
6349 "layout(local_size_x = 128) in;" NL "struct s {" NL " int ene;" NL " int due;" NL " int like;" NL
6350 " int fake;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL " s a[128];" NL "} g_buffer;" NL
6351 "void main() {" NL " g_buffer.a[gl_LocalInvocationIndex].due = g_buffer.a[gl_LocalInvocationIndex].ene;" NL
6352 " groupMemoryBarrier();" NL " barrier();" NL " g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].like = "
6353 "g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].due;" NL " groupMemoryBarrier();" NL " barrier();" NL
6354 " g_buffer.a[(gl_LocalInvocationIndex + 17u) % 128u].fake "
6355 "= g_buffer.a[(gl_LocalInvocationIndex + 17u) % "
6356 "128u].like;" NL "}";
6357 m_program = CreateProgramCS(glsl_cs);
6358 glLinkProgram(m_program);
6359 if (!CheckProgram(m_program))
6360 return ERROR;
6361
6362 glGenBuffers(1, &m_storage_buffer);
6363 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6364 GLint data[128 * 4];
6365 for (int i = 0; i < 128; ++i)
6366 {
6367 data[i * 4] = i + 256;
6368 data[i * 4 + 1] = 0;
6369 data[i * 4 + 2] = 0;
6370 data[i * 4 + 3] = 0;
6371 }
6372 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6373
6374 glUseProgram(m_program);
6375 glDispatchCompute(1, 1, 1);
6376 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6377 GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6378 if (!out_data)
6379 return ERROR;
6380 for (int i = 0; i < 128; ++i)
6381 {
6382 if (out_data[i * 4 + 3] != data[i * 4])
6383 {
6384 m_context.getTestContext().getLog()
6385 << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", but expected: " << data[i * 4]
6386 << " -> " << out_data[i * 4 + 1] << " -> " << out_data[i * 4 + 2] << " -> "
6387 << tcu::TestLog::EndMessage;
6388 status = false;
6389 }
6390 }
6391 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6392 for (int i = 0; i < 128; ++i)
6393 {
6394 data[i * 4] = i + 512;
6395 data[i * 4 + 1] = 0;
6396 data[i * 4 + 2] = 0;
6397 data[i * 4 + 3] = 0;
6398 }
6399 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6400
6401 glDispatchCompute(1, 1, 1);
6402 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6403 out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6404 if (!out_data)
6405 return ERROR;
6406 for (int i = 0; i < 128; ++i)
6407 {
6408 if (out_data[i * 4 + 3] != data[i * 4])
6409 {
6410 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3]
6411 << ", but expected: " << data[i * 4] << tcu::TestLog::EndMessage;
6412 status = false;
6413 }
6414 }
6415 if (status)
6416 return NO_ERROR;
6417 else
6418 return ERROR;
6419 }
6420
Cleanup()6421 virtual long Cleanup()
6422 {
6423 glUseProgram(0);
6424 glDeleteProgram(m_program);
6425 glDeleteBuffers(1, &m_storage_buffer);
6426 return NO_ERROR;
6427 }
6428 };
6429 //-----------------------------------------------------------------------------
6430 // 2.6.1 AdvancedUsageCase1
6431 //-----------------------------------------------------------------------------
6432 class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6433 {
6434 GLuint m_program;
6435 GLuint m_storage_buffer[3];
6436 GLuint m_vertex_array;
6437 GLuint m_vertex_buffer;
6438 GLuint m_fbo, m_rt;
6439
Setup()6440 virtual long Setup()
6441 {
6442 m_program = 0;
6443 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6444 m_vertex_array = 0;
6445 m_vertex_buffer = 0;
6446 glGenFramebuffers(1, &m_fbo);
6447 glGenTextures(1, &m_rt);
6448 return NO_ERROR;
6449 }
6450
Run()6451 virtual long Run()
6452 {
6453 if (!IsVSFSAvailable(2, 2))
6454 return NOT_SUPPORTED;
6455 const char* const glsl_vs =
6456 NL "layout(location = 0) in vec4 g_position;" NL "layout(location = 1) in int g_object_id;" NL
6457 "flat out int object_id;" NL "layout(binding = 0) buffer TransformBuffer {" NL
6458 " mat4 g_transform[4];" NL "};" NL "void main() {" NL " mat4 mvp = g_transform[g_object_id];" NL
6459 " gl_Position = mvp * g_position;" NL " object_id = g_object_id;" NL "}";
6460 const char* const glsl_fs =
6461 NL "flat in int object_id;" NL "layout(location = 0) out vec4 g_fs_out;" NL "struct Material {" NL
6462 " vec3 color;" NL "};" NL "layout(binding = 1, std430) buffer MaterialBuffer {" NL
6463 " Material g_material[4];" NL "};" NL "layout(binding = 2, std430) buffer MaterialIDBuffer {" NL
6464 " int g_material_id[4];" NL "};" NL "void main() {" NL " int mid = g_material_id[object_id];" NL
6465 " Material m = g_material[mid];" NL " g_fs_out = vec4(m.color, 1);" NL "}";
6466 m_program = CreateProgram(glsl_vs, glsl_fs);
6467 glLinkProgram(m_program);
6468 if (!CheckProgram(m_program))
6469 return ERROR;
6470
6471 glGenBuffers(3, m_storage_buffer);
6472
6473 /* transform buffer */
6474 {
6475 mat4 data[] = { Translation(-0.5f, -0.5f, 0.0f), Translation(0.5f, -0.5f, 0.0f),
6476 Translation(-0.5f, 0.5f, 0.0f), Translation(0.5f, 0.5f, 0.0f) };
6477 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6478 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6479 }
6480 /* material buffer */
6481 {
6482 vec4 data[] = { vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 0), vec4(1, 1, 0, 1) };
6483 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6484 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6485 }
6486 /* material id buffer */
6487 {
6488 int data[] = { 0, 1, 2, 3 };
6489 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6490 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6491 }
6492 /* vertex buffer */
6493 {
6494 struct
6495 {
6496 vec2 position;
6497 int object_id;
6498 } data[] = { { vec2(-0.4f, -0.4f), 0 }, { vec2(0.4f, -0.4f), 0 }, { vec2(-0.4f, 0.4f), 0 },
6499 { vec2(0.4f, 0.4f), 0 }, { vec2(-0.4f, -0.4f), 1 }, { vec2(0.4f, -0.4f), 1 },
6500 { vec2(-0.4f, 0.4f), 1 }, { vec2(0.4f, 0.4f), 1 }, { vec2(-0.4f, -0.4f), 2 },
6501 { vec2(0.4f, -0.4f), 2 }, { vec2(-0.4f, 0.4f), 2 }, { vec2(0.4f, 0.4f), 2 },
6502 { vec2(-0.4f, -0.4f), 3 }, { vec2(0.4f, -0.4f), 3 }, { vec2(-0.4f, 0.4f), 3 },
6503 { vec2(0.4f, 0.4f), 3 } };
6504 glGenBuffers(1, &m_vertex_buffer);
6505 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6506 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6507 glBindBuffer(GL_ARRAY_BUFFER, 0);
6508 }
6509
6510 glBindTexture(GL_TEXTURE_2D, m_rt);
6511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6513 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6514 glBindTexture(GL_TEXTURE_2D, 0);
6515 glViewport(0, 0, 100, 100);
6516 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6517 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
6518
6519 glGenVertexArrays(1, &m_vertex_array);
6520 glBindVertexArray(m_vertex_array);
6521 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6522 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2) + sizeof(int), 0);
6523 glVertexAttribIPointer(1, 1, GL_INT, sizeof(vec2) + sizeof(int), reinterpret_cast<void*>(sizeof(vec2)));
6524 glBindBuffer(GL_ARRAY_BUFFER, 0);
6525 glEnableVertexAttribArray(0);
6526 glEnableVertexAttribArray(1);
6527 glBindVertexArray(0);
6528
6529 glClear(GL_COLOR_BUFFER_BIT);
6530 glUseProgram(m_program);
6531 glBindVertexArray(m_vertex_array);
6532 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6533 glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
6534 glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
6535 glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
6536 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
6537 {
6538 return ERROR;
6539 }
6540 return NO_ERROR;
6541 }
6542
Cleanup()6543 virtual long Cleanup()
6544 {
6545 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6546 glUseProgram(0);
6547 glDeleteProgram(m_program);
6548 glDeleteBuffers(3, m_storage_buffer);
6549 glDeleteBuffers(1, &m_vertex_buffer);
6550 glDeleteVertexArrays(1, &m_vertex_array);
6551 glDeleteFramebuffers(1, &m_fbo);
6552 glDeleteTextures(1, &m_rt);
6553 return NO_ERROR;
6554 }
6555 };
6556
6557 //-----------------------------------------------------------------------------
6558 // 2.6.2 AdvancedUsageSync
6559 //-----------------------------------------------------------------------------
6560 class AdvancedUsageSyncVSFS : public ShaderStorageBufferObjectBase
6561 {
6562 GLuint m_program;
6563 GLuint m_storage_buffer[7];
6564 GLuint m_vertex_array;
6565
Setup()6566 virtual long Setup()
6567 {
6568 m_program = 0;
6569 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6570 m_vertex_array = 0;
6571 return NO_ERROR;
6572 }
6573
Run()6574 virtual long Run()
6575 {
6576 if (!IsVSFSAvailable(3, 4))
6577 return NOT_SUPPORTED;
6578 const char* const glsl_vs = NL
6579 "layout(std430, binding = 0) coherent buffer Buffer0 {" NL " int g_data0, g_inc0;" NL
6580 " int g_data1, g_inc1;" NL "};" NL "layout(std430, binding = 1) buffer Buffer12 {" NL " int inc, data;" NL
6581 "} g_buffer12[2];" NL "flat out int primitive_id;" NL NL "void Modify(int path) {" NL
6582 " if (path == 0) {" NL " atomicAdd(g_data0, g_inc0);" NL " atomicAdd(g_data1, g_inc0);" NL
6583 " } else if (path == 1) {" NL " atomicAdd(g_data0, - g_inc0);" NL " atomicAdd(g_data1, - g_inc0);" NL
6584 " } else if (path == 2) {" NL " atomicAdd(g_data0, g_inc1);" NL " atomicAdd(g_data1, g_inc1);" NL
6585 " }" NL NL " if (path == 0) {" NL " g_buffer12[0].data += g_buffer12[1].inc;" NL
6586 " } else if (path == 1) {" NL " g_buffer12[1].data += g_buffer12[0].inc;" NL " }" NL "}" NL NL
6587 "void main() {" NL " Modify(gl_VertexID);" NL " primitive_id = gl_VertexID;" NL
6588 " gl_Position = vec4(0, 0, 0, 1);" NL "#ifdef GL_ES" NL " gl_PointSize = 1.0f;" NL "#endif" NL "}";
6589 const char* glsl_fs =
6590 NL "layout(binding = 3, std430) coherent buffer Buffer3 {" NL " int data;" NL "} g_buffer3;" NL
6591 "layout(std430, binding = 4) coherent buffer Buffer4 {" NL " int data0, inc0;" NL
6592 " int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
6593 " int inc, data;" NL "} g_buffer56[2];" NL "flat in int primitive_id;" NL NL
6594 "void ModifyFS(int path) {" NL " if (path == 0) {" NL
6595 " atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
6596 " } else if (path == 1) {" NL " atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
6597 " atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL " } else if (path == 2) {" NL
6598 " atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
6599 " }" NL NL " if (path == 0) {" NL " g_buffer56[0].data += g_buffer56[1].inc;" NL
6600 " } else if (path == 1) {" NL " g_buffer56[1].data += g_buffer56[0].inc;" NL " }" NL "}" NL
6601 "void main() {" NL " atomicAdd(g_buffer3.data, 1);" NL " ModifyFS(primitive_id);" NL "}";
6602 m_program = CreateProgram(glsl_vs, glsl_fs);
6603 glLinkProgram(m_program);
6604 if (!CheckProgram(m_program))
6605 return ERROR;
6606
6607 glGenVertexArrays(1, &m_vertex_array);
6608 glGenBuffers(7, m_storage_buffer);
6609
6610 /* Buffer0 */
6611 {
6612 int data[4] = { 0, 1, 0, 2 };
6613 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6614 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6615 }
6616 /* Buffer1 */
6617 {
6618 int data[2] = { 3, 1 };
6619 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6620 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6621 }
6622 /* Buffer2 */
6623 {
6624 int data[2] = { 2, 4 };
6625 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6626 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6627 }
6628 /* Buffer3 */
6629 {
6630 int data[1] = { 0 };
6631 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6632 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6633 }
6634 /* Buffer4 */
6635 {
6636 int data[4] = { 0, 1, 0, 2 };
6637 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6638 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6639 }
6640 /* Buffer5 */
6641 {
6642 int data[2] = { 3, 1 };
6643 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
6644 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6645 }
6646 /* Buffer6 */
6647 {
6648 int data[2] = { 2, 4 };
6649 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
6650 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6651 }
6652
6653 glUseProgram(m_program);
6654 glBindVertexArray(m_vertex_array);
6655
6656 glDrawArrays(GL_POINTS, 0, 3);
6657 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6658 glDrawArrays(GL_POINTS, 0, 3);
6659 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6660
6661 /* Buffer0 */
6662 {
6663 const int ref_data[4] = { 4, 1, 4, 2 };
6664 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
6665 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6666 if (!data)
6667 return ERROR;
6668 for (int i = 0; i < 4; ++i)
6669 {
6670 if (data[i] != ref_data[i])
6671 {
6672 m_context.getTestContext().getLog()
6673 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
6674 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6675 return ERROR;
6676 }
6677 }
6678 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6679 }
6680 /* Buffer1 */
6681 {
6682 const int ref_data[2] = { 3, 5 };
6683 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6684 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6685 if (!data)
6686 return ERROR;
6687 for (int i = 0; i < 2; ++i)
6688 {
6689 if (data[i] != ref_data[i])
6690 {
6691 m_context.getTestContext().getLog()
6692 << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
6693 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6694 return ERROR;
6695 }
6696 }
6697 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6698 }
6699 /* Buffer2 */
6700 {
6701 const int ref_data[2] = { 2, 10 };
6702 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
6703 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6704 if (!data)
6705 return ERROR;
6706 for (int i = 0; i < 2; ++i)
6707 {
6708 if (data[i] != ref_data[i])
6709 {
6710 m_context.getTestContext().getLog()
6711 << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
6712 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6713 return ERROR;
6714 }
6715 }
6716 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6717 }
6718 /* Buffer3 */
6719 {
6720 const int ref_data[1] = { 6 };
6721 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6722 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
6723 if (!data)
6724 return ERROR;
6725 for (int i = 0; i < 1; ++i)
6726 {
6727 if (data[i] != ref_data[i])
6728 {
6729 m_context.getTestContext().getLog()
6730 << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
6731 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6732 return ERROR;
6733 }
6734 }
6735 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6736 }
6737 /* Buffer4 */
6738 {
6739 const int ref_data[4] = { 4, 1, 4, 2 };
6740 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6741 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6742 if (!data)
6743 return ERROR;
6744 for (int i = 0; i < 4; ++i)
6745 {
6746 if (data[i] != ref_data[i])
6747 {
6748 m_context.getTestContext().getLog()
6749 << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
6750 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6751 return ERROR;
6752 }
6753 }
6754 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6755 }
6756 /* Buffer5 */
6757 {
6758 const int ref_data[2] = { 3, 5 };
6759 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
6760 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6761 if (!data)
6762 return ERROR;
6763 for (int i = 0; i < 2; ++i)
6764 {
6765 if (data[i] != ref_data[i])
6766 {
6767 m_context.getTestContext().getLog()
6768 << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
6769 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6770 return ERROR;
6771 }
6772 }
6773 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6774 }
6775 /* Buffer6 */
6776 {
6777 const int ref_data[2] = { 2, 10 };
6778 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
6779 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6780 if (!data)
6781 return ERROR;
6782 for (int i = 0; i < 2; ++i)
6783 {
6784 if (data[i] != ref_data[i])
6785 {
6786 m_context.getTestContext().getLog()
6787 << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
6788 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6789 return ERROR;
6790 }
6791 }
6792 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6793 }
6794
6795 return NO_ERROR;
6796 }
6797
Cleanup()6798 virtual long Cleanup()
6799 {
6800 glUseProgram(0);
6801 glDeleteProgram(m_program);
6802 glDeleteBuffers(7, m_storage_buffer);
6803 glDeleteVertexArrays(1, &m_vertex_array);
6804 return NO_ERROR;
6805 }
6806 };
6807 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
6808 {
6809 GLuint m_program;
6810 GLuint m_storage_buffer[7];
6811
Setup()6812 virtual long Setup()
6813 {
6814 m_program = 0;
6815 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6816 return NO_ERROR;
6817 }
6818
Run()6819 virtual long Run()
6820 {
6821 const char* const glsl_cs =
6822 NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL
6823 " int g_data0, g_inc0;" NL " int g_data1, g_inc1;" NL "};" NL
6824 "layout(std430, binding = 1) buffer Buffer12 {" NL " int inc, data;" NL "} g_buffer12[2];" NL
6825 "layout(binding = 3, std430) coherent buffer Buffer3 {" NL " int data;" NL "} g_buffer3;" NL
6826 "layout(std430, binding = 4) coherent buffer Buffer4 {" NL " int data0, inc0;" NL
6827 " int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
6828 " int inc, data;" NL "} g_buffer56[2];" NL NL "void Modify1(int path) {" NL " if (path == 0) {" NL
6829 " atomicAdd(g_data0, g_inc0);" NL " atomicAdd(g_data1, g_inc0);" NL " } else if (path == 1) {" NL
6830 " atomicAdd(g_data0, - g_inc0);" NL " atomicAdd(g_data1, - g_inc0);" NL
6831 " } else if (path == 2) {" NL " atomicAdd(g_data0, g_inc1);" NL " atomicAdd(g_data1, g_inc1);" NL
6832 " }" NL " if (path == 0) {" NL " g_buffer12[0].data += g_buffer12[1].inc;" NL
6833 " } else if (path == 1) {" NL " g_buffer12[1].data += g_buffer12[0].inc;" NL " }" NL "}" NL NL
6834 "void Modify2(int path) {" NL " if (path == 0) {" NL
6835 " atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
6836 " } else if (path == 1) {" NL " atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
6837 " atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL " } else if (path == 2) {" NL
6838 " atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL " atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
6839 " }" NL " if (path == 0) {" NL " g_buffer56[0].data += g_buffer56[1].inc;" NL
6840 " } else if (path == 1) {" NL " g_buffer56[1].data += g_buffer56[0].inc;" NL " }" NL "}" NL NL
6841 "void main() {" NL " Modify1(int(gl_WorkGroupID.z));" NL " atomicAdd(g_buffer3.data, 1);" NL
6842 " Modify2(int(gl_WorkGroupID.z));" NL "}";
6843 m_program = CreateProgramCS(glsl_cs);
6844 glLinkProgram(m_program);
6845 if (!CheckProgram(m_program))
6846 return ERROR;
6847
6848 glGenBuffers(7, m_storage_buffer);
6849
6850 /* Buffer0 */
6851 {
6852 int data[4] = { 0, 1, 0, 2 };
6853 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6854 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6855 }
6856 /* Buffer1 */
6857 {
6858 int data[2] = { 3, 1 };
6859 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6860 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6861 }
6862 /* Buffer2 */
6863 {
6864 int data[2] = { 2, 4 };
6865 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6866 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6867 }
6868 /* Buffer3 */
6869 {
6870 int data[1] = { 0 };
6871 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6872 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6873 }
6874 /* Buffer4 */
6875 {
6876 int data[4] = { 0, 1, 0, 2 };
6877 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6878 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6879 }
6880 /* Buffer5 */
6881 {
6882 int data[2] = { 3, 1 };
6883 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
6884 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6885 }
6886 /* Buffer6 */
6887 {
6888 int data[2] = { 2, 4 };
6889 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
6890 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6891 }
6892
6893 glUseProgram(m_program);
6894
6895 glDispatchCompute(1, 1, 3);
6896 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6897 glDispatchCompute(1, 1, 3);
6898
6899 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6900
6901 /* Buffer0 */
6902 {
6903 const int ref_data[4] = { 4, 1, 4, 2 };
6904 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
6905 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6906 if (!data)
6907 return ERROR;
6908 for (int i = 0; i < 4; ++i)
6909 {
6910 if (data[i] != ref_data[i])
6911 {
6912 m_context.getTestContext().getLog()
6913 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
6914 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6915 return ERROR;
6916 }
6917 }
6918 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6919 }
6920 /* Buffer1 */
6921 {
6922 const int ref_data[2] = { 3, 5 };
6923 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6924 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6925 if (!data)
6926 return ERROR;
6927 for (int i = 0; i < 2; ++i)
6928 {
6929 if (data[i] != ref_data[i])
6930 {
6931 m_context.getTestContext().getLog()
6932 << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
6933 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6934 return ERROR;
6935 }
6936 }
6937 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6938 }
6939 /* Buffer2 */
6940 {
6941 const int ref_data[2] = { 2, 10 };
6942 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
6943 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6944 if (!data)
6945 return ERROR;
6946 for (int i = 0; i < 2; ++i)
6947 {
6948 if (data[i] != ref_data[i])
6949 {
6950 m_context.getTestContext().getLog()
6951 << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
6952 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6953 return ERROR;
6954 }
6955 }
6956 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6957 }
6958 /* Buffer3 */
6959 {
6960 const int ref_data[1] = { 6 };
6961 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6962 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
6963 if (!data)
6964 return ERROR;
6965 for (int i = 0; i < 1; ++i)
6966 {
6967 if (data[i] != ref_data[i])
6968 {
6969 m_context.getTestContext().getLog()
6970 << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
6971 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6972 return ERROR;
6973 }
6974 }
6975 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6976 }
6977 /* Buffer4 */
6978 {
6979 const int ref_data[4] = { 4, 1, 4, 2 };
6980 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6981 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6982 if (!data)
6983 return ERROR;
6984 for (int i = 0; i < 4; ++i)
6985 {
6986 if (data[i] != ref_data[i])
6987 {
6988 m_context.getTestContext().getLog()
6989 << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
6990 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6991 return ERROR;
6992 }
6993 }
6994 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6995 }
6996 /* Buffer5 */
6997 {
6998 const int ref_data[2] = { 3, 5 };
6999 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7000 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7001 if (!data)
7002 return ERROR;
7003 for (int i = 0; i < 2; ++i)
7004 {
7005 if (data[i] != ref_data[i])
7006 {
7007 m_context.getTestContext().getLog()
7008 << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7009 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7010 return ERROR;
7011 }
7012 }
7013 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7014 }
7015 /* Buffer6 */
7016 {
7017 const int ref_data[2] = { 2, 10 };
7018 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7019 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7020 if (!data)
7021 return ERROR;
7022 for (int i = 0; i < 2; ++i)
7023 {
7024 if (data[i] != ref_data[i])
7025 {
7026 m_context.getTestContext().getLog()
7027 << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7028 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7029 return ERROR;
7030 }
7031 }
7032 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7033 }
7034
7035 return NO_ERROR;
7036 }
7037
Cleanup()7038 virtual long Cleanup()
7039 {
7040 glUseProgram(0);
7041 glDeleteProgram(m_program);
7042 glDeleteBuffers(7, m_storage_buffer);
7043 return NO_ERROR;
7044 }
7045 };
7046 //-----------------------------------------------------------------------------
7047 // 2.6.3 AdvancedUsageOperators
7048 //-----------------------------------------------------------------------------
7049 class AdvancedUsageOperatorsVS : public ShaderStorageBufferObjectBase
7050 {
7051 GLuint m_program;
7052 GLuint m_storage_buffer[2];
7053 GLuint m_vertex_array;
7054
Setup()7055 virtual long Setup()
7056 {
7057 m_program = 0;
7058 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7059 m_vertex_array = 0;
7060 return NO_ERROR;
7061 }
7062
Run()7063 virtual long Run()
7064 {
7065 if (!IsVSFSAvailable(2, 0))
7066 return NOT_SUPPORTED;
7067 const char* const glsl_vs =
7068 NL "layout(std430, binding = 0) buffer Buffer0 {" NL " readonly int g_i0;" NL " int g_o0;" NL "};" NL
7069 "layout(std430, binding = 1) buffer Buffer1 {" NL " int i0;" NL "} g_buffer1;" NL
7070 "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL " g_o0 += g_i0;" NL
7071 " g_o0 <<= 1;" NL " g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL " g_o0 *= g_i0;" NL
7072 " g_o0 = --g_o0 + g_values[g_i0];" NL " g_o0++;" NL " ++g_o0;" NL " g_buffer1.i0 = 0xff2f;" NL
7073 " g_o0 &= g_buffer1.i0;" NL "}";
7074 const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7075 " o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
7076
7077 m_program = CreateProgram(glsl_vs, glsl_fs);
7078 glLinkProgram(m_program);
7079 if (!CheckProgram(m_program))
7080 return ERROR;
7081
7082 glGenVertexArrays(1, &m_vertex_array);
7083 glGenBuffers(2, m_storage_buffer);
7084
7085 /* Buffer0 */
7086 {
7087 int data[4] = { 3, 5 };
7088 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7089 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7090 }
7091 /* Buffer1 */
7092 {
7093 int data[1] = { 0 };
7094 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7095 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7096 }
7097
7098 glEnable(GL_RASTERIZER_DISCARD);
7099 glUseProgram(m_program);
7100 glBindVertexArray(m_vertex_array);
7101 glDrawArrays(GL_POINTS, 0, 1);
7102 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7103
7104 /* Buffer0 */
7105 {
7106 const int ref_data[2] = { 3, 37 };
7107 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7108 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7109 if (!data)
7110 return ERROR;
7111 for (int i = 0; i < 2; ++i)
7112 {
7113 if (data[i] != ref_data[i])
7114 {
7115 m_context.getTestContext().getLog()
7116 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7117 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7118 return ERROR;
7119 }
7120 }
7121 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7122 }
7123 /* Buffer0 */
7124 {
7125 const int ref_data[1] = { 0xff2f };
7126 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7127 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
7128 if (!data)
7129 return ERROR;
7130 for (int i = 0; i < 1; ++i)
7131 {
7132 if (data[i] != ref_data[i])
7133 {
7134 m_context.getTestContext().getLog()
7135 << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7136 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7137 return ERROR;
7138 }
7139 }
7140 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7141 }
7142
7143 return NO_ERROR;
7144 }
7145
Cleanup()7146 virtual long Cleanup()
7147 {
7148 glDisable(GL_RASTERIZER_DISCARD);
7149 glUseProgram(0);
7150 glDeleteProgram(m_program);
7151 glDeleteBuffers(2, m_storage_buffer);
7152 glDeleteVertexArrays(1, &m_vertex_array);
7153 return NO_ERROR;
7154 }
7155 };
7156 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7157 {
7158 GLuint m_program;
7159 GLuint m_storage_buffer[2];
7160
Setup()7161 virtual long Setup()
7162 {
7163 m_program = 0;
7164 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7165 return NO_ERROR;
7166 }
7167
Run()7168 virtual long Run()
7169 {
7170 const char* const glsl_cs =
7171 NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Buffer0 {" NL
7172 " readonly int g_i0;" NL " int g_o0;" NL "};" NL "layout(std430, binding = 1) buffer Buffer1 {" NL
7173 " int i0;" NL "} g_buffer1;" NL "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL
7174 " 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
7175 " g_o0 = --g_o0 + g_values[g_i0];" NL " g_o0++;" NL " ++g_o0;" NL " g_buffer1.i0 = 0xff2f;" NL
7176 " g_o0 &= g_buffer1.i0;" NL "}";
7177
7178 m_program = CreateProgramCS(glsl_cs);
7179 glLinkProgram(m_program);
7180 if (!CheckProgram(m_program))
7181 return ERROR;
7182
7183 glGenBuffers(2, m_storage_buffer);
7184
7185 /* Buffer0 */
7186 {
7187 int data[4] = { 3, 5 };
7188 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7189 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7190 }
7191 /* Buffer1 */
7192 {
7193 int data[1] = { 0 };
7194 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7195 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7196 }
7197
7198 glUseProgram(m_program);
7199 glDispatchCompute(1, 1, 1);
7200 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7201
7202 /* Buffer0 */
7203 {
7204 const int ref_data[2] = { 3, 37 };
7205 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7206 int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7207 if (!data)
7208 return ERROR;
7209 for (int i = 0; i < 2; ++i)
7210 {
7211 if (data[i] != ref_data[i])
7212 {
7213 m_context.getTestContext().getLog()
7214 << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7215 << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7216 return ERROR;
7217 }
7218 }
7219 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7220 }
7221
7222 return NO_ERROR;
7223 }
7224
Cleanup()7225 virtual long Cleanup()
7226 {
7227 glUseProgram(0);
7228 glDeleteProgram(m_program);
7229 glDeleteBuffers(2, m_storage_buffer);
7230 return NO_ERROR;
7231 }
7232 };
7233
7234 //-----------------------------------------------------------------------------
7235 // 2.7 AdvancedUnsizedArrayLength
7236 //-----------------------------------------------------------------------------
7237 template <int stage>
7238 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7239 {
7240 GLuint m_program;
7241 GLuint m_storage_buffer[4];
7242 GLuint m_vertex_array;
7243
Setup()7244 virtual long Setup()
7245 {
7246 m_program = 0;
7247 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7248 m_vertex_array = 0;
7249 return NO_ERROR;
7250 }
7251
Cleanup()7252 virtual long Cleanup()
7253 {
7254 glUseProgram(0);
7255 glDeleteProgram(m_program);
7256 glDeleteBuffers(4, m_storage_buffer);
7257 if (stage != compute)
7258 glDeleteVertexArrays(1, &m_vertex_array);
7259 return NO_ERROR;
7260 }
BuildShaderPT(int st)7261 std::string BuildShaderPT(int st)
7262 {
7263 std::ostringstream os;
7264 if (st == vertex)
7265 {
7266 os << NL "void main() {" NL " gl_Position = vec4(0,0,0,1);" NL "#ifdef GL_ES" NL
7267 " gl_PointSize = 1.0f;" NL "#endif";
7268 }
7269 if (st == fragment)
7270 {
7271 os << NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7272 " o_color = vec4(0.0, 1.0, 0.0, 1.0);";
7273 }
7274 os << NL "}";
7275 return os.str();
7276 }
BuildShader()7277 std::string BuildShader()
7278 {
7279 std::ostringstream os;
7280 std::string decl =
7281 NL "layout(std430, binding = 0) readonly buffer Input0 {" NL " uint g_input0[];" NL "};" NL
7282 "layout(std430, binding = 1) readonly buffer Input23 {" NL " float data[];" NL "} g_input23[2];" NL
7283 "layout(std430, binding = 3) buffer Output {" NL " int g_length2;" NL " int g_length[];" NL "};";
7284 std::string expr = NL " g_length[0] = g_input0.length();" NL " g_length[1] = g_input23[0].data.length();" NL
7285 " g_length[2] = g_input23[1].data.length();" NL " g_length2 = g_length.length();";
7286 if (stage == vertex)
7287 {
7288 os << decl << NL "void main() {" NL "#ifdef GL_ES" NL " gl_PointSize = 1.0f;" NL "#endif" NL
7289 " gl_Position = vec4(0,0,0,1);"
7290 << expr;
7291 }
7292 if (stage == fragment)
7293 {
7294 os << NL "layout(location = 0) out vec4 o_color;" << decl
7295 << NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" << expr;
7296 }
7297 if (stage == compute)
7298 {
7299 os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7300 }
7301 os << NL "}";
7302 return os.str();
7303 }
7304
Run()7305 virtual long Run()
7306 {
7307 const int kSize = 10000;
7308 const int kBufs = 4;
7309 if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7310 return NOT_SUPPORTED;
7311 if (stage == vertex)
7312 {
7313 std::string glsl_vs = BuildShader();
7314 std::string glsl_fs = BuildShaderPT(fragment);
7315 m_program = CreateProgram(glsl_vs, glsl_fs);
7316 }
7317 else if (stage == fragment)
7318 {
7319 std::string glsl_vs = BuildShaderPT(vertex);
7320 std::string glsl_fs = BuildShader();
7321 m_program = CreateProgram(glsl_vs, glsl_fs);
7322 }
7323 else
7324 { // compute
7325 std::string glsl_cs = BuildShader();
7326 m_program = CreateProgramCS(glsl_cs);
7327 }
7328 glLinkProgram(m_program);
7329 if (!CheckProgram(m_program))
7330 return ERROR;
7331 glUseProgram(m_program);
7332
7333 glGenBuffers(kBufs, m_storage_buffer);
7334 int sizes[kBufs] = { 7, 3, 4, 5 };
7335 std::vector<int> data(kSize, 41);
7336 for (int i = 0; i < kBufs; ++i)
7337 {
7338 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7339 glBufferData(GL_SHADER_STORAGE_BUFFER, sizes[i] * 4, &data[0], GL_DYNAMIC_COPY);
7340 }
7341
7342 if (stage != compute)
7343 {
7344 glGenVertexArrays(1, &m_vertex_array);
7345 glBindVertexArray(m_vertex_array);
7346 glDrawArrays(GL_POINTS, 0, 1);
7347 }
7348 else
7349 {
7350 glDispatchCompute(1, 1, 1);
7351 }
7352 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7353
7354 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7355 int* dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
7356 if (!dataout)
7357 return ERROR;
7358 bool status = true;
7359 for (int i = 0; i < kBufs - 1; ++i)
7360 if (dataout[i + 1] != sizes[i])
7361 {
7362 m_context.getTestContext().getLog()
7363 << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i + 1] << " should be "
7364 << sizes[i] << tcu::TestLog::EndMessage;
7365 status = false;
7366 }
7367 if (dataout[0] != sizes[kBufs - 1] - 1)
7368 {
7369 m_context.getTestContext().getLog()
7370 << tcu::TestLog::Message << "Array " << (kBufs - 1) << " length is " << dataout[0] << " should be "
7371 << (sizes[kBufs - 1] - 1) << tcu::TestLog::EndMessage;
7372 status = false;
7373 }
7374 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7375
7376 if (!status)
7377 return ERROR;
7378
7379 return NO_ERROR;
7380 }
7381 };
7382
7383 class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7384 {
7385 GLuint m_program;
7386 GLuint m_storage_buffer[8];
7387 GLuint m_vertex_array;
7388 virtual void SetPath() = 0;
7389
Setup()7390 virtual long Setup()
7391 {
7392 m_program = 0;
7393 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7394 m_vertex_array = 0;
7395 return NO_ERROR;
7396 }
7397
Cleanup()7398 virtual long Cleanup()
7399 {
7400 glUseProgram(0);
7401 glDeleteProgram(m_program);
7402 glDeleteBuffers(8, m_storage_buffer);
7403 if (stage != compute)
7404 glDeleteVertexArrays(1, &m_vertex_array);
7405 return NO_ERROR;
7406 }
BuildShaderPT(int stagept)7407 std::string BuildShaderPT(int stagept)
7408 {
7409 std::ostringstream os;
7410 if (stagept == vertex)
7411 {
7412 os << NL "void main() {" NL " gl_Position = vec4(0,0,0,1);" NL "#ifdef GL_ES" NL
7413 " gl_PointSize = 1.0f;" NL "#endif";
7414 }
7415 if (stagept == fragment)
7416 {
7417 os << NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7418 " o_color = vec4(0.0, 1.0, 0.0, 1.0);";
7419 }
7420 os << NL "}";
7421 return os.str();
7422 }
BuildShader()7423 std::string BuildShader()
7424 {
7425 std::ostringstream os;
7426 std::string e[4][7] = { { "bvec3", "vec4", "ivec3", "ivec3", "uvec2", "vec2", "uvec4" },
7427 { "mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2" },
7428 { "mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2" },
7429 { "S0", "S1", "S2", "S2", "S4", "S5", "S6" } };
7430 std::string sd =
7431 NL "struct S0 {" NL " float f;" NL " int i;" NL " uint ui;" NL " bool b;" NL "};" NL "struct S1 {" NL
7432 " ivec3 iv;" NL " bvec2 bv;" NL " vec4 v;" NL " uvec2 uv;" NL "};" NL "struct S2 {" NL
7433 " mat2x2 m22;" NL " mat4x4 m44;" NL " mat2x3 m23;" NL " mat4x2 m42;" NL " mat3x4 m34;" NL "};" NL
7434 "struct S4 {" NL " float f[1];" NL " int i[2];" NL " uint ui[3];" NL " bool b[4];" NL
7435 " ivec3 iv[5];" NL " bvec2 bv[6];" NL " vec4 v[7];" NL " uvec2 uv[8];" NL "};" NL "struct S5 {" NL
7436 " S0 s0;" NL " S1 s1;" NL " S2 s2;" NL "};" NL "struct S6 {" NL " S4 s4[3];" NL "};";
7437
7438 std::string lo = "";
7439 std::string l[4] = { "std140", "std430", "shared", "packed" };
7440 lo += l[layout];
7441 if (etype == matrix_rm)
7442 lo += ", row_major";
7443 std::string decl = sd + NL "layout(" + lo + ") buffer;" NL "layout(binding = 0) readonly buffer Input0 {" +
7444 ((other_members) ? ("\n " + e[etype][0] + " pad0;") : "") + NL " " + e[etype][0] +
7445 " g_input0[];" NL "};" NL "layout(binding = 1) readonly buffer Input1 {" +
7446 ((other_members) ? ("\n " + e[etype][1] + " pad1;") : "") + NL " " + e[etype][1] +
7447 " data[];" NL "} g_input1;" NL "layout(binding = 2) readonly buffer Input23 {" +
7448 ((other_members) ? ("\n " + e[etype][2] + " pad2;") : "") + NL " " + e[etype][2] +
7449 " data[];" NL "} g_input23[2];" NL "layout(binding = 4) buffer Output0 {" +
7450 ((other_members) ? ("\n " + e[etype][4] + " pad4;") : "") + NL " " + e[etype][4] +
7451 " data[];" NL "} g_output0;" NL "layout(binding = 5) readonly buffer Input4 {" +
7452 ((other_members) ? ("\n " + e[etype][5] + " pad5;") : "") + NL " " + e[etype][5] +
7453 " data[];" NL "} g_input4;" NL "layout(binding = 6) buffer Output1 {" +
7454 ((other_members) ? ("\n " + e[etype][6] + " pad6;") : "") + NL " " + e[etype][6] +
7455 " data[];" NL "} g_output1;" NL "layout(std430, binding = 7) buffer Output {" NL
7456 " int g_length[];" NL "};";
7457 std::string expr =
7458 NL " g_length[0] = g_input0.length();" NL " g_length[1] = g_input1.data.length();" NL
7459 " g_length[2] = g_input23[0].data.length();" NL " g_length[3] = g_input23[1].data.length();" NL
7460 " g_length[4] = g_output0.data.length();" NL " g_length[5] = g_input4.data.length();" NL
7461 " g_length[6] = g_output1.data.length();";
7462 std::string lastelemexpr =
7463 NL " g_output0.data[g_output0.data.length()-2] += g_output0.data[g_output0.data.length()-1];" NL
7464 " g_output1.data[g_output1.data.length()-2] += g_output1.data[g_output1.data.length()-1];";
7465 if (length_as_index)
7466 expr += lastelemexpr;
7467 if (stage == vertex)
7468 {
7469 os << decl << NL "void main() {" NL "#ifdef GL_ES" NL " gl_PointSize = 1.0f;" NL "#endif" NL
7470 " gl_Position = vec4(0,0,0,1);"
7471 << expr;
7472 }
7473 if (stage == fragment)
7474 {
7475 os << NL "layout(location = 0) out vec4 o_color;" << decl
7476 << NL "void main() {" NL " o_color = vec4(0.0, 1.0, 0.0, 1.0);" << expr;
7477 }
7478 if (stage == compute)
7479 {
7480 os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7481 }
7482 os << NL "}";
7483 return os.str();
7484 }
7485
Run()7486 virtual long Run()
7487 {
7488 const int kSize = 100000;
7489 const int kBufs = 8;
7490 SetPath();
7491 if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7492 return NOT_SUPPORTED;
7493 GLint blocksC;
7494 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
7495 GLint minA;
7496 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
7497 if (blocksC < kBufs)
7498 return NOT_SUPPORTED;
7499 if (stage == vertex)
7500 {
7501 std::string glsl_vs = BuildShader();
7502 std::string glsl_fs = BuildShaderPT(fragment);
7503 m_program = CreateProgram(glsl_vs, glsl_fs);
7504 }
7505 else if (stage == fragment)
7506 {
7507 std::string glsl_vs = BuildShaderPT(vertex);
7508 std::string glsl_fs = BuildShader();
7509 m_program = CreateProgram(glsl_vs, glsl_fs);
7510 }
7511 else
7512 { // compute
7513 std::string glsl_cs = BuildShader();
7514 m_program = CreateProgramCS(glsl_cs);
7515 }
7516 glLinkProgram(m_program);
7517 if (!CheckProgram(m_program))
7518 return ERROR;
7519 glUseProgram(m_program);
7520
7521 glGenBuffers(kBufs, m_storage_buffer);
7522 int sizes[kBufs] = { 7, 5, 3, 4, 23, 123, 419, 8 };
7523 int columns[4][kBufs] = { { 1, 1, 1, 1, 1, 1, 1, 1 }, // vector: 1 col
7524 { 2, 3, 4, 4, 2, 3, 4, 1 }, // mat: # of cols
7525 { 2, 3, 4, 4, 3, 2, 2, 1 }, // RM mat: # of rows
7526 { 1, 1, 1, 1, 1, 1, 1, 1 } }; // structure: not used
7527 int scalars[4][kBufs] = { { 4, 4, 4, 4, 2, 2, 4, 1 }, //vector: size
7528 { 2, 4, 4, 4, 4, 2, 2, 1 }, //matrix column_major: rows
7529 { 2, 4, 4, 4, 2, 4, 4, 1 }, //matrix row_major: columns
7530 { 1, 1, 1, 1, 1, 1, 1, 1 } }; //structure: not used
7531 int mindw[4][kBufs] = { { 3, 4, 3, 3, 2, 2, 4, 1 }, // # of real 32bit items
7532 { 4, 9, 16, 16, 6, 6, 8, 1 },
7533 { 4, 9, 16, 16, 6, 6, 8, 1 },
7534 { 4, 11, 35, 35, 81, 127, 381, 1 } };
7535 int std430struct[kBufs] = { 4, 16, 48, 48, 88, 68, 264, 1 };
7536 int std140struct[kBufs] = { 4, 16, 60, 60, 144, 80, 432, 1 };
7537 int bufsize[kBufs][2] = { { 0 }, { 0 } };
7538
7539 std::vector<ivec4> data(kSize, ivec4(41));
7540 for (int i = 0; i < kBufs; ++i)
7541 {
7542 if (layout == std430)
7543 {
7544 bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
7545 if (etype == structure)
7546 {
7547 bufsize[i][1] = 4 * std430struct[i];
7548 }
7549 }
7550 else if (layout == std140)
7551 {
7552 bufsize[i][1] = 4 * columns[etype][i] * 4;
7553 if (etype == structure)
7554 {
7555 bufsize[i][1] = 4 * std140struct[i];
7556 }
7557 }
7558 else
7559 {
7560 bufsize[i][1] = 4 * mindw[etype][i];
7561 }
7562 bufsize[i][0] = sizes[i] * bufsize[i][1];
7563 if (i == kBufs - 1 || bind_seq == bindbasebefore)
7564 { // never trim feedback storage
7565 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7566 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
7567 }
7568 else
7569 {
7570 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[i]);
7571 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
7572 if (bind_seq == bindbaseafter)
7573 {
7574 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7575 }
7576 else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
7577 {
7578 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 2 * bufsize[i][1],
7579 bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
7580 }
7581 else
7582 { // bind_seq == bindrangesize || 2*bufsize[i][1] < minA
7583 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 0,
7584 bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
7585 }
7586 }
7587 }
7588
7589 if (stage != compute)
7590 {
7591 glGenVertexArrays(1, &m_vertex_array);
7592 glBindVertexArray(m_vertex_array);
7593 glDrawArrays(GL_POINTS, 0, 1);
7594 }
7595 else
7596 {
7597 glDispatchCompute(1, 1, 1);
7598 }
7599 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7600
7601 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[kBufs - 1]);
7602 int* dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
7603 if (!dataout)
7604 return ERROR;
7605 bool status = true;
7606 for (int i = 0; i < kBufs - 1; ++i)
7607 {
7608 if (other_members)
7609 sizes[i] -= 1; // space consumed by a pad
7610 if (bind_seq == bindrangesize || bind_seq == bindrangeoffset)
7611 sizes[i] -= 2; // space constrained by offset of range size
7612 if ((layout == std140 || layout == std430) && dataout[i] != sizes[i])
7613 {
7614 m_context.getTestContext().getLog()
7615 << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i] << " should be "
7616 << sizes[i] << tcu::TestLog::EndMessage;
7617 status = false;
7618 }
7619 if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
7620 {
7621 m_context.getTestContext().getLog()
7622 << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i]
7623 << " should be not greater that " << sizes[i] << tcu::TestLog::EndMessage;
7624 status = false;
7625 }
7626 }
7627 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7628
7629 if (length_as_index)
7630 {
7631 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7632 dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[4][0], GL_MAP_READ_BIT);
7633 if (!dataout)
7634 return ERROR;
7635 int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
7636 if (dataout[i] != 82)
7637 {
7638 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 index " << i << " is "
7639 << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
7640 status = false;
7641 }
7642 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7643 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7644 dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[6][0], GL_MAP_READ_BIT);
7645 if (!dataout)
7646 return ERROR;
7647 i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
7648 if (dataout[i] != 82)
7649 {
7650 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 6 index " << i << " is "
7651 << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
7652 status = false;
7653 }
7654 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7655 }
7656
7657 if (!status)
7658 return ERROR;
7659
7660 return NO_ERROR;
7661 }
7662
7663 public:
7664 int stage;
7665 int etype;
7666 int layout;
7667 bool other_members;
7668 int bind_seq;
7669 bool length_as_index;
7670
AdvancedUnsizedArrayLength2()7671 AdvancedUnsizedArrayLength2()
7672 : m_program(0)
7673 , m_vertex_array(0)
7674 , stage(compute)
7675 , etype(vector)
7676 , layout(std430)
7677 , other_members(false)
7678 , bind_seq(bindbasebefore)
7679 , length_as_index(false)
7680 {
7681 for (int i = 0; i < 8; i++)
7682 {
7683 m_storage_buffer[i] = 0;
7684 }
7685 }
7686 };
7687
7688 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
7689 {
7690 public:
SetPath()7691 virtual void SetPath()
7692 {
7693 length_as_index = true;
7694 }
7695 };
7696
7697 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
7698 {
7699 public:
SetPath()7700 virtual void SetPath()
7701 {
7702 bind_seq = bindbaseafter;
7703 }
7704 };
7705
7706 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
7707 {
7708 public:
SetPath()7709 virtual void SetPath()
7710 {
7711 bind_seq = bindrangeoffset;
7712 }
7713 };
7714
7715 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
7716 {
7717 public:
SetPath()7718 virtual void SetPath()
7719 {
7720 bind_seq = bindrangesize;
7721 }
7722 };
7723
7724 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
7725 {
7726 public:
SetPath()7727 virtual void SetPath()
7728 {
7729 etype = vector;
7730 }
7731 };
7732
7733 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
7734 {
7735 public:
SetPath()7736 virtual void SetPath()
7737 {
7738 etype = matrix_cm;
7739 }
7740 };
7741
7742 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
7743 {
7744 public:
SetPath()7745 virtual void SetPath()
7746 {
7747 etype = matrix_rm;
7748 }
7749 };
7750
7751 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
7752 {
7753 public:
SetPath()7754 virtual void SetPath()
7755 {
7756 etype = structure;
7757 }
7758 };
7759
7760 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
7761 {
7762 public:
SetPath()7763 virtual void SetPath()
7764 {
7765 stage = compute;
7766 layout = std140;
7767 }
7768 };
7769
7770 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
7771 {
7772 public:
SetPath()7773 virtual void SetPath()
7774 {
7775 etype = matrix_cm;
7776 layout = std140;
7777 }
7778 };
7779
7780 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
7781 {
7782 public:
SetPath()7783 virtual void SetPath()
7784 {
7785 etype = matrix_rm;
7786 layout = std140;
7787 }
7788 };
7789
7790 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
7791 {
7792 public:
SetPath()7793 virtual void SetPath()
7794 {
7795 etype = structure;
7796 layout = std140;
7797 }
7798 };
7799
7800 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
7801 {
7802 public:
SetPath()7803 virtual void SetPath()
7804 {
7805 etype = vector;
7806 layout = packed;
7807 }
7808 };
7809
7810 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
7811 {
7812 public:
SetPath()7813 virtual void SetPath()
7814 {
7815 etype = matrix_cm;
7816 layout = packed;
7817 }
7818 };
7819
7820 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
7821 {
7822 public:
SetPath()7823 virtual void SetPath()
7824 {
7825 etype = matrix_rm;
7826 layout = shared;
7827 }
7828 };
7829
7830 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
7831 {
7832 public:
SetPath()7833 virtual void SetPath()
7834 {
7835 stage = fragment;
7836 etype = vector;
7837 layout = std430;
7838 }
7839 };
7840
7841 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7842 {
7843 public:
SetPath()7844 virtual void SetPath()
7845 {
7846 stage = fragment;
7847 etype = matrix_cm;
7848 layout = std430;
7849 other_members = true;
7850 }
7851 };
7852
7853 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
7854 {
7855 public:
SetPath()7856 virtual void SetPath()
7857 {
7858 stage = fragment;
7859 etype = matrix_rm;
7860 layout = std140;
7861 }
7862 };
7863
7864 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
7865 {
7866 public:
SetPath()7867 virtual void SetPath()
7868 {
7869 stage = fragment;
7870 etype = structure;
7871 layout = std140;
7872 }
7873 };
7874
7875 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7876 {
7877 public:
SetPath()7878 virtual void SetPath()
7879 {
7880 stage = vertex;
7881 etype = vector;
7882 layout = std430;
7883 other_members = true;
7884 }
7885 };
7886
7887 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
7888 {
7889 public:
SetPath()7890 virtual void SetPath()
7891 {
7892 stage = vertex;
7893 etype = matrix_cm;
7894 layout = std140;
7895 }
7896 };
7897
7898 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
7899 {
7900 public:
SetPath()7901 virtual void SetPath()
7902 {
7903 stage = vertex;
7904 etype = matrix_rm;
7905 layout = packed;
7906 }
7907 };
7908
7909 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
7910 {
7911 public:
SetPath()7912 virtual void SetPath()
7913 {
7914 stage = vertex;
7915 etype = structure;
7916 layout = std140;
7917 }
7918 };
7919
7920 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7921 {
7922 public:
SetPath()7923 virtual void SetPath()
7924 {
7925 etype = vector;
7926 other_members = true;
7927 }
7928 };
7929
7930 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7931 {
7932 public:
SetPath()7933 virtual void SetPath()
7934 {
7935 etype = matrix_cm;
7936 other_members = true;
7937 }
7938 };
7939
7940 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
7941 {
7942 public:
SetPath()7943 virtual void SetPath()
7944 {
7945 etype = matrix_rm;
7946 layout = std140;
7947 other_members = true;
7948 }
7949 };
7950
7951 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
7952 {
7953 public:
SetPath()7954 virtual void SetPath()
7955 {
7956 etype = structure;
7957 other_members = true;
7958 }
7959 };
7960
7961 //-----------------------------------------------------------------------------
7962 // 2.8 AdvancedMatrix
7963 //-----------------------------------------------------------------------------
7964 class AdvancedMatrixVSFS : public ShaderStorageBufferObjectBase
7965 {
7966 GLuint m_program;
7967 GLuint m_storage_buffer[3];
7968 GLuint m_vertex_array;
7969 GLuint m_vertex_buffer;
7970 GLuint m_fbo, m_rt;
7971
Setup()7972 virtual long Setup()
7973 {
7974 m_program = 0;
7975 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7976 m_vertex_array = 0;
7977 m_vertex_buffer = 0;
7978 glGenFramebuffers(1, &m_fbo);
7979 glGenTextures(1, &m_rt);
7980 return NO_ERROR;
7981 }
7982
Run()7983 virtual long Run()
7984 {
7985 if (!IsVSFSAvailable(2, 2))
7986 return NOT_SUPPORTED;
7987 const char* const glsl_vs =
7988 NL "layout(location = 0) in vec4 g_position;" NL "flat out int instance_id;" NL
7989 "layout(binding = 0, std430) coherent buffer Buffer0 {" NL " mat3x4 g_transform[4];" NL
7990 " mat4x3 g_color;" NL " mat3 g_data0;" NL "};" NL
7991 "layout(binding = 1, std430) readonly buffer Buffer1 {" NL " mat4 color;" NL "} g_buffer1;" NL
7992 "uniform int g_index1;" NL "uniform int g_index2;" NL "void main() {" NL
7993 " gl_Position = vec4(transpose(g_transform[gl_InstanceID]) * g_position, 1);" NL
7994 " g_color[gl_InstanceID] = g_buffer1.color[gl_InstanceID].rgb;" NL
7995 " if (gl_VertexID == 0 && gl_InstanceID == 0) {" NL " g_data0[1][1] = 1.0;" NL
7996 " g_data0[g_index1][g_index2] += 3.0;" NL " }" NL " memoryBarrier();" NL
7997 " instance_id = gl_InstanceID;" NL "}";
7998 const char* const glsl_fs =
7999 NL "flat in int instance_id;" NL "layout(location = 0) out vec4 g_ocolor;" NL
8000 "layout(binding = 0, std430) coherent buffer Buffer0 {" NL " mat3x4 g_transform[4];" NL
8001 " mat4x3 g_color;" NL " mat3 g_data0;" NL "};" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8002 "void main() {" NL " if (g_data0[g_index1][g_index1] != 1.0) g_ocolor = vec4(0);" NL
8003 " else if (g_data0[g_index1][g_index2] != 3.0) g_ocolor = vec4(0);" NL
8004 " else g_ocolor = vec4(g_color[instance_id], 1);" NL "}";
8005 m_program = CreateProgram(glsl_vs, glsl_fs);
8006 glLinkProgram(m_program);
8007 if (!CheckProgram(m_program))
8008 return ERROR;
8009
8010 glGenBuffers(3, m_storage_buffer);
8011
8012 /* transform buffer */
8013 {
8014 float data[48 + 16 + 12 + 16] = {
8015 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,
8016 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,
8017 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,
8018 };
8019 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
8020 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8021 }
8022 /* transform buffer */
8023 {
8024 float data[16] = {
8025 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,
8026 };
8027 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
8028 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8029 }
8030 /* vertex buffer */
8031 {
8032 float data[8] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
8033 glGenBuffers(1, &m_vertex_buffer);
8034 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8035 glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8036 glBindBuffer(GL_ARRAY_BUFFER, 0);
8037 }
8038
8039 glBindTexture(GL_TEXTURE_2D, m_rt);
8040 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8041 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8042 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
8043 glBindTexture(GL_TEXTURE_2D, 0);
8044 glViewport(0, 0, 100, 100);
8045 glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
8046 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
8047
8048 glGenVertexArrays(1, &m_vertex_array);
8049 glBindVertexArray(m_vertex_array);
8050 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8051 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
8052 glBindBuffer(GL_ARRAY_BUFFER, 0);
8053 glEnableVertexAttribArray(0);
8054 glBindVertexArray(0);
8055
8056 glClear(GL_COLOR_BUFFER_BIT);
8057 glUseProgram(m_program);
8058 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8059 glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8060
8061 glBindVertexArray(m_vertex_array);
8062 glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
8063 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)))
8064 {
8065 return ERROR;
8066 }
8067 return NO_ERROR;
8068 }
8069
Cleanup()8070 virtual long Cleanup()
8071 {
8072 glViewport(0, 0, getWindowWidth(), getWindowHeight());
8073 glUseProgram(0);
8074 glDeleteProgram(m_program);
8075 glDeleteBuffers(3, m_storage_buffer);
8076 glDeleteBuffers(1, &m_vertex_buffer);
8077 glDeleteVertexArrays(1, &m_vertex_array);
8078 glDeleteFramebuffers(1, &m_fbo);
8079 glDeleteTextures(1, &m_rt);
8080 return NO_ERROR;
8081 }
8082 };
8083
8084 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8085 {
8086 GLuint m_program;
8087 GLuint m_storage_buffer;
8088
Setup()8089 virtual long Setup()
8090 {
8091 m_program = 0;
8092 m_storage_buffer = 0;
8093 return NO_ERROR;
8094 }
8095
Run()8096 virtual long Run()
8097 {
8098 bool status = true;
8099 const char* const glsl_cs =
8100 NL "layout(local_size_x = 1) in;" NL "layout(std430) buffer Buffer {" NL " mat4x3 dst4x3;" NL
8101 " mat4 dst4;" NL " mat4 src4;" NL "} b;" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8102 "void main() {" NL " b.dst4x3[gl_LocalInvocationIndex] = b.src4[gl_LocalInvocationIndex].rgb;" NL
8103 " b.dst4x3[gl_LocalInvocationIndex + 1u] = b.src4[gl_LocalInvocationIndex + 1u].aar;" NL
8104 " b.dst4[g_index2][g_index1] = 17.0;" NL " b.dst4[g_index2][g_index1] += 6.0;" NL
8105 " b.dst4[3][0] = b.src4[3][0] != 44.0 ? 3.0 : 7.0;" NL " b.dst4[3][1] = b.src4[3][1];" NL "}";
8106 m_program = CreateProgramCS(glsl_cs);
8107 glLinkProgram(m_program);
8108 if (!CheckProgram(m_program))
8109 return ERROR;
8110
8111 glGenBuffers(1, &m_storage_buffer);
8112 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
8113 GLfloat data[16 + 16 + 16];
8114 for (int i = 0; i < 32; ++i)
8115 data[i] = 0.0f;
8116 for (int i = 32; i < 48; ++i)
8117 data[i] = (GLfloat)i;
8118 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
8119
8120 glUseProgram(m_program);
8121 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8122 glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8123 glDispatchCompute(1, 1, 1);
8124 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8125 GLfloat* out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
8126 if (!out_data)
8127 return ERROR;
8128 GLfloat expected[32] = { 32.0f, 33.0f, 34.0f, 0.0f, 39.0f, 39.0f, 36.0f, 0.0f,
8129 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
8130
8131 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
8132 0.0f, 23.0f, 0.0f, 0.0f, 7.0f, 45.0f, 0.0f, 0.0f };
8133 for (int i = 0; i < 32; ++i)
8134 {
8135 if (out_data[i] != expected[i])
8136 {
8137 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i]
8138 << ", but expected: " << expected[i] << tcu::TestLog::EndMessage;
8139 status = false;
8140 }
8141 }
8142 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8143 if (status)
8144 return NO_ERROR;
8145 else
8146 return ERROR;
8147 }
8148
Cleanup()8149 virtual long Cleanup()
8150 {
8151 glUseProgram(0);
8152 glDeleteProgram(m_program);
8153 glDeleteBuffers(1, &m_storage_buffer);
8154 return NO_ERROR;
8155 }
8156 };
8157
8158 //-----------------------------------------------------------------------------
8159 // 4.1.1 NegativeAPIBind
8160 //-----------------------------------------------------------------------------
8161 class NegativeAPIBind : public ShaderStorageBufferObjectBase
8162 {
Run()8163 virtual long Run()
8164 {
8165 GLint bindings;
8166 GLint alignment;
8167 GLuint buffer;
8168 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8169 m_context.getTestContext().getLog()
8170 << tcu::TestLog::Message << "Max storage buffer bindings " << bindings << tcu::TestLog::EndMessage;
8171 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
8172 m_context.getTestContext().getLog()
8173 << tcu::TestLog::Message << "Storage buffer offset alignment " << alignment << tcu::TestLog::EndMessage;
8174
8175 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8176 if (glGetError() != GL_INVALID_VALUE)
8177 {
8178 m_context.getTestContext().getLog()
8179 << tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8180 << "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8181 << "MAX_SHADER_STORAGE_BUFFER_BINDINGS." << tcu::TestLog::EndMessage;
8182 return ERROR;
8183 }
8184
8185 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8186 if (glGetError() != GL_INVALID_VALUE)
8187 {
8188 m_context.getTestContext().getLog()
8189 << tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8190 << "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8191 << "MAX_SHADER_STORAGE_BUFFER_BINDINGS." << tcu::TestLog::EndMessage;
8192 return ERROR;
8193 }
8194
8195 glGenBuffers(1, &buffer);
8196 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, alignment - 1, 0);
8197 if (glGetError() != GL_INVALID_VALUE)
8198 {
8199 m_context.getTestContext().getLog()
8200 << tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8201 << "SHADER_STORAGE_BUFFER and <offset> is not a multiple of the value of\n"
8202 << "SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT." << tcu::TestLog::EndMessage;
8203 return ERROR;
8204 }
8205
8206 return NO_ERROR;
8207 }
8208 };
8209
8210 //-----------------------------------------------------------------------------
8211 // 4.2.1 NegativeGLSLCompileTime
8212 //-----------------------------------------------------------------------------
8213 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8214 {
Shader1(int binding)8215 static std::string Shader1(int binding)
8216 {
8217 std::stringstream ss;
8218 ss << NL "layout(binding = " << binding
8219 << ") buffer Buffer {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}";
8220 return ss.str();
8221 }
8222
Shader2(int binding)8223 static std::string Shader2(int binding)
8224 {
8225 std::stringstream ss;
8226 ss << NL "layout(binding = " << binding
8227 << ") buffer Buffer {" NL " int x;" NL "} g_array[4];" NL "void main() {" NL " g_array[0].x = 0;" NL
8228 " g_array[1].x = 0;" NL " g_array[2].x = 0;" NL " g_array[3].x = 0;" NL "}";
8229 return ss.str();
8230 }
8231
Run()8232 virtual long Run()
8233 {
8234 GLint bindings;
8235 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8236
8237 // initialization of buffer block member 'x' not allowed
8238 if (!Compile(NL "buffer Buffer { int x = 10; };" NL "void main() {" NL " x = 0;" NL "}"))
8239 return ERROR;
8240
8241 // syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8242 if (!Compile(Shader1(-1)))
8243 return ERROR;
8244 // invalid value 96 for layout specifier 'binding'
8245 if (!Compile(Shader1(bindings)))
8246 return ERROR;
8247
8248 // invalid value 98 for layout specifier 'binding'
8249 if (!Compile(Shader2(bindings - 2)))
8250 return ERROR;
8251
8252 // OpenGL does not allow declaring buffer variable 'x' in the global scope. Use buffer blocks instead
8253 if (!Compile(NL "buffer int x;" NL "void main() {" NL " x = 0;" NL "}"))
8254 return ERROR;
8255
8256 // OpenGL requires buffer variables to be declared in a shader storage block in the global scope
8257 if (!Compile(NL "buffer Buffer { int y; };" NL "void main() {" NL " y = 0;" NL " buffer int x = 0;" NL "}"))
8258 return ERROR;
8259
8260 // OpenGL does not allow a parameter to be a buffer
8261 if (!Compile(NL "buffer Buffer { int y; };" NL "void Modify(buffer int a) {" NL " atomicAdd(a, 1);" NL "}" NL
8262 "void main() {" NL " Modify(y);" NL "}"))
8263 return ERROR;
8264
8265 // layout specifier 'std430', incompatible with 'uniform blocks'
8266 if (!Compile(NL "layout(std430) uniform UBO { int x; };" NL "buffer SSBO { int y; };" NL "void main() {" NL
8267 " y = x;" NL "}"))
8268 return ERROR;
8269
8270 // unknown layout specifier 'std430'
8271 if (!Compile(NL "buffer SSBO {" NL " layout(std430) int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}"))
8272 return ERROR;
8273
8274 // unknown layout specifier 'binding = 1'
8275 if (!Compile(NL "buffer SSBO {" NL " layout(binding = 1) int x;" NL "};" NL "void main() {" NL " x = 0;" NL
8276 "}"))
8277 return ERROR;
8278
8279 // OpenGL does not allow writing to readonly variable 'x'
8280 if (!Compile(NL "readonly buffer SSBO {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}"))
8281 return ERROR;
8282
8283 // OpenGL does not allow reading writeonly variable 'y'
8284 if (!Compile(NL "buffer SSBO {" NL " int x;" NL "};" NL "writeonly buffer SSBO2 {" NL " int y;" NL "};" NL
8285 "void main() {" NL " x = y;" NL "}"))
8286 return ERROR;
8287
8288 // OpenGL does not allow writing to readonly variable 'z'
8289 if (!Compile(NL "buffer SSBO {" NL " int x;" NL "};" NL "buffer SSBO2 {" NL " writeonly int y;" NL
8290 " readonly int z;" NL "};" NL "void main() {" NL " x = y;" NL " z = 0;" NL "}"))
8291 return ERROR;
8292
8293 // OpenGL does not allow having both readonly and writeonly qualifiers on a variable
8294 if (!Compile(NL "buffer SSBO {" NL " int x;" NL "};" NL "readonly buffer SSBO2 {" NL " writeonly int y;" NL
8295 "};" NL "void main() {" NL " x = y;" NL "}"))
8296 return ERROR;
8297
8298 // ["layout(binding = 1) buffer;" should cause compile-time error
8299 if (!Compile(NL "layout(binding = 1) buffer;" //
8300 NL "buffer SSBO {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}"))
8301 return ERROR;
8302
8303 // [" atomicAdd(y, 2);" should cause compile-time error
8304 if (!Compile(NL "buffer coherent Buffer { int x; };" NL "int y;" NL "void main() {" NL " atomicAdd(x, 1);" NL
8305 " atomicAdd(y, 2);" //
8306 NL "}"))
8307 return ERROR;
8308
8309 if (!Compile( // can't construct vector from an array
8310 NL "buffer b {" NL " vec4 x[10];" NL "};" NL "void main() {" NL " vec4 y = vec4(x);" NL "}"))
8311 return ERROR;
8312
8313 if (!Compile( // ESSL31 does not allow dynamically uniform indexing of SSBO arrays
8314 NL "layout(std430, binding = 0) buffer Input {" NL " float data0;" NL "} g_input[4];" NL
8315 "layout(std430, binding = 4) buffer Output {" NL " float data0;" NL "} g_output[4];" NL
8316 "void main() {" NL " for (int i = 0; i < 4; ++i) {" NL
8317 " g_output[i].data0 = g_input[i].data0;" NL " }" NL "}"))
8318 return ERROR;
8319
8320 if (!Compile( // ESSL31 does not allow dynamically uniform indexing of SSBO arrays
8321 NL "layout(binding = 0, std430) buffer Material {" NL " vec3 color;" NL "} g_material[4];" NL
8322 "layout(binding = 4, std430) buffer OutputBuffer {" NL " vec3 color[4];" NL "};" NL
8323 "uniform int g_material_id;" NL "void main() {" NL
8324 " color[gl_LocalInvocationIndex] = vec3(g_material[g_material_id].color);" NL "}"))
8325 return ERROR;
8326
8327 return NO_ERROR;
8328 }
Compile(const std::string & source)8329 bool Compile(const std::string& source)
8330 {
8331 const char* const csVer = "#version 310 es" NL "layout(local_size_x = 1) in;";
8332 const char* const src[2] = { csVer, source.c_str() };
8333 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
8334 glShaderSource(sh, 2, src, NULL);
8335 glCompileShader(sh);
8336
8337 GLchar log[1024];
8338 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8339 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
8340 << log << tcu::TestLog::EndMessage;
8341
8342 GLint status;
8343 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8344 glDeleteShader(sh);
8345
8346 if (status == GL_TRUE)
8347 {
8348 m_context.getTestContext().getLog()
8349 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
8350 return false;
8351 }
8352
8353 return true;
8354 }
8355 };
8356
8357 //-----------------------------------------------------------------------------
8358 // 4.2.2 NegativeGLSLLinkTime
8359 //-----------------------------------------------------------------------------
8360 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8361 {
Run()8362 virtual long Run()
8363 {
8364 if (!IsVSFSAvailable(1, 1))
8365 return NOT_SUPPORTED;
8366 if (!Link("#version 310 es" NL "buffer Buffer { int x; };" NL "void main() {" NL " x += 2;" NL "}",
8367 "#version 310 es" NL "precision highp float;" NL "buffer Buffer { uint x; };" NL "void main() {" NL
8368 " x += 3u;" NL "}"))
8369 return ERROR;
8370
8371 if (!Link("#version 310 es" NL "buffer Buffer { int x; int y; };" NL "void main() {" NL " x += 2;" NL "}",
8372 "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x; };" NL "void main() {" NL
8373 " x += 3;" NL "}"))
8374 return ERROR;
8375
8376 if (!Link("#version 310 es" NL "buffer Buffer { int y; };" NL "void main() {" NL " y += 2;" NL "}",
8377 "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x; };" NL "void main() {" NL
8378 " x += 3;" NL "}"))
8379 return ERROR;
8380
8381 if (!Link("#version 310 es" NL "buffer Buffer { int x[2]; };" NL "void main() {" NL " x[1] += 2;" NL "}",
8382 "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x[3]; };" NL "void main() {" NL
8383 " x[1] += 3;" NL "}"))
8384 return ERROR;
8385
8386 return NO_ERROR;
8387 }
Link(const std::string & cs0,const std::string & cs1)8388 bool Link(const std::string& cs0, const std::string& cs1)
8389 {
8390 const GLuint p = glCreateProgram();
8391
8392 /* shader 0 */
8393 {
8394 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8395 glAttachShader(p, sh);
8396 glDeleteShader(sh);
8397 const char* const src = cs0.c_str();
8398 glShaderSource(sh, 1, &src, NULL);
8399 glCompileShader(sh);
8400
8401 GLint status;
8402 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8403 if (status == GL_FALSE)
8404 {
8405 m_context.getTestContext().getLog()
8406 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
8407 CheckProgram(p);
8408 glDeleteProgram(p);
8409 return false;
8410 }
8411 }
8412 /* shader 1 */
8413 {
8414 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8415 glAttachShader(p, sh);
8416 glDeleteShader(sh);
8417 const char* const src = cs1.c_str();
8418 glShaderSource(sh, 1, &src, NULL);
8419 glCompileShader(sh);
8420
8421 GLint status;
8422 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8423 if (status == GL_FALSE)
8424 {
8425 m_context.getTestContext().getLog()
8426 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
8427 CheckProgram(p);
8428 glDeleteProgram(p);
8429 return false;
8430 }
8431 }
8432
8433 glLinkProgram(p);
8434
8435 GLchar log[1024];
8436 glGetProgramInfoLog(p, sizeof(log), NULL, log);
8437 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
8438 << log << tcu::TestLog::EndMessage;
8439
8440 GLint status;
8441 glGetProgramiv(p, GL_LINK_STATUS, &status);
8442 glDeleteProgram(p);
8443
8444 if (status == GL_TRUE)
8445 {
8446 m_context.getTestContext().getLog()
8447 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
8448 return false;
8449 }
8450
8451 return true;
8452 }
8453 };
8454 } // anonymous namespace
8455
ShaderStorageBufferObjectTests(deqp::Context & context)8456 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context& context)
8457 : TestCaseGroup(context, "shader_storage_buffer_object", "")
8458 {
8459 }
8460
~ShaderStorageBufferObjectTests(void)8461 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
8462 {
8463 }
8464
init()8465 void ShaderStorageBufferObjectTests::init()
8466 {
8467 using namespace deqp;
8468 addChild(new TestSubcase(m_context, "basic-basic-vs", TestSubcase::Create<BasicBasicVS>));
8469 addChild(new TestSubcase(m_context, "basic-basic-cs", TestSubcase::Create<BasicBasicCS>));
8470 addChild(new TestSubcase(m_context, "basic-max", TestSubcase::Create<BasicMax>));
8471 addChild(new TestSubcase(m_context, "basic-binding", TestSubcase::Create<BasicBinding>));
8472 addChild(new TestSubcase(m_context, "basic-syntax-vs", TestSubcase::Create<BasicSyntaxVS>));
8473 addChild(new TestSubcase(m_context, "basic-syntax-cs", TestSubcase::Create<BasicSyntaxCS>));
8474 addChild(new TestSubcase(m_context, "basic-syntaxSSO", TestSubcase::Create<BasicSyntaxSSO>));
8475 addChild(new TestSubcase(m_context, "basic-std430Layout-case1-vs", TestSubcase::Create<BasicStd430LayoutCase1VS>));
8476 addChild(new TestSubcase(m_context, "basic-std430Layout-case1-cs", TestSubcase::Create<BasicStd430LayoutCase1CS>));
8477 addChild(new TestSubcase(m_context, "basic-std430Layout-case2-vs", TestSubcase::Create<BasicStd430LayoutCase2VS>));
8478 addChild(new TestSubcase(m_context, "basic-std430Layout-case2-cs", TestSubcase::Create<BasicStd430LayoutCase2CS>));
8479 addChild(new TestSubcase(m_context, "basic-std430Layout-case3-vs", TestSubcase::Create<BasicStd430LayoutCase3VS>));
8480 addChild(new TestSubcase(m_context, "basic-std430Layout-case3-cs", TestSubcase::Create<BasicStd430LayoutCase3CS>));
8481 addChild(new TestSubcase(m_context, "basic-std430Layout-case4-vs", TestSubcase::Create<BasicStd430LayoutCase4VS>));
8482 addChild(new TestSubcase(m_context, "basic-std430Layout-case4-cs", TestSubcase::Create<BasicStd430LayoutCase4CS>));
8483 addChild(new TestSubcase(m_context, "basic-std430Layout-case5-vs", TestSubcase::Create<BasicStd430LayoutCase5VS>));
8484 addChild(new TestSubcase(m_context, "basic-std430Layout-case5-cs", TestSubcase::Create<BasicStd430LayoutCase5CS>));
8485 addChild(new TestSubcase(m_context, "basic-std430Layout-case6-vs", TestSubcase::Create<BasicStd430LayoutCase6VS>));
8486 addChild(new TestSubcase(m_context, "basic-std430Layout-case6-cs", TestSubcase::Create<BasicStd430LayoutCase6CS>));
8487 addChild(new TestSubcase(m_context, "basic-std430Layout-case7-vs", TestSubcase::Create<BasicStd430LayoutCase7VS>));
8488 addChild(new TestSubcase(m_context, "basic-std430Layout-case7-cs", TestSubcase::Create<BasicStd430LayoutCase7CS>));
8489 addChild(new TestSubcase(m_context, "basic-std140Layout-case1-vs", TestSubcase::Create<BasicStd140LayoutCase1VS>));
8490 addChild(new TestSubcase(m_context, "basic-std140Layout-case1-cs", TestSubcase::Create<BasicStd140LayoutCase1CS>));
8491 addChild(new TestSubcase(m_context, "basic-std140Layout-case2-vs", TestSubcase::Create<BasicStd140LayoutCase2VS>));
8492 addChild(new TestSubcase(m_context, "basic-std140Layout-case2-cs", TestSubcase::Create<BasicStd140LayoutCase2CS>));
8493 addChild(new TestSubcase(m_context, "basic-std140Layout-case3-vs", TestSubcase::Create<BasicStd140LayoutCase3VS>));
8494 addChild(new TestSubcase(m_context, "basic-std140Layout-case3-cs", TestSubcase::Create<BasicStd140LayoutCase3CS>));
8495 addChild(new TestSubcase(m_context, "basic-std140Layout-case4-vs", TestSubcase::Create<BasicStd140LayoutCase4VS>));
8496 addChild(new TestSubcase(m_context, "basic-std140Layout-case4-cs", TestSubcase::Create<BasicStd140LayoutCase4CS>));
8497 addChild(new TestSubcase(m_context, "basic-std140Layout-case5-vs", TestSubcase::Create<BasicStd140LayoutCase5VS>));
8498 addChild(new TestSubcase(m_context, "basic-std140Layout-case5-cs", TestSubcase::Create<BasicStd140LayoutCase5CS>));
8499 addChild(new TestSubcase(m_context, "basic-std140Layout-case6-vs", TestSubcase::Create<BasicStd140LayoutCase6VS>));
8500 addChild(new TestSubcase(m_context, "basic-std140Layout-case6-cs", TestSubcase::Create<BasicStd140LayoutCase6CS>));
8501 addChild(new TestSubcase(m_context, "basic-atomic-case1-vsfs", TestSubcase::Create<BasicAtomicCase1VSFS>));
8502 addChild(new TestSubcase(m_context, "basic-atomic-case1-cs", TestSubcase::Create<BasicAtomicCase1CS>));
8503 addChild(new TestSubcase(m_context, "basic-atomic-case3-vsfs", TestSubcase::Create<BasicAtomicCase3VSFS>));
8504 addChild(new TestSubcase(m_context, "basic-atomic-case3-cs", TestSubcase::Create<BasicAtomicCase3CS>));
8505 addChild(new TestSubcase(m_context, "basic-atomic-case4-vsfs", TestSubcase::Create<BasicAtomicCase4VSFS>));
8506 addChild(new TestSubcase(m_context, "basic-atomic-case4-cs", TestSubcase::Create<BasicAtomicCase4CS>));
8507 addChild(new TestSubcase(m_context, "basic-stdLayout-case1-vs", TestSubcase::Create<BasicStdLayoutCase1VS>));
8508 addChild(new TestSubcase(m_context, "basic-stdLayout-case1-cs", TestSubcase::Create<BasicStdLayoutCase1CS>));
8509 addChild(new TestSubcase(m_context, "basic-stdLayout-case2-vs", TestSubcase::Create<BasicStdLayoutCase2VS>));
8510 addChild(new TestSubcase(m_context, "basic-stdLayout-case2-cs", TestSubcase::Create<BasicStdLayoutCase2CS>));
8511 addChild(new TestSubcase(m_context, "basic-stdLayout-case3-vs", TestSubcase::Create<BasicStdLayoutCase3VS>));
8512 addChild(new TestSubcase(m_context, "basic-stdLayout-case3-cs", TestSubcase::Create<BasicStdLayoutCase3CS>));
8513 addChild(new TestSubcase(m_context, "basic-stdLayout-case4-vs", TestSubcase::Create<BasicStdLayoutCase4VS>));
8514 addChild(new TestSubcase(m_context, "basic-stdLayout-case4-cs", TestSubcase::Create<BasicStdLayoutCase4CS>));
8515 addChild(new TestSubcase(m_context, "basic-operations-case1-vs", TestSubcase::Create<BasicOperationsCase1VS>));
8516 addChild(new TestSubcase(m_context, "basic-operations-case1-cs", TestSubcase::Create<BasicOperationsCase1CS>));
8517 addChild(new TestSubcase(m_context, "basic-operations-case2-vs", TestSubcase::Create<BasicOperationsCase2VS>));
8518 addChild(new TestSubcase(m_context, "basic-operations-case2-cs", TestSubcase::Create<BasicOperationsCase2CS>));
8519 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-vs",
8520 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1VS>));
8521 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-cs",
8522 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1CS>));
8523 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-vs",
8524 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2VS>));
8525 addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-cs",
8526 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2CS>));
8527 addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-vs",
8528 TestSubcase::Create<BasicMatrixOperationsCase1VS>));
8529 addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-cs",
8530 TestSubcase::Create<BasicMatrixOperationsCase1CS>));
8531 addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-vs",
8532 TestSubcase::Create<BasicMatrixOperationsCase2VS>));
8533 addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-cs",
8534 TestSubcase::Create<BasicMatrixOperationsCase2CS>));
8535 addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-vs",
8536 TestSubcase::Create<BasicMatrixOperationsCase3VS>));
8537 addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-cs",
8538 TestSubcase::Create<BasicMatrixOperationsCase3CS>));
8539 addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-vs",
8540 TestSubcase::Create<BasicMatrixOperationsCase4VS>));
8541 addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-cs",
8542 TestSubcase::Create<BasicMatrixOperationsCase4CS>));
8543 addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-vs",
8544 TestSubcase::Create<BasicMatrixOperationsCase5VS>));
8545 addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-cs",
8546 TestSubcase::Create<BasicMatrixOperationsCase5CS>));
8547 addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-vs",
8548 TestSubcase::Create<BasicMatrixOperationsCase6VS>));
8549 addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-cs",
8550 TestSubcase::Create<BasicMatrixOperationsCase6CS>));
8551 addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-vs",
8552 TestSubcase::Create<BasicMatrixOperationsCase7VS>));
8553 addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-cs",
8554 TestSubcase::Create<BasicMatrixOperationsCase7CS>));
8555 addChild(new TestSubcase(m_context, "advanced-switchBuffers-vs", TestSubcase::Create<AdvancedSwitchBuffersVS>));
8556 addChild(new TestSubcase(m_context, "advanced-switchBuffers-cs", TestSubcase::Create<AdvancedSwitchBuffersCS>));
8557 addChild(new TestSubcase(m_context, "advanced-switchPrograms-vs", TestSubcase::Create<AdvancedSwitchProgramsVS>));
8558 addChild(new TestSubcase(m_context, "advanced-switchPrograms-cs", TestSubcase::Create<AdvancedSwitchProgramsCS>));
8559 addChild(new TestSubcase(m_context, "advanced-write-fragment-fs", TestSubcase::Create<AdvancedWriteFragmentFS>));
8560 addChild(new TestSubcase(m_context, "advanced-write-fragment-cs", TestSubcase::Create<AdvancedWriteFragmentCS>));
8561 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-vs",
8562 TestSubcase::Create<AdvancedIndirectAddressingCase1VS>));
8563 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-cs",
8564 TestSubcase::Create<AdvancedIndirectAddressingCase1CS>));
8565 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-vsfs",
8566 TestSubcase::Create<AdvancedIndirectAddressingCase2VSFS>));
8567 addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-cs",
8568 TestSubcase::Create<AdvancedIndirectAddressingCase2CS>));
8569 addChild(
8570 new TestSubcase(m_context, "advanced-readWrite-case1-vsfs", TestSubcase::Create<AdvancedReadWriteCase1VSFS>));
8571 addChild(new TestSubcase(m_context, "advanced-readWrite-case1-cs", TestSubcase::Create<AdvancedReadWriteCase1CS>));
8572 addChild(new TestSubcase(m_context, "advanced-usage-case1", TestSubcase::Create<AdvancedUsageCase1>));
8573 addChild(new TestSubcase(m_context, "advanced-usage-sync-vsfs", TestSubcase::Create<AdvancedUsageSyncVSFS>));
8574 addChild(new TestSubcase(m_context, "advanced-usage-sync-cs", TestSubcase::Create<AdvancedUsageSyncCS>));
8575 addChild(new TestSubcase(m_context, "advanced-usage-operators-vs", TestSubcase::Create<AdvancedUsageOperatorsVS>));
8576 addChild(new TestSubcase(m_context, "advanced-usage-operators-cs", TestSubcase::Create<AdvancedUsageOperatorsCS>));
8577 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-int",
8578 TestSubcase::Create<AdvancedUnsizedArrayLength<compute> >));
8579 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-int",
8580 TestSubcase::Create<AdvancedUnsizedArrayLength<fragment> >));
8581 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-int",
8582 TestSubcase::Create<AdvancedUnsizedArrayLength<vertex> >));
8583 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec",
8584 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec>));
8585 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC",
8586 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC>));
8587 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matR",
8588 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matR>));
8589 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct",
8590 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct>));
8591 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-vec",
8592 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_vec>));
8593 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matC",
8594 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matC>));
8595 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR",
8596 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR>));
8597 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-struct",
8598 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_struct>));
8599 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-vec",
8600 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_vec>));
8601 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-matC",
8602 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_matC>));
8603 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-shared-matR",
8604 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_shared_matR>));
8605 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-vec",
8606 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_vec>));
8607 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-matC-pad",
8608 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_matC_pad>));
8609 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-matR",
8610 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_matR>));
8611 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-struct",
8612 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_struct>));
8613 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std430-vec",
8614 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std430_vec_pad>));
8615 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-matC",
8616 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_matC>));
8617 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-packed-matR",
8618 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_packed_matR>));
8619 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-struct",
8620 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_struct>));
8621 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-pad",
8622 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_pad>));
8623 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC-pad",
8624 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC_pad>));
8625 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR-pad",
8626 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR_pad>));
8627 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct-pad",
8628 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct_pad>));
8629
8630 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
8631 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
8632
8633 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
8634 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
8635
8636 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
8637 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
8638
8639 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
8640 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
8641
8642 addChild(new TestSubcase(m_context, "advanced-matrix-vsfs", TestSubcase::Create<AdvancedMatrixVSFS>));
8643 addChild(new TestSubcase(m_context, "advanced-matrix-cs", TestSubcase::Create<AdvancedMatrixCS>));
8644 addChild(new TestSubcase(m_context, "negative-api-bind", TestSubcase::Create<NegativeAPIBind>));
8645 addChild(new TestSubcase(m_context, "negative-glsl-compileTime", TestSubcase::Create<NegativeGLSLCompileTime>));
8646 addChild(new TestSubcase(m_context, "negative-glsl-linkTime", TestSubcase::Create<NegativeGLSLLinkTime>));
8647 }
8648
8649 } // namespace es31compatibility
8650 } // namespace gl4cts
8651