1fcdeb20a61e3f3b152a6dbfc6f4feea471aa25e
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gles32 / es32cRobustBufferAccessBehaviorTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 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 /**
25  * \file  es32cRobustBufferAccessBehaviorTests.cpp
26  * \brief Implements conformance tests for "Robust Buffer Access Behavior" functionality.
27  */ /*-------------------------------------------------------------------*/
28
29 #include "es32cRobustBufferAccessBehaviorTests.hpp"
30
31 #include "gluDefs.hpp"
32 #include "gluStrUtil.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuTestLog.hpp"
36
37 #include <cstring>
38 #include <string>
39
40 using namespace glw;
41 using namespace deqp::RobustBufferAccessBehavior;
42
43 namespace es32cts
44 {
45 namespace RobustBufferAccessBehavior
46 {
47 /** Constructor
48  *
49  * @param context Test context
50  **/
51 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context)
52         : deqp::RobustBufferAccessBehavior::VertexBufferObjectsTest(
53                   context, "vertex_buffer_objects", "Verifies that out-of-bound reads from VB result in zero")
54 {
55         /* Nothing to be done */
56 }
57
58 /** Execute test
59  *
60  * @return tcu::TestNode::STOP
61  **/
62 tcu::TestNode::IterateResult VertexBufferObjectsTest::iterate()
63 {
64         return deqp::RobustBufferAccessBehavior::VertexBufferObjectsTest::iterate();
65 }
66
67 /** Prepare shader for current test case
68  *
69  * @return Source
70  **/
71 std::string VertexBufferObjectsTest::getFragmentShader()
72 {
73         return std::string("#version 320 es\n"
74                                            "\n"
75                                            "layout (location = 0) out lowp uvec4 out_fs_color;\n"
76                                            "\n"
77                                            "void main()\n"
78                                            "{\n"
79                                            "    out_fs_color = uvec4(1, 255, 255, 255);\n"
80                                            "}\n"
81                                            "\n");
82 }
83
84 /** Prepare shader for current test case
85  *
86  * @return Source
87  **/
88 std::string VertexBufferObjectsTest::getVertexShader()
89 {
90         return std::string("#version 320 es\n"
91                                            "\n"
92                                            "layout (location = 0) in vec4 in_vs_position;\n"
93                                            "\n"
94                                            "void main()\n"
95                                            "{\n"
96                                            "    gl_Position = in_vs_position;\n"
97                                            "}\n"
98                                            "\n");
99 }
100
101 /** No verification because of undefined out-of-bound behavior in OpenGL ES
102  *
103  * @param texture_id Id of texture
104  *
105  * @return true
106  **/
107 bool VertexBufferObjectsTest::verifyInvalidResults(glw::GLuint texture_id)
108 {
109         (void)texture_id;
110         return true;
111 }
112
113 /** Verifies that texutre is filled with 1
114  *
115  * @param texture_id Id of texture
116  *
117  * @return true when image is filled with 1, false otherwise
118  **/
119 bool VertexBufferObjectsTest::verifyResults(glw::GLuint texture_id)
120 {
121         static const GLuint height       = 8;
122         static const GLuint width         = 8;
123         static const GLuint pixel_size = 4 * sizeof(GLuint);
124
125         const Functions& gl = m_context.getRenderContext().getFunctions();
126
127         const GLint buf_size = width * height * pixel_size;
128         GLubyte         pixels[buf_size];
129         deMemset(pixels, 0, buf_size);
130
131         Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
132
133         Texture::GetData(gl, texture_id, 0 /* level */, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, pixels);
134
135         /* Unbind */
136         Texture::Bind(gl, 0, GL_TEXTURE_2D);
137
138         /* Verify */
139         for (GLuint i = 0; i < buf_size; i += pixel_size)
140         {
141                 if (1 != pixels[i])
142                 {
143                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
144                                                                                                 << " at offset: " << i << tcu::TestLog::EndMessage;
145
146                         return false;
147                 }
148         }
149
150         return true;
151 }
152
153 /** Constructor
154  *
155  * @param context Test context
156  **/
157 TexelFetchTest::TexelFetchTest(deqp::Context& context)
158         : deqp::RobustBufferAccessBehavior::TexelFetchTest(context, "texel_fetch",
159                                                                                                            "Verifies that out-of-bound fetches from texture result in zero")
160 {
161         /* Nothing to be done */
162 }
163
164 TexelFetchTest::TexelFetchTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
165         : deqp::RobustBufferAccessBehavior::TexelFetchTest(context, name, description)
166 {
167         /* Nothing to be done */
168 }
169
170 /** Execute test
171  *
172  * @return tcu::TestNode::STOP
173  **/
174 tcu::TestNode::IterateResult TexelFetchTest::iterate()
175 {
176         return deqp::RobustBufferAccessBehavior::TexelFetchTest::iterate();
177 }
178
179 /** Prepares source code for fragment shader
180  *
181  * @param is_case_valid Selects if valid or invalid case is tested
182  *
183  * @return string with prepared code
184  **/
185 std::string TexelFetchTest::getFragmentShader(bool is_case_valid)
186 {
187         static const GLchar* plane_0 = "    int   plane  = 0;\n";
188
189         static const GLchar* plane_1 = "    int   plane  = 1;\n";
190
191         static const GLchar* plane_2 = "    int   plane  = 2;\n";
192
193         static const GLchar* plane_sample_invalid = "    int   plane  = 9;\n";
194
195         static const GLchar* plane_sample_valid = "    int   plane  = gl_SampleID;\n";
196
197         static const GLchar* point_invalid = "    ivec2 point  = ivec2(gs_fs_tex_coord * 16.0) + ivec2(16, 16);\n";
198
199         static const GLchar* point_valid = "    ivec2 point  = ivec2(gs_fs_tex_coord * 16.0);\n";
200
201         static const GLchar* sampler_regular            = "sampler2D";
202         static const GLchar* sampler_regular_u          = "usampler2D";
203         static const GLchar* sampler_multisampled_u = "usampler2DMS";
204
205         static const GLchar* template_code = "#version 320 es\n"
206                                                                                  "\n"
207                                                                                  "                      in  lowp vec2      gs_fs_tex_coord;\n"
208                                                                                  "layout (location = 0) out lowp TYPE      out_fs_color;\n"
209                                                                                  "\n"
210                                                                                  "layout (location = 0) uniform lowp SAMPLER uni_texture;\n"
211                                                                                  "\n"
212                                                                                  "void main()\n"
213                                                                                  "{\n"
214                                                                                  "PLANE\n"
215                                                                                  "POINT\n"
216                                                                                  "    out_fs_color = texelFetch(uni_texture, point, plane);\n"
217                                                                                  "}\n"
218                                                                                  "\n";
219
220         static const GLchar* type_vec4  = "vec4";
221         static const GLchar* type_uvec4 = "uvec4";
222
223         const GLchar* plane   = plane_0;
224         const GLchar* point   = point_valid;
225         const GLchar* sampler = sampler_regular;
226         const GLchar* type      = type_vec4;
227
228         if ((R8 == m_test_case) || (RG8_SNORM == m_test_case) || (RGBA32F == m_test_case))
229         {
230                 if (false == is_case_valid)
231                 {
232                         point = point_invalid;
233                 }
234         }
235         else if (R32UI_MIPMAP == m_test_case)
236         {
237                 plane   = plane_1;
238                 sampler = sampler_regular_u;
239                 type    = type_uvec4;
240
241                 if (false == is_case_valid)
242                 {
243                         plane = plane_2;
244                 }
245         }
246         else if (R32UI_MULTISAMPLE == m_test_case)
247         {
248                 plane   = plane_sample_valid;
249                 sampler = sampler_multisampled_u;
250                 type    = type_uvec4;
251
252                 if (false == is_case_valid)
253                 {
254                         plane = plane_sample_invalid;
255                 }
256         }
257
258         size_t          position = 0;
259         std::string source   = template_code;
260         replaceToken("TYPE", position, type, source);
261         replaceToken("SAMPLER", position, sampler, source);
262         replaceToken("PLANE", position, plane, source);
263         replaceToken("POINT", position, point, source);
264
265         return source;
266 }
267
268 /** Prepare shader for current test case
269  *
270  * @return Source
271  **/
272 std::string TexelFetchTest::getGeometryShader()
273 {
274         return std::string("#version 320 es\n"
275                                            "\n"
276                                            "layout(points)                           in;\n"
277                                            "layout(triangle_strip, max_vertices = 4) out;\n"
278                                            "\n"
279                                            "out vec2 gs_fs_tex_coord;\n"
280                                            "\n"
281                                            "void main()\n"
282                                            "{\n"
283                                            "    gs_fs_tex_coord = vec2(0, 0);\n"
284                                            "    gl_Position     = vec4(-1, -1, 0, 1);\n"
285                                            "    EmitVertex();\n"
286                                            "\n"
287                                            "    gs_fs_tex_coord = vec2(0, 1);\n"
288                                            "    gl_Position     = vec4(-1, 1, 0, 1);\n"
289                                            "    EmitVertex();\n"
290                                            "\n"
291                                            "    gs_fs_tex_coord = vec2(1, 0);\n"
292                                            "    gl_Position     = vec4(1, -1, 0, 1);\n"
293                                            "    EmitVertex();\n"
294                                            "\n"
295                                            "    gs_fs_tex_coord = vec2(1, 1);\n"
296                                            "    gl_Position     = vec4(1, 1, 0, 1);\n"
297                                            "    EmitVertex();\n"
298                                            "}\n"
299                                            "\n");
300 }
301
302 /** Prepare shader for current test case
303  *
304  * @return Source
305  **/
306 std::string TexelFetchTest::getVertexShader()
307 {
308         return std::string("#version 320 es\n"
309                                            "\n"
310                                            "void main()\n"
311                                            "{\n"
312                                            "    gl_Position = vec4(0, 0, 0, 1);\n"
313                                            "}\n"
314                                            "\n");
315 }
316
317 /** Prepare a texture
318  *
319  * @param is_source  Selects if texutre will be used as source or destination
320  * @param texture_id Id of texutre
321  **/
322 void TexelFetchTest::prepareTexture(bool is_source, glw::GLuint texture_id)
323 {
324         /* Image size */
325         static const GLuint image_height = 16;
326         static const GLuint image_width  = 16;
327
328         /* GL entry points */
329         const Functions& gl = m_context.getRenderContext().getFunctions();
330
331         /* Texture storage parameters */
332         GLuint  height                  = image_height;
333         GLenum  internal_format = 0;
334         GLsizei n_levels                = 1;
335         GLenum  target                  = GL_TEXTURE_2D;
336         GLuint  width                   = image_width;
337
338         /* Prepare texture storage parameters */
339         switch (m_test_case)
340         {
341         case R8:
342                 internal_format = GL_R8;
343                 break;
344         case RG8_SNORM:
345                 internal_format = GL_RG8_SNORM;
346                 break;
347         case RGBA32F:
348                 internal_format = GL_RGBA32F;
349                 break;
350         case R32UI_MIPMAP:
351                 height                  = 2 * image_height;
352                 internal_format = GL_R32UI;
353                 n_levels                = 2;
354                 width                   = 2 * image_width;
355                 break;
356         case R32UI_MULTISAMPLE:
357                 internal_format = GL_R32UI;
358                 n_levels                = 4;
359                 target                  = GL_TEXTURE_2D_MULTISAMPLE;
360                 break;
361         default:
362                 TCU_FAIL("Invalid enum");
363         }
364
365         /* Prepare storage */
366         Texture::Bind(gl, texture_id, target);
367         Texture::Storage(gl, target, n_levels, internal_format, width, height, 0);
368
369         /* Set samplers to NEAREST/NEAREST if required */
370         if (R32UI_MULTISAMPLE != m_test_case)
371         {
372                 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
373                 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
374         }
375
376         /* Destination image can be left empty */
377         if (false == is_source)
378         {
379                 Texture::Bind(gl, 0, target);
380                 return;
381         }
382
383         /* Prepare texture */
384         if (R8 == m_test_case)
385         {
386                 GLubyte source_pixels[image_width * image_height];
387                 for (GLuint i = 0; i < image_width * image_height; ++i)
388                 {
389                         source_pixels[i] = (GLubyte)i;
390                 }
391
392                 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
393                                                   0 /* depth */, GL_RED, GL_UNSIGNED_BYTE, source_pixels);
394         }
395         else if (RG8_SNORM == m_test_case)
396         {
397                 static const GLuint n_components = 2;
398
399                 GLbyte source_pixels[image_width * image_height * n_components];
400                 for (GLuint i = 0; i < image_width * image_height; ++i)
401                 {
402                         source_pixels[i * n_components + 0] = (GLubyte)((i % 16));
403                         source_pixels[i * n_components + 1] = (GLubyte)((i / 16));
404                 }
405
406                 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
407                                                   0 /* depth */, GL_RG, GL_BYTE, source_pixels);
408         }
409         else if (RGBA32F == m_test_case)
410         {
411                 static const GLuint n_components = 4;
412
413                 GLfloat source_pixels[image_width * image_height * n_components];
414                 for (GLuint i = 0; i < image_width * image_height; ++i)
415                 {
416                         source_pixels[i * n_components + 0] = (GLfloat)(i % 16) / 16.0f;
417                         source_pixels[i * n_components + 1] = (GLfloat)(i / 16) / 16.0f;
418                         source_pixels[i * n_components + 2] = (GLfloat)i / 256.0f;
419                         source_pixels[i * n_components + 3] = 1.0f;
420                 }
421
422                 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
423                                                   0 /* depth */, GL_RGBA, GL_FLOAT, source_pixels);
424         }
425         else if (R32UI_MIPMAP == m_test_case)
426         {
427                 GLuint source_pixels[image_width * image_height];
428                 for (GLuint i = 0; i < image_width * image_height; ++i)
429                 {
430                         source_pixels[i] = i;
431                 }
432
433                 Texture::SubImage(gl, GL_TEXTURE_2D, 1 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, image_width, image_height,
434                                                   0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_INT, source_pixels);
435
436                 /* texelFetch() undefined if the computed level of detail is not the texture’s base level and the texture’s
437                         minification filter is NEAREST or LINEAR */
438                 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
439         }
440         else if (R32UI_MULTISAMPLE == m_test_case)
441         {
442                 /* Compute Shader */
443                 static const GLchar* cs = "#version 320 es\n"
444                                                                   "\n"
445                                                                   "layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;\n"
446                                                                   "\n"
447                                                                   "layout (binding = 0, r32ui) writeonly uniform highp uimage2DMS uni_image;\n"
448                                                                   "\n"
449                                                                   "void main()\n"
450                                                                   "{\n"
451                                                                   "    ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
452                                                                   "    uint  index = gl_WorkGroupID.y * 16U + gl_WorkGroupID.x;\n"
453                                                                   "\n"
454                                                                   "    imageStore(uni_image, point, 0, uvec4(index + 0U, 0, 0, 0));\n"
455                                                                   "    imageStore(uni_image, point, 1, uvec4(index + 1U, 0, 0, 0));\n"
456                                                                   "    imageStore(uni_image, point, 2, uvec4(index + 2U, 0, 0, 0));\n"
457                                                                   "    imageStore(uni_image, point, 3, uvec4(index + 3U, 0, 0, 0));\n"
458                                                                   "}\n"
459                                                                   "\n";
460
461                 Program program(m_context);
462                 program.Init(cs, "", "", "", "", "");
463                 program.Use();
464
465                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
466                                                         GL_WRITE_ONLY, GL_R32UI);
467                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
468
469                 gl.dispatchCompute(16, 16, 1);
470                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
471         }
472
473         Texture::Bind(gl, 0, target);
474 }
475
476 /** No verification because of undefined out-of-bound behavior in OpenGL ES
477  *
478  * @param texture_id Id of texture
479  *
480  * @return true
481  **/
482 bool TexelFetchTest::verifyInvalidResults(glw::GLuint texture_id)
483 {
484         (void)texture_id;
485         return true;
486 }
487
488 /** Verifies that texutre is filled with increasing values
489  *
490  * @param texture_id Id of texture
491  *
492  * @return true when image is filled with increasing values, false otherwise
493  **/
494 bool TexelFetchTest::verifyValidResults(glw::GLuint texture_id)
495 {
496         static const GLuint height   = 16;
497         static const GLuint width       = 16;
498         static const GLuint n_pixels = height * width;
499
500         const Functions& gl = m_context.getRenderContext().getFunctions();
501
502         bool result = true;
503
504         if (R8 == m_test_case)
505         {
506                 static const GLuint n_channels = 4;
507
508                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
509
510                 std::vector<GLubyte> pixels;
511                 pixels.resize(n_pixels * n_channels);
512                 for (GLuint i = 0; i < n_pixels; ++i)
513                 {
514                         pixels[i] = (GLubyte)i;
515                 }
516
517                 Texture::GetData(gl, texture_id, 0 /* level */, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
518
519                 /* Unbind */
520                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
521
522                 /* Verify */
523                 for (GLuint i = 0; i < n_pixels; ++i)
524                 {
525                         const GLubyte expected_red = (GLubyte)i;
526                         const GLubyte drawn_red = pixels[i * n_channels];
527
528                         if (expected_red != drawn_red)
529                         {
530                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
531                                                                                                         << ". Expected value: " << (GLuint)expected_red
532                                                                                                         << " at offset: " << i << tcu::TestLog::EndMessage;
533
534                                 result = false;
535                                 break;
536                         }
537                 }
538         }
539         else if (RG8_SNORM == m_test_case)
540         {
541                 static const GLuint n_channels = 4;
542
543                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
544
545                 std::vector<GLubyte> pixels;
546                 pixels.resize(n_pixels * n_channels);
547                 for (GLuint i = 0; i < n_pixels; ++i)
548                 {
549                         pixels[i * n_channels + 0] = (GLubyte)i;
550                         pixels[i * n_channels + 1] = (GLubyte)i;
551                 }
552
553                 Texture::GetData(gl, texture_id, 0 /* level */, width, height, GL_RGBA, GL_BYTE, &pixels[0]);
554
555                 /* Unbind */
556                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
557
558                 /* Verify */
559                 for (GLuint i = 0; i < n_pixels; ++i)
560                 {
561                         const GLbyte expected_red   = (GLubyte)(i % 16);
562                         const GLbyte expected_green = (GLubyte)(i / 16);
563                         const GLbyte drawn_red          = pixels[i * n_channels + 0];
564                         const GLbyte drawn_green        = pixels[i * n_channels + 1];
565
566                         if ((expected_red != drawn_red) || (expected_green != drawn_green))
567                         {
568                                 m_context.getTestContext().getLog()
569                                         << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
570                                         << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
571                                         << ". At offset: " << i << tcu::TestLog::EndMessage;
572
573                                 result = false;
574                                 break;
575                         }
576                 }
577         }
578         else if (RGBA32F == m_test_case)
579         {
580                 static const GLuint n_channels = 4;
581
582                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
583
584                 std::vector<GLfloat> pixels;
585                 pixels.resize(n_pixels * n_channels);
586                 for (GLuint i = 0; i < n_pixels; ++i)
587                 {
588                         pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
589                         pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
590                         pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
591                         pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
592                 }
593
594                 Texture::GetData(gl, texture_id, 0 /* level */, width, height, GL_RGBA, GL_FLOAT, &pixels[0]);
595
596                 /* Unbind */
597                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
598
599                 /* Verify */
600                 for (GLuint i = 0; i < n_pixels; ++i)
601                 {
602                         const GLfloat expected_red   = (GLfloat)(i % 16) / 16.0f;
603                         const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
604                         const GLfloat expected_blue  = (GLfloat)i / 256.0f;
605                         const GLfloat expected_alpha = 1.0f;
606                         const GLfloat drawn_red          = pixels[i * n_channels + 0];
607                         const GLfloat drawn_green       = pixels[i * n_channels + 1];
608                         const GLfloat drawn_blue         = pixels[i * n_channels + 2];
609                         const GLfloat drawn_alpha       = pixels[i * n_channels + 3];
610
611                         if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
612                                 (expected_alpha != drawn_alpha))
613                         {
614                                 m_context.getTestContext().getLog()
615                                         << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
616                                         << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
617                                         << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
618                                         << tcu::TestLog::EndMessage;
619
620                                 result = false;
621                                 break;
622                         }
623                 }
624         }
625         else if (R32UI_MIPMAP == m_test_case)
626         {
627                 static const GLuint n_channels = 4;
628
629                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
630
631                 std::vector<GLuint> pixels;
632                 pixels.resize(n_pixels * n_channels);
633                 deMemset(&pixels[0], 0, n_pixels * n_channels * sizeof(GLuint));
634
635                 Texture::GetData(gl, texture_id, 1 /* level */, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
636
637                 /* Unbind */
638                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
639
640                 /* Verify */
641                 for (GLuint i = 0; i < n_pixels; ++i)
642                 {
643                         const GLuint expected_red = i;
644                         const GLuint drawn_red  = pixels[i * n_channels];
645
646                         if (expected_red != drawn_red)
647                         {
648                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
649                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
650                                                                                                         << tcu::TestLog::EndMessage;
651
652                                 result = false;
653                                 break;
654                         }
655                 }
656         }
657         else if (R32UI_MULTISAMPLE == m_test_case)
658         {
659                 static const GLuint n_channels = 4;
660
661                 /* Compute Shader */
662                 static const GLchar* cs =
663                         "#version 320 es\n"
664                         "\n"
665                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
666                         "\n"
667                         "layout (binding = 1, r32ui) writeonly uniform lowp uimage2D   uni_destination_image;\n"
668                         "layout (binding = 0, r32ui) readonly  uniform lowp uimage2DMS uni_source_image;\n"
669                         "\n"
670                         "void main()\n"
671                         "{\n"
672                         "    ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
673                         "    uint  index = gl_WorkGroupID.y * 16U + gl_WorkGroupID.x;\n"
674                         "\n"
675                         "    uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
676                         "    uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
677                         "    uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
678                         "    uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
679                         "\n"
680                         "    if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3U))))\n"
681                         "    {\n"
682                         "        imageStore(uni_destination_image, point, uvec4(1U));\n"
683                         "    }\n"
684                         "    else\n"
685                         "    {\n"
686                         "        imageStore(uni_destination_image, point, uvec4(0U));\n"
687                         "    }\n"
688                         "}\n"
689                         "\n";
690
691                 Program program(m_context);
692                 Texture destination_texture(m_context);
693
694                 Texture::Generate(gl, destination_texture.m_id);
695                 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
696                 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
697
698                 program.Init(cs, "", "", "", "", "");
699                 program.Use();
700                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
701                                                         GL_READ_ONLY, GL_R32UI);
702                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
703                 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
704                                                         0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
705                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
706
707                 gl.dispatchCompute(16, 16, 1);
708                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
709
710                 /* Pixels buffer initialization */
711                 std::vector<GLuint> pixels;
712                 pixels.resize(n_pixels * n_channels);
713                 for (GLuint i = 0; i < n_pixels * n_channels; ++i)
714                 {
715                         pixels[i] = i;
716                 }
717
718                 Texture::GetData(gl, destination_texture.m_id, 0 /* level */, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT,
719                                                  &pixels[0]);
720
721                 /* Unbind */
722                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
723
724                 /* Verify */
725                 for (GLuint i = 0; i < n_pixels; ++i)
726                 {
727                         const GLuint expected_red = 1;
728                         const GLuint drawn_red  = pixels[i * n_channels];
729
730                         if (expected_red != drawn_red)
731                         {
732                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
733                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
734                                                                                                         << tcu::TestLog::EndMessage;
735
736                                 result = false;
737                                 break;
738                         }
739                 }
740         }
741
742         return result;
743 }
744
745 /** Constructor
746  *
747  * @param context Test context
748  **/
749 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context)
750         : TexelFetchTest(context, "image_load_store", "Verifies that out-of-bound to image result in zero or is discarded")
751 {
752         /* start from RGBA32F as R8, R32UI_MULTISAMPLE and R8_SNORM are not supported under GLES */
753         m_test_case = RGBA32F;
754 }
755
756 /** Execute test
757  *
758  * @return tcu::TestNode::STOP
759  **/
760 tcu::TestNode::IterateResult ImageLoadStoreTest::iterate()
761 {
762         /* Constants */
763         static const GLuint height = 16;
764         static const GLuint width  = 16;
765
766         /* GL entry points */
767         const Functions& gl = m_context.getRenderContext().getFunctions();
768
769         /* Test result indicator */
770         bool test_result = true;
771
772         /* Iterate over all cases */
773         while (LAST != m_test_case)
774         {
775                 /* Test case result indicator */
776                 bool case_result = true;
777
778                 /* Test case objects */
779                 Texture destination_texture(m_context);
780                 Program invalid_destination_program(m_context);
781                 Program invalid_source_program(m_context);
782                 Texture source_texture(m_context);
783                 Program valid_program(m_context);
784
785                 const std::string& cs_invalid_destination = getComputeShader(DESTINATION_INVALID);
786                 const std::string& cs_invalid_source      = getComputeShader(SOURCE_INVALID);
787                 const std::string& cs_valid                               = getComputeShader(VALID);
788
789                 /* Prepare textures */
790                 Texture::Generate(gl, destination_texture.m_id);
791                 Texture::Generate(gl, source_texture.m_id);
792
793                 prepareTexture(false, destination_texture.m_id);
794                 prepareTexture(true, source_texture.m_id);
795
796                 /* Prepare programs */
797                 invalid_destination_program.Init(cs_invalid_destination, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
798                                                                                  "" /* vs */);
799                 invalid_source_program.Init(cs_invalid_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
800                                                                         "" /* vs */);
801                 valid_program.Init(cs_valid, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
802
803                 /* Test invalid source case */
804                 /* Set program */
805                 invalid_source_program.Use();
806
807                 /* Set texture */
808                 setTextures(destination_texture.m_id, source_texture.m_id);
809
810                 /* Dispatch */
811                 gl.dispatchCompute(width, height, 1 /* depth */);
812                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
813
814                 /* Verification */
815                 if (false == verifyInvalidResults(destination_texture.m_id))
816                 {
817                         case_result = false;
818                 }
819
820                 /* Test valid case */
821                 /* Set program */
822                 valid_program.Use();
823
824                 /* Set texture */
825                 setTextures(destination_texture.m_id, source_texture.m_id);
826
827                 /* Dispatch */
828                 gl.dispatchCompute(width, height, 1 /* depth */);
829                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
830
831                 /* Verification */
832                 if (false == verifyValidResults(destination_texture.m_id))
833                 {
834                         case_result = false;
835                 }
836
837                 /* Test invalid destination case */
838                 /* Set program */
839                 invalid_destination_program.Use();
840
841                 /* Set texture */
842                 setTextures(destination_texture.m_id, source_texture.m_id);
843
844                 /* Dispatch */
845                 gl.dispatchCompute(width, height, 1 /* depth */);
846                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
847
848                 /* Verification */
849                 if (false == verifyValidResults(destination_texture.m_id))
850                 {
851                         case_result = false;
852                 }
853
854                 /* Set test result */
855                 if (false == case_result)
856                 {
857                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
858                                                                                                 << " failed" << tcu::TestLog::EndMessage;
859
860                         test_result = false;
861                 }
862
863                 /* Increment */
864                 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
865         }
866
867         /* Set result */
868         if (true == test_result)
869         {
870                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
871         }
872         else
873         {
874                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
875         }
876
877         /* Done */
878         return tcu::TestNode::STOP;
879 }
880
881 /** Prepare shader for current test case
882  *
883  * @param version Specify which version should be prepared
884  *
885  * @return Source
886  **/
887 std::string ImageLoadStoreTest::getComputeShader(VERSION version)
888 {
889         static const GLchar* template_code =
890                 "#version 320 es\n"
891                 "\n"
892                 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
893                 "\n"
894                 "layout (binding = 1, FORMAT) writeonly uniform highp IMAGE uni_destination_image;\n"
895                 "layout (binding = 0, FORMAT) readonly  uniform highp IMAGE uni_source_image;\n"
896                 "\n"
897                 "void main()\n"
898                 "{\n"
899                 "    ivec2 point_destination = POINT;\n"
900                 "    ivec2 point_source      = POINT;\n"
901                 "\n"
902                 "COPY"
903                 "}\n"
904                 "\n";
905
906         static const GLchar* copy_regular = "    TYPE color = imageLoad(uni_source_image, point_source);\n"
907                                                                                 "    imageStore(uni_destination_image, point_destination, color);\n";
908
909         static const GLchar* format_rgba32f = "rgba32f";
910         static const GLchar* format_r32ui   = "r32ui";
911
912         static const GLchar* image_vec4 = "image2D";
913
914         static const GLchar* image_uvec4 = "uimage2D";
915
916         static const GLchar* point_invalid = "ivec2(gl_WorkGroupID.x + 16U, gl_WorkGroupID.y + 16U)";
917
918         static const GLchar* point_valid = "ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
919
920         static const GLchar* type_vec4  = "vec4";
921         static const GLchar* type_uvec4 = "uvec4";
922
923         const GLchar* copy                               = copy_regular;
924         const GLchar* format                     = format_rgba32f;
925         const GLchar* image                              = image_vec4;
926         const GLchar* point_destination  = point_valid;
927         const GLchar* point_source               = point_valid;
928         const GLchar* type                               = type_vec4;
929
930         switch (version)
931         {
932         case VALID:
933                 break;
934         case SOURCE_INVALID:
935                 point_source  = point_invalid;
936                 break;
937         case DESTINATION_INVALID:
938                 point_destination  = point_invalid;
939                 break;
940         default:
941                 TCU_FAIL("Invalid enum");
942         }
943
944         switch (m_test_case)
945         {
946         case RGBA32F:
947                 format = format_rgba32f;
948                 break;
949         case R32UI_MIPMAP:
950                 format = format_r32ui;
951                 image  = image_uvec4;
952                 type   = type_uvec4;
953                 break;
954         default:
955                 TCU_FAIL("Invalid enum");
956         };
957
958         size_t          position = 0;
959         std::string source   = template_code;
960
961         replaceToken("FORMAT", position, format, source);
962         replaceToken("IMAGE", position, image, source);
963         replaceToken("FORMAT", position, format, source);
964         replaceToken("IMAGE", position, image, source);
965         replaceToken("POINT", position, point_destination, source);
966         replaceToken("POINT", position, point_source, source);
967
968         size_t temp_position = position;
969         replaceToken("COPY", position, copy, source);
970         position = temp_position;
971
972         switch (m_test_case)
973         {
974         case RGBA32F:
975         case R32UI_MIPMAP:
976                 replaceToken("TYPE", position, type, source);
977                 break;
978         default:
979                 TCU_FAIL("Invalid enum");
980         }
981
982         return source;
983 }
984
985 /** Set textures as images
986  *
987  * @param id_destination Id of texture used as destination
988  * @param id_source      Id of texture used as source
989  **/
990 void ImageLoadStoreTest::setTextures(glw::GLuint id_destination, glw::GLuint id_source)
991 {
992         const Functions& gl = m_context.getRenderContext().getFunctions();
993
994         GLenum format = 0;
995         GLint  level  = 0;
996
997         switch (m_test_case)
998         {
999         case RGBA32F:
1000                 format = GL_RGBA32F;
1001                 break;
1002         case R32UI_MIPMAP:
1003                 format = GL_R32UI;
1004                 level  = 1;
1005                 break;
1006         default:
1007                 TCU_FAIL("Invalid enum");
1008         }
1009
1010         gl.bindImageTexture(0 /* unit */, id_source, level, GL_FALSE /* layered */, 0 /* layer */, GL_READ_ONLY, format);
1011         GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1012
1013         gl.bindImageTexture(1 /* unit */, id_destination, level, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY,
1014                                                 format);
1015         GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1016 }
1017
1018 /** No verification because of undefined out-of-bound behavior in OpenGL ES
1019  *
1020  * @param texture_id Id of texture
1021  *
1022  * @return true
1023  **/
1024 bool ImageLoadStoreTest::verifyInvalidResults(glw::GLuint texture_id)
1025 {
1026         (void)texture_id;
1027         return true;
1028 }
1029
1030 /** Verifies that texutre is filled with increasing values
1031  *
1032  * @param texture_id Id of texture
1033  *
1034  * @return true when image is filled with increasing values, false otherwise
1035  **/
1036 bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
1037 {
1038         static const GLuint height   = 16;
1039         static const GLuint width       = 16;
1040         static const GLuint n_pixels = height * width;
1041
1042         const Functions& gl = m_context.getRenderContext().getFunctions();
1043         gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1044         GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
1045
1046         bool result = true;
1047
1048         if (RGBA32F == m_test_case)
1049         {
1050                 static const GLuint n_channels = 4;
1051
1052                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1053
1054                 std::vector<GLfloat> pixels;
1055                 pixels.resize(n_pixels * n_channels);
1056                 for (GLuint i = 0; i < n_pixels; ++i)
1057                 {
1058                         pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
1059                         pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
1060                         pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
1061                         pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
1062                 }
1063
1064                 Texture::GetData(gl, texture_id, 0 /* level */, width, height, GL_RGBA, GL_FLOAT, &pixels[0]);
1065
1066                 /* Unbind */
1067                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1068
1069                 /* Verify */
1070                 for (GLuint i = 0; i < n_pixels; ++i)
1071                 {
1072                         const GLfloat expected_red   = (GLfloat)(i % 16) / 16.0f;
1073                         const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
1074                         const GLfloat expected_blue  = (GLfloat)i / 256.0f;
1075                         const GLfloat expected_alpha = 1.0f;
1076                         const GLfloat drawn_red          = pixels[i * n_channels + 0];
1077                         const GLfloat drawn_green       = pixels[i * n_channels + 1];
1078                         const GLfloat drawn_blue         = pixels[i * n_channels + 2];
1079                         const GLfloat drawn_alpha       = pixels[i * n_channels + 3];
1080
1081                         if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
1082                                 (expected_alpha != drawn_alpha))
1083                         {
1084                                 m_context.getTestContext().getLog()
1085                                         << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
1086                                         << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
1087                                         << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
1088                                         << tcu::TestLog::EndMessage;
1089
1090                                 result = false;
1091                                 break;
1092                         }
1093                 }
1094         }
1095         else if (R32UI_MIPMAP == m_test_case)
1096         {
1097                 static const GLuint n_channels = 4;
1098
1099                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1100
1101                 std::vector<GLuint> pixels;
1102                 pixels.resize(n_pixels * n_channels);
1103                 for (GLuint i = 0; i < n_pixels * n_channels; ++i)
1104                 {
1105                         pixels[i] = 0;
1106                 }
1107
1108                 Texture::GetData(gl, texture_id, 1 /* level */, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
1109
1110                 /* Unbind */
1111                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1112
1113                 /* Verify */
1114                 for (GLuint i = 0; i < n_pixels; ++i)
1115                 {
1116                         const GLuint expected_red = i;
1117                         const GLuint drawn_red  = pixels[i * n_channels];
1118
1119                         if (expected_red != drawn_red)
1120                         {
1121                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
1122                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
1123                                                                                                         << tcu::TestLog::EndMessage;
1124
1125                                 result = false;
1126                                 break;
1127                         }
1128                 }
1129         }
1130
1131         return result;
1132 }
1133
1134 /** Constructor
1135  *
1136  * @param context Test context
1137  **/
1138 StorageBufferTest::StorageBufferTest(deqp::Context& context)
1139         : deqp::RobustBufferAccessBehavior::StorageBufferTest(
1140                   context, "storage_buffer", "Verifies that out-of-bound access to SSBO results with no error")
1141 {
1142         /* Nothing to be done here */
1143 }
1144
1145 /** Execute test
1146  *
1147  * @return tcu::TestNode::STOP
1148  **/
1149 tcu::TestNode::IterateResult StorageBufferTest::iterate()
1150 {
1151         return deqp::RobustBufferAccessBehavior::StorageBufferTest::iterate();
1152 }
1153
1154 /** Prepare shader for current test case
1155  *
1156  * @return Source
1157  **/
1158 std::string StorageBufferTest::getComputeShader()
1159 {
1160         static const GLchar* cs = "#version 320 es\n"
1161                                                           "\n"
1162                                                           "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
1163                                                           "\n"
1164                                                           "layout (binding = 1) buffer Source {\n"
1165                                                           "    float data[];\n"
1166                                                           "} source;\n"
1167                                                           "\n"
1168                                                           "layout (binding = 0) buffer Destination {\n"
1169                                                           "    float data[];\n"
1170                                                           "} destination;\n"
1171                                                           "\n"
1172                                                           "void main()\n"
1173                                                           "{\n"
1174                                                           "    uint index_destination = gl_LocalInvocationID.x + OFFSETU;\n"
1175                                                           "    uint index_source      = gl_LocalInvocationID.x + OFFSETU;\n"
1176                                                           "\n"
1177                                                           "    destination.data[index_destination] = source.data[index_source];\n"
1178                                                           "}\n"
1179                                                           "\n";
1180
1181         const GLchar* destination_offset;
1182         size_t            position = 0;
1183         std::string   source   = cs;
1184         const GLchar* source_offset;
1185
1186         switch (m_test_case)
1187         {
1188         case VALID:
1189                 destination_offset = "0";
1190                 source_offset     = "0";
1191                 break;
1192         case SOURCE_INVALID:
1193                 destination_offset = "0";
1194                 source_offset     = "16";
1195                 break;
1196         case DESTINATION_INVALID:
1197                 destination_offset = "16";
1198                 source_offset     = "0";
1199                 break;
1200         default:
1201                 TCU_FAIL("Invalid enum");
1202         }
1203
1204         replaceToken("OFFSET", position, destination_offset, source);
1205         replaceToken("OFFSET", position, source_offset, source);
1206
1207         return source;
1208 }
1209
1210 /** Verify test case results
1211  *
1212  * @param buffer_data Buffer data to verify
1213  *
1214  * @return true if buffer_data is as expected, false othrewise
1215  **/
1216 bool StorageBufferTest::verifyResults(GLfloat* buffer_data)
1217 {
1218         static const GLfloat expected_data_valid[4]                               = { 2.0f, 3.0f, 4.0f, 5.0f };
1219         static const GLfloat expected_data_invalid_destination[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
1220         static const GLfloat expected_data_invalid_source[4]      = { 0.0f, 0.0f, 0.0f, 0.0f };
1221
1222         int size = sizeof(GLfloat) * 4;
1223
1224         /* Prepare expected data const for proper case*/
1225         const GLfloat* expected_data = 0;
1226         const GLchar*  name                      = 0;
1227         switch (m_test_case)
1228         {
1229         case VALID:
1230                 expected_data = expected_data_valid;
1231                 name              = "valid indices";
1232                 break;
1233         case SOURCE_INVALID:
1234                 expected_data = expected_data_invalid_source;
1235                 name              = "invalid source indices";
1236                 break;
1237         case DESTINATION_INVALID:
1238                 expected_data = expected_data_invalid_destination;
1239                 name              = "invalid destination indices";
1240                 break;
1241         default:
1242                 TCU_FAIL("Invalid enum");
1243         }
1244
1245         /* Verify buffer data */
1246         if (m_test_case == VALID && memcmp(expected_data, buffer_data, size) != 0)
1247         {
1248                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
1249                                                                                         << tcu::TestLog::EndMessage;
1250                 return false;
1251         }
1252
1253         return true;
1254 }
1255
1256 /** Constructor
1257  *
1258  * @param context Test context
1259  **/
1260 UniformBufferTest::UniformBufferTest(deqp::Context& context)
1261         : deqp::RobustBufferAccessBehavior::UniformBufferTest(
1262                   context, "uniform_buffer", "Verifies that out-of-bound access to UBO resutls with no error")
1263 {
1264         /* Nothing to be done here */
1265 }
1266
1267 /** Execute test
1268  *
1269  * @return tcu::TestNode::STOP
1270  **/
1271 tcu::TestNode::IterateResult UniformBufferTest::iterate()
1272 {
1273         return deqp::RobustBufferAccessBehavior::UniformBufferTest::iterate();
1274 }
1275
1276 /** Prepare shader for current test case
1277  *
1278  * @return Source
1279  **/
1280 std::string UniformBufferTest::getComputeShader()
1281 {
1282         static const GLchar* cs = "#version 320 es\n"
1283                                                           "\n"
1284                                                           "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
1285                                                           "\n"
1286                                                           "layout (binding = 0) uniform Source {\n"
1287                                                           "    float data[16];\n"
1288                                                           "} source;\n"
1289                                                           "\n"
1290                                                           "layout (binding = 0) buffer Destination {\n"
1291                                                           "    float data[];\n"
1292                                                           "} destination;\n"
1293                                                           "\n"
1294                                                           "void main()\n"
1295                                                           "{\n"
1296                                                           "    uint index_destination = gl_LocalInvocationID.x + OFFSETU;\n"
1297                                                           "    uint index_source      = gl_LocalInvocationID.x + OFFSETU;\n"
1298                                                           "\n"
1299                                                           "    destination.data[index_destination] = source.data[index_source];\n"
1300                                                           "}\n"
1301                                                           "\n";
1302
1303         const GLchar* destination_offset;
1304         size_t            position = 0;
1305         std::string   source   = cs;
1306         const GLchar* source_offset;
1307
1308         switch (m_test_case)
1309         {
1310         case VALID:
1311                 destination_offset = "0";
1312                 source_offset     = "0";
1313                 break;
1314         case SOURCE_INVALID:
1315                 destination_offset = "0";
1316                 source_offset     = "16";
1317                 break;
1318         default:
1319                 TCU_FAIL("Invalid enum");
1320         }
1321
1322         replaceToken("OFFSET", position, destination_offset, source);
1323         replaceToken("OFFSET", position, source_offset, source);
1324
1325         return source;
1326 }
1327
1328 /** Verify test case results
1329  *
1330  * @param buffer_data Buffer data to verify
1331  *
1332  * @return true if buffer_data is as expected, false othrewise
1333  **/
1334 bool UniformBufferTest::verifyResults(GLfloat* buffer_data)
1335 {
1336         static const GLfloat expected_data_valid[4]                      = { 2.0f, 3.0f, 4.0f, 5.0f };
1337         static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1338
1339         int size = sizeof(GLfloat) * 4;
1340
1341         /* Prepare expected data const for proper case*/
1342         const GLfloat* expected_data = 0;
1343         const GLchar*  name                      = 0;
1344         switch (m_test_case)
1345         {
1346         case VALID:
1347                 expected_data = expected_data_valid;
1348                 name              = "valid indices";
1349                 break;
1350         case SOURCE_INVALID:
1351                 expected_data = expected_data_invalid_source;
1352                 name              = "invalid source indices";
1353                 break;
1354         default:
1355                 TCU_FAIL("Invalid enum");
1356         }
1357
1358         /* Verify buffer data */
1359         if (m_test_case == VALID && memcmp(expected_data, buffer_data, size) != 0)
1360         {
1361                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
1362                                                                                         << tcu::TestLog::EndMessage;
1363                 return false;
1364         }
1365
1366         return true;
1367 }
1368
1369 } /* RobustBufferAccessBehavior */
1370
1371 /** Constructor.
1372  *
1373  *  @param context Rendering context.
1374  **/
1375 RobustBufferAccessBehaviorTests::RobustBufferAccessBehaviorTests(deqp::Context& context)
1376         : deqp::RobustBufferAccessBehaviorTests(context)
1377 {
1378         /* Left blank on purpose */
1379 }
1380
1381 /** Initializes a multi_bind test group.
1382  *
1383  **/
1384 void RobustBufferAccessBehaviorTests::init(void)
1385 {
1386         addChild(new RobustBufferAccessBehavior::VertexBufferObjectsTest(m_context));
1387         addChild(new RobustBufferAccessBehavior::TexelFetchTest(m_context));
1388         addChild(new RobustBufferAccessBehavior::ImageLoadStoreTest(m_context));
1389         addChild(new RobustBufferAccessBehavior::StorageBufferTest(m_context));
1390         addChild(new RobustBufferAccessBehavior::UniformBufferTest(m_context));
1391 }
1392
1393 } /* es32cts namespace */