ab719d30653aee66d4630577cb16c82c6f220dab
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcRobustBufferAccessBehaviorTests.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  * \file  glcRobustBufferAccessBehaviorTests.cpp
25  * \brief Implements conformance tests for "Robust Buffer Access Behavior" functionality.
26  */ /*-------------------------------------------------------------------*/
27
28 #include "glcRobustBufferAccessBehaviorTests.hpp"
29
30 #include "gluDefs.hpp"
31 #include "glwEnums.hpp"
32 #include "glwFunctions.hpp"
33 #include "tcuTestLog.hpp"
34
35 #include <cstring>
36 #include <string>
37
38 using namespace glw;
39
40 namespace deqp
41 {
42 namespace RobustBufferAccessBehavior
43 {
44 /* Buffer constants */
45 const GLuint Buffer::m_invalid_id = -1;
46
47 const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
48         GL_ARRAY_BUFFER,                          /*  0 */
49         GL_ATOMIC_COUNTER_BUFFER,        /*  1 */
50         GL_COPY_READ_BUFFER,              /*  2 */
51         GL_COPY_WRITE_BUFFER,             /*  3 */
52         GL_DISPATCH_INDIRECT_BUFFER,  /*  4 */
53         GL_DRAW_INDIRECT_BUFFER,          /*  5 */
54         GL_ELEMENT_ARRAY_BUFFER,          /*  6 */
55         GL_PIXEL_PACK_BUFFER,             /*  7 */
56         GL_PIXEL_UNPACK_BUFFER,           /*  8 */
57         GL_QUERY_BUFFER,                          /*  9 */
58         GL_SHADER_STORAGE_BUFFER,        /* 10 */
59         GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
60         GL_UNIFORM_BUFFER,                        /* 12 */
61 };
62
63 /** Constructor.
64  *
65  * @param context CTS context.
66  **/
67 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
68 {
69 }
70
71 /** Destructor
72  *
73  **/
74 Buffer::~Buffer()
75 {
76         Release();
77 }
78
79 /** Initialize buffer instance
80  *
81  * @param target Buffer target
82  * @param usage  Buffer usage enum
83  * @param size   <size> parameter
84  * @param data   <data> parameter
85  **/
86 void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data)
87 {
88         /* Delete previous buffer instance */
89         Release();
90
91         m_target = target;
92
93         const Functions& gl = m_context.getRenderContext().getFunctions();
94
95         Generate(gl, m_id);
96         Bind(gl, m_id, m_target);
97         Data(gl, m_target, usage, size, data);
98 }
99
100 /** Release buffer instance
101  *
102  **/
103 void Buffer::Release()
104 {
105         if (m_invalid_id != m_id)
106         {
107                 const Functions& gl = m_context.getRenderContext().getFunctions();
108
109                 gl.deleteBuffers(1, &m_id);
110                 m_id = m_invalid_id;
111         }
112 }
113
114 /** Binds buffer to its target
115  *
116  **/
117 void Buffer::Bind() const
118 {
119         const Functions& gl = m_context.getRenderContext().getFunctions();
120
121         Bind(gl, m_id, m_target);
122 }
123
124 /** Binds indexed buffer
125  *
126  * @param index <index> parameter
127  **/
128 void Buffer::BindBase(glw::GLuint index) const
129 {
130         const Functions& gl = m_context.getRenderContext().getFunctions();
131
132         BindBase(gl, m_id, m_target, index);
133 }
134
135 /** Bind buffer to given target
136  *
137  * @param gl     GL functions
138  * @param id     Id of buffer
139  * @param target Buffer target
140  **/
141 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
142 {
143         gl.bindBuffer(target, id);
144         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
145 }
146
147 /** Binds indexed buffer
148  *
149  * @param gl     GL functions
150  * @param id     Id of buffer
151  * @param target Buffer target
152  * @param index  <index> parameter
153  **/
154 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
155 {
156         gl.bindBufferBase(target, index, id);
157         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
158 }
159
160 /** Allocate memory for buffer and sends initial content
161  *
162  * @param gl     GL functions
163  * @param target Buffer target
164  * @param usage  Buffer usage enum
165  * @param size   <size> parameter
166  * @param data   <data> parameter
167  **/
168 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
169                                   const glw::GLvoid* data)
170 {
171         gl.bufferData(target, size, data, usage);
172         GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
173 }
174
175 /** Generate buffer
176  *
177  * @param gl     GL functions
178  * @param out_id Id of buffer
179  **/
180 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
181 {
182         GLuint id = m_invalid_id;
183
184         gl.genBuffers(1, &id);
185         GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
186
187         if (m_invalid_id == id)
188         {
189                 TCU_FAIL("Got invalid id");
190         }
191
192         out_id = id;
193 }
194
195 /** Update range of buffer
196  *
197  * @param gl     GL functions
198  * @param target Buffer target
199  * @param offset Offset in buffer
200  * @param size   <size> parameter
201  * @param data   <data> parameter
202  **/
203 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
204                                          glw::GLvoid* data)
205 {
206         gl.bufferSubData(target, offset, size, data);
207         GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
208 }
209
210 /* Framebuffer constants */
211 const GLuint Framebuffer::m_invalid_id = -1;
212
213 /** Constructor.
214  *
215  * @param context CTS context.
216  **/
217 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
218 {
219         /* Nothing to done here */
220 }
221
222 /** Destructor
223  *
224  **/
225 Framebuffer::~Framebuffer()
226 {
227         Release();
228 }
229
230 /** Release texture instance
231  *
232  **/
233 void Framebuffer::Release()
234 {
235         if (m_invalid_id != m_id)
236         {
237                 const Functions& gl = m_context.getRenderContext().getFunctions();
238
239                 gl.deleteFramebuffers(1, &m_id);
240                 m_id = m_invalid_id;
241         }
242 }
243
244 /** Attach texture to specified attachment
245  *
246  * @param gl         GL functions
247  * @param target     Framebuffer target
248  * @param attachment Attachment
249  * @param texture_id Texture id
250  * @param level      Level of mipmap
251  * @param width      Texture width
252  * @param height     Texture height
253  **/
254 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
255                                                                 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height)
256 {
257         gl.framebufferTexture(target, attachment, texture_id, level);
258         GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
259
260         gl.viewport(0 /* x */, 0 /* y */, width, height);
261         GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
262 }
263
264 /** Binds framebuffer to DRAW_FRAMEBUFFER
265  *
266  * @param gl     GL functions
267  * @param target Framebuffer target
268  * @param id     ID of framebuffer
269  **/
270 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
271 {
272         gl.bindFramebuffer(target, id);
273         GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
274 }
275
276 /** Generate framebuffer
277  *
278  **/
279 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
280 {
281         GLuint id = m_invalid_id;
282
283         gl.genFramebuffers(1, &id);
284         GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
285
286         if (m_invalid_id == id)
287         {
288                 TCU_FAIL("Invalid id");
289         }
290
291         out_id = id;
292 }
293
294 /* Program constants */
295 const GLuint Program::m_invalid_id = 0;
296
297 /** Constructor.
298  *
299  * @param context CTS context.
300  **/
301 Program::Program(deqp::Context& context)
302         : m_id(m_invalid_id)
303         , m_compute(context)
304         , m_fragment(context)
305         , m_geometry(context)
306         , m_tess_ctrl(context)
307         , m_tess_eval(context)
308         , m_vertex(context)
309         , m_context(context)
310 {
311         /* Nothing to be done here */
312 }
313
314 /** Destructor
315  *
316  **/
317 Program::~Program()
318 {
319         Release();
320 }
321
322 /** Initialize program instance
323  *
324  * @param compute_shader                Compute shader source code
325  * @param fragment_shader               Fragment shader source code
326  * @param geometry_shader               Geometry shader source code
327  * @param tesselation_control_shader    Tesselation control shader source code
328  * @param tesselation_evaluation_shader Tesselation evaluation shader source code
329  * @param vertex_shader                 Vertex shader source code
330  **/
331 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
332                                    const std::string& geometry_shader, const std::string& tesselation_control_shader,
333                                    const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
334 {
335         /* Delete previous program */
336         Release();
337
338         /* GL entry points */
339         const Functions& gl = m_context.getRenderContext().getFunctions();
340
341         /* Initialize shaders */
342         m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
343         m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
344         m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
345         m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
346         m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
347         m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
348
349         /* Create program, set up transform feedback and attach shaders */
350         Create(gl, m_id);
351         Attach(gl, m_id, m_compute.m_id);
352         Attach(gl, m_id, m_fragment.m_id);
353         Attach(gl, m_id, m_geometry.m_id);
354         Attach(gl, m_id, m_tess_ctrl.m_id);
355         Attach(gl, m_id, m_tess_eval.m_id);
356         Attach(gl, m_id, m_vertex.m_id);
357
358         /* Link program */
359         Link(gl, m_id);
360 }
361
362 /** Release program instance
363  *
364  **/
365 void Program::Release()
366 {
367         const Functions& gl = m_context.getRenderContext().getFunctions();
368
369         if (m_invalid_id != m_id)
370         {
371                 Use(gl, m_invalid_id);
372
373                 gl.deleteProgram(m_id);
374                 m_id = m_invalid_id;
375         }
376
377         m_compute.Release();
378         m_fragment.Release();
379         m_geometry.Release();
380         m_tess_ctrl.Release();
381         m_tess_eval.Release();
382         m_vertex.Release();
383 }
384
385 /** Set program as active
386  *
387  **/
388 void Program::Use() const
389 {
390         const Functions& gl = m_context.getRenderContext().getFunctions();
391
392         Use(gl, m_id);
393 }
394
395 /** Attach shader to program
396  *
397  * @param gl         GL functions
398  * @param program_id Id of program
399  * @param shader_id  Id of shader
400  **/
401 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
402 {
403         /* Sanity checks */
404         if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
405         {
406                 return;
407         }
408
409         gl.attachShader(program_id, shader_id);
410         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
411 }
412
413 /** Create program instance
414  *
415  * @param gl     GL functions
416  * @param out_id Id of program
417  **/
418 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
419 {
420         const GLuint id = gl.createProgram();
421         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
422
423         if (m_invalid_id == id)
424         {
425                 TCU_FAIL("Failed to create program");
426         }
427
428         out_id = id;
429 }
430
431 /** Link program
432  *
433  * @param gl GL functions
434  * @param id Id of program
435  **/
436 void Program::Link(const glw::Functions& gl, glw::GLuint id)
437 {
438         GLint status = GL_FALSE;
439
440         gl.linkProgram(id);
441         GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
442
443         /* Get link status */
444         gl.getProgramiv(id, GL_LINK_STATUS, &status);
445         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
446
447         /* Log link error */
448         if (GL_TRUE != status)
449         {
450                 glw::GLint  length = 0;
451                 std::string message;
452
453                 /* Get error log length */
454                 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
455                 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
456
457                 message.resize(length, 0);
458
459                 /* Get error log */
460                 gl.getProgramInfoLog(id, length, 0, &message[0]);
461                 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
462
463                 TCU_FAIL(message.c_str());
464         }
465 }
466
467 /** Use program
468  *
469  * @param gl GL functions
470  * @param id Id of program
471  **/
472 void Program::Use(const glw::Functions& gl, glw::GLuint id)
473 {
474         gl.useProgram(id);
475         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
476 }
477
478 /* Shader's constants */
479 const GLuint Shader::m_invalid_id = 0;
480
481 /** Constructor.
482  *
483  * @param context CTS context.
484  **/
485 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
486 {
487         /* Nothing to be done here */
488 }
489
490 /** Destructor
491  *
492  **/
493 Shader::~Shader()
494 {
495         Release();
496 }
497
498 /** Initialize shader instance
499  *
500  * @param stage  Shader stage
501  * @param source Source code
502  **/
503 void Shader::Init(glw::GLenum stage, const std::string& source)
504 {
505         if (true == source.empty())
506         {
507                 /* No source == no shader */
508                 return;
509         }
510
511         /* Delete any previous shader */
512         Release();
513
514         /* Create, set source and compile */
515         const Functions& gl = m_context.getRenderContext().getFunctions();
516
517         Create(gl, stage, m_id);
518         Source(gl, m_id, source);
519
520         Compile(gl, m_id);
521 }
522
523 /** Release shader instance
524  *
525  **/
526 void Shader::Release()
527 {
528         if (m_invalid_id != m_id)
529         {
530                 const Functions& gl = m_context.getRenderContext().getFunctions();
531
532                 gl.deleteShader(m_id);
533                 m_id = m_invalid_id;
534         }
535 }
536
537 /** Compile shader
538  *
539  * @param gl GL functions
540  * @param id Shader id
541  **/
542 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
543 {
544         GLint status = GL_FALSE;
545
546         /* Compile */
547         gl.compileShader(id);
548         GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
549
550         /* Get compilation status */
551         gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
552         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
553
554         /* Log compilation error */
555         if (GL_TRUE != status)
556         {
557                 glw::GLint  length = 0;
558                 std::string message;
559
560                 /* Error log length */
561                 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
562                 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
563
564                 /* Prepare storage */
565                 message.resize(length, 0);
566
567                 /* Get error log */
568                 gl.getShaderInfoLog(id, length, 0, &message[0]);
569                 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
570
571                 TCU_FAIL(message.c_str());
572         }
573 }
574
575 /** Create shader
576  *
577  * @param gl     GL functions
578  * @param stage  Shader stage
579  * @param out_id Shader id
580  **/
581 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
582 {
583         const GLuint id = gl.createShader(stage);
584         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
585
586         if (m_invalid_id == id)
587         {
588                 TCU_FAIL("Failed to create shader");
589         }
590
591         out_id = id;
592 }
593
594 /** Set shader's source code
595  *
596  * @param gl     GL functions
597  * @param id     Shader id
598  * @param source Shader source code
599  **/
600 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
601 {
602         const GLchar* code = source.c_str();
603
604         gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
605         GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
606 }
607
608 /* Texture static fields */
609 const GLuint Texture::m_invalid_id = -1;
610
611 /** Constructor.
612  *
613  * @param context CTS context.
614  **/
615 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
616 {
617         /* Nothing to done here */
618 }
619
620 /** Destructor
621  *
622  **/
623 Texture::~Texture()
624 {
625         Release();
626 }
627
628 /** Release texture instance
629  *
630  **/
631 void Texture::Release()
632 {
633         if (m_invalid_id != m_id)
634         {
635                 const Functions& gl = m_context.getRenderContext().getFunctions();
636
637                 gl.deleteTextures(1, &m_id);
638                 m_id = m_invalid_id;
639         }
640 }
641
642 /** Bind texture to target
643  *
644  * @param gl       GL functions
645  * @param id       Id of texture
646  * @param tex_type Type of texture
647  **/
648 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
649 {
650         gl.bindTexture(target, id);
651         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
652 }
653
654 /** Set contents of compressed texture
655  *
656  * @param gl              GL functions
657  * @param target          Texture target
658  * @param level           Mipmap level
659  * @param internal_format Format of data
660  * @param width           Width of texture
661  * @param height          Height of texture
662  * @param depth           Depth of texture
663  * @param image_size      Size of data
664  * @param data            Buffer with image data
665  **/
666 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
667                                                           glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
668                                                           glw::GLsizei image_size, const glw::GLvoid* data)
669 {
670         switch (target)
671         {
672         case GL_TEXTURE_1D:
673                 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
674                 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
675                 break;
676         case GL_TEXTURE_1D_ARRAY:
677         case GL_TEXTURE_2D:
678         case GL_TEXTURE_RECTANGLE:
679                 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
680                 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
681                 break;
682         case GL_TEXTURE_CUBE_MAP:
683                 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
684                                                                 image_size, data);
685                 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
686                                                                 image_size, data);
687                 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
688                                                                 image_size, data);
689                 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
690                                                                 image_size, data);
691                 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
692                                                                 image_size, data);
693                 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
694                                                                 image_size, data);
695                 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
696                 break;
697         case GL_TEXTURE_3D:
698         case GL_TEXTURE_2D_ARRAY:
699                 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
700                 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
701                 break;
702         default:
703                 TCU_FAIL("Invliad enum");
704                 break;
705         }
706 }
707
708 /** Generate texture instance
709  *
710  * @param gl     GL functions
711  * @param out_id Id of texture
712  **/
713 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
714 {
715         GLuint id = m_invalid_id;
716
717         gl.genTextures(1, &id);
718         GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
719
720         if (m_invalid_id == id)
721         {
722                 TCU_FAIL("Invalid id");
723         }
724
725         out_id = id;
726 }
727
728 /** Get texture data
729  *
730  * @param gl       GL functions
731  * @param target   Texture target
732  * @param format   Format of data
733  * @param type     Type of data
734  * @param out_data Buffer for data
735  **/
736 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
737                                           glw::GLenum type, glw::GLvoid* out_data)
738 {
739         gl.getTexImage(target, level, format, type, out_data);
740         GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
741 }
742
743 /** Get texture data
744  *
745  * @param gl       GL functions
746  * @param id       Texture id
747  * @param level    Mipmap level
748  * @param width    Texture width
749  * @param height   Texture height
750  * @param format   Format of data
751  * @param type     Type of data
752  * @param out_data Buffer for data
753  **/
754 void Texture::GetData(const glw::Functions& gl, glw::GLuint id, glw::GLint level, glw::GLuint width, glw::GLuint height,
755                                           glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data)
756 {
757         GLuint fbo;
758         gl.genFramebuffers(1, &fbo);
759         GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
760         gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
761         GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
762         gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, level);
763         GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
764
765         gl.readPixels(0, 0, width, height, format, type, out_data);
766         GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
767
768         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
769 }
770
771 /** Generate texture instance
772  *
773  * @param gl     GL functions
774  * @param target Texture target
775  * @param level  Mipmap level
776  * @param pname  Parameter to query
777  * @param param  Result of query
778  **/
779 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
780                                                                 glw::GLint* param)
781 {
782         gl.getTexLevelParameteriv(target, level, pname, param);
783         GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
784 }
785
786 /** Set contents of texture
787  *
788  * @param gl              GL functions
789  * @param target          Texture target
790  * @param level           Mipmap level
791  * @param internal_format Format of data
792  * @param width           Width of texture
793  * @param height          Height of texture
794  * @param depth           Depth of texture
795  * @param format          Format of data
796  * @param type            Type of data
797  * @param data            Buffer with image data
798  **/
799 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
800                                         glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
801                                         const glw::GLvoid* data)
802 {
803         switch (target)
804         {
805         case GL_TEXTURE_1D:
806                 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
807                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
808                 break;
809         case GL_TEXTURE_1D_ARRAY:
810         case GL_TEXTURE_2D:
811         case GL_TEXTURE_RECTANGLE:
812                 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
813                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
814                 break;
815         case GL_TEXTURE_CUBE_MAP:
816                 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
817                                           type, data);
818                 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
819                                           type, data);
820                 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
821                                           type, data);
822                 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
823                                           type, data);
824                 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
825                                           type, data);
826                 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
827                                           type, data);
828                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
829                 break;
830         case GL_TEXTURE_3D:
831         case GL_TEXTURE_2D_ARRAY:
832                 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
833                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
834                 break;
835         default:
836                 TCU_FAIL("Invliad enum");
837                 break;
838         }
839 }
840
841 /** Allocate storage for texture
842  *
843  * @param gl              GL functions
844  * @param target          Texture target
845  * @param levels          Number of levels
846  * @param internal_format Internal format of texture
847  * @param width           Width of texture
848  * @param height          Height of texture
849  * @param depth           Depth of texture
850  **/
851 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
852                                           glw::GLuint width, glw::GLuint height, glw::GLuint depth)
853 {
854         switch (target)
855         {
856         case GL_TEXTURE_1D:
857                 gl.texStorage1D(target, levels, internal_format, width);
858                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
859                 break;
860         case GL_TEXTURE_1D_ARRAY:
861         case GL_TEXTURE_2D:
862         case GL_TEXTURE_RECTANGLE:
863         case GL_TEXTURE_CUBE_MAP:
864                 gl.texStorage2D(target, levels, internal_format, width, height);
865                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
866                 break;
867         case GL_TEXTURE_2D_MULTISAMPLE:
868                 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
869                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
870                 break;
871         case GL_TEXTURE_3D:
872         case GL_TEXTURE_2D_ARRAY:
873                 gl.texStorage3D(target, levels, internal_format, width, height, depth);
874                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
875                 break;
876         default:
877                 TCU_FAIL("Invliad enum");
878                 break;
879         }
880 }
881
882 /** Set contents of texture
883  *
884  * @param gl              GL functions
885  * @param target          Texture target
886  * @param level           Mipmap level
887  * @param x               X offset
888  * @param y               Y offset
889  * @param z               Z offset
890  * @param width           Width of texture
891  * @param height          Height of texture
892  * @param depth           Depth of texture
893  * @param format          Format of data
894  * @param type            Type of data
895  * @param pixels          Buffer with image data
896  **/
897 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
898                                            glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
899                                            glw::GLenum type, const glw::GLvoid* pixels)
900 {
901         switch (target)
902         {
903         case GL_TEXTURE_1D:
904                 gl.texSubImage1D(target, level, x, width, format, type, pixels);
905                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
906                 break;
907         case GL_TEXTURE_1D_ARRAY:
908         case GL_TEXTURE_2D:
909         case GL_TEXTURE_RECTANGLE:
910                 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
911                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
912                 break;
913         case GL_TEXTURE_CUBE_MAP:
914                 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
915                 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
916                 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
917                 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
918                 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
919                 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
920                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
921                 break;
922         case GL_TEXTURE_3D:
923         case GL_TEXTURE_2D_ARRAY:
924                 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
925                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
926                 break;
927         default:
928                 TCU_FAIL("Invliad enum");
929                 break;
930         }
931 }
932
933 /* VertexArray constants */
934 const GLuint VertexArray::m_invalid_id = -1;
935
936 /** Constructor.
937  *
938  * @param context CTS context.
939  **/
940 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
941 {
942 }
943
944 /** Destructor
945  *
946  **/
947 VertexArray::~VertexArray()
948 {
949         Release();
950 }
951
952 /** Release vertex array object instance
953  *
954  **/
955 void VertexArray::Release()
956 {
957         if (m_invalid_id != m_id)
958         {
959                 const Functions& gl = m_context.getRenderContext().getFunctions();
960
961                 Bind(gl, 0);
962
963                 gl.deleteVertexArrays(1, &m_id);
964
965                 m_id = m_invalid_id;
966         }
967 }
968
969 /** Binds Vertex array object
970  *
971  * @param gl GL functions
972  * @param id ID of vertex array object
973  **/
974 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
975 {
976         gl.bindVertexArray(id);
977         GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
978 }
979
980 /** Generates Vertex array object
981  *
982  * @param gl     GL functions
983  * @param out_id ID of vertex array object
984  **/
985 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
986 {
987         GLuint id = m_invalid_id;
988
989         gl.genVertexArrays(1, &id);
990         GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
991
992         if (m_invalid_id == id)
993         {
994                 TCU_FAIL("Invalid id");
995         }
996
997         out_id = id;
998 }
999
1000 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1001  *
1002  * @param token           Token string
1003  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1004  * @param text            String that will be used as replacement for <token>
1005  * @param string          String to work on
1006  **/
1007 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1008 {
1009         const size_t text_length        = strlen(text);
1010         const size_t token_length   = strlen(token);
1011         const size_t token_position = string.find(token, search_position);
1012
1013         string.replace(token_position, token_length, text, text_length);
1014
1015         search_position = token_position + text_length;
1016 }
1017
1018 /** Constructor
1019  *
1020  * @param context Test context
1021  **/
1022 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context)
1023         : TestCase(context, "vertex_buffer_objects", "Verifies that out-of-bound reads from VB result in zero")
1024 {
1025         /* Nothing to be done */
1026 }
1027
1028 /** Constructor
1029  *
1030  * @param context Test context
1031  **/
1032 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context, const char* name, const char* description)
1033         : TestCase(context, name, description)
1034 {
1035         /* Nothing to be done */
1036 }
1037
1038 /** Execute test
1039  *
1040  * @return tcu::TestNode::STOP
1041  **/
1042 tcu::TestNode::IterateResult VertexBufferObjectsTest::iterate()
1043 {
1044         static const GLuint invalid_elements[] = {
1045                 9, 1, 2, 10, 2, 3, 11, 3, 4, 12, 4, 5, 13, 5, 6, 14, 6, 7, 15, 7, 8, 16, 8, 1,
1046         };
1047
1048         static const GLuint valid_elements[] = {
1049                 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
1050         };
1051
1052         static const GLfloat vertices[] = {
1053                 0.0f,  0.0f,  0.0f, /* 0 */
1054                 -1.0f, 0.0f,  0.0f, /* 1 */
1055                 -1.0f, 1.0f,  0.0f, /* 2 */
1056                 0.0f,  1.0f,  0.0f, /* 3 */
1057                 1.0f,  1.0f,  0.0f, /* 4 */
1058                 1.0f,  0.0f,  0.0f, /* 5 */
1059                 1.0f,  -1.0f, 0.0f, /* 6 */
1060                 0.0f,  -1.0f, 0.0f, /* 7 */
1061                 -1.0f, -1.0f, 0.0f, /* 8 */
1062         };
1063
1064         static const GLuint height       = 8;
1065         static const GLuint n_vertices = 24;
1066         static const GLuint width         = 8;
1067
1068         /* GL entry points */
1069         const Functions& gl = m_context.getRenderContext().getFunctions();
1070
1071         /* Test result indicator */
1072         bool test_result = true;
1073
1074         /* Test case objects */
1075         Framebuffer framebuffer(m_context);
1076         Buffer          invalid_elements_buffer(m_context);
1077         Program         program(m_context);
1078         Texture         texture(m_context);
1079         Buffer          valid_elements_buffer(m_context);
1080         Buffer          vertices_buffer(m_context);
1081         VertexArray vao(m_context);
1082
1083         /* Vertex array */
1084         VertexArray::Generate(gl, vao.m_id);
1085         VertexArray::Bind(gl, vao.m_id);
1086
1087         /* Buffers initialization */
1088         invalid_elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(invalid_elements),
1089                                                                          invalid_elements);
1090         valid_elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(valid_elements), valid_elements);
1091         vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices);
1092
1093         /* Texture initialization */
1094         Texture::Generate(gl, texture.m_id);
1095         Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
1096         Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0);
1097         Texture::Bind(gl, 0, GL_TEXTURE_2D);
1098
1099         /* Framebuffer initialization*/
1100         Framebuffer::Generate(gl, framebuffer.m_id);
1101         Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1102         Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
1103                                                            height);
1104
1105         /* Shaders initialization */
1106         program.Init("" /* cs */, getFragmentShader(), "" /* gs */, "" /* tcs */, "" /* tes */, getVertexShader());
1107         Program::Use(gl, program.m_id);
1108
1109         /* Vertex buffer initialization */
1110         vertices_buffer.Bind();
1111         gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 12 /* stride */);
1112         gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, NULL);
1113         gl.enableVertexAttribArray(0 /* location */);
1114
1115         /* Binding elements/indices buffer */
1116         valid_elements_buffer.Bind();
1117
1118         cleanTexture(texture.m_id);
1119
1120         gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1121         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1122
1123         if (false == verifyValidResults(texture.m_id))
1124         {
1125                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for valid input"
1126                                                                                         << tcu::TestLog::EndMessage;
1127
1128                 test_result = false;
1129         }
1130
1131         /* Binding elements/indices buffer */
1132         invalid_elements_buffer.Bind();
1133
1134         cleanTexture(texture.m_id);
1135
1136         gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1137         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1138
1139         if (false == verifyInvalidResults(texture.m_id))
1140         {
1141                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for invalid input"
1142                                                                                         << tcu::TestLog::EndMessage;
1143
1144                 test_result = false;
1145         }
1146
1147         /* Set result */
1148         if (true == test_result)
1149         {
1150                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1151         }
1152         else
1153         {
1154                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1155         }
1156
1157         /* Done */
1158         return tcu::TestNode::STOP;
1159 }
1160
1161 /** Prepare shader for current test case
1162  *
1163  * @return Source
1164  **/
1165 std::string VertexBufferObjectsTest::getFragmentShader()
1166 {
1167         return std::string("#version 430 core\n"
1168                                            "\n"
1169                                            "layout (location = 0) out vec4 out_fs_color;\n"
1170                                            "\n"
1171                                            "void main()\n"
1172                                            "{\n"
1173                                            "    out_fs_color = vec4(1.0 / 256.0, 1.0, 1.0, 1.0);\n"
1174                                            "}\n"
1175                                            "\n");
1176 }
1177
1178 /** Prepare shader for current test case
1179  *
1180  * @return Source
1181  **/
1182 std::string VertexBufferObjectsTest::getVertexShader()
1183 {
1184         return std::string("#version 430 core\n"
1185                                            "\n"
1186                                            "layout (location = 0) in vec4 in_vs_position;\n"
1187                                            "\n"
1188                                            "void main()\n"
1189                                            "{\n"
1190                                            "    gl_Position = in_vs_position;\n"
1191                                            "}\n"
1192                                            "\n");
1193 }
1194
1195 /** Fill texture with value 128
1196  *
1197  * @param texture_id Id of texture
1198  **/
1199 void VertexBufferObjectsTest::cleanTexture(glw::GLuint texture_id)
1200 {
1201         static const GLuint height = 8;
1202         static const GLuint width  = 8;
1203
1204         const Functions& gl = m_context.getRenderContext().getFunctions();
1205
1206         GLubyte pixels[width * height];
1207         for (GLuint i = 0; i < width * height; ++i)
1208         {
1209                 pixels[i] = 128;
1210         }
1211
1212         Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1213
1214         Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level  */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
1215                                           GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1216
1217         /* Unbind */
1218         Texture::Bind(gl, 0, GL_TEXTURE_2D);
1219 }
1220
1221 /** Verifies that texutre is filled with 1
1222  *
1223  * @param texture_id Id of texture
1224  *
1225  * @return true when image is filled with 1, false otherwise
1226  **/
1227 bool VertexBufferObjectsTest::verifyInvalidResults(glw::GLuint texture_id)
1228 {
1229         return verifyResults(texture_id);
1230 }
1231
1232 /** Verifies that texutre is filled with 1
1233  *
1234  * @param texture_id Id of texture
1235  *
1236  * @return true when image is filled with 1, false otherwise
1237  **/
1238 bool VertexBufferObjectsTest::verifyValidResults(glw::GLuint texture_id)
1239 {
1240         return verifyResults(texture_id);
1241 }
1242
1243 /** Verifies that texutre is filled with 1
1244  *
1245  * @param texture_id Id of texture
1246  *
1247  * @return true when image is filled with 1, false otherwise
1248  **/
1249 bool VertexBufferObjectsTest::verifyResults(glw::GLuint texture_id)
1250 {
1251         static const GLuint height = 8;
1252         static const GLuint width  = 8;
1253
1254         const Functions& gl = m_context.getRenderContext().getFunctions();
1255
1256         GLubyte pixels[width * height];
1257         for (GLuint i = 0; i < width * height; ++i)
1258         {
1259                 pixels[i] = 0;
1260         }
1261
1262         Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1263
1264         Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1265
1266         /* Unbind */
1267         Texture::Bind(gl, 0, GL_TEXTURE_2D);
1268
1269         /* Verify */
1270         for (GLuint i = 0; i < width * height; ++i)
1271         {
1272                 if (255 != pixels[i])
1273                 {
1274                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
1275                                                                                                 << " at offset: " << i << tcu::TestLog::EndMessage;
1276
1277                         return false;
1278                 }
1279         }
1280
1281         return true;
1282 }
1283
1284 /** Constructor
1285  *
1286  * @param context Test context
1287  **/
1288 TexelFetchTest::TexelFetchTest(deqp::Context& context)
1289         : TestCase(context, "texel_fetch", "Verifies that out-of-bound fetches from texture result in zero")
1290         , m_test_case(R8)
1291 {
1292         /* Nothing to be done */
1293 }
1294
1295 /** Constructor
1296  *
1297  * @param context Test context
1298  **/
1299 TexelFetchTest::TexelFetchTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
1300         : TestCase(context, name, description), m_test_case(R8)
1301 {
1302         /* Nothing to be done */
1303 }
1304
1305 /** Execute test
1306  *
1307  * @return tcu::TestNode::STOP
1308  **/
1309 tcu::TestNode::IterateResult TexelFetchTest::iterate()
1310 {
1311         /* Constants */
1312         static const GLuint height = 16;
1313         static const GLuint width  = 16;
1314
1315         /* GL entry points */
1316         const Functions& gl = m_context.getRenderContext().getFunctions();
1317
1318         /* Test result indicator */
1319         bool test_result = true;
1320
1321         /* Iterate over all cases */
1322         for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
1323         {
1324                 bool   case_result      = true;
1325                 GLint  level              = 0;
1326                 GLenum texture_target = GL_TEXTURE_2D;
1327
1328                 if (R32UI_MULTISAMPLE == m_test_case || RG8_SNORM == m_test_case)
1329                 {
1330                         // 1. RG8_SNORM case:
1331                         // Skip RG8_SNORM format case.
1332                         // RG8_SNORM is not required to be used as a render target
1333                         // OpenGL 4.5 Core Spec, Page 197
1334                         //
1335                         // 2. R32UI_MULTISAMPLE case
1336                         // Skip test in multi sample case
1337                         // texelFetch with invalid lod plane results undefined value
1338                         // OpenGL 4.5 Core Spec, around page 377
1339                         m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
1340                         continue;
1341                 }
1342
1343                 /* */
1344                 Texture         destination_texture(m_context);
1345                 Framebuffer framebuffer(m_context);
1346                 Program         invalid_program(m_context);
1347                 Texture         source_texture(m_context);
1348                 Program         valid_program(m_context);
1349                 VertexArray vao(m_context);
1350
1351                 const std::string& fs_invalid = getFragmentShader(false);
1352                 const std::string& fs_valid   = getFragmentShader(true);
1353
1354                 /* Prepare VAO */
1355                 VertexArray::Generate(gl, vao.m_id);
1356                 VertexArray::Bind(gl, vao.m_id);
1357
1358                 /* Prepare textures */
1359                 Texture::Generate(gl, destination_texture.m_id);
1360                 Texture::Generate(gl, source_texture.m_id);
1361
1362                 if (R32UI_MULTISAMPLE == m_test_case)
1363                 {
1364                         GLint max_integer_samples;
1365                         gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
1366                         GLint max_image_samples;
1367                         gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
1368                         if (max_integer_samples < 4 || max_image_samples < 4)
1369                         {
1370                                 /* prepareTexture() hard-codes 4 samples (n_levels) for
1371                                  * R32UI_MULTISAMPLE case. This value exceeds the required
1372                                  * min-max value (1 in OpenGL ES 3.2) and is not supported
1373                                  * by all implementations.
1374                                  *
1375                                  * Also, the test uses a compute shader with images
1376                                  * to upload the texture so max_image_samples >= 4
1377                                  * is also required.
1378                                  */
1379                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1380                                                                                                         << " not supported" << tcu::TestLog::EndMessage;
1381
1382                                 continue;
1383                         }
1384                 }
1385
1386                 prepareTexture(false, destination_texture.m_id);
1387                 prepareTexture(true, source_texture.m_id);
1388
1389                 /* Select FBO settings */
1390                 if (R32UI_MIPMAP == m_test_case)
1391                 {
1392                         level = 1;
1393                 }
1394                 else if (R32UI_MULTISAMPLE == m_test_case)
1395                 {
1396                         texture_target = GL_TEXTURE_2D_MULTISAMPLE;
1397                 }
1398
1399                 /* Prepare FBO */
1400                 Framebuffer::Generate(gl, framebuffer.m_id);
1401                 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1402                 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destination_texture.m_id, level,
1403                                                                    width, height);
1404
1405                 /* Prepare programs */
1406                 valid_program.Init("" /* cs */, fs_valid, getGeometryShader(), "" /* tcs */, "" /* tes */, getVertexShader());
1407                 invalid_program.Init("" /* cs */, fs_invalid, getGeometryShader(), "" /* tcs */, "" /* tes */,
1408                                                          getVertexShader());
1409
1410                 /* Test valid case */
1411                 /* Set program */
1412                 Program::Use(gl, valid_program.m_id);
1413
1414                 /* Set texture */
1415                 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1416                 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1417                 Texture::Bind(gl, source_texture.m_id, texture_target);
1418                 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1419                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1420
1421                 /* Check if setup is supported */
1422                 GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1423                 GLU_EXPECT_NO_ERROR(gl.getError(), "CheckFramebufferStatus");
1424                 if (GL_FRAMEBUFFER_COMPLETE != fbo_status)
1425                 {
1426                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1427                                                                                                 << " not supported" << tcu::TestLog::EndMessage;
1428
1429                         continue;
1430                 }
1431
1432                 /* Enable multisampling */
1433                 if (R32UI_MULTISAMPLE == m_test_case)
1434                 {
1435                         gl.enable(GL_MULTISAMPLE);
1436                         GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
1437                 }
1438
1439                 /* Draw */
1440                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1441                 {
1442                         /* Get error from draw */
1443                         GLenum error = gl.getError();
1444
1445                         /* Disable multisampling */
1446                         if (R32UI_MULTISAMPLE == m_test_case)
1447                         {
1448                                 gl.disable(GL_MULTISAMPLE);
1449                                 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
1450                         }
1451
1452                         /* Handle error from draw */
1453                         GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1454                 }
1455
1456                 /* Verification */
1457                 if (false == verifyValidResults(destination_texture.m_id))
1458                 {
1459                         case_result = false;
1460                 }
1461
1462                 /* Test invalid case */
1463                 /* Set program */
1464                 Program::Use(gl, invalid_program.m_id);
1465
1466                 /* Set texture */
1467                 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1468                 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1469                 Texture::Bind(gl, source_texture.m_id, texture_target);
1470                 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1471                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1472
1473                 /* Draw */
1474                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1475                 {
1476                         /* Get error from draw */
1477                         GLenum error = gl.getError();
1478
1479                         /* Handle error from draw */
1480                         GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1481                 }
1482
1483                 /* Verification */
1484                 if (false == verifyInvalidResults(destination_texture.m_id))
1485                 {
1486                         case_result = false;
1487                 }
1488
1489                 /* Set test result */
1490                 if (false == case_result)
1491                 {
1492                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1493                                                                                                 << " failed" << tcu::TestLog::EndMessage;
1494
1495                         test_result = false;
1496                 }
1497         }
1498
1499         /* Set result */
1500         if (true == test_result)
1501         {
1502                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1503         }
1504         else
1505         {
1506                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1507         }
1508
1509         /* Done */
1510         return tcu::TestNode::STOP;
1511 }
1512
1513 /** Prepares source code for fragment shader
1514  *
1515  * @param is_case_valid Selects if valid or invalid case is tested
1516  *
1517  * @return string with prepared code
1518  **/
1519 std::string TexelFetchTest::getFragmentShader(bool is_case_valid)
1520 {
1521         static const GLchar* plane_0 = "    int   plane  = 0;\n";
1522
1523         static const GLchar* plane_1 = "    int   plane  = 1;\n";
1524
1525         static const GLchar* plane_2 = "    int   plane  = 2;\n";
1526
1527         static const GLchar* plane_sample_invalid = "    int   plane  = 9;\n";
1528         //"    int   plane  = gl_SampleID + 4;\n";
1529
1530         static const GLchar* plane_sample_valid = "    int   plane  = gl_SampleID;\n";
1531
1532         static const GLchar* point_invalid = "    ivec2 point  = ivec2(gs_fs_tex_coord * 16.0) + ivec2(16, 16);\n";
1533
1534         static const GLchar* point_valid = "    ivec2 point  = ivec2(gs_fs_tex_coord * 16.0);\n";
1535
1536         static const GLchar* sampler_regular            = "sampler2D";
1537         static const GLchar* sampler_regular_u          = "usampler2D";
1538         static const GLchar* sampler_multisampled_u = "usampler2DMS";
1539
1540         static const GLchar* template_code = "#version 430 core\n"
1541                                                                                  "\n"
1542                                                                                  "                      in      vec2      gs_fs_tex_coord;\n"
1543                                                                                  "layout (location = 0) out     TYPE      out_fs_color;\n"
1544                                                                                  "layout (location = 0) uniform SAMPLER uni_texture;\n"
1545                                                                                  "\n"
1546                                                                                  "void main()\n"
1547                                                                                  "{\n"
1548                                                                                  "PLANE\n"
1549                                                                                  "POINT\n"
1550                                                                                  "    out_fs_color = texelFetch(uni_texture, point, plane);\n"
1551                                                                                  "}\n"
1552                                                                                  "\n";
1553
1554         static const GLchar* type_vec4  = "vec4";
1555         static const GLchar* type_uvec4 = "uvec4";
1556
1557         const GLchar* plane   = plane_0;
1558         const GLchar* point   = point_valid;
1559         const GLchar* sampler = sampler_regular;
1560         const GLchar* type      = type_vec4;
1561
1562         if ((R8 == m_test_case) || (RG8_SNORM == m_test_case) || (RGBA32F == m_test_case))
1563         {
1564                 if (false == is_case_valid)
1565                 {
1566                         point = point_invalid;
1567                 }
1568         }
1569         else if (R32UI_MIPMAP == m_test_case)
1570         {
1571                 plane   = plane_1;
1572                 sampler = sampler_regular_u;
1573                 type    = type_uvec4;
1574
1575                 if (false == is_case_valid)
1576                 {
1577                         plane = plane_2;
1578                 }
1579         }
1580         else if (R32UI_MULTISAMPLE == m_test_case)
1581         {
1582                 plane   = plane_sample_valid;
1583                 sampler = sampler_multisampled_u;
1584                 type    = type_uvec4;
1585
1586                 if (false == is_case_valid)
1587                 {
1588                         plane = plane_sample_invalid;
1589                 }
1590         }
1591
1592         size_t          position = 0;
1593         std::string source   = template_code;
1594         replaceToken("TYPE", position, type, source);
1595         replaceToken("SAMPLER", position, sampler, source);
1596         replaceToken("PLANE", position, plane, source);
1597         replaceToken("POINT", position, point, source);
1598
1599         return source;
1600 }
1601
1602 /** Prepare shader for current test case
1603  *
1604  * @return Source
1605  **/
1606 std::string TexelFetchTest::getGeometryShader()
1607 {
1608         return std::string("#version 430 core\n"
1609                                            "\n"
1610                                            "layout(points)                           in;\n"
1611                                            "layout(triangle_strip, max_vertices = 4) out;\n"
1612                                            "\n"
1613                                            "out vec2 gs_fs_tex_coord;\n"
1614                                            "\n"
1615                                            "void main()\n"
1616                                            "{\n"
1617                                            "    gs_fs_tex_coord = vec2(0, 0);\n"
1618                                            "    gl_Position     = vec4(-1, -1, 0, 1);\n"
1619                                            "    EmitVertex();\n"
1620                                            "\n"
1621                                            "    gs_fs_tex_coord = vec2(0, 1);\n"
1622                                            "    gl_Position     = vec4(-1, 1, 0, 1);\n"
1623                                            "    EmitVertex();\n"
1624                                            "\n"
1625                                            "    gs_fs_tex_coord = vec2(1, 0);\n"
1626                                            "    gl_Position     = vec4(1, -1, 0, 1);\n"
1627                                            "    EmitVertex();\n"
1628                                            "\n"
1629                                            "    gs_fs_tex_coord = vec2(1, 1);\n"
1630                                            "    gl_Position     = vec4(1, 1, 0, 1);\n"
1631                                            "    EmitVertex();\n"
1632                                            "}\n"
1633                                            "\n");
1634 }
1635
1636 /** Prepare shader for current test case
1637  *
1638  * @return Source
1639  **/
1640 std::string TexelFetchTest::getVertexShader()
1641 {
1642         return std::string("#version 430 core\n"
1643                                            "\n"
1644                                            "void main()\n"
1645                                            "{\n"
1646                                            "    gl_Position = vec4(0, 0, 0, 1);\n"
1647                                            "}\n"
1648                                            "\n");
1649 }
1650
1651 /** Returns name of current test case
1652  *
1653  * @return Name of test case
1654  **/
1655 const glw::GLchar* TexelFetchTest::getTestCaseName() const
1656 {
1657         const GLchar* name = "";
1658
1659         switch (m_test_case)
1660         {
1661         case R8:
1662                 name = "\"Sampling GL_R8 texture\"";
1663                 break;
1664         case RG8_SNORM:
1665                 name = "\"Sampling GL_RG8_SNORM  texture\"";
1666                 break;
1667         case RGBA32F:
1668                 name = "\"Sampling GL_RGBA32F  texture\"";
1669                 break;
1670         case R32UI_MIPMAP:
1671                 name = "\"Sampling mipmap of GL_32UI texture\"";
1672                 break;
1673         case R32UI_MULTISAMPLE:
1674                 name = "\"Sampling GL_32UI multisampled texture\"";
1675                 break;
1676         default:
1677                 TCU_FAIL("Invalid enum");
1678                 break;
1679         }
1680
1681         return name;
1682 }
1683
1684 /** Prepare a texture
1685  *
1686  * @param is_source  Selects if texutre will be used as source or destination
1687  * @param texture_id Id of texutre
1688  **/
1689 void TexelFetchTest::prepareTexture(bool is_source, glw::GLuint texture_id)
1690 {
1691         /* Image size */
1692         static const GLuint image_height = 16;
1693         static const GLuint image_width  = 16;
1694
1695         /* GL entry points */
1696         const Functions& gl = m_context.getRenderContext().getFunctions();
1697
1698         /* Texture storage parameters */
1699         GLuint  height                  = image_height;
1700         GLenum  internal_format = 0;
1701         GLsizei n_levels                = 1;
1702         GLenum  target                  = GL_TEXTURE_2D;
1703         GLuint  width                   = image_width;
1704
1705         /* Prepare texture storage parameters */
1706         switch (m_test_case)
1707         {
1708         case R8:
1709                 internal_format = GL_R8;
1710                 break;
1711         case RG8_SNORM:
1712                 internal_format = GL_RG8_SNORM;
1713                 break;
1714         case RGBA32F:
1715                 internal_format = GL_RGBA32F;
1716                 break;
1717         case R32UI_MIPMAP:
1718                 height                  = 2 * image_height;
1719                 internal_format = GL_R32UI;
1720                 n_levels                = 2;
1721                 width                   = 2 * image_width;
1722                 break;
1723         case R32UI_MULTISAMPLE:
1724                 internal_format = GL_R32UI;
1725                 n_levels                = 4;
1726                 target                  = GL_TEXTURE_2D_MULTISAMPLE;
1727                 break;
1728         default:
1729                 TCU_FAIL("Invalid enum");
1730         }
1731
1732         /* Prepare storage */
1733         Texture::Bind(gl, texture_id, target);
1734         Texture::Storage(gl, target, n_levels, internal_format, width, height, 0);
1735
1736         gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1737         gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1738
1739         /* Destination image can be left empty */
1740         if (false == is_source)
1741         {
1742                 Texture::Bind(gl, 0, target);
1743                 return;
1744         }
1745
1746         /* Prepare texture */
1747         if (R8 == m_test_case)
1748         {
1749                 GLubyte source_pixels[image_width * image_height];
1750                 for (GLuint i = 0; i < image_width * image_height; ++i)
1751                 {
1752                         source_pixels[i] = static_cast<GLubyte>(i);
1753                 }
1754
1755                 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1756                                                   0 /* depth */, GL_RED, GL_UNSIGNED_BYTE, source_pixels);
1757         }
1758         else if (RG8_SNORM == m_test_case)
1759         {
1760                 static const GLuint n_components = 2;
1761
1762                 GLbyte source_pixels[image_width * image_height * n_components];
1763                 for (GLuint i = 0; i < image_width * image_height; ++i)
1764                 {
1765                         source_pixels[i * n_components + 0] = static_cast<GLubyte>((i % 16) - 8);
1766                         source_pixels[i * n_components + 1] = static_cast<GLubyte>((i / 16) - 8);
1767                 }
1768
1769                 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1770                                                   0 /* depth */, GL_RG, GL_BYTE, source_pixels);
1771         }
1772         else if (RGBA32F == m_test_case)
1773         {
1774                 static const GLuint n_components = 4;
1775
1776                 GLfloat source_pixels[image_width * image_height * n_components];
1777                 for (GLuint i = 0; i < image_width * image_height; ++i)
1778                 {
1779                         source_pixels[i * n_components + 0] = (GLfloat)(i % 16) / 16.0f;
1780                         source_pixels[i * n_components + 1] = (GLfloat)(i / 16) / 16.0f;
1781                         source_pixels[i * n_components + 2] = (GLfloat)i / 256.0f;
1782                         source_pixels[i * n_components + 3] = 1.0f;
1783                 }
1784
1785                 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1786                                                   0 /* depth */, GL_RGBA, GL_FLOAT, source_pixels);
1787         }
1788         else if (R32UI_MIPMAP == m_test_case)
1789         {
1790                 GLuint source_pixels[image_width * image_height];
1791                 for (GLuint i = 0; i < image_width * image_height; ++i)
1792                 {
1793                         source_pixels[i] = i;
1794                 }
1795
1796                 Texture::SubImage(gl, GL_TEXTURE_2D, 1 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, image_width, image_height,
1797                                                   0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_INT, source_pixels);
1798         }
1799         else if (R32UI_MULTISAMPLE == m_test_case)
1800         {
1801                 /* Compute shader */
1802                 static const GLchar* cs = "#version 430 core\n"
1803                                                                   "\n"
1804                                                                   "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1805                                                                   "\n"
1806                                                                   "layout (location = 0) writeonly uniform uimage2DMS uni_image;\n"
1807                                                                   "\n"
1808                                                                   "void main()\n"
1809                                                                   "{\n"
1810                                                                   "    const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
1811                                                                   "    const uint  index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
1812                                                                   "\n"
1813                                                                   "    imageStore(uni_image, point, 0, uvec4(index + 0, 0, 0, 0));\n"
1814                                                                   "    imageStore(uni_image, point, 1, uvec4(index + 1, 0, 0, 0));\n"
1815                                                                   "    imageStore(uni_image, point, 2, uvec4(index + 2, 0, 0, 0));\n"
1816                                                                   "    imageStore(uni_image, point, 3, uvec4(index + 3, 0, 0, 0));\n"
1817                                                                   "}\n"
1818                                                                   "\n";
1819
1820                 Program program(m_context);
1821                 program.Init(cs, "", "", "", "", "");
1822                 program.Use();
1823
1824                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1825                                                         GL_WRITE_ONLY, GL_R32UI);
1826                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1827
1828                 gl.uniform1i(0 /* location */, 0 /* image unit*/);
1829                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1830
1831                 gl.dispatchCompute(16, 16, 1);
1832                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1833         }
1834
1835         Texture::Bind(gl, 0, target);
1836 }
1837
1838 /** Verifies that texutre is filled with 0 or with (0, 0, 0, x),
1839  *  where x may be 0, 1 or the biggest representable integer value.
1840  *
1841  * @param texture_id Id of texture
1842  *
1843  * @return true when image is filled with 0, 1 or biggest represetable integer number, false otherwise
1844  **/
1845 bool TexelFetchTest::verifyInvalidResults(glw::GLuint texture_id)
1846 {
1847         static const GLuint height   = 16;
1848         static const GLuint width       = 16;
1849         static const GLuint n_pixels = height * width;
1850
1851         const Functions& gl = m_context.getRenderContext().getFunctions();
1852
1853         bool result = true;
1854
1855         if (R8 == m_test_case)
1856         {
1857                 static const GLuint n_channels = 1;
1858
1859                 std::vector<GLubyte> pixels;
1860                 pixels.resize(n_pixels * n_channels);
1861                 for (GLuint i = 0; i < n_pixels; ++i)
1862                 {
1863                         pixels[i] = static_cast<GLubyte>(i);
1864                 }
1865
1866                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1867
1868                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
1869
1870                 /* Unbind */
1871                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1872
1873                 /* Verify */
1874                 for (GLuint i = 0; i < n_pixels; ++i)
1875                 {
1876                         const GLubyte expected_red = 0;
1877                         const GLubyte drawn_red = pixels[i];
1878
1879                         if (expected_red != drawn_red)
1880                         {
1881                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
1882                                                                                                         << ". Expected value: " << (GLuint)expected_red
1883                                                                                                         << " at offset: " << i << tcu::TestLog::EndMessage;
1884
1885                                 result = false;
1886                                 break;
1887                         }
1888                 }
1889         }
1890         else if (RG8_SNORM == m_test_case)
1891         {
1892                 static const GLuint n_channels = 2;
1893
1894                 std::vector<GLbyte> pixels;
1895                 pixels.resize(n_pixels * n_channels);
1896                 for (GLuint i = 0; i < n_pixels; ++i)
1897                 {
1898                         pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
1899                         pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
1900                 }
1901
1902                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1903
1904                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
1905
1906                 /* Unbind */
1907                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1908
1909                 /* Verify */
1910                 for (GLuint i = 0; i < n_pixels; ++i)
1911                 {
1912                         const GLbyte expected_red   = 0;
1913                         const GLbyte expected_green = 0;
1914                         const GLbyte drawn_red          = pixels[i * n_channels + 0];
1915                         const GLbyte drawn_green        = pixels[i * n_channels + 1];
1916
1917                         if ((expected_red != drawn_red) || (expected_green != drawn_green))
1918                         {
1919                                 m_context.getTestContext().getLog()
1920                                         << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
1921                                         << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
1922                                         << ". At offset: " << i << tcu::TestLog::EndMessage;
1923
1924                                 result = false;
1925                                 break;
1926                         }
1927                 }
1928         }
1929         else if (RGBA32F == m_test_case)
1930         {
1931                 static const GLuint n_channels = 4;
1932
1933                 std::vector<GLfloat> pixels;
1934                 pixels.resize(n_pixels * n_channels);
1935                 for (GLuint i = 0; i < n_pixels; ++i)
1936                 {
1937                         pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
1938                         pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
1939                         pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
1940                         pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
1941                 }
1942
1943                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1944
1945                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
1946
1947                 /* Unbind */
1948                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1949
1950                 /* Verify */
1951                 for (GLuint i = 0; i < n_pixels; ++i)
1952                 {
1953                         const GLfloat expected_red   = 0.0f;
1954                         const GLfloat expected_green = 0.0f;
1955                         const GLfloat expected_blue  = 0.0f;
1956                         const GLfloat expected_alpha_0 =
1957                                 0.0f; /* OpenGL 4.5 (and ES) specifies two possiblities (0 or 1) for alpha channel (Chapter 11.1.3.12). */
1958                         const GLfloat expected_alpha_1 = 1.0f;
1959                         const GLfloat drawn_red            = pixels[i * n_channels + 0];
1960                         const GLfloat drawn_green         = pixels[i * n_channels + 1];
1961                         const GLfloat drawn_blue           = pixels[i * n_channels + 2];
1962                         const GLfloat drawn_alpha         = pixels[i * n_channels + 3];
1963
1964                         const GLfloat precision = 0.0009765625; /* (1.f / 1024.f) */
1965
1966                         if ((de::abs(expected_red - drawn_red) > precision) ||
1967                                 (de::abs(expected_green - drawn_green) > precision) ||
1968                                 (de::abs(expected_blue - drawn_blue) > precision) ||
1969                                 ((de::abs(expected_alpha_0 - drawn_alpha) > precision) &&
1970                                  (de::abs(expected_alpha_1 - drawn_alpha) > precision)))
1971                         {
1972                                 m_context.getTestContext().getLog()
1973                                         << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
1974                                         << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
1975                                         << expected_green << ", " << expected_blue << ", " << expected_alpha_0 << " or " << expected_alpha_1
1976                                         << ". At offset: " << i << tcu::TestLog::EndMessage;
1977
1978                                 result = false;
1979                                 break;
1980                         }
1981                 }
1982         }
1983         else if (R32UI_MIPMAP == m_test_case)
1984         {
1985                 static const GLuint n_channels = 1;
1986
1987                 std::vector<GLuint> pixels;
1988                 pixels.resize(n_pixels * n_channels);
1989                 for (GLuint i = 0; i < n_pixels; ++i)
1990                 {
1991                         pixels[i] = i;
1992                 }
1993
1994                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1995
1996                 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
1997
1998                 /* Unbind */
1999                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2000
2001                 /* Verify */
2002                 for (GLuint i = 0; i < n_pixels; ++i)
2003                 {
2004                         const GLuint expected_red = 0;
2005                         const GLuint drawn_red  = pixels[i];
2006
2007                         if (expected_red != drawn_red)
2008                         {
2009                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2010                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
2011                                                                                                         << tcu::TestLog::EndMessage;
2012
2013                                 result = false;
2014                                 break;
2015                         }
2016                 }
2017         }
2018         else if (R32UI_MULTISAMPLE == m_test_case)
2019         {
2020                 static const GLuint n_channels = 1;
2021
2022                 /* Compute shader */
2023                 static const GLchar* cs = "#version 430 core\n"
2024                                                                   "\n"
2025                                                                   "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2026                                                                   "\n"
2027                                                                   "layout (location = 1)        writeonly uniform uimage2D   uni_destination_image;\n"
2028                                                                   "layout (location = 0, r32ui) readonly  uniform uimage2DMS uni_source_image;\n"
2029                                                                   "\n"
2030                                                                   "void main()\n"
2031                                                                   "{\n"
2032                                                                   "    const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2033                                                                   "\n"
2034                                                                   "    const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2035                                                                   "    const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2036                                                                   "    const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2037                                                                   "    const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2038                                                                   "\n"
2039                                                                   "    if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2040                                                                   "    {\n"
2041                                                                   "        imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2042                                                                   "    }\n"
2043                                                                   "    else\n"
2044                                                                   "    {\n"
2045                                                                   "        imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2046                                                                   "    }\n"
2047                                                                   "}\n"
2048                                                                   "\n";
2049
2050                 Program program(m_context);
2051                 Texture destination_texture(m_context);
2052
2053                 Texture::Generate(gl, destination_texture.m_id);
2054                 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2055                 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2056
2057                 program.Init(cs, "", "", "", "", "");
2058                 program.Use();
2059                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2060                                                         GL_READ_ONLY, GL_R32UI);
2061                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2062                 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2063                                                         0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2064                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2065
2066                 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2067                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2068
2069                 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2070                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2071
2072                 gl.dispatchCompute(16, 16, 1);
2073                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2074
2075                 /* Pixels buffer initialization */
2076                 std::vector<GLuint> pixels;
2077                 pixels.resize(n_pixels * n_channels);
2078                 for (GLuint i = 0; i < n_pixels; ++i)
2079                 {
2080                         pixels[i] = i;
2081                 }
2082
2083                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2084
2085                 /* Unbind */
2086                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2087
2088                 /* Verify */
2089                 for (GLuint i = 0; i < n_pixels; ++i)
2090                 {
2091                         const GLuint expected_red = 1;
2092                         const GLuint drawn_red  = pixels[i];
2093
2094                         if (expected_red != drawn_red)
2095                         {
2096                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2097                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
2098                                                                                                         << tcu::TestLog::EndMessage;
2099
2100                                 result = false;
2101                                 break;
2102                         }
2103                 }
2104         }
2105
2106         return result;
2107 }
2108
2109 /** Verifies that texutre is filled with increasing values
2110  *
2111  * @param texture_id Id of texture
2112  *
2113  * @return true when image is filled with increasing values, false otherwise
2114  **/
2115 bool TexelFetchTest::verifyValidResults(glw::GLuint texture_id)
2116 {
2117         static const GLuint height   = 16;
2118         static const GLuint width       = 16;
2119         static const GLuint n_pixels = height * width;
2120
2121         const Functions& gl = m_context.getRenderContext().getFunctions();
2122
2123         bool result = true;
2124
2125         if (R8 == m_test_case)
2126         {
2127                 static const GLuint n_channels = 1;
2128
2129                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2130
2131                 std::vector<GLubyte> pixels;
2132                 pixels.resize(n_pixels * n_channels);
2133                 for (GLuint i = 0; i < n_pixels; ++i)
2134                 {
2135                         pixels[i] = static_cast<GLubyte>(i);
2136                 }
2137
2138                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2139
2140                 /* Unbind */
2141                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2142
2143                 /* Verify */
2144                 for (GLuint i = 0; i < n_pixels; ++i)
2145                 {
2146                         const GLubyte expected_red = static_cast<GLubyte>(i);
2147                         const GLubyte drawn_red = pixels[i];
2148
2149                         if (expected_red != drawn_red)
2150                         {
2151                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2152                                                                                                         << ". Expected value: " << (GLuint)expected_red
2153                                                                                                         << " at offset: " << i << tcu::TestLog::EndMessage;
2154
2155                                 result = false;
2156                                 break;
2157                         }
2158                 }
2159         }
2160         else if (RG8_SNORM == m_test_case)
2161         {
2162                 static const GLuint n_channels = 2;
2163
2164                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2165
2166                 std::vector<GLbyte> pixels;
2167                 pixels.resize(n_pixels * n_channels);
2168                 for (GLuint i = 0; i < n_pixels; ++i)
2169                 {
2170                         pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2171                         pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2172                 }
2173
2174                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2175
2176                 /* Unbind */
2177                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2178
2179                 /* Verify */
2180                 for (GLuint i = 0; i < n_pixels; ++i)
2181                 {
2182                         const GLbyte expected_red   = static_cast<GLubyte>((i % 16) - 8);
2183                         const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
2184                         const GLbyte drawn_red          = pixels[i * n_channels + 0];
2185                         const GLbyte drawn_green        = pixels[i * n_channels + 1];
2186
2187                         if ((expected_red != drawn_red) || (expected_green != drawn_green))
2188                         {
2189                                 m_context.getTestContext().getLog()
2190                                         << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2191                                         << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2192                                         << ". At offset: " << i << tcu::TestLog::EndMessage;
2193
2194                                 result = false;
2195                                 break;
2196                         }
2197                 }
2198         }
2199         else if (RGBA32F == m_test_case)
2200         {
2201                 static const GLuint n_channels = 4;
2202
2203                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2204
2205                 std::vector<GLfloat> pixels;
2206                 pixels.resize(n_pixels * n_channels);
2207                 for (GLuint i = 0; i < n_pixels; ++i)
2208                 {
2209                         pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2210                         pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2211                         pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2212                         pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2213                 }
2214
2215                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2216
2217                 /* Unbind */
2218                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2219
2220                 /* Verify */
2221                 for (GLuint i = 0; i < n_pixels; ++i)
2222                 {
2223                         const GLfloat expected_red   = (GLfloat)(i % 16) / 16.0f;
2224                         const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
2225                         const GLfloat expected_blue  = (GLfloat)i / 256.0f;
2226                         const GLfloat expected_alpha = 1.0f;
2227                         const GLfloat drawn_red          = pixels[i * n_channels + 0];
2228                         const GLfloat drawn_green       = pixels[i * n_channels + 1];
2229                         const GLfloat drawn_blue         = pixels[i * n_channels + 2];
2230                         const GLfloat drawn_alpha       = pixels[i * n_channels + 3];
2231
2232                         if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2233                                 (expected_alpha != drawn_alpha))
2234                         {
2235                                 m_context.getTestContext().getLog()
2236                                         << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2237                                         << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2238                                         << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2239                                         << tcu::TestLog::EndMessage;
2240
2241                                 result = false;
2242                                 break;
2243                         }
2244                 }
2245         }
2246         else if (R32UI_MIPMAP == m_test_case)
2247         {
2248                 static const GLuint n_channels = 1;
2249
2250                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2251
2252                 std::vector<GLuint> pixels;
2253                 pixels.resize(n_pixels * n_channels * 4);
2254                 for (GLuint i = 0; i < n_pixels; ++i)
2255                 {
2256                         pixels[i] = 0;
2257                 }
2258
2259                 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2260
2261                 /* Unbind */
2262                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2263
2264                 /* Verify */
2265                 for (GLuint i = 0; i < n_pixels; ++i)
2266                 {
2267                         const GLuint expected_red = i;
2268                         const GLuint drawn_red  = pixels[i];
2269
2270                         if (expected_red != drawn_red)
2271                         {
2272                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2273                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
2274                                                                                                         << tcu::TestLog::EndMessage;
2275
2276                                 result = false;
2277                                 break;
2278                         }
2279                 }
2280         }
2281         else if (R32UI_MULTISAMPLE == m_test_case)
2282         {
2283                 static const GLuint n_channels = 1;
2284
2285                 /* Compute shader */
2286                 static const GLchar* cs =
2287                         "#version 430 core\n"
2288                         "\n"
2289                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2290                         "\n"
2291                         "layout (location = 1)        writeonly uniform uimage2D   uni_destination_image;\n"
2292                         "layout (location = 0, r32ui) readonly  uniform uimage2DMS uni_source_image;\n"
2293                         "\n"
2294                         "void main()\n"
2295                         "{\n"
2296                         "    const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2297                         "    const uint  index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
2298                         "\n"
2299                         "    const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2300                         "    const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2301                         "    const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2302                         "    const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2303                         "\n"
2304                         "    if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
2305                         "    {\n"
2306                         "        imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2307                         "    }\n"
2308                         "    else\n"
2309                         "    {\n"
2310                         "        imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2311                         "    }\n"
2312                         "}\n"
2313                         "\n";
2314
2315                 Program program(m_context);
2316                 Texture destination_texture(m_context);
2317
2318                 Texture::Generate(gl, destination_texture.m_id);
2319                 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2320                 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2321
2322                 program.Init(cs, "", "", "", "", "");
2323                 program.Use();
2324                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2325                                                         GL_READ_ONLY, GL_R32UI);
2326                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2327                 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2328                                                         0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2329                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2330
2331                 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2332                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2333
2334                 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2335                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2336
2337                 gl.dispatchCompute(16, 16, 1);
2338                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2339
2340                 /* Pixels buffer initialization */
2341                 std::vector<GLuint> pixels;
2342                 pixels.resize(n_pixels * n_channels);
2343                 for (GLuint i = 0; i < n_pixels; ++i)
2344                 {
2345                         pixels[i] = i;
2346                 }
2347
2348                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2349
2350                 /* Unbind */
2351                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2352
2353                 /* Verify */
2354                 for (GLuint i = 0; i < n_pixels; ++i)
2355                 {
2356                         const GLuint expected_red = 1;
2357                         const GLuint drawn_red  = pixels[i];
2358
2359                         if (expected_red != drawn_red)
2360                         {
2361                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2362                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
2363                                                                                                         << tcu::TestLog::EndMessage;
2364
2365                                 result = false;
2366                                 break;
2367                         }
2368                 }
2369         }
2370
2371         return result;
2372 }
2373
2374 /** Constructor
2375  *
2376  * @param context Test context
2377  **/
2378 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context)
2379         : TexelFetchTest(context, "image_load_store", "Verifies that out-of-bound to image result in zero or is discarded")
2380 {
2381         /* Nothing to be done */
2382 }
2383
2384 /** Constructor
2385  *
2386  * @param context Test context
2387  **/
2388 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
2389         : TexelFetchTest(context, name, description)
2390 {
2391         /* Nothing to be done */
2392 }
2393
2394 /** Execute test
2395  *
2396  * @return tcu::TestNode::STOP
2397  **/
2398 tcu::TestNode::IterateResult ImageLoadStoreTest::iterate()
2399 {
2400         /* Constants */
2401         static const GLuint height = 16;
2402         static const GLuint width  = 16;
2403
2404         /* GL entry points */
2405         const Functions& gl = m_context.getRenderContext().getFunctions();
2406
2407         /* Test result indicator */
2408         bool test_result = true;
2409
2410         /* Iterate over all cases */
2411         for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
2412         {
2413                 /* Test case result indicator */
2414                 bool case_result = true;
2415
2416                 if (R32UI_MULTISAMPLE == m_test_case)
2417                 {
2418                         // Skip invalid program test in multi sample case
2419                         // texelFetch with invalid lod plane results undefined value
2420                         // OpenGL 4.5 Core Spec, around page 377
2421                         m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
2422                         continue;
2423                 }
2424
2425                 /* */
2426                 Texture destination_texture(m_context);
2427                 Program invalid_destination_program(m_context);
2428                 Program invalid_source_program(m_context);
2429                 Texture source_texture(m_context);
2430                 Program valid_program(m_context);
2431
2432                 const std::string& cs_invalid_destination = getComputeShader(DESTINATION_INVALID);
2433                 const std::string& cs_invalid_source      = getComputeShader(SOURCE_INVALID);
2434                 const std::string& cs_valid                               = getComputeShader(VALID);
2435
2436                 /* Prepare textures */
2437                 Texture::Generate(gl, destination_texture.m_id);
2438                 Texture::Generate(gl, source_texture.m_id);
2439
2440                 if (R32UI_MULTISAMPLE == m_test_case)
2441                 {
2442                         GLint max_integer_samples;
2443                         gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
2444                         GLint max_image_samples;
2445                         gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
2446                         if (max_integer_samples < 4 || max_image_samples < 4)
2447                         {
2448                                 /* prepareTexture() hard-codes 4 samples (n_levels) for
2449                                  * R32UI_MULTISAMPLE case. This value exceeds the required
2450                                  * min-max value (1 in OpenGL ES 3.2) and is not supported
2451                                  * by all implementations.
2452                                  *
2453                                  * Also, the test uses a compute shader with images
2454                                  * to upload the texture so max_image_samples >= 4
2455                                  * is also required.
2456                                  */
2457                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2458                                                                                                         << " not supported" << tcu::TestLog::EndMessage;
2459
2460                                 continue;
2461                         }
2462                 }
2463
2464                 prepareTexture(false, destination_texture.m_id);
2465                 prepareTexture(true, source_texture.m_id);
2466
2467                 /* Prepare programs */
2468                 invalid_destination_program.Init(cs_invalid_destination, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
2469                                                                                  "" /* vs */);
2470                 invalid_source_program.Init(cs_invalid_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
2471                                                                         "" /* vs */);
2472                 valid_program.Init(cs_valid, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
2473
2474                 /* Test invalid source case */
2475                 /* Set program */
2476                 invalid_source_program.Use();
2477
2478                 /* Set texture */
2479                 setTextures(destination_texture.m_id, source_texture.m_id);
2480
2481                 /* Dispatch */
2482                 gl.dispatchCompute(width, height, 1 /* depth */);
2483                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2484
2485                 /* Verification */
2486                 if (false == verifyInvalidResults(destination_texture.m_id))
2487                 {
2488                         case_result = false;
2489                 }
2490
2491                 /* Test valid case */
2492                 /* Set program */
2493                 valid_program.Use();
2494
2495                 /* Set texture */
2496                 setTextures(destination_texture.m_id, source_texture.m_id);
2497
2498                 /* Dispatch */
2499                 gl.dispatchCompute(width, height, 1 /* depth */);
2500                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2501
2502                 /* Verification */
2503                 if (false == verifyValidResults(destination_texture.m_id))
2504                 {
2505                         case_result = false;
2506                 }
2507
2508                 /* Test invalid destination case */
2509                 /* Set program */
2510                 invalid_destination_program.Use();
2511
2512                 /* Set texture */
2513                 setTextures(destination_texture.m_id, source_texture.m_id);
2514
2515                 /* Dispatch */
2516                 gl.dispatchCompute(width, height, 1 /* depth */);
2517                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2518
2519                 /* Verification */
2520                 if (false == verifyValidResults(destination_texture.m_id))
2521                 {
2522                         case_result = false;
2523                 }
2524
2525                 /* Set test result */
2526                 if (false == case_result)
2527                 {
2528                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2529                                                                                                 << " failed" << tcu::TestLog::EndMessage;
2530
2531                         test_result = false;
2532                 }
2533         }
2534
2535         /* Set result */
2536         if (true == test_result)
2537         {
2538                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2539         }
2540         else
2541         {
2542                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2543         }
2544
2545         /* Done */
2546         return tcu::TestNode::STOP;
2547 }
2548
2549 /** Prepare shader for current test case
2550  *
2551  * @param version Specify which version should be prepared
2552  *
2553  * @return Source
2554  **/
2555 std::string ImageLoadStoreTest::getComputeShader(VERSION version)
2556 {
2557         static const GLchar* template_code = "#version 430 core\n"
2558                                                                                  "\n"
2559                                                                                  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2560                                                                                  "\n"
2561                                                                                  "layout (location = 1)        writeonly uniform IMAGE uni_destination_image;\n"
2562                                                                                  "layout (location = 0, FORMAT) readonly  uniform IMAGE uni_source_image;\n"
2563                                                                                  "\n"
2564                                                                                  "void main()\n"
2565                                                                                  "{\n"
2566                                                                                  "    const ivec2 point_destination = POINT;\n"
2567                                                                                  "    const ivec2 point_source      = POINT;\n"
2568                                                                                  "\n"
2569                                                                                  "COPY"
2570                                                                                  "}\n"
2571                                                                                  "\n";
2572
2573         static const GLchar* copy_multisampled =
2574                 "    const TYPE color_0 = imageLoad(uni_source_image, point_source, 0 + OFFSET);\n"
2575                 "    const TYPE color_1 = imageLoad(uni_source_image, point_source, 1 + OFFSET);\n"
2576                 "    const TYPE color_2 = imageLoad(uni_source_image, point_source, 2 + OFFSET);\n"
2577                 "    const TYPE color_3 = imageLoad(uni_source_image, point_source, 3 + OFFSET);\n"
2578                 "    imageStore(uni_destination_image, point_destination, 0 + OFFSET, color_0);\n"
2579                 "    imageStore(uni_destination_image, point_destination, 1 + OFFSET, color_1);\n"
2580                 "    imageStore(uni_destination_image, point_destination, 2 + OFFSET, color_2);\n"
2581                 "    imageStore(uni_destination_image, point_destination, 3 + OFFSET, color_3);\n";
2582
2583         static const GLchar* copy_regular =
2584                 "    const TYPE color = imageLoad(uni_source_image, point_source);\n"
2585                 "    //imageStore(uni_destination_image, point_destination, vec4(0, 0, 0, 0));\n"
2586                 "    imageStore(uni_destination_image, point_destination, color);\n";
2587
2588         static const GLchar* format_r8            = "r8";
2589         static const GLchar* format_rg8_snorm = "rg8_snorm";
2590         static const GLchar* format_rgba32f   = "rgba32f";
2591         static const GLchar* format_r32ui        = "r32ui";
2592
2593         static const GLchar* image_vec4 = "image2D";
2594
2595         static const GLchar* image_uvec4 = "uimage2D";
2596
2597         static const GLchar* image_uvec4_ms = "uimage2DMS";
2598
2599         static const GLchar* offset_invalid = "4";
2600         static const GLchar* offset_valid   = "0";
2601
2602         static const GLchar* point_invalid = "ivec2(gl_WorkGroupID.x + 16, gl_WorkGroupID.y + 16)";
2603
2604         static const GLchar* point_valid = "ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
2605
2606         static const GLchar* type_vec4  = "vec4";
2607         static const GLchar* type_uvec4 = "uvec4";
2608
2609         const GLchar* copy                               = copy_regular;
2610         const GLchar* format                     = format_r8;
2611         const GLchar* image                              = image_vec4;
2612         const GLchar* offset_destination = offset_valid;
2613         const GLchar* offset_source              = offset_valid;
2614         const GLchar* point_destination  = point_valid;
2615         const GLchar* point_source               = point_valid;
2616         const GLchar* type                               = type_vec4;
2617
2618         switch (version)
2619         {
2620         case VALID:
2621                 break;
2622         case SOURCE_INVALID:
2623                 point_source  = point_invalid;
2624                 offset_source = offset_invalid;
2625                 break;
2626         case DESTINATION_INVALID:
2627                 point_destination  = point_invalid;
2628                 offset_destination = offset_invalid;
2629                 break;
2630         default:
2631                 TCU_FAIL("Invalid enum");
2632         }
2633
2634         switch (m_test_case)
2635         {
2636         case R8:
2637                 break;
2638         case RG8_SNORM:
2639                 format = format_rg8_snorm;
2640                 break;
2641         case RGBA32F:
2642                 format = format_rgba32f;
2643                 break;
2644         case R32UI_MIPMAP:
2645                 format = format_r32ui;
2646                 image  = image_uvec4;
2647                 type   = type_uvec4;
2648                 break;
2649         case R32UI_MULTISAMPLE:
2650                 copy                      = copy_multisampled;
2651                 format                    = format_r32ui;
2652                 image                     = image_uvec4_ms;
2653                 point_destination = point_valid;
2654                 point_source      = point_valid;
2655                 type                      = type_uvec4;
2656                 break;
2657         default:
2658                 TCU_FAIL("Invalid enum");
2659         };
2660
2661         size_t          position = 0;
2662         std::string source   = template_code;
2663
2664         replaceToken("IMAGE", position, image, source);
2665         replaceToken("FORMAT", position, format, source);
2666         replaceToken("IMAGE", position, image, source);
2667         replaceToken("POINT", position, point_destination, source);
2668         replaceToken("POINT", position, point_source, source);
2669
2670         size_t temp_position = position;
2671         replaceToken("COPY", position, copy, source);
2672         position = temp_position;
2673
2674         switch (m_test_case)
2675         {
2676         case R8:
2677         case RG8_SNORM:
2678         case RGBA32F:
2679         case R32UI_MIPMAP:
2680                 replaceToken("TYPE", position, type, source);
2681                 break;
2682         case R32UI_MULTISAMPLE:
2683                 replaceToken("TYPE", position, type, source);
2684                 replaceToken("OFFSET", position, offset_source, source);
2685                 replaceToken("TYPE", position, type, source);
2686                 replaceToken("OFFSET", position, offset_source, source);
2687                 replaceToken("TYPE", position, type, source);
2688                 replaceToken("OFFSET", position, offset_source, source);
2689                 replaceToken("TYPE", position, type, source);
2690                 replaceToken("OFFSET", position, offset_source, source);
2691                 replaceToken("OFFSET", position, offset_destination, source);
2692                 replaceToken("OFFSET", position, offset_destination, source);
2693                 replaceToken("OFFSET", position, offset_destination, source);
2694                 replaceToken("OFFSET", position, offset_destination, source);
2695                 break;
2696         default:
2697                 TCU_FAIL("Invalid enum");
2698         }
2699
2700         return source;
2701 }
2702
2703 /** Set textures as images
2704  *
2705  * @param id_destination Id of texture used as destination
2706  * @param id_source      Id of texture used as source
2707  **/
2708 void ImageLoadStoreTest::setTextures(glw::GLuint id_destination, glw::GLuint id_source)
2709 {
2710         const Functions& gl = m_context.getRenderContext().getFunctions();
2711
2712         GLenum format = 0;
2713         GLint  level  = 0;
2714
2715         switch (m_test_case)
2716         {
2717         case R8:
2718                 format = GL_R8;
2719                 break;
2720         case RG8_SNORM:
2721                 format = GL_RG8_SNORM;
2722                 break;
2723         case RGBA32F:
2724                 format = GL_RGBA32F;
2725                 break;
2726         case R32UI_MIPMAP:
2727                 format = GL_R32UI;
2728                 level  = 1;
2729                 break;
2730         case R32UI_MULTISAMPLE:
2731                 format = GL_R32UI;
2732                 break;
2733         default:
2734                 TCU_FAIL("Invalid enum");
2735         }
2736
2737         gl.bindImageTexture(0 /* unit */, id_source, level, GL_FALSE /* layered */, 0 /* layer */, GL_READ_ONLY, format);
2738         GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2739
2740         gl.bindImageTexture(1 /* unit */, id_destination, level, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY,
2741                                                 format);
2742         GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2743
2744         gl.uniform1i(0 /* location */, 0 /* image unit*/);
2745         GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2746
2747         gl.uniform1i(1 /* location */, 1 /* image unit*/);
2748         GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2749 }
2750
2751 /** Verifies that texutre is filled with 0
2752  *
2753  * @param texture_id Id of texture
2754  *
2755  * @return true when image is filled with 0, false otherwise
2756  **/
2757 bool ImageLoadStoreTest::verifyInvalidResults(glw::GLuint texture_id)
2758 {
2759         static const GLuint height   = 16;
2760         static const GLuint width       = 16;
2761         static const GLuint n_pixels = height * width;
2762
2763         const Functions& gl = m_context.getRenderContext().getFunctions();
2764         gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2765         GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2766
2767         bool result = true;
2768
2769         if (R8 == m_test_case)
2770         {
2771                 static const GLuint n_channels = 1;
2772
2773                 std::vector<GLubyte> pixels;
2774                 pixels.resize(n_pixels * n_channels);
2775                 for (GLuint i = 0; i < n_pixels; ++i)
2776                 {
2777                         pixels[i] = static_cast<GLubyte>(i);
2778                 }
2779
2780                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2781
2782                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2783
2784                 /* Unbind */
2785                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2786
2787                 /* Verify */
2788                 for (GLuint i = 0; i < n_pixels; ++i)
2789                 {
2790                         const GLubyte expected_red = 0;
2791                         const GLubyte drawn_red = pixels[i];
2792
2793                         if (expected_red != drawn_red)
2794                         {
2795                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2796                                                                                                         << ". Expected value: " << (GLuint)expected_red
2797                                                                                                         << " at offset: " << i << tcu::TestLog::EndMessage;
2798
2799                                 result = false;
2800                                 break;
2801                         }
2802                 }
2803         }
2804         else if (RG8_SNORM == m_test_case)
2805         {
2806                 static const GLuint n_channels = 2;
2807
2808                 std::vector<GLbyte> pixels;
2809                 pixels.resize(n_pixels * n_channels);
2810                 for (GLuint i = 0; i < n_pixels; ++i)
2811                 {
2812                         pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2813                         pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2814                 }
2815
2816                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2817
2818                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2819
2820                 /* Unbind */
2821                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2822
2823                 /* Verify */
2824                 for (GLuint i = 0; i < n_pixels; ++i)
2825                 {
2826                         const GLbyte expected_red   = 0;
2827                         const GLbyte expected_green = 0;
2828                         const GLbyte drawn_red          = pixels[i * n_channels + 0];
2829                         const GLbyte drawn_green        = pixels[i * n_channels + 1];
2830
2831                         if ((expected_red != drawn_red) || (expected_green != drawn_green))
2832                         {
2833                                 m_context.getTestContext().getLog()
2834                                         << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2835                                         << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2836                                         << ". At offset: " << i << tcu::TestLog::EndMessage;
2837
2838                                 result = false;
2839                                 break;
2840                         }
2841                 }
2842         }
2843         else if (RGBA32F == m_test_case)
2844         {
2845                 static const GLuint n_channels = 4;
2846
2847                 std::vector<GLfloat> pixels;
2848                 pixels.resize(n_pixels * n_channels);
2849                 for (GLuint i = 0; i < n_pixels; ++i)
2850                 {
2851                         pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2852                         pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2853                         pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2854                         pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2855                 }
2856
2857                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2858
2859                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2860
2861                 /* Unbind */
2862                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2863
2864                 /* Verify */
2865                 for (GLuint i = 0; i < n_pixels; ++i)
2866                 {
2867                         const GLfloat expected_red   = 0.0f;
2868                         const GLfloat expected_green = 0.0f;
2869                         const GLfloat expected_blue  = 0.0f;
2870                         const GLfloat expected_alpha = 0.0f;
2871                         const GLfloat drawn_red          = pixels[i * n_channels + 0];
2872                         const GLfloat drawn_green       = pixels[i * n_channels + 1];
2873                         const GLfloat drawn_blue         = pixels[i * n_channels + 2];
2874                         const GLfloat drawn_alpha       = pixels[i * n_channels + 3];
2875
2876                         if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2877                                 (expected_alpha != drawn_alpha))
2878                         {
2879                                 m_context.getTestContext().getLog()
2880                                         << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2881                                         << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2882                                         << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2883                                         << tcu::TestLog::EndMessage;
2884
2885                                 result = false;
2886                                 break;
2887                         }
2888                 }
2889         }
2890         else if (R32UI_MIPMAP == m_test_case)
2891         {
2892                 static const GLuint n_channels = 1;
2893
2894                 std::vector<GLuint> pixels;
2895                 pixels.resize(n_pixels * n_channels);
2896                 for (GLuint i = 0; i < n_pixels; ++i)
2897                 {
2898                         pixels[i] = i;
2899                 }
2900
2901                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2902
2903                 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2904
2905                 /* Unbind */
2906                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2907
2908                 /* Verify */
2909                 for (GLuint i = 0; i < n_pixels; ++i)
2910                 {
2911                         const GLuint expected_red = 0;
2912                         const GLuint drawn_red  = pixels[i];
2913
2914                         if (expected_red != drawn_red)
2915                         {
2916                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2917                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
2918                                                                                                         << tcu::TestLog::EndMessage;
2919
2920                                 result = false;
2921                                 break;
2922                         }
2923                 }
2924         }
2925         else if (R32UI_MULTISAMPLE == m_test_case)
2926         {
2927                 static const GLuint n_channels = 1;
2928
2929                 /* Compute shader */
2930                 static const GLchar* cs = "#version 430 core\n"
2931                                                                   "\n"
2932                                                                   "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2933                                                                   "\n"
2934                                                                   "layout (location = 1)        writeonly uniform uimage2D   uni_destination_image;\n"
2935                                                                   "layout (location = 0, r32ui) readonly  uniform uimage2DMS uni_source_image;\n"
2936                                                                   "\n"
2937                                                                   "void main()\n"
2938                                                                   "{\n"
2939                                                                   "    const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2940                                                                   "\n"
2941                                                                   "    const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2942                                                                   "    const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2943                                                                   "    const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2944                                                                   "    const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2945                                                                   "\n"
2946                                                                   "    if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2947                                                                   "    {\n"
2948                                                                   "        imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2949                                                                   "    }\n"
2950                                                                   "    else\n"
2951                                                                   "    {\n"
2952                                                                   "        imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2953                                                                   "    }\n"
2954                                                                   "}\n"
2955                                                                   "\n";
2956
2957                 Program program(m_context);
2958                 Texture destination_texture(m_context);
2959
2960                 Texture::Generate(gl, destination_texture.m_id);
2961                 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2962                 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2963
2964                 program.Init(cs, "", "", "", "", "");
2965                 program.Use();
2966                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2967                                                         GL_READ_ONLY, GL_R32UI);
2968                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2969                 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2970                                                         0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2971                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2972
2973                 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2974                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2975
2976                 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2977                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2978
2979                 gl.dispatchCompute(16, 16, 1);
2980                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2981
2982                 /* Pixels buffer initialization */
2983                 std::vector<GLuint> pixels;
2984                 pixels.resize(n_pixels * n_channels);
2985                 for (GLuint i = 0; i < n_pixels; ++i)
2986                 {
2987                         pixels[i] = i;
2988                 }
2989
2990                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2991
2992                 /* Unbind */
2993                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2994
2995                 /* Verify */
2996                 for (GLuint i = 0; i < n_pixels; ++i)
2997                 {
2998                         const GLuint expected_red = 1;
2999                         const GLuint drawn_red  = pixels[i];
3000
3001                         if (expected_red != drawn_red)
3002                         {
3003                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3004                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
3005                                                                                                         << tcu::TestLog::EndMessage;
3006
3007                                 result = false;
3008                                 break;
3009                         }
3010                 }
3011         }
3012
3013         return result;
3014 }
3015
3016 /** Verifies that texutre is filled with increasing values
3017  *
3018  * @param texture_id Id of texture
3019  *
3020  * @return true when image is filled with increasing values, false otherwise
3021  **/
3022 bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
3023 {
3024         static const GLuint height   = 16;
3025         static const GLuint width       = 16;
3026         static const GLuint n_pixels = height * width;
3027
3028         const Functions& gl = m_context.getRenderContext().getFunctions();
3029         gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3030         GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3031
3032         bool result = true;
3033
3034         if (R8 == m_test_case)
3035         {
3036                 static const GLuint n_channels = 1;
3037
3038                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3039
3040                 std::vector<GLubyte> pixels;
3041                 pixels.resize(n_pixels * n_channels);
3042                 for (GLuint i = 0; i < n_pixels; ++i)
3043                 {
3044                         pixels[i] = static_cast<GLubyte>(i);
3045                 }
3046
3047                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
3048
3049                 /* Unbind */
3050                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3051
3052                 /* Verify */
3053                 for (GLuint i = 0; i < n_pixels; ++i)
3054                 {
3055                         const GLubyte expected_red = static_cast<GLubyte>(i);
3056                         const GLubyte drawn_red = pixels[i];
3057
3058                         if (expected_red != drawn_red)
3059                         {
3060                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
3061                                                                                                         << ". Expected value: " << (GLuint)expected_red
3062                                                                                                         << " at offset: " << i << tcu::TestLog::EndMessage;
3063
3064                                 result = false;
3065                                 break;
3066                         }
3067                 }
3068         }
3069         else if (RG8_SNORM == m_test_case)
3070         {
3071                 static const GLuint n_channels = 2;
3072
3073                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3074
3075                 std::vector<GLbyte> pixels;
3076                 pixels.resize(n_pixels * n_channels);
3077                 for (GLuint i = 0; i < n_pixels; ++i)
3078                 {
3079                         pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
3080                         pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
3081                 }
3082
3083                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
3084
3085                 /* Unbind */
3086                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3087
3088                 /* Verify */
3089                 for (GLuint i = 0; i < n_pixels; ++i)
3090                 {
3091                         const GLbyte expected_red   = static_cast<GLubyte>((i % 16) - 8);
3092                         const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
3093                         const GLbyte drawn_red          = pixels[i * n_channels + 0];
3094                         const GLbyte drawn_green        = pixels[i * n_channels + 1];
3095
3096                         if ((expected_red != drawn_red) || (expected_green != drawn_green))
3097                         {
3098                                 m_context.getTestContext().getLog()
3099                                         << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
3100                                         << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
3101                                         << ". At offset: " << i << tcu::TestLog::EndMessage;
3102
3103                                 result = false;
3104                                 break;
3105                         }
3106                 }
3107         }
3108         else if (RGBA32F == m_test_case)
3109         {
3110                 static const GLuint n_channels = 4;
3111
3112                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3113
3114                 std::vector<GLfloat> pixels;
3115                 pixels.resize(n_pixels * n_channels);
3116                 for (GLuint i = 0; i < n_pixels; ++i)
3117                 {
3118                         pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
3119                         pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
3120                         pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
3121                         pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
3122                 }
3123
3124                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
3125
3126                 /* Unbind */
3127                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3128
3129                 /* Verify */
3130                 for (GLuint i = 0; i < n_pixels; ++i)
3131                 {
3132                         const GLfloat expected_red   = (GLfloat)(i % 16) / 16.0f;
3133                         const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
3134                         const GLfloat expected_blue  = (GLfloat)i / 256.0f;
3135                         const GLfloat expected_alpha = 1.0f;
3136                         const GLfloat drawn_red          = pixels[i * n_channels + 0];
3137                         const GLfloat drawn_green       = pixels[i * n_channels + 1];
3138                         const GLfloat drawn_blue         = pixels[i * n_channels + 2];
3139                         const GLfloat drawn_alpha       = pixels[i * n_channels + 3];
3140
3141                         if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
3142                                 (expected_alpha != drawn_alpha))
3143                         {
3144                                 m_context.getTestContext().getLog()
3145                                         << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
3146                                         << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
3147                                         << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
3148                                         << tcu::TestLog::EndMessage;
3149
3150                                 result = false;
3151                                 break;
3152                         }
3153                 }
3154         }
3155         else if (R32UI_MIPMAP == m_test_case)
3156         {
3157                 static const GLuint n_channels = 1;
3158
3159                 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3160
3161                 std::vector<GLuint> pixels;
3162                 pixels.resize(n_pixels * n_channels * 4);
3163                 for (GLuint i = 0; i < n_pixels; ++i)
3164                 {
3165                         pixels[i] = 0;
3166                 }
3167
3168                 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3169
3170                 /* Unbind */
3171                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3172
3173                 /* Verify */
3174                 for (GLuint i = 0; i < n_pixels; ++i)
3175                 {
3176                         const GLuint expected_red = i;
3177                         const GLuint drawn_red  = pixels[i];
3178
3179                         if (expected_red != drawn_red)
3180                         {
3181                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3182                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
3183                                                                                                         << tcu::TestLog::EndMessage;
3184
3185                                 result = false;
3186                                 break;
3187                         }
3188                 }
3189         }
3190         else if (R32UI_MULTISAMPLE == m_test_case)
3191         {
3192                 static const GLuint n_channels = 1;
3193
3194                 /* Compute shader */
3195                 static const GLchar* cs =
3196                         "#version 430 core\n"
3197                         "\n"
3198                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3199                         "\n"
3200                         "layout (location = 1)        writeonly uniform uimage2D   uni_destination_image;\n"
3201                         "layout (location = 0, r32ui) readonly  uniform uimage2DMS uni_source_image;\n"
3202                         "\n"
3203                         "void main()\n"
3204                         "{\n"
3205                         "    const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
3206                         "    const uint  index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
3207                         "\n"
3208                         "    const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
3209                         "    const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
3210                         "    const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
3211                         "    const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
3212                         "\n"
3213                         "    if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
3214                         "    {\n"
3215                         "        imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
3216                         "    }\n"
3217                         "    else\n"
3218                         "    {\n"
3219                         "        imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
3220                         "    }\n"
3221                         "}\n"
3222                         "\n";
3223
3224                 Program program(m_context);
3225                 Texture destination_texture(m_context);
3226
3227                 Texture::Generate(gl, destination_texture.m_id);
3228                 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
3229                 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
3230
3231                 program.Init(cs, "", "", "", "", "");
3232                 program.Use();
3233                 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3234                                                         GL_READ_ONLY, GL_R32UI);
3235                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3236                 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
3237                                                         0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
3238                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3239
3240                 gl.uniform1i(0 /* location */, 0 /* image unit*/);
3241                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3242
3243                 gl.uniform1i(1 /* location */, 1 /* image unit*/);
3244                 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3245
3246                 gl.dispatchCompute(16, 16, 1);
3247                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3248
3249                 /* Pixels buffer initialization */
3250                 std::vector<GLuint> pixels;
3251                 pixels.resize(n_pixels * n_channels);
3252                 for (GLuint i = 0; i < n_pixels; ++i)
3253                 {
3254                         pixels[i] = i;
3255                 }
3256
3257                 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3258
3259                 /* Unbind */
3260                 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3261
3262                 /* Verify */
3263                 for (GLuint i = 0; i < n_pixels; ++i)
3264                 {
3265                         const GLuint expected_red = 1;
3266                         const GLuint drawn_red  = pixels[i];
3267
3268                         if (expected_red != drawn_red)
3269                         {
3270                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3271                                                                                                         << ". Expected value: " << expected_red << " at offset: " << i
3272                                                                                                         << tcu::TestLog::EndMessage;
3273
3274                                 result = false;
3275                                 break;
3276                         }
3277                 }
3278         }
3279
3280         return result;
3281 }
3282
3283 /** Constructor
3284  *
3285  * @param context Test context
3286  **/
3287 StorageBufferTest::StorageBufferTest(deqp::Context& context)
3288         : TestCase(context, "storage_buffer", "Verifies that out-of-bound access to SSBO is discared or resutls in 0")
3289         , m_test_case(VALID)
3290 {
3291         /* Nothing to be done here */
3292 }
3293
3294 /** Constructor
3295  *
3296  * @param context Test context
3297  **/
3298 StorageBufferTest::StorageBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3299         : TestCase(context, name, description), m_test_case(VALID)
3300 {
3301         /* Nothing to be done */
3302 }
3303
3304 /** Execute test
3305  *
3306  * @return tcu::TestNode::STOP
3307  **/
3308 tcu::TestNode::IterateResult StorageBufferTest::iterate()
3309 {
3310         static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3311         static const GLfloat source_data[4]              = { 2.0f, 3.0f, 4.0f, 5.0f };
3312
3313         /* GL entry points */
3314         const Functions& gl = m_context.getRenderContext().getFunctions();
3315
3316         /* Test result indicator */
3317         bool test_result = true;
3318
3319         /* Iterate over all cases */
3320         while (LAST != m_test_case)
3321         {
3322                 /* Test case objects */
3323                 Buffer  destination_buffer(m_context);
3324                 Buffer  source_buffer(m_context);
3325                 Program program(m_context);
3326
3327                 /* Compute Shader */
3328                 const std::string& cs = getComputeShader();
3329
3330                 /* Buffers initialization */
3331                 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
3332                                                                         destination_data);
3333                 source_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
3334
3335                 destination_buffer.BindBase(0);
3336                 source_buffer.BindBase(1);
3337
3338                 /* Shaders initialization */
3339                 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3340                 program.Use();
3341
3342                 /* Dispatch compute */
3343                 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3344                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3345
3346                 /* Set memory barrier */
3347                 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3348                 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3349
3350                 /* Verify results */
3351                 destination_buffer.Bind();
3352                 GLfloat* buffer_data =
3353                         (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
3354                 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3355
3356                 test_result = verifyResults(buffer_data);
3357
3358                 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3359                 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3360
3361                 /* Increment */
3362                 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3363         }
3364
3365         /* Set result */
3366         if (true == test_result)
3367         {
3368                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3369         }
3370         else
3371         {
3372                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3373         }
3374
3375         /* Done */
3376         return tcu::TestNode::STOP;
3377 }
3378
3379 /** Prepare shader for current test case
3380  *
3381  * @return Source
3382  **/
3383 std::string StorageBufferTest::getComputeShader()
3384 {
3385         static const GLchar* cs = "#version 430 core\n"
3386                                                           "\n"
3387                                                           "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3388                                                           "\n"
3389                                                           "layout (binding = 1, std430) buffer Source {\n"
3390                                                           "    float data[];\n"
3391                                                           "} source;\n"
3392                                                           "\n"
3393                                                           "layout (binding = 0, std430) buffer Destination {\n"
3394                                                           "    float data[];\n"
3395                                                           "} destination;\n"
3396                                                           "\n"
3397                                                           "void main()\n"
3398                                                           "{\n"
3399                                                           "    const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3400                                                           "    const uint index_source      = gl_LocalInvocationID.x + OFFSET;\n"
3401                                                           "\n"
3402                                                           "    destination.data[index_destination] = source.data[index_source];\n"
3403                                                           "}\n"
3404                                                           "\n";
3405
3406         const GLchar* destination_offset;
3407         size_t            position = 0;
3408         std::string   source   = cs;
3409         const GLchar* source_offset;
3410
3411         switch (m_test_case)
3412         {
3413         case VALID:
3414                 destination_offset = "0";
3415                 source_offset     = "0";
3416                 break;
3417         case SOURCE_INVALID:
3418                 destination_offset = "0";
3419                 source_offset     = "16";
3420                 break;
3421         case DESTINATION_INVALID:
3422                 destination_offset = "16";
3423                 source_offset     = "0";
3424                 break;
3425         default:
3426                 TCU_FAIL("Invalid enum");
3427         }
3428
3429         replaceToken("OFFSET", position, destination_offset, source);
3430         replaceToken("OFFSET", position, source_offset, source);
3431
3432         return source;
3433 }
3434
3435 /** Verify test case results
3436  *
3437  * @param buffer_data Buffer data to verify
3438  *
3439  * @return true if buffer_data is as expected, false othrewise
3440  **/
3441 bool StorageBufferTest::verifyResults(GLfloat* buffer_data)
3442 {
3443         static const GLfloat expected_data_valid[4]                               = { 2.0f, 3.0f, 4.0f, 5.0f };
3444         static const GLfloat expected_data_invalid_destination[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3445         static const GLfloat expected_data_invalid_source[4]      = { 0.0f, 0.0f, 0.0f, 0.0f };
3446
3447         int size = static_cast<int>(sizeof(GLfloat) * 4);
3448
3449         /* Prepare expected data const for proper case*/
3450         const GLfloat* expected_data = 0;
3451         const GLchar*  name                      = 0;
3452         switch (m_test_case)
3453         {
3454         case VALID:
3455                 expected_data = expected_data_valid;
3456                 name              = "valid indices";
3457                 break;
3458         case SOURCE_INVALID:
3459                 expected_data = expected_data_invalid_source;
3460                 name              = "invalid source indices";
3461                 break;
3462         case DESTINATION_INVALID:
3463                 expected_data = expected_data_invalid_destination;
3464                 name              = "invalid destination indices";
3465                 break;
3466         default:
3467                 TCU_FAIL("Invalid enum");
3468         }
3469
3470         /* Verify buffer data */
3471         if (0 != memcmp(expected_data, buffer_data, size))
3472         {
3473                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3474                                                                                         << tcu::TestLog::EndMessage;
3475                 return false;
3476         }
3477
3478         return true;
3479 }
3480
3481 /** Constructor
3482  *
3483  * @param context Test context
3484  **/
3485 UniformBufferTest::UniformBufferTest(deqp::Context& context)
3486         : TestCase(context, "uniform_buffer", "Verifies that out-of-bound access to UBO resutls in 0"), m_test_case(VALID)
3487 {
3488         /* Nothing to be done here */
3489 }
3490
3491 /** Constructor
3492  *
3493  * @param context Test context
3494  **/
3495 UniformBufferTest::UniformBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3496         : TestCase(context, name, description), m_test_case(VALID)
3497 {
3498         /* Nothing to be done */
3499 }
3500
3501 /** Execute test
3502  *
3503  * @return tcu::TestNode::STOP
3504  **/
3505 tcu::TestNode::IterateResult UniformBufferTest::iterate()
3506 {
3507         static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3508         /* The source buffer is packed std140 so we need vec4s */
3509         static const GLfloat source_data[16] = {
3510                 2.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 4.0f, 0.0f, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f,
3511         };
3512
3513         /* GL entry points */
3514         const Functions& gl = m_context.getRenderContext().getFunctions();
3515
3516         /* Test result indicator */
3517         bool test_result = true;
3518
3519         /* Iterate over all cases */
3520         while (LAST != m_test_case)
3521         {
3522                 /* Test case objects */
3523                 Buffer  destination_buffer(m_context);
3524                 Buffer  source_buffer(m_context);
3525                 Program program(m_context);
3526
3527                 /* Compute Shader */
3528                 const std::string& cs = getComputeShader();
3529
3530                 /* Buffers initialization */
3531                 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
3532                                                                         destination_data);
3533                 source_buffer.InitData(GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
3534
3535                 destination_buffer.BindBase(0);
3536                 source_buffer.BindBase(0);
3537
3538                 /* Shaders initialization */
3539                 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3540                 program.Use();
3541
3542                 /* Dispatch compute */
3543                 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3544                 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3545
3546                 /* Set memory barrier */
3547                 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3548                 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3549
3550                 /* Verify results */
3551                 destination_buffer.Bind();
3552                 GLfloat* buffer_data =
3553                         (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
3554                 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3555
3556                 test_result = verifyResults(buffer_data);
3557
3558                 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3559                 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3560
3561                 /* Increment */
3562                 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3563         }
3564
3565         /* Set result */
3566         if (true == test_result)
3567         {
3568                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3569         }
3570         else
3571         {
3572                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3573         }
3574
3575         /* Done */
3576         return tcu::TestNode::STOP;
3577 }
3578
3579 /** Prepare shader for current test case
3580  *
3581  * @return Source
3582  **/
3583 std::string UniformBufferTest::getComputeShader()
3584 {
3585         static const GLchar* cs = "#version 430 core\n"
3586                                                           "\n"
3587                                                           "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3588                                                           "\n"
3589                                                           "layout (binding = 0, std140) uniform Source {\n"
3590                                                           "    float data[16];\n"
3591                                                           "} source;\n"
3592                                                           "\n"
3593                                                           "layout (binding = 0, std430) buffer Destination {\n"
3594                                                           "    float data[];\n"
3595                                                           "} destination;\n"
3596                                                           "\n"
3597                                                           "void main()\n"
3598                                                           "{\n"
3599                                                           "    const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3600                                                           "    const uint index_source      = gl_LocalInvocationID.x + OFFSET;\n"
3601                                                           "\n"
3602                                                           "    destination.data[index_destination] = source.data[index_source];\n"
3603                                                           "}\n"
3604                                                           "\n";
3605
3606         const GLchar* destination_offset;
3607         size_t            position = 0;
3608         std::string   source   = cs;
3609         const GLchar* source_offset;
3610
3611         switch (m_test_case)
3612         {
3613         case VALID:
3614                 destination_offset = "0";
3615                 source_offset     = "0";
3616                 break;
3617         case SOURCE_INVALID:
3618                 destination_offset = "0";
3619                 source_offset     = "16";
3620                 break;
3621         default:
3622                 TCU_FAIL("Invalid enum");
3623         }
3624
3625         replaceToken("OFFSET", position, destination_offset, source);
3626         replaceToken("OFFSET", position, source_offset, source);
3627
3628         return source;
3629 }
3630
3631 /** Verify test case results
3632  *
3633  * @param buffer_data Buffer data to verify
3634  *
3635  * @return true if buffer_data is as expected, false othrewise
3636  **/
3637 bool UniformBufferTest::verifyResults(GLfloat* buffer_data)
3638 {
3639         static const GLfloat expected_data_valid[4]                      = { 2.0f, 3.0f, 4.0f, 5.0f };
3640         static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3641
3642         int size = static_cast<int>(sizeof(GLfloat) * 4);
3643
3644         /* Prepare expected data const for proper case*/
3645         const GLfloat* expected_data = 0;
3646         const GLchar*  name                      = 0;
3647         switch (m_test_case)
3648         {
3649         case VALID:
3650                 expected_data = expected_data_valid;
3651                 name              = "valid indices";
3652                 break;
3653         case SOURCE_INVALID:
3654                 expected_data = expected_data_invalid_source;
3655                 name              = "invalid source indices";
3656                 break;
3657         default:
3658                 TCU_FAIL("Invalid enum");
3659         }
3660
3661         /* Verify buffer data */
3662         if (0 != memcmp(expected_data, buffer_data, size))
3663         {
3664                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3665                                                                                         << tcu::TestLog::EndMessage;
3666                 return false;
3667         }
3668
3669         return true;
3670 }
3671 } /* RobustBufferAccessBehavior */
3672
3673 /** Constructor.
3674  *
3675  *  @param context Rendering context.
3676  **/
3677 RobustBufferAccessBehaviorTests::RobustBufferAccessBehaviorTests(deqp::Context& context)
3678         : TestCaseGroup(context, "robust_buffer_access_behavior",
3679                                         "Verifies \"robust buffer access behavior\" functionality")
3680 {
3681         /* Left blank on purpose */
3682 }
3683
3684 /** Initializes a multi_bind test group.
3685  *
3686  **/
3687 void RobustBufferAccessBehaviorTests::init(void)
3688 {
3689         addChild(new RobustBufferAccessBehavior::VertexBufferObjectsTest(m_context));
3690         addChild(new RobustBufferAccessBehavior::TexelFetchTest(m_context));
3691         addChild(new RobustBufferAccessBehavior::ImageLoadStoreTest(m_context));
3692         addChild(new RobustBufferAccessBehavior::StorageBufferTest(m_context));
3693         addChild(new RobustBufferAccessBehavior::UniformBufferTest(m_context));
3694 }
3695
3696 } /* deqp */