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