1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * \file glcRobustBufferAccessBehaviorTests.cpp
21 * \brief Implements conformance tests for "Robust Buffer Access Behavior" functionality.
22 */ /*-------------------------------------------------------------------*/
24 #include "glcRobustBufferAccessBehaviorTests.hpp"
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "gluShaderUtil.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "tcuTestLog.hpp"
40 namespace RobustBufferAccessBehavior
42 /* Buffer constants */
43 const GLuint Buffer::m_invalid_id = -1;
45 const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
46 GL_ARRAY_BUFFER, /* 0 */
47 GL_ATOMIC_COUNTER_BUFFER, /* 1 */
48 GL_COPY_READ_BUFFER, /* 2 */
49 GL_COPY_WRITE_BUFFER, /* 3 */
50 GL_DISPATCH_INDIRECT_BUFFER, /* 4 */
51 GL_DRAW_INDIRECT_BUFFER, /* 5 */
52 GL_ELEMENT_ARRAY_BUFFER, /* 6 */
53 GL_PIXEL_PACK_BUFFER, /* 7 */
54 GL_PIXEL_UNPACK_BUFFER, /* 8 */
55 GL_QUERY_BUFFER, /* 9 */
56 GL_SHADER_STORAGE_BUFFER, /* 10 */
57 GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
58 GL_UNIFORM_BUFFER, /* 12 */
63 * @param context CTS context.
65 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
77 /** Initialize buffer instance
79 * @param target Buffer target
80 * @param usage Buffer usage enum
81 * @param size <size> parameter
82 * @param data <data> parameter
84 void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data)
86 /* Delete previous buffer instance */
91 const Functions& gl = m_context.getRenderContext().getFunctions();
94 Bind(gl, m_id, m_target);
95 Data(gl, m_target, usage, size, data);
98 /** Release buffer instance
101 void Buffer::Release()
103 if (m_invalid_id != m_id)
105 const Functions& gl = m_context.getRenderContext().getFunctions();
107 gl.deleteBuffers(1, &m_id);
112 /** Binds buffer to its target
115 void Buffer::Bind() const
117 const Functions& gl = m_context.getRenderContext().getFunctions();
119 Bind(gl, m_id, m_target);
122 /** Binds indexed buffer
124 * @param index <index> parameter
126 void Buffer::BindBase(glw::GLuint index) const
128 const Functions& gl = m_context.getRenderContext().getFunctions();
130 BindBase(gl, m_id, m_target, index);
133 /** Bind buffer to given target
135 * @param gl GL functions
136 * @param id Id of buffer
137 * @param target Buffer target
139 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
141 gl.bindBuffer(target, id);
142 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
145 /** Binds indexed buffer
147 * @param gl GL functions
148 * @param id Id of buffer
149 * @param target Buffer target
150 * @param index <index> parameter
152 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
154 gl.bindBufferBase(target, index, id);
155 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
158 /** Allocate memory for buffer and sends initial content
160 * @param gl GL functions
161 * @param target Buffer target
162 * @param usage Buffer usage enum
163 * @param size <size> parameter
164 * @param data <data> parameter
166 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
167 const glw::GLvoid* data)
169 gl.bufferData(target, size, data, usage);
170 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
175 * @param gl GL functions
176 * @param out_id Id of buffer
178 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
180 GLuint id = m_invalid_id;
182 gl.genBuffers(1, &id);
183 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
185 if (m_invalid_id == id)
187 TCU_FAIL("Got invalid id");
193 /** Update range of buffer
195 * @param gl GL functions
196 * @param target Buffer target
197 * @param offset Offset in buffer
198 * @param size <size> parameter
199 * @param data <data> parameter
201 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
204 gl.bufferSubData(target, offset, size, data);
205 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
208 /* Framebuffer constants */
209 const GLuint Framebuffer::m_invalid_id = -1;
213 * @param context CTS context.
215 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
217 /* Nothing to done here */
223 Framebuffer::~Framebuffer()
228 /** Release texture instance
231 void Framebuffer::Release()
233 if (m_invalid_id != m_id)
235 const Functions& gl = m_context.getRenderContext().getFunctions();
237 gl.deleteFramebuffers(1, &m_id);
242 /** Attach texture to specified attachment
244 * @param gl GL functions
245 * @param target Framebuffer target
246 * @param attachment Attachment
247 * @param texture_id Texture id
248 * @param level Level of mipmap
249 * @param width Texture width
250 * @param height Texture height
252 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
253 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height)
255 gl.framebufferTexture(target, attachment, texture_id, level);
256 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
258 gl.viewport(0 /* x */, 0 /* y */, width, height);
259 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
262 /** Binds framebuffer to DRAW_FRAMEBUFFER
264 * @param gl GL functions
265 * @param target Framebuffer target
266 * @param id ID of framebuffer
268 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
270 gl.bindFramebuffer(target, id);
271 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
274 /** Generate framebuffer
277 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
279 GLuint id = m_invalid_id;
281 gl.genFramebuffers(1, &id);
282 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
284 if (m_invalid_id == id)
286 TCU_FAIL("Invalid id");
292 /* Program constants */
293 const GLuint Program::m_invalid_id = 0;
297 * @param context CTS context.
299 Program::Program(deqp::Context& context)
302 , m_fragment(context)
303 , m_geometry(context)
304 , m_tess_ctrl(context)
305 , m_tess_eval(context)
309 /* Nothing to be done here */
320 /** Initialize program instance
322 * @param compute_shader Compute shader source code
323 * @param fragment_shader Fragment shader source code
324 * @param geometry_shader Geometry shader source code
325 * @param tesselation_control_shader Tesselation control shader source code
326 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
327 * @param vertex_shader Vertex shader source code
329 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
330 const std::string& geometry_shader, const std::string& tesselation_control_shader,
331 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
333 /* Delete previous program */
336 /* GL entry points */
337 const Functions& gl = m_context.getRenderContext().getFunctions();
339 /* Initialize shaders */
340 m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
341 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
342 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
343 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
344 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
345 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
347 /* Create program, set up transform feedback and attach shaders */
349 Attach(gl, m_id, m_compute.m_id);
350 Attach(gl, m_id, m_fragment.m_id);
351 Attach(gl, m_id, m_geometry.m_id);
352 Attach(gl, m_id, m_tess_ctrl.m_id);
353 Attach(gl, m_id, m_tess_eval.m_id);
354 Attach(gl, m_id, m_vertex.m_id);
360 /** Release program instance
363 void Program::Release()
365 const Functions& gl = m_context.getRenderContext().getFunctions();
367 if (m_invalid_id != m_id)
369 Use(gl, m_invalid_id);
371 gl.deleteProgram(m_id);
376 m_fragment.Release();
377 m_geometry.Release();
378 m_tess_ctrl.Release();
379 m_tess_eval.Release();
383 /** Set program as active
386 void Program::Use() const
388 const Functions& gl = m_context.getRenderContext().getFunctions();
393 /** Attach shader to program
395 * @param gl GL functions
396 * @param program_id Id of program
397 * @param shader_id Id of shader
399 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
402 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
407 gl.attachShader(program_id, shader_id);
408 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
411 /** Create program instance
413 * @param gl GL functions
414 * @param out_id Id of program
416 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
418 const GLuint id = gl.createProgram();
419 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
421 if (m_invalid_id == id)
423 TCU_FAIL("Failed to create program");
431 * @param gl GL functions
432 * @param id Id of program
434 void Program::Link(const glw::Functions& gl, glw::GLuint id)
436 GLint status = GL_FALSE;
439 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
441 /* Get link status */
442 gl.getProgramiv(id, GL_LINK_STATUS, &status);
443 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
446 if (GL_TRUE != status)
448 glw::GLint length = 0;
451 /* Get error log length */
452 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
453 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
455 message.resize(length, 0);
458 gl.getProgramInfoLog(id, length, 0, &message[0]);
459 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
461 TCU_FAIL(message.c_str());
467 * @param gl GL functions
468 * @param id Id of program
470 void Program::Use(const glw::Functions& gl, glw::GLuint id)
473 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
476 /* Shader's constants */
477 const GLuint Shader::m_invalid_id = 0;
481 * @param context CTS context.
483 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
485 /* Nothing to be done here */
496 /** Initialize shader instance
498 * @param stage Shader stage
499 * @param source Source code
501 void Shader::Init(glw::GLenum stage, const std::string& source)
503 if (true == source.empty())
505 /* No source == no shader */
509 /* Delete any previous shader */
512 /* Create, set source and compile */
513 const Functions& gl = m_context.getRenderContext().getFunctions();
515 Create(gl, stage, m_id);
516 Source(gl, m_id, source);
521 /** Release shader instance
524 void Shader::Release()
526 if (m_invalid_id != m_id)
528 const Functions& gl = m_context.getRenderContext().getFunctions();
530 gl.deleteShader(m_id);
537 * @param gl GL functions
538 * @param id Shader id
540 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
542 GLint status = GL_FALSE;
545 gl.compileShader(id);
546 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
548 /* Get compilation status */
549 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
550 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
552 /* Log compilation error */
553 if (GL_TRUE != status)
555 glw::GLint length = 0;
558 /* Error log length */
559 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
560 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
562 /* Prepare storage */
563 message.resize(length, 0);
566 gl.getShaderInfoLog(id, length, 0, &message[0]);
567 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
569 TCU_FAIL(message.c_str());
575 * @param gl GL functions
576 * @param stage Shader stage
577 * @param out_id Shader id
579 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
581 const GLuint id = gl.createShader(stage);
582 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
584 if (m_invalid_id == id)
586 TCU_FAIL("Failed to create shader");
592 /** Set shader's source code
594 * @param gl GL functions
595 * @param id Shader id
596 * @param source Shader source code
598 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
600 const GLchar* code = source.c_str();
602 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
603 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
606 /* Texture static fields */
607 const GLuint Texture::m_invalid_id = -1;
611 * @param context CTS context.
613 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
615 /* Nothing to done here */
626 /** Release texture instance
629 void Texture::Release()
631 if (m_invalid_id != m_id)
633 const Functions& gl = m_context.getRenderContext().getFunctions();
635 gl.deleteTextures(1, &m_id);
640 /** Bind texture to target
642 * @param gl GL functions
643 * @param id Id of texture
644 * @param tex_type Type of texture
646 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
648 gl.bindTexture(target, id);
649 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
652 /** Set contents of compressed texture
654 * @param gl GL functions
655 * @param target Texture target
656 * @param level Mipmap level
657 * @param internal_format Format of data
658 * @param width Width of texture
659 * @param height Height of texture
660 * @param depth Depth of texture
661 * @param image_size Size of data
662 * @param data Buffer with image data
664 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
665 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
666 glw::GLsizei image_size, const glw::GLvoid* data)
671 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
672 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
674 case GL_TEXTURE_1D_ARRAY:
676 case GL_TEXTURE_RECTANGLE:
677 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
678 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
680 case GL_TEXTURE_CUBE_MAP:
681 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
683 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
685 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
687 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
689 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
691 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
693 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
696 case GL_TEXTURE_2D_ARRAY:
697 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
698 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
701 TCU_FAIL("Invliad enum");
706 /** Generate texture instance
708 * @param gl GL functions
709 * @param out_id Id of texture
711 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
713 GLuint id = m_invalid_id;
715 gl.genTextures(1, &id);
716 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
718 if (m_invalid_id == id)
720 TCU_FAIL("Invalid id");
728 * @param gl GL functions
729 * @param target Texture target
730 * @param format Format of data
731 * @param type Type of data
732 * @param out_data Buffer for data
734 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
735 glw::GLenum type, glw::GLvoid* out_data)
737 gl.getTexImage(target, level, format, type, out_data);
738 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
743 * @param gl GL functions
744 * @param id Texture id
745 * @param level Mipmap level
746 * @param width Texture width
747 * @param height Texture height
748 * @param format Format of data
749 * @param type Type of data
750 * @param out_data Buffer for data
752 void Texture::GetData(const glw::Functions& gl, glw::GLuint id, glw::GLint level, glw::GLuint width, glw::GLuint height,
753 glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data)
756 gl.genFramebuffers(1, &fbo);
757 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
758 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
759 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
760 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, level);
761 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
763 gl.readPixels(0, 0, width, height, format, type, out_data);
764 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
766 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
769 /** Generate texture instance
771 * @param gl GL functions
772 * @param target Texture target
773 * @param level Mipmap level
774 * @param pname Parameter to query
775 * @param param Result of query
777 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
780 gl.getTexLevelParameteriv(target, level, pname, param);
781 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
784 /** Set contents of texture
786 * @param gl GL functions
787 * @param target Texture target
788 * @param level Mipmap level
789 * @param internal_format Format of data
790 * @param width Width of texture
791 * @param height Height of texture
792 * @param depth Depth of texture
793 * @param format Format of data
794 * @param type Type of data
795 * @param data Buffer with image data
797 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
798 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
799 const glw::GLvoid* data)
804 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
805 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
807 case GL_TEXTURE_1D_ARRAY:
809 case GL_TEXTURE_RECTANGLE:
810 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
811 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
813 case GL_TEXTURE_CUBE_MAP:
814 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
816 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
818 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
820 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
822 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
824 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
826 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
829 case GL_TEXTURE_2D_ARRAY:
830 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
831 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
834 TCU_FAIL("Invliad enum");
839 /** Allocate storage for texture
841 * @param gl GL functions
842 * @param target Texture target
843 * @param levels Number of levels
844 * @param internal_format Internal format of texture
845 * @param width Width of texture
846 * @param height Height of texture
847 * @param depth Depth of texture
849 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
850 glw::GLuint width, glw::GLuint height, glw::GLuint depth)
855 gl.texStorage1D(target, levels, internal_format, width);
856 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
858 case GL_TEXTURE_1D_ARRAY:
860 case GL_TEXTURE_RECTANGLE:
861 case GL_TEXTURE_CUBE_MAP:
862 gl.texStorage2D(target, levels, internal_format, width, height);
863 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
865 case GL_TEXTURE_2D_MULTISAMPLE:
866 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
867 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
870 case GL_TEXTURE_2D_ARRAY:
871 gl.texStorage3D(target, levels, internal_format, width, height, depth);
872 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
875 TCU_FAIL("Invliad enum");
880 /** Set contents of texture
882 * @param gl GL functions
883 * @param target Texture target
884 * @param level Mipmap level
888 * @param width Width of texture
889 * @param height Height of texture
890 * @param depth Depth of texture
891 * @param format Format of data
892 * @param type Type of data
893 * @param pixels Buffer with image data
895 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
896 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
897 glw::GLenum type, const glw::GLvoid* pixels)
902 gl.texSubImage1D(target, level, x, width, format, type, pixels);
903 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
905 case GL_TEXTURE_1D_ARRAY:
907 case GL_TEXTURE_RECTANGLE:
908 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
909 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
911 case GL_TEXTURE_CUBE_MAP:
912 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
913 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
914 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
915 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
916 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
917 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
918 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
921 case GL_TEXTURE_2D_ARRAY:
922 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
923 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
926 TCU_FAIL("Invliad enum");
931 /* VertexArray constants */
932 const GLuint VertexArray::m_invalid_id = -1;
936 * @param context CTS context.
938 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
945 VertexArray::~VertexArray()
950 /** Release vertex array object instance
953 void VertexArray::Release()
955 if (m_invalid_id != m_id)
957 const Functions& gl = m_context.getRenderContext().getFunctions();
961 gl.deleteVertexArrays(1, &m_id);
967 /** Binds Vertex array object
969 * @param gl GL functions
970 * @param id ID of vertex array object
972 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
974 gl.bindVertexArray(id);
975 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
978 /** Generates Vertex array object
980 * @param gl GL functions
981 * @param out_id ID of vertex array object
983 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
985 GLuint id = m_invalid_id;
987 gl.genVertexArrays(1, &id);
988 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
990 if (m_invalid_id == id)
992 TCU_FAIL("Invalid id");
998 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1000 * @param token Token string
1001 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1002 * @param text String that will be used as replacement for <token>
1003 * @param string String to work on
1005 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1007 const size_t text_length = strlen(text);
1008 const size_t token_length = strlen(token);
1009 const size_t token_position = string.find(token, search_position);
1011 string.replace(token_position, token_length, text, text_length);
1013 search_position = token_position + text_length;
1016 bool isRobustBufferAccessBehaviorFeatureSupported(deqp::Context& context)
1018 glu::ContextType context_type = context.getRenderContext().getType();
1019 if (context.getContextInfo().isExtensionSupported("GL_KHR_robust_buffer_access_behavior") ||
1020 context.getContextInfo().isExtensionSupported("GL_ARB_robust_buffer_access_behavior") ||
1021 contextSupports(context_type, glu::ApiType::core(4, 3)))
1025 context.getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1031 * @param context Test context
1033 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context)
1034 : TestCase(context, "vertex_buffer_objects", "Verifies that out-of-bound reads from VB result in zero")
1036 /* Nothing to be done */
1041 * @param context Test context
1043 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context, const char* name, const char* description)
1044 : TestCase(context, name, description)
1046 /* Nothing to be done */
1051 * @return tcu::TestNode::STOP
1053 tcu::TestNode::IterateResult VertexBufferObjectsTest::iterate()
1055 if (!isRobustBufferAccessBehaviorFeatureSupported(m_context))
1058 static const GLuint invalid_elements[] = {
1059 9, 1, 12, 10, 2, 3, 11, 3, 4, 12, 4, 5, 13, 5, 6, 14, 6, 7, 15, 7, 8, 16, 8, 1,
1062 static const GLuint valid_elements[] = {
1063 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
1066 static const GLfloat vertices[] = {
1067 0.0f, 0.0f, 0.0f, /* 0 */
1068 -1.0f, 0.0f, 0.0f, /* 1 */
1069 -1.0f, 1.0f, 0.0f, /* 2 */
1070 0.0f, 1.0f, 0.0f, /* 3 */
1071 1.0f, 1.0f, 0.0f, /* 4 */
1072 1.0f, 0.0f, 0.0f, /* 5 */
1073 1.0f, -1.0f, 0.0f, /* 6 */
1074 0.0f, -1.0f, 0.0f, /* 7 */
1075 -1.0f, -1.0f, 0.0f, /* 8 */
1078 static const GLuint height = 8;
1079 static const GLuint n_vertices = 24;
1080 static const GLuint width = 8;
1082 /* GL entry points */
1083 const Functions& gl = m_context.getRenderContext().getFunctions();
1085 /* Test case objects */
1086 Framebuffer framebuffer(m_context);
1087 Program program(m_context);
1088 Texture texture(m_context);
1089 Buffer elements_buffer(m_context);
1090 Buffer vertices_buffer(m_context);
1091 VertexArray vao(m_context);
1094 VertexArray::Generate(gl, vao.m_id);
1095 VertexArray::Bind(gl, vao.m_id);
1097 /* Buffers initialization */
1098 elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(valid_elements), valid_elements);
1099 vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices);
1101 /* Texture initialization */
1102 Texture::Generate(gl, texture.m_id);
1103 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
1104 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0);
1105 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1107 /* Framebuffer initialization*/
1108 Framebuffer::Generate(gl, framebuffer.m_id);
1109 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1110 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
1113 /* Shaders initialization */
1114 program.Init("" /* cs */, getFragmentShader(), "" /* gs */, "" /* tcs */, "" /* tes */, getVertexShader());
1115 Program::Use(gl, program.m_id);
1117 /* Vertex buffer initialization */
1118 vertices_buffer.Bind();
1119 gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 12 /* stride */);
1120 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, NULL);
1121 gl.enableVertexAttribArray(0 /* location */);
1123 /* Binding elements/indices buffer */
1124 elements_buffer.Bind();
1126 cleanTexture(texture.m_id);
1128 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1129 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1131 if (false == verifyValidResults(texture.m_id))
1133 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for valid input"
1134 << tcu::TestLog::EndMessage;
1136 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1137 return tcu::TestNode::STOP;
1140 /* Generate invalid data sets */
1141 const GLuint invalid_elements_offsets[] = {
1143 4 * 1024, // near fetch (4K of the end of the object)
1144 1024 * 1024, // medium fetch (1MB past the end of the object)
1145 10 * 1024 * 1024 // high fetch (10MB beyond the end of the object)
1147 const GLuint invalid_buffers_count = DE_LENGTH_OF_ARRAY(invalid_elements_offsets);
1148 const GLuint item_count = DE_LENGTH_OF_ARRAY(invalid_elements);
1149 GLuint invalid_elements_set[invalid_buffers_count][item_count];
1150 for (GLuint buffer_index = 0; buffer_index < invalid_buffers_count; ++buffer_index)
1152 for (GLuint item_index = 0; item_index < item_count; ++item_index)
1153 invalid_elements_set[buffer_index][item_index] =
1154 invalid_elements[item_index] + invalid_elements_offsets[buffer_index];
1157 for (GLuint buffer_index = 0; buffer_index < invalid_buffers_count; ++buffer_index)
1159 /* Create elements/indices buffer */
1160 elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(invalid_elements_set[buffer_index]),
1161 invalid_elements_set[buffer_index]);
1162 elements_buffer.Bind();
1164 cleanTexture(texture.m_id);
1166 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1167 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1169 if (false == verifyInvalidResults(texture.m_id))
1171 m_context.getTestContext().getLog()
1172 << tcu::TestLog::Message << "Invalid result for invalid input" << tcu::TestLog::EndMessage;
1173 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1174 return tcu::TestNode::STOP;
1179 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1180 return tcu::TestNode::STOP;
1183 /** Prepare shader for current test case
1187 std::string VertexBufferObjectsTest::getFragmentShader()
1189 return std::string("#version 430 core\n"
1191 "layout (location = 0) out vec4 out_fs_color;\n"
1195 " out_fs_color = vec4(1.0 / 256.0, 1.0, 1.0, 1.0);\n"
1200 /** Prepare shader for current test case
1204 std::string VertexBufferObjectsTest::getVertexShader()
1206 return std::string("#version 430 core\n"
1208 "layout (location = 0) in vec4 in_vs_position;\n"
1212 " gl_Position = in_vs_position;\n"
1217 /** Fill texture with value 128
1219 * @param texture_id Id of texture
1221 void VertexBufferObjectsTest::cleanTexture(glw::GLuint texture_id)
1223 static const GLuint height = 8;
1224 static const GLuint width = 8;
1226 const Functions& gl = m_context.getRenderContext().getFunctions();
1228 GLubyte pixels[width * height];
1229 for (GLuint i = 0; i < width * height; ++i)
1234 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1236 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
1237 GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1240 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1243 /** Verifies that texutre is not filled with 1
1245 * @param texture_id Id of texture
1247 * @return false when image is filled with 1, true otherwise
1249 bool VertexBufferObjectsTest::verifyInvalidResults(glw::GLuint texture_id)
1251 return !verifyResults(texture_id);
1254 /** Verifies that texutre is filled with 1
1256 * @param texture_id Id of texture
1258 * @return true when image is filled with 1, false otherwise
1260 bool VertexBufferObjectsTest::verifyValidResults(glw::GLuint texture_id)
1262 return verifyResults(texture_id);
1265 /** Verifies that texutre is filled with 1
1267 * @param texture_id Id of texture
1269 * @return true when image is filled with 1, false otherwise
1271 bool VertexBufferObjectsTest::verifyResults(glw::GLuint texture_id)
1273 static const GLuint height = 8;
1274 static const GLuint width = 8;
1276 const Functions& gl = m_context.getRenderContext().getFunctions();
1278 GLubyte pixels[width * height];
1279 for (GLuint i = 0; i < width * height; ++i)
1284 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1286 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1289 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1292 for (GLuint i = 0; i < width * height; ++i)
1294 if (255 != pixels[i])
1303 * @param context Test context
1305 TexelFetchTest::TexelFetchTest(deqp::Context& context)
1306 : TestCase(context, "texel_fetch", "Verifies that out-of-bound fetches from texture result in zero")
1309 /* Nothing to be done */
1314 * @param context Test context
1316 TexelFetchTest::TexelFetchTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
1317 : TestCase(context, name, description), m_test_case(R8)
1319 /* Nothing to be done */
1324 * @return tcu::TestNode::STOP
1326 tcu::TestNode::IterateResult TexelFetchTest::iterate()
1328 if (!isRobustBufferAccessBehaviorFeatureSupported(m_context))
1332 static const GLuint height = 16;
1333 static const GLuint width = 16;
1335 /* GL entry points */
1336 const Functions& gl = m_context.getRenderContext().getFunctions();
1338 /* Test result indicator */
1339 bool test_result = true;
1341 GLuint invalid_fetch_offsets[] = {
1343 512, // medium fetch
1346 GLuint fetch_offsets_count = sizeof(invalid_fetch_offsets) / sizeof(GLuint);
1348 /* Iterate over all cases */
1349 for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
1352 GLenum texture_target = GL_TEXTURE_2D;
1354 if (R32UI_MULTISAMPLE == m_test_case || RG8_SNORM == m_test_case)
1356 // 1. RG8_SNORM case:
1357 // Skip RG8_SNORM format case.
1358 // RG8_SNORM is not required to be used as a render target
1359 // OpenGL 4.5 Core Spec, Page 197
1361 // 2. R32UI_MULTISAMPLE case
1362 // Skip test in multi sample case
1363 // texelFetch with invalid lod plane results undefined value
1364 // OpenGL 4.5 Core Spec, around page 377
1365 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
1370 Texture destination_texture(m_context);
1371 Framebuffer framebuffer(m_context);
1372 Texture source_texture(m_context);
1373 Program program(m_context);
1374 VertexArray vao(m_context);
1377 VertexArray::Generate(gl, vao.m_id);
1378 VertexArray::Bind(gl, vao.m_id);
1380 /* Prepare textures */
1381 Texture::Generate(gl, destination_texture.m_id);
1382 Texture::Generate(gl, source_texture.m_id);
1384 if (R32UI_MULTISAMPLE == m_test_case)
1386 GLint max_integer_samples;
1387 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
1388 GLint max_image_samples;
1389 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
1390 if (max_integer_samples < 4 || max_image_samples < 4)
1392 /* prepareTexture() hard-codes 4 samples (n_levels) for
1393 * R32UI_MULTISAMPLE case. This value exceeds the required
1394 * min-max value (1 in OpenGL ES 3.2) and is not supported
1395 * by all implementations.
1397 * Also, the test uses a compute shader with images
1398 * to upload the texture so max_image_samples >= 4
1401 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1402 << " not supported" << tcu::TestLog::EndMessage;
1408 prepareTexture(false, destination_texture.m_id);
1409 prepareTexture(true, source_texture.m_id);
1411 /* Select FBO settings */
1412 if (R32UI_MIPMAP == m_test_case)
1416 else if (R32UI_MULTISAMPLE == m_test_case)
1418 texture_target = GL_TEXTURE_2D_MULTISAMPLE;
1422 Framebuffer::Generate(gl, framebuffer.m_id);
1423 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1424 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destination_texture.m_id, level,
1427 /* Prepare valid program */
1428 program.Init("" /* cs */, getFragmentShader(true), getGeometryShader(), "" /* tcs */, "" /* tes */,
1431 /* Test valid case */
1433 Program::Use(gl, program.m_id);
1436 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1437 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1438 Texture::Bind(gl, source_texture.m_id, texture_target);
1439 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1440 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1442 /* Check if setup is supported */
1443 GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1444 GLU_EXPECT_NO_ERROR(gl.getError(), "CheckFramebufferStatus");
1445 if (GL_FRAMEBUFFER_COMPLETE != fbo_status)
1447 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1448 << " not supported" << tcu::TestLog::EndMessage;
1453 /* Enable multisampling */
1454 if (R32UI_MULTISAMPLE == m_test_case)
1456 gl.enable(GL_MULTISAMPLE);
1457 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
1461 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1463 /* Get error from draw */
1464 GLenum error = gl.getError();
1466 /* Disable multisampling */
1467 if (R32UI_MULTISAMPLE == m_test_case)
1469 gl.disable(GL_MULTISAMPLE);
1470 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
1473 /* Handle error from draw */
1474 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1478 if (false == verifyValidResults(destination_texture.m_id))
1480 test_result = false;
1483 /* Test invalid cases */
1484 for (GLuint index = 0; index < fetch_offsets_count; ++index)
1486 /* Prepare invalid program */
1487 program.Init("" /* cs */, getFragmentShader(false, invalid_fetch_offsets[index]), getGeometryShader(),
1488 "" /* tcs */, "" /* tes */, getVertexShader());
1489 Program::Use(gl, program.m_id);
1492 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1493 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1494 Texture::Bind(gl, source_texture.m_id, texture_target);
1495 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1496 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1499 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1500 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
1503 if (false == verifyInvalidResults(destination_texture.m_id))
1505 test_result = false;
1506 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1507 << " failed" << tcu::TestLog::EndMessage;
1513 if (true == test_result)
1515 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1519 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1523 return tcu::TestNode::STOP;
1526 /** Prepares source code for fragment shader
1528 * @param is_case_valid Selects if valid or invalid case is tested
1530 * @return string with prepared code
1532 std::string TexelFetchTest::getFragmentShader(bool is_case_valid, GLuint fetch_offset)
1534 static const GLchar* plane_0 = " int plane = 0;\n";
1536 static const GLchar* plane_1 = " int plane = 1;\n";
1538 static const GLchar* plane_2 = " int plane = 2;\n";
1540 static const GLchar* plane_sample_invalid = " int plane = 9;\n";
1541 //" int plane = gl_SampleID + 4;\n";
1543 static const GLchar* plane_sample_valid = " int plane = gl_SampleID;\n";
1545 static const GLchar* sampler_regular = "sampler2D";
1546 static const GLchar* sampler_regular_u = "usampler2D";
1547 static const GLchar* sampler_multisampled_u = "usampler2DMS";
1549 static const GLchar* template_code = "VERSION"
1551 " in lowp vec2 gs_fs_tex_coord;\n"
1552 "layout (location = 0) out lowp TYPE out_fs_color;\n"
1553 "layout (location = 0) uniform lowp SAMPLER uni_texture;\n"
1558 " ivec2 point = ivec2(gs_fs_tex_coord * 16.0) + ivec2(OFFSET);\n"
1559 " out_fs_color = texelFetch(uni_texture, point, plane);\n"
1563 static const GLchar* type_vec4 = "vec4";
1564 static const GLchar* type_uvec4 = "uvec4";
1566 const GLchar* plane = plane_0;
1567 const GLchar* sampler = sampler_regular;
1568 const GLchar* type = type_vec4;
1570 if (R32UI_MIPMAP == m_test_case)
1573 sampler = sampler_regular_u;
1576 if (false == is_case_valid)
1582 else if (R32UI_MULTISAMPLE == m_test_case)
1584 plane = plane_sample_valid;
1585 sampler = sampler_multisampled_u;
1588 if (false == is_case_valid)
1591 plane = plane_sample_invalid;
1595 glu::ContextType contextType = m_context.getRenderContext().getType();
1596 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType);
1597 const GLchar* version = glu::getGLSLVersionDeclaration(glslVersion);
1599 size_t position = 0;
1600 std::string source = template_code;
1601 std::stringstream offset;
1602 offset << fetch_offset;
1603 std::string offset_str = offset.str();
1605 replaceToken("VERSION", position, version, source);
1606 replaceToken("TYPE", position, type, source);
1607 replaceToken("SAMPLER", position, sampler, source);
1608 replaceToken("PLANE", position, plane, source);
1609 replaceToken("OFFSET", position, offset_str.c_str(), source);
1614 /** Prepare shader for current test case
1618 std::string TexelFetchTest::getGeometryShader()
1620 return std::string("#version 430 core\n"
1622 "layout(points) in;\n"
1623 "layout(triangle_strip, max_vertices = 4) out;\n"
1625 "out vec2 gs_fs_tex_coord;\n"
1629 " gs_fs_tex_coord = vec2(0, 0);\n"
1630 " gl_Position = vec4(-1, -1, 0, 1);\n"
1633 " gs_fs_tex_coord = vec2(0, 1);\n"
1634 " gl_Position = vec4(-1, 1, 0, 1);\n"
1637 " gs_fs_tex_coord = vec2(1, 0);\n"
1638 " gl_Position = vec4(1, -1, 0, 1);\n"
1641 " gs_fs_tex_coord = vec2(1, 1);\n"
1642 " gl_Position = vec4(1, 1, 0, 1);\n"
1648 /** Prepare shader for current test case
1652 std::string TexelFetchTest::getVertexShader()
1654 return std::string("#version 430 core\n"
1658 " gl_Position = vec4(0, 0, 0, 1);\n"
1663 /** Returns name of current test case
1665 * @return Name of test case
1667 const glw::GLchar* TexelFetchTest::getTestCaseName() const
1669 const GLchar* name = "";
1671 switch (m_test_case)
1674 name = "\"Sampling GL_R8 texture\"";
1677 name = "\"Sampling GL_RG8_SNORM texture\"";
1680 name = "\"Sampling GL_RGBA32F texture\"";
1683 name = "\"Sampling mipmap of GL_32UI texture\"";
1685 case R32UI_MULTISAMPLE:
1686 name = "\"Sampling GL_32UI multisampled texture\"";
1689 TCU_FAIL("Invalid enum");
1696 /** Prepare a texture
1698 * @param is_source Selects if texutre will be used as source or destination
1699 * @param texture_id Id of texutre
1701 void TexelFetchTest::prepareTexture(bool is_source, glw::GLuint texture_id)
1704 static const GLuint image_height = 16;
1705 static const GLuint image_width = 16;
1707 /* GL entry points */
1708 const Functions& gl = m_context.getRenderContext().getFunctions();
1710 /* Texture storage parameters */
1711 GLuint height = image_height;
1712 GLenum internal_format = 0;
1713 GLsizei n_levels = 1;
1714 GLenum target = GL_TEXTURE_2D;
1715 GLuint width = image_width;
1717 /* Prepare texture storage parameters */
1718 switch (m_test_case)
1721 internal_format = GL_R8;
1724 internal_format = GL_RG8_SNORM;
1727 internal_format = GL_RGBA32F;
1730 height = 2 * image_height;
1731 internal_format = GL_R32UI;
1733 width = 2 * image_width;
1735 case R32UI_MULTISAMPLE:
1736 internal_format = GL_R32UI;
1738 target = GL_TEXTURE_2D_MULTISAMPLE;
1741 TCU_FAIL("Invalid enum");
1744 /* Prepare storage */
1745 Texture::Bind(gl, texture_id, target);
1746 Texture::Storage(gl, target, n_levels, internal_format, width, height, 0);
1748 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1749 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1751 /* Destination image can be left empty */
1752 if (false == is_source)
1754 Texture::Bind(gl, 0, target);
1758 /* Prepare texture */
1759 if (R8 == m_test_case)
1761 GLubyte source_pixels[image_width * image_height];
1762 for (GLuint i = 0; i < image_width * image_height; ++i)
1764 source_pixels[i] = static_cast<GLubyte>(i);
1767 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1768 0 /* depth */, GL_RED, GL_UNSIGNED_BYTE, source_pixels);
1770 else if (RG8_SNORM == m_test_case)
1772 static const GLuint n_components = 2;
1774 GLbyte source_pixels[image_width * image_height * n_components];
1775 for (GLuint i = 0; i < image_width * image_height; ++i)
1777 source_pixels[i * n_components + 0] = static_cast<GLubyte>((i % 16) - 8);
1778 source_pixels[i * n_components + 1] = static_cast<GLubyte>((i / 16) - 8);
1781 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1782 0 /* depth */, GL_RG, GL_BYTE, source_pixels);
1784 else if (RGBA32F == m_test_case)
1786 static const GLuint n_components = 4;
1788 GLfloat source_pixels[image_width * image_height * n_components];
1789 for (GLuint i = 0; i < image_width * image_height; ++i)
1791 source_pixels[i * n_components + 0] = (GLfloat)(i % 16) / 16.0f;
1792 source_pixels[i * n_components + 1] = (GLfloat)(i / 16) / 16.0f;
1793 source_pixels[i * n_components + 2] = (GLfloat)i / 256.0f;
1794 source_pixels[i * n_components + 3] = 1.0f;
1797 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1798 0 /* depth */, GL_RGBA, GL_FLOAT, source_pixels);
1800 else if (R32UI_MIPMAP == m_test_case)
1802 GLuint source_pixels[image_width * image_height];
1803 for (GLuint i = 0; i < image_width * image_height; ++i)
1805 source_pixels[i] = i;
1808 Texture::SubImage(gl, GL_TEXTURE_2D, 1 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, image_width, image_height,
1809 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_INT, source_pixels);
1811 else if (R32UI_MULTISAMPLE == m_test_case)
1813 /* Compute shader */
1814 static const GLchar* cs = "#version 430 core\n"
1816 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1818 "layout (location = 0) writeonly uniform uimage2DMS uni_image;\n"
1822 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
1823 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
1825 " imageStore(uni_image, point, 0, uvec4(index + 0, 0, 0, 0));\n"
1826 " imageStore(uni_image, point, 1, uvec4(index + 1, 0, 0, 0));\n"
1827 " imageStore(uni_image, point, 2, uvec4(index + 2, 0, 0, 0));\n"
1828 " imageStore(uni_image, point, 3, uvec4(index + 3, 0, 0, 0));\n"
1832 Program program(m_context);
1833 program.Init(cs, "", "", "", "", "");
1836 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1837 GL_WRITE_ONLY, GL_R32UI);
1838 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1840 gl.uniform1i(0 /* location */, 0 /* image unit*/);
1841 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1843 gl.dispatchCompute(16, 16, 1);
1844 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1847 Texture::Bind(gl, 0, target);
1850 /** Verifies that texutre is filled with 0 or with (0, 0, 0, x),
1851 * where x may be 0, 1 or the biggest representable integer value.
1853 * @param texture_id Id of texture
1855 * @return true when image is filled with 0, 1 or biggest represetable integer number, false otherwise
1857 bool TexelFetchTest::verifyInvalidResults(glw::GLuint texture_id)
1859 static const GLuint height = 16;
1860 static const GLuint width = 16;
1861 static const GLuint n_pixels = height * width;
1863 const Functions& gl = m_context.getRenderContext().getFunctions();
1867 if (R8 == m_test_case)
1869 static const GLuint n_channels = 1;
1871 std::vector<GLubyte> pixels;
1872 pixels.resize(n_pixels * n_channels);
1873 for (GLuint i = 0; i < n_pixels; ++i)
1875 pixels[i] = static_cast<GLubyte>(i);
1878 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1880 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
1883 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1886 for (GLuint i = 0; i < n_pixels; ++i)
1888 const GLubyte expected_red = 0;
1889 const GLubyte drawn_red = pixels[i];
1891 if (expected_red != drawn_red)
1893 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
1894 << ". Expected value: " << (GLuint)expected_red
1895 << " at offset: " << i << tcu::TestLog::EndMessage;
1902 else if (RG8_SNORM == m_test_case)
1904 static const GLuint n_channels = 2;
1906 std::vector<GLbyte> pixels;
1907 pixels.resize(n_pixels * n_channels);
1908 for (GLuint i = 0; i < n_pixels; ++i)
1910 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
1911 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
1914 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1916 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
1919 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1922 for (GLuint i = 0; i < n_pixels; ++i)
1924 const GLbyte expected_red = 0;
1925 const GLbyte expected_green = 0;
1926 const GLbyte drawn_red = pixels[i * n_channels + 0];
1927 const GLbyte drawn_green = pixels[i * n_channels + 1];
1929 if ((expected_red != drawn_red) || (expected_green != drawn_green))
1931 m_context.getTestContext().getLog()
1932 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
1933 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
1934 << ". At offset: " << i << tcu::TestLog::EndMessage;
1941 else if (RGBA32F == m_test_case)
1943 static const GLuint n_channels = 4;
1945 std::vector<GLfloat> pixels;
1946 pixels.resize(n_pixels * n_channels);
1947 for (GLuint i = 0; i < n_pixels; ++i)
1949 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
1950 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
1951 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
1952 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
1955 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1957 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
1960 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1963 for (GLuint i = 0; i < n_pixels; ++i)
1965 const GLfloat expected_red = 0.0f;
1966 const GLfloat expected_green = 0.0f;
1967 const GLfloat expected_blue = 0.0f;
1968 const GLfloat expected_alpha_0 =
1969 0.0f; /* OpenGL 4.5 (and ES) specifies two possiblities (0 or 1) for alpha channel (Chapter 11.1.3.12). */
1970 const GLfloat expected_alpha_1 = 1.0f;
1971 const GLfloat drawn_red = pixels[i * n_channels + 0];
1972 const GLfloat drawn_green = pixels[i * n_channels + 1];
1973 const GLfloat drawn_blue = pixels[i * n_channels + 2];
1974 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
1976 const GLfloat precision = 0.0009765625; /* (1.f / 1024.f) */
1978 if ((de::abs(expected_red - drawn_red) > precision) ||
1979 (de::abs(expected_green - drawn_green) > precision) ||
1980 (de::abs(expected_blue - drawn_blue) > precision) ||
1981 ((de::abs(expected_alpha_0 - drawn_alpha) > precision) &&
1982 (de::abs(expected_alpha_1 - drawn_alpha) > precision)))
1984 m_context.getTestContext().getLog()
1985 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
1986 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
1987 << expected_green << ", " << expected_blue << ", " << expected_alpha_0 << " or " << expected_alpha_1
1988 << ". At offset: " << i << tcu::TestLog::EndMessage;
1995 else if (R32UI_MIPMAP == m_test_case)
1997 static const GLuint n_channels = 1;
1999 std::vector<GLuint> pixels;
2000 pixels.resize(n_pixels * n_channels);
2001 for (GLuint i = 0; i < n_pixels; ++i)
2006 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2008 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2011 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2014 for (GLuint i = 0; i < n_pixels; ++i)
2016 const GLuint expected_red = 0;
2017 const GLuint drawn_red = pixels[i];
2019 if (expected_red != drawn_red)
2021 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2022 << ". Expected value: " << expected_red << " at offset: " << i
2023 << tcu::TestLog::EndMessage;
2030 else if (R32UI_MULTISAMPLE == m_test_case)
2032 static const GLuint n_channels = 1;
2034 /* Compute shader */
2035 static const GLchar* cs = "#version 430 core\n"
2037 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2039 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2040 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2044 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2046 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2047 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2048 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2049 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2051 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2053 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2057 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2062 Program program(m_context);
2063 Texture destination_texture(m_context);
2065 Texture::Generate(gl, destination_texture.m_id);
2066 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2067 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2069 program.Init(cs, "", "", "", "", "");
2071 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2072 GL_READ_ONLY, GL_R32UI);
2073 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2074 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2075 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2076 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2078 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2079 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2081 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2082 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2084 gl.dispatchCompute(16, 16, 1);
2085 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2087 /* Pixels buffer initialization */
2088 std::vector<GLuint> pixels;
2089 pixels.resize(n_pixels * n_channels);
2090 for (GLuint i = 0; i < n_pixels; ++i)
2095 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2098 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2101 for (GLuint i = 0; i < n_pixels; ++i)
2103 const GLuint expected_red = 1;
2104 const GLuint drawn_red = pixels[i];
2106 if (expected_red != drawn_red)
2108 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2109 << ". Expected value: " << expected_red << " at offset: " << i
2110 << tcu::TestLog::EndMessage;
2121 /** Verifies that texutre is filled with increasing values
2123 * @param texture_id Id of texture
2125 * @return true when image is filled with increasing values, false otherwise
2127 bool TexelFetchTest::verifyValidResults(glw::GLuint texture_id)
2129 static const GLuint height = 16;
2130 static const GLuint width = 16;
2131 static const GLuint n_pixels = height * width;
2133 const Functions& gl = m_context.getRenderContext().getFunctions();
2137 if (R8 == m_test_case)
2139 static const GLuint n_channels = 1;
2141 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2143 std::vector<GLubyte> pixels;
2144 pixels.resize(n_pixels * n_channels);
2145 for (GLuint i = 0; i < n_pixels; ++i)
2147 pixels[i] = static_cast<GLubyte>(i);
2150 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2153 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2156 for (GLuint i = 0; i < n_pixels; ++i)
2158 const GLubyte expected_red = static_cast<GLubyte>(i);
2159 const GLubyte drawn_red = pixels[i];
2161 if (expected_red != drawn_red)
2163 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2164 << ". Expected value: " << (GLuint)expected_red
2165 << " at offset: " << i << tcu::TestLog::EndMessage;
2172 else if (RG8_SNORM == m_test_case)
2174 static const GLuint n_channels = 2;
2176 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2178 std::vector<GLbyte> pixels;
2179 pixels.resize(n_pixels * n_channels);
2180 for (GLuint i = 0; i < n_pixels; ++i)
2182 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2183 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2186 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2189 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2192 for (GLuint i = 0; i < n_pixels; ++i)
2194 const GLbyte expected_red = static_cast<GLubyte>((i % 16) - 8);
2195 const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
2196 const GLbyte drawn_red = pixels[i * n_channels + 0];
2197 const GLbyte drawn_green = pixels[i * n_channels + 1];
2199 if ((expected_red != drawn_red) || (expected_green != drawn_green))
2201 m_context.getTestContext().getLog()
2202 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2203 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2204 << ". At offset: " << i << tcu::TestLog::EndMessage;
2211 else if (RGBA32F == m_test_case)
2213 static const GLuint n_channels = 4;
2215 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2217 std::vector<GLfloat> pixels;
2218 pixels.resize(n_pixels * n_channels);
2219 for (GLuint i = 0; i < n_pixels; ++i)
2221 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2222 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2223 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2224 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2227 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2230 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2233 for (GLuint i = 0; i < n_pixels; ++i)
2235 const GLfloat expected_red = (GLfloat)(i % 16) / 16.0f;
2236 const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
2237 const GLfloat expected_blue = (GLfloat)i / 256.0f;
2238 const GLfloat expected_alpha = 1.0f;
2239 const GLfloat drawn_red = pixels[i * n_channels + 0];
2240 const GLfloat drawn_green = pixels[i * n_channels + 1];
2241 const GLfloat drawn_blue = pixels[i * n_channels + 2];
2242 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
2244 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2245 (expected_alpha != drawn_alpha))
2247 m_context.getTestContext().getLog()
2248 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2249 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2250 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2251 << tcu::TestLog::EndMessage;
2258 else if (R32UI_MIPMAP == m_test_case)
2260 static const GLuint n_channels = 1;
2262 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2264 std::vector<GLuint> pixels;
2265 pixels.resize(n_pixels * n_channels * 4);
2266 for (GLuint i = 0; i < n_pixels; ++i)
2271 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2274 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2277 for (GLuint i = 0; i < n_pixels; ++i)
2279 const GLuint expected_red = i;
2280 const GLuint drawn_red = pixels[i];
2282 if (expected_red != drawn_red)
2284 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2285 << ". Expected value: " << expected_red << " at offset: " << i
2286 << tcu::TestLog::EndMessage;
2293 else if (R32UI_MULTISAMPLE == m_test_case)
2295 static const GLuint n_channels = 1;
2297 /* Compute shader */
2298 static const GLchar* cs =
2299 "#version 430 core\n"
2301 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2303 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2304 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2308 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2309 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
2311 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2312 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2313 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2314 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2316 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
2318 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2322 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2327 Program program(m_context);
2328 Texture destination_texture(m_context);
2330 Texture::Generate(gl, destination_texture.m_id);
2331 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2332 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2334 program.Init(cs, "", "", "", "", "");
2336 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2337 GL_READ_ONLY, GL_R32UI);
2338 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2339 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2340 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2341 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2343 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2344 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2346 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2347 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2349 gl.dispatchCompute(16, 16, 1);
2350 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2352 /* Pixels buffer initialization */
2353 std::vector<GLuint> pixels;
2354 pixels.resize(n_pixels * n_channels);
2355 for (GLuint i = 0; i < n_pixels; ++i)
2360 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2363 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2366 for (GLuint i = 0; i < n_pixels; ++i)
2368 const GLuint expected_red = 1;
2369 const GLuint drawn_red = pixels[i];
2371 if (expected_red != drawn_red)
2373 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2374 << ". Expected value: " << expected_red << " at offset: " << i
2375 << tcu::TestLog::EndMessage;
2388 * @param context Test context
2390 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context)
2391 : TexelFetchTest(context, "image_load_store", "Verifies that out-of-bound to image result in zero or is discarded")
2393 /* Nothing to be done */
2398 * @param context Test context
2400 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
2401 : TexelFetchTest(context, name, description)
2403 /* Nothing to be done */
2408 * @return tcu::TestNode::STOP
2410 tcu::TestNode::IterateResult ImageLoadStoreTest::iterate()
2412 if (!isRobustBufferAccessBehaviorFeatureSupported(m_context))
2416 static const GLuint height = 16;
2417 static const GLuint width = 16;
2419 /* GL entry points */
2420 const Functions& gl = m_context.getRenderContext().getFunctions();
2422 struct FetchingOffset
2424 GLuint coord_offset;
2425 GLuint sample_offset;
2427 const FetchingOffset fetching_offsets[] = {
2428 { 16, 4 }, { 512, 4 }, { 1024, 8 }, { 2048, 8 },
2431 /* Test result indicator */
2432 bool test_result = true;
2434 /* Iterate over all cases */
2435 for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
2437 /* Test case result indicator */
2438 bool case_result = true;
2440 if (R32UI_MULTISAMPLE == m_test_case)
2442 // Skip invalid program test in multi sample case
2443 // texelFetch with invalid lod plane results undefined value
2444 // OpenGL 4.5 Core Spec, around page 377
2445 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
2449 /* Test case objects */
2450 Texture destination_texture(m_context);
2451 Texture source_texture(m_context);
2452 Program program(m_context);
2454 /* Prepare textures */
2455 Texture::Generate(gl, destination_texture.m_id);
2456 Texture::Generate(gl, source_texture.m_id);
2458 if (R32UI_MULTISAMPLE == m_test_case)
2460 GLint max_integer_samples;
2461 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
2462 GLint max_image_samples;
2463 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
2464 if (max_integer_samples < 4 || max_image_samples < 4)
2466 /* prepareTexture() hard-codes 4 samples (n_levels) for
2467 * R32UI_MULTISAMPLE case. This value exceeds the required
2468 * min-max value (1 in OpenGL ES 3.2) and is not supported
2469 * by all implementations.
2471 * Also, the test uses a compute shader with images
2472 * to upload the texture so max_image_samples >= 4
2475 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2476 << " not supported" << tcu::TestLog::EndMessage;
2482 prepareTexture(false, destination_texture.m_id);
2483 prepareTexture(true, source_texture.m_id);
2485 /* Test invalid source cases */
2486 for (GLuint i = 0; i < DE_LENGTH_OF_ARRAY(fetching_offsets); ++i)
2488 const FetchingOffset& fo = fetching_offsets[i];
2489 const std::string& cs = getComputeShader(SOURCE_INVALID, fo.coord_offset, fo.sample_offset);
2490 program.Init(cs, "", "", "", "", "");
2494 setTextures(destination_texture.m_id, source_texture.m_id);
2497 gl.dispatchCompute(width, height, 1 /* depth */);
2498 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2501 if (false == verifyInvalidResults(destination_texture.m_id))
2503 case_result = false;
2507 /* Test valid case */
2508 program.Init(getComputeShader(VALID), "", "", "", "", "");
2512 setTextures(destination_texture.m_id, source_texture.m_id);
2515 gl.dispatchCompute(width, height, 1 /* depth */);
2516 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2519 if (false == verifyValidResults(destination_texture.m_id))
2521 case_result = false;
2524 /* Test invalid destination cases */
2525 for (GLuint i = 0; i < DE_LENGTH_OF_ARRAY(fetching_offsets); ++i)
2527 const FetchingOffset& fo = fetching_offsets[i];
2528 const std::string& cs = getComputeShader(DESTINATION_INVALID, fo.coord_offset, fo.sample_offset);
2529 program.Init(cs, "", "", "", "", "");
2533 setTextures(destination_texture.m_id, source_texture.m_id);
2536 gl.dispatchCompute(width, height, 1 /* depth */);
2537 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2540 if (false == verifyValidResults(destination_texture.m_id))
2542 case_result = false;
2546 /* Set test result */
2547 if (false == case_result)
2549 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2550 << " failed" << tcu::TestLog::EndMessage;
2552 test_result = false;
2557 if (true == test_result)
2559 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2563 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2567 return tcu::TestNode::STOP;
2570 /** Prepare shader for current test case
2572 * @param version Specify which version should be prepared
2576 std::string ImageLoadStoreTest::getComputeShader(VERSION version, GLuint coord_offset, GLuint sample_offset)
2578 static const GLchar* template_code =
2579 "#version 430 core\n"
2581 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2583 "layout (location = 1) writeonly uniform IMAGE uni_destination_image;\n"
2584 "layout (location = 0, FORMAT) readonly uniform IMAGE uni_source_image;\n"
2588 " const ivec2 point_destination = ivec2(gl_WorkGroupID.xy) + ivec2(COORD_OFFSET);\n"
2589 " const ivec2 point_source = ivec2(gl_WorkGroupID.xy) + ivec2(COORD_OFFSET);\n"
2595 static const GLchar* copy_multisampled =
2596 " const TYPE color_0 = imageLoad(uni_source_image, point_source, 0 + SAMPLE_OFFSET);\n"
2597 " const TYPE color_1 = imageLoad(uni_source_image, point_source, 1 + SAMPLE_OFFSET);\n"
2598 " const TYPE color_2 = imageLoad(uni_source_image, point_source, 2 + SAMPLE_OFFSET);\n"
2599 " const TYPE color_3 = imageLoad(uni_source_image, point_source, 3 + SAMPLE_OFFSET);\n"
2600 " imageStore(uni_destination_image, point_destination, 0 + SAMPLE_OFFSET, color_0);\n"
2601 " imageStore(uni_destination_image, point_destination, 1 + SAMPLE_OFFSET, color_1);\n"
2602 " imageStore(uni_destination_image, point_destination, 2 + SAMPLE_OFFSET, color_2);\n"
2603 " imageStore(uni_destination_image, point_destination, 3 + SAMPLE_OFFSET, color_3);\n";
2605 static const GLchar* copy_regular =
2606 " const TYPE color = imageLoad(uni_source_image, point_source);\n"
2607 " imageStore(uni_destination_image, point_destination, color);\n";
2609 static const GLchar* format_r8 = "r8";
2610 static const GLchar* format_rg8_snorm = "rg8_snorm";
2611 static const GLchar* format_rgba32f = "rgba32f";
2612 static const GLchar* format_r32ui = "r32ui";
2614 static const GLchar* image_vec4 = "image2D";
2615 static const GLchar* image_uvec4 = "uimage2D";
2616 static const GLchar* image_uvec4_ms = "uimage2DMS";
2618 static const GLchar* type_vec4 = "vec4";
2619 static const GLchar* type_uvec4 = "uvec4";
2621 const GLchar* copy = copy_regular;
2622 const GLchar* format = format_r8;
2623 const GLchar* image = image_vec4;
2624 const GLchar* type = type_vec4;
2626 std::string src_coord_offset_str("0");
2627 std::string dst_coord_offset_str("0");
2628 std::string src_sample_offset_str("0");
2629 std::string dst_sample_offset_str("0");
2631 std::stringstream coord_offset_stream;
2632 coord_offset_stream << coord_offset;
2633 std::stringstream sample_offset_stream;
2634 sample_offset_stream << sample_offset;
2636 if (version == SOURCE_INVALID)
2638 src_coord_offset_str = coord_offset_stream.str();
2639 src_sample_offset_str = sample_offset_stream.str();
2641 else if (version == DESTINATION_INVALID)
2643 dst_coord_offset_str = coord_offset_stream.str();
2644 dst_sample_offset_str = sample_offset_stream.str();
2647 switch (m_test_case)
2652 format = format_rg8_snorm;
2655 format = format_rgba32f;
2658 format = format_r32ui;
2659 image = image_uvec4;
2662 case R32UI_MULTISAMPLE:
2663 copy = copy_multisampled;
2664 format = format_r32ui;
2665 image = image_uvec4_ms;
2670 TCU_FAIL("Invalid enum");
2673 size_t position = 0;
2674 std::string source = template_code;
2676 replaceToken("IMAGE", position, image, source);
2677 replaceToken("FORMAT", position, format, source);
2678 replaceToken("IMAGE", position, image, source);
2679 replaceToken("COORD_OFFSET", position, dst_coord_offset_str.c_str(), source);
2680 replaceToken("COORD_OFFSET", position, src_coord_offset_str.c_str(), source);
2682 size_t temp_position = position;
2683 replaceToken("COPY", position, copy, source);
2684 position = temp_position;
2686 switch (m_test_case)
2692 replaceToken("TYPE", position, type, source);
2694 case R32UI_MULTISAMPLE:
2695 replaceToken("TYPE", position, type, source);
2696 replaceToken("SAMPLE_OFFSET", position, src_sample_offset_str.c_str(), source);
2697 replaceToken("TYPE", position, type, source);
2698 replaceToken("SAMPLE_OFFSET", position, src_sample_offset_str.c_str(), source);
2699 replaceToken("TYPE", position, type, source);
2700 replaceToken("SAMPLE_OFFSET", position, src_sample_offset_str.c_str(), source);
2701 replaceToken("TYPE", position, type, source);
2702 replaceToken("SAMPLE_OFFSET", position, src_sample_offset_str.c_str(), source);
2703 replaceToken("SAMPLE_OFFSET", position, dst_sample_offset_str.c_str(), source);
2704 replaceToken("SAMPLE_OFFSET", position, dst_sample_offset_str.c_str(), source);
2705 replaceToken("SAMPLE_OFFSET", position, dst_sample_offset_str.c_str(), source);
2706 replaceToken("SAMPLE_OFFSET", position, dst_sample_offset_str.c_str(), source);
2709 TCU_FAIL("Invalid enum");
2715 /** Set textures as images
2717 * @param id_destination Id of texture used as destination
2718 * @param id_source Id of texture used as source
2720 void ImageLoadStoreTest::setTextures(glw::GLuint id_destination, glw::GLuint id_source)
2722 const Functions& gl = m_context.getRenderContext().getFunctions();
2727 switch (m_test_case)
2733 format = GL_RG8_SNORM;
2736 format = GL_RGBA32F;
2742 case R32UI_MULTISAMPLE:
2746 TCU_FAIL("Invalid enum");
2749 gl.bindImageTexture(0 /* unit */, id_source, level, GL_FALSE /* layered */, 0 /* layer */, GL_READ_ONLY, format);
2750 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2752 gl.bindImageTexture(1 /* unit */, id_destination, level, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY,
2754 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2756 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2757 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2759 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2760 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2763 /** Verifies that texutre is filled with 0
2765 * @param texture_id Id of texture
2767 * @return true when image is filled with 0, false otherwise
2769 bool ImageLoadStoreTest::verifyInvalidResults(glw::GLuint texture_id)
2771 static const GLuint height = 16;
2772 static const GLuint width = 16;
2773 static const GLuint n_pixels = height * width;
2775 const Functions& gl = m_context.getRenderContext().getFunctions();
2776 gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2777 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2781 if (R8 == m_test_case)
2783 static const GLuint n_channels = 1;
2785 std::vector<GLubyte> pixels;
2786 pixels.resize(n_pixels * n_channels);
2787 for (GLuint i = 0; i < n_pixels; ++i)
2789 pixels[i] = static_cast<GLubyte>(i);
2792 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2794 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2797 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2800 for (GLuint i = 0; i < n_pixels; ++i)
2802 const GLubyte expected_red = 0;
2803 const GLubyte drawn_red = pixels[i];
2805 if (expected_red != drawn_red)
2807 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2808 << ". Expected value: " << (GLuint)expected_red
2809 << " at offset: " << i << tcu::TestLog::EndMessage;
2816 else if (RG8_SNORM == m_test_case)
2818 static const GLuint n_channels = 2;
2820 std::vector<GLbyte> pixels;
2821 pixels.resize(n_pixels * n_channels);
2822 for (GLuint i = 0; i < n_pixels; ++i)
2824 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2825 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2828 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2830 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2833 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2836 for (GLuint i = 0; i < n_pixels; ++i)
2838 const GLbyte expected_red = 0;
2839 const GLbyte expected_green = 0;
2840 const GLbyte drawn_red = pixels[i * n_channels + 0];
2841 const GLbyte drawn_green = pixels[i * n_channels + 1];
2843 if ((expected_red != drawn_red) || (expected_green != drawn_green))
2845 m_context.getTestContext().getLog()
2846 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2847 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2848 << ". At offset: " << i << tcu::TestLog::EndMessage;
2855 else if (RGBA32F == m_test_case)
2857 static const GLuint n_channels = 4;
2859 std::vector<GLfloat> pixels;
2860 pixels.resize(n_pixels * n_channels);
2861 for (GLuint i = 0; i < n_pixels; ++i)
2863 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2864 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2865 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2866 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2869 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2871 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2874 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2877 for (GLuint i = 0; i < n_pixels; ++i)
2879 const GLfloat expected_red = 0.0f;
2880 const GLfloat expected_green = 0.0f;
2881 const GLfloat expected_blue = 0.0f;
2882 const GLfloat expected_alpha = 0.0f;
2883 const GLfloat drawn_red = pixels[i * n_channels + 0];
2884 const GLfloat drawn_green = pixels[i * n_channels + 1];
2885 const GLfloat drawn_blue = pixels[i * n_channels + 2];
2886 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
2888 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2889 (expected_alpha != drawn_alpha))
2891 m_context.getTestContext().getLog()
2892 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2893 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2894 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2895 << tcu::TestLog::EndMessage;
2902 else if (R32UI_MIPMAP == m_test_case)
2904 static const GLuint n_channels = 1;
2906 std::vector<GLuint> pixels;
2907 pixels.resize(n_pixels * n_channels);
2908 for (GLuint i = 0; i < n_pixels; ++i)
2913 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2915 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2918 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2921 for (GLuint i = 0; i < n_pixels; ++i)
2923 const GLuint expected_red = 0;
2924 const GLuint drawn_red = pixels[i];
2926 if (expected_red != drawn_red)
2928 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2929 << ". Expected value: " << expected_red << " at offset: " << i
2930 << tcu::TestLog::EndMessage;
2937 else if (R32UI_MULTISAMPLE == m_test_case)
2939 static const GLuint n_channels = 1;
2941 /* Compute shader */
2942 static const GLchar* cs = "#version 430 core\n"
2944 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2946 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2947 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2951 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2953 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2954 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2955 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2956 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2958 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2960 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2964 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2969 Program program(m_context);
2970 Texture destination_texture(m_context);
2972 Texture::Generate(gl, destination_texture.m_id);
2973 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2974 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2976 program.Init(cs, "", "", "", "", "");
2978 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2979 GL_READ_ONLY, GL_R32UI);
2980 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2981 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2982 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2983 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2985 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2986 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2988 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2989 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2991 gl.dispatchCompute(16, 16, 1);
2992 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2994 /* Pixels buffer initialization */
2995 std::vector<GLuint> pixels;
2996 pixels.resize(n_pixels * n_channels);
2997 for (GLuint i = 0; i < n_pixels; ++i)
3002 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3005 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3008 for (GLuint i = 0; i < n_pixels; ++i)
3010 const GLuint expected_red = 1;
3011 const GLuint drawn_red = pixels[i];
3013 if (expected_red != drawn_red)
3015 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3016 << ". Expected value: " << expected_red << " at offset: " << i
3017 << tcu::TestLog::EndMessage;
3028 /** Verifies that texutre is filled with increasing values
3030 * @param texture_id Id of texture
3032 * @return true when image is filled with increasing values, false otherwise
3034 bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
3036 static const GLuint height = 16;
3037 static const GLuint width = 16;
3038 static const GLuint n_pixels = height * width;
3040 const Functions& gl = m_context.getRenderContext().getFunctions();
3041 gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3042 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3046 if (R8 == m_test_case)
3048 static const GLuint n_channels = 1;
3050 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3052 std::vector<GLubyte> pixels;
3053 pixels.resize(n_pixels * n_channels);
3054 for (GLuint i = 0; i < n_pixels; ++i)
3056 pixels[i] = static_cast<GLubyte>(i);
3059 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
3062 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3065 for (GLuint i = 0; i < n_pixels; ++i)
3067 const GLubyte expected_red = static_cast<GLubyte>(i);
3068 const GLubyte drawn_red = pixels[i];
3070 if (expected_red != drawn_red)
3072 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
3073 << ". Expected value: " << (GLuint)expected_red
3074 << " at offset: " << i << tcu::TestLog::EndMessage;
3081 else if (RG8_SNORM == m_test_case)
3083 static const GLuint n_channels = 2;
3085 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3087 std::vector<GLbyte> pixels;
3088 pixels.resize(n_pixels * n_channels);
3089 for (GLuint i = 0; i < n_pixels; ++i)
3091 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
3092 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
3095 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
3098 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3101 for (GLuint i = 0; i < n_pixels; ++i)
3103 const GLbyte expected_red = static_cast<GLubyte>((i % 16) - 8);
3104 const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
3105 const GLbyte drawn_red = pixels[i * n_channels + 0];
3106 const GLbyte drawn_green = pixels[i * n_channels + 1];
3108 if ((expected_red != drawn_red) || (expected_green != drawn_green))
3110 m_context.getTestContext().getLog()
3111 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
3112 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
3113 << ". At offset: " << i << tcu::TestLog::EndMessage;
3120 else if (RGBA32F == m_test_case)
3122 static const GLuint n_channels = 4;
3124 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3126 std::vector<GLfloat> pixels;
3127 pixels.resize(n_pixels * n_channels);
3128 for (GLuint i = 0; i < n_pixels; ++i)
3130 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
3131 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
3132 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
3133 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
3136 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
3139 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3142 for (GLuint i = 0; i < n_pixels; ++i)
3144 const GLfloat expected_red = (GLfloat)(i % 16) / 16.0f;
3145 const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
3146 const GLfloat expected_blue = (GLfloat)i / 256.0f;
3147 const GLfloat expected_alpha = 1.0f;
3148 const GLfloat drawn_red = pixels[i * n_channels + 0];
3149 const GLfloat drawn_green = pixels[i * n_channels + 1];
3150 const GLfloat drawn_blue = pixels[i * n_channels + 2];
3151 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
3153 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
3154 (expected_alpha != drawn_alpha))
3156 m_context.getTestContext().getLog()
3157 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
3158 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
3159 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
3160 << tcu::TestLog::EndMessage;
3167 else if (R32UI_MIPMAP == m_test_case)
3169 static const GLuint n_channels = 1;
3171 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3173 std::vector<GLuint> pixels;
3174 pixels.resize(n_pixels * n_channels * 4);
3175 for (GLuint i = 0; i < n_pixels; ++i)
3180 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3183 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3186 for (GLuint i = 0; i < n_pixels; ++i)
3188 const GLuint expected_red = i;
3189 const GLuint drawn_red = pixels[i];
3191 if (expected_red != drawn_red)
3193 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3194 << ". Expected value: " << expected_red << " at offset: " << i
3195 << tcu::TestLog::EndMessage;
3202 else if (R32UI_MULTISAMPLE == m_test_case)
3204 static const GLuint n_channels = 1;
3206 /* Compute shader */
3207 static const GLchar* cs =
3208 "#version 430 core\n"
3210 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3212 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
3213 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
3217 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
3218 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
3220 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
3221 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
3222 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
3223 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
3225 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
3227 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
3231 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
3236 Program program(m_context);
3237 Texture destination_texture(m_context);
3239 Texture::Generate(gl, destination_texture.m_id);
3240 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
3241 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
3243 program.Init(cs, "", "", "", "", "");
3245 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3246 GL_READ_ONLY, GL_R32UI);
3247 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3248 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
3249 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
3250 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3252 gl.uniform1i(0 /* location */, 0 /* image unit*/);
3253 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3255 gl.uniform1i(1 /* location */, 1 /* image unit*/);
3256 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3258 gl.dispatchCompute(16, 16, 1);
3259 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3261 /* Pixels buffer initialization */
3262 std::vector<GLuint> pixels;
3263 pixels.resize(n_pixels * n_channels);
3264 for (GLuint i = 0; i < n_pixels; ++i)
3269 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3272 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3275 for (GLuint i = 0; i < n_pixels; ++i)
3277 const GLuint expected_red = 1;
3278 const GLuint drawn_red = pixels[i];
3280 if (expected_red != drawn_red)
3282 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3283 << ". Expected value: " << expected_red << " at offset: " << i
3284 << tcu::TestLog::EndMessage;
3295 /* StorageBufferTest constants */
3296 const GLfloat StorageBufferTest::m_destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3297 const GLfloat StorageBufferTest::m_source_data[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3301 * @param context Test context
3303 StorageBufferTest::StorageBufferTest(deqp::Context& context)
3304 : TestCase(context, "storage_buffer", "Verifies that out-of-bound access to SSBO is discared or resutls in 0")
3305 , m_test_case(VALID)
3306 , m_hasKhrRobustBufferAccess(false)
3308 /* Nothing to be done here */
3313 * @param context Test context
3315 StorageBufferTest::StorageBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3316 : TestCase(context, name, description), m_test_case(VALID)
3318 /* Nothing to be done */
3323 * @return tcu::TestNode::STOP
3325 tcu::TestNode::IterateResult StorageBufferTest::iterate()
3327 if (!isRobustBufferAccessBehaviorFeatureSupported(m_context))
3330 /* GL entry points */
3331 const Functions& gl = m_context.getRenderContext().getFunctions();
3333 glu::ContextType contextType = m_context.getRenderContext().getType();
3334 m_hasKhrRobustBufferAccess =
3335 m_context.getContextInfo().isExtensionSupported("GL_KHR_robust_buffer_access_behavior") ||
3336 contextSupports(contextType, glu::ApiType::core(4, 5));
3338 /* Test result indicator */
3339 bool test_result = true;
3341 GLuint test_offsets[] = {
3343 4 * 1024, // near fetch (4K of the end of the object)
3344 1024 * 1024, // medium fetch (1MB past the end of the object)
3345 10 * 1024 * 1024 // high fetch (10MB beyond the end of the object)
3348 /* Iterate over all cases */
3349 while (LAST != m_test_case)
3351 /* Test case objects */
3352 Buffer destination_buffer(m_context);
3353 Buffer source_buffer(m_context);
3354 Program program(m_context);
3356 /* Buffers initialization */
3357 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(m_destination_data),
3358 m_destination_data);
3359 source_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(m_source_data), m_source_data);
3361 destination_buffer.BindBase(0);
3362 source_buffer.BindBase(1);
3364 for (GLuint i = 0; i < DE_LENGTH_OF_ARRAY(test_offsets); ++i)
3366 /* Initialize shader */
3367 const std::string& cs = getComputeShader(test_offsets[i]);
3368 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3371 /* Dispatch compute */
3372 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3373 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3375 /* Set memory barrier */
3376 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3377 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3379 /* Verify results */
3380 destination_buffer.Bind();
3381 GLfloat* buffer_data =
3382 (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(m_destination_data), GL_MAP_READ_BIT);
3383 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3385 test_result &= verifyResults(buffer_data);
3387 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3388 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3392 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3396 if (true == test_result)
3398 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3402 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3406 return tcu::TestNode::STOP;
3409 /** Prepare shader for current test case
3413 std::string StorageBufferTest::getComputeShader(GLuint offset)
3415 static const GLchar* cs = "#version 430 core\n"
3417 "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3419 "layout (binding = 1, std430) buffer Source {\n"
3423 "layout (binding = 0, std430) buffer Destination {\n"
3429 " const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3430 " const uint index_source = gl_LocalInvocationID.x + OFFSET;\n"
3432 " destination.data[index_destination] = source.data[index_source];\n"
3436 std::string destination_offset("0");
3437 std::string source_offset("0");
3438 size_t position = 0;
3439 std::string source = cs;
3441 std::stringstream offset_stream;
3442 offset_stream << offset;
3444 if (m_test_case == SOURCE_INVALID)
3445 source_offset = offset_stream.str();
3446 else if (m_test_case == DESTINATION_INVALID)
3447 destination_offset = offset_stream.str();
3449 replaceToken("OFFSET", position, destination_offset.c_str(), source);
3450 replaceToken("OFFSET", position, source_offset.c_str(), source);
3455 /** Verify test case results
3457 * @param buffer_data Buffer data to verify
3459 * @return true if buffer_data is as expected, false othrewise
3461 bool StorageBufferTest::verifyResults(GLfloat* buffer_data)
3463 /* KHR_robust_buffer_access_behavior (and also GL 4.5 and later) states
3464 * which values can be expected when reading or writing outside of a
3465 * buffer's range. If supported, we will compare results against those
3468 * Otherwise, we will attempt to match results against previously observed
3469 * and valid behavior.
3471 static const GLfloat expected_data_valid[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3472 static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3473 static const GLfloat expected_data_invalid_destination[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3475 /* Prepare expected data const for proper case*/
3476 const GLchar* name = 0;
3477 bool check_expected_data = false;
3478 const GLfloat* expected_data = 0;
3479 switch (m_test_case)
3482 name = "valid indices";
3483 check_expected_data = true;
3484 expected_data = expected_data_valid;
3486 case SOURCE_INVALID:
3487 name = "invalid source indices";
3488 if (m_hasKhrRobustBufferAccess)
3490 for (int b = 0; b < 4; b++)
3492 /* Each out-of-range read can either be 0 or any value within
3493 * the source buffer.
3496 if (buffer_data[b] == 0.0f)
3502 for (int c = 0; c < 4 && !valid; c++)
3504 if (buffer_data[b] == m_source_data[c])
3512 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3513 << tcu::TestLog::EndMessage;
3519 check_expected_data = true;
3520 expected_data = expected_data_invalid_source;
3523 case DESTINATION_INVALID:
3524 name = "invalid destination indices";
3525 if (m_hasKhrRobustBufferAccess)
3527 for (int b = 0; b < 4; b++)
3530 /* Each out-of-range write can either be discarded (in which
3531 * case it would have the original destination value) or it
3532 * could write any value within the buffer (so we need to check
3533 * against each possible source value).
3535 if (buffer_data[b] == m_destination_data[b])
3541 for (int c = 0; c < 4 && !valid; c++)
3543 if (buffer_data[b] == m_source_data[c])
3551 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3552 << tcu::TestLog::EndMessage;
3558 check_expected_data = true;
3559 expected_data = expected_data_invalid_destination;
3563 TCU_FAIL("Invalid enum");
3566 if (check_expected_data)
3568 /* Verify buffer data */
3569 int size = static_cast<int>(sizeof(GLfloat) * 4);
3570 if (0 != memcmp(expected_data, buffer_data, size))
3572 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3573 << tcu::TestLog::EndMessage;
3583 * @param context Test context
3585 UniformBufferTest::UniformBufferTest(deqp::Context& context)
3586 : TestCase(context, "uniform_buffer", "Verifies that out-of-bound access to UBO resutls in 0"), m_test_case(VALID)
3588 /* Nothing to be done here */
3593 * @param context Test context
3595 UniformBufferTest::UniformBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3596 : TestCase(context, name, description), m_test_case(VALID)
3598 /* Nothing to be done */
3603 * @return tcu::TestNode::STOP
3605 tcu::TestNode::IterateResult UniformBufferTest::iterate()
3607 if (!isRobustBufferAccessBehaviorFeatureSupported(m_context))
3610 static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3611 /* The source buffer is packed std140 so we need vec4s */
3612 static const GLfloat source_data[16] = {
3613 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,
3616 GLuint test_offsets[] = {
3618 4 * 1024, // near fetch (4K of the end of the object)
3619 1024 * 1024, // medium fetch (1MB past the end of the object)
3620 10 * 1024 * 1024 // high fetch (10MB beyond the end of the object)
3623 /* GL entry points */
3624 const Functions& gl = m_context.getRenderContext().getFunctions();
3626 /* Test result indicator */
3627 bool test_result = true;
3629 /* Iterate over all cases */
3630 while (LAST != m_test_case)
3632 /* Test case objects */
3633 Buffer destination_buffer(m_context);
3634 Buffer source_buffer(m_context);
3635 Program program(m_context);
3637 /* Buffers initialization */
3638 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
3640 source_buffer.InitData(GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
3642 destination_buffer.BindBase(0);
3643 source_buffer.BindBase(0);
3645 for (GLuint i = 0; i < DE_LENGTH_OF_ARRAY(test_offsets); ++i)
3647 /* Initialize shader */
3648 const std::string& cs = getComputeShader(test_offsets[i]);
3649 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3652 /* Dispatch compute */
3653 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3654 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3656 /* Set memory barrier */
3657 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3658 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3660 /* Verify results */
3661 destination_buffer.Bind();
3662 GLfloat* buffer_data =
3663 (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
3664 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3666 test_result &= verifyResults(buffer_data);
3668 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3669 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3673 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3677 if (true == test_result)
3679 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3683 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3687 return tcu::TestNode::STOP;
3690 /** Prepare shader for current test case
3694 std::string UniformBufferTest::getComputeShader(GLuint offset)
3696 static const GLchar* cs = "#version 430 core\n"
3698 "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3700 "layout (binding = 0, std140) uniform Source {\n"
3701 " float data[16];\n"
3704 "layout (binding = 0, std430) buffer Destination {\n"
3710 " const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3711 " const uint index_source = gl_LocalInvocationID.x + OFFSET;\n"
3713 " destination.data[index_destination] = source.data[index_source];\n"
3717 const GLchar* destination_offset = "0";
3718 std::string source_offset("0");
3719 size_t position = 0;
3720 std::string source = cs;
3722 std::stringstream offset_stream;
3723 offset_stream << offset;
3725 if (m_test_case == SOURCE_INVALID)
3726 source_offset = offset_stream.str();
3728 replaceToken("OFFSET", position, destination_offset, source);
3729 replaceToken("OFFSET", position, source_offset.c_str(), source);
3734 /** Verify test case results
3736 * @param buffer_data Buffer data to verify
3738 * @return true if buffer_data is as expected, false othrewise
3740 bool UniformBufferTest::verifyResults(GLfloat* buffer_data)
3742 static const GLfloat expected_data_valid[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3743 static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3745 int size = static_cast<int>(sizeof(GLfloat) * 4);
3747 /* Prepare expected data const for proper case*/
3748 const GLfloat* expected_data = 0;
3749 const GLchar* name = 0;
3750 switch (m_test_case)
3753 expected_data = expected_data_valid;
3754 name = "valid indices";
3756 case SOURCE_INVALID:
3757 expected_data = expected_data_invalid_source;
3758 name = "invalid source indices";
3761 TCU_FAIL("Invalid enum");
3764 /* Verify buffer data */
3765 if (0 != memcmp(expected_data, buffer_data, size))
3767 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3768 << tcu::TestLog::EndMessage;
3774 } /* RobustBufferAccessBehavior */
3778 * @param context Rendering context.
3780 RobustBufferAccessBehaviorTests::RobustBufferAccessBehaviorTests(deqp::Context& context)
3781 : TestCaseGroup(context, "robust_buffer_access_behavior",
3782 "Verifies \"robust buffer access behavior\" functionality")
3784 /* Left blank on purpose */
3787 /** Initializes a multi_bind test group.
3790 void RobustBufferAccessBehaviorTests::init(void)
3792 addChild(new RobustBufferAccessBehavior::VertexBufferObjectsTest(m_context));
3793 addChild(new RobustBufferAccessBehavior::TexelFetchTest(m_context));
3794 addChild(new RobustBufferAccessBehavior::ImageLoadStoreTest(m_context));
3795 addChild(new RobustBufferAccessBehavior::StorageBufferTest(m_context));
3796 addChild(new RobustBufferAccessBehavior::UniformBufferTest(m_context));