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.
22 */ /*-------------------------------------------------------------------*/
24 * \file glcRobustBufferAccessBehaviorTests.cpp
25 * \brief Implements conformance tests for "Robust Buffer Access Behavior" functionality.
26 */ /*-------------------------------------------------------------------*/
28 #include "glcRobustBufferAccessBehaviorTests.hpp"
30 #include "gluDefs.hpp"
31 #include "glwEnums.hpp"
32 #include "glwFunctions.hpp"
33 #include "tcuTestLog.hpp"
42 namespace RobustBufferAccessBehavior
44 /* Buffer constants */
45 const GLuint Buffer::m_invalid_id = -1;
47 const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
48 GL_ARRAY_BUFFER, /* 0 */
49 GL_ATOMIC_COUNTER_BUFFER, /* 1 */
50 GL_COPY_READ_BUFFER, /* 2 */
51 GL_COPY_WRITE_BUFFER, /* 3 */
52 GL_DISPATCH_INDIRECT_BUFFER, /* 4 */
53 GL_DRAW_INDIRECT_BUFFER, /* 5 */
54 GL_ELEMENT_ARRAY_BUFFER, /* 6 */
55 GL_PIXEL_PACK_BUFFER, /* 7 */
56 GL_PIXEL_UNPACK_BUFFER, /* 8 */
57 GL_QUERY_BUFFER, /* 9 */
58 GL_SHADER_STORAGE_BUFFER, /* 10 */
59 GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
60 GL_UNIFORM_BUFFER, /* 12 */
65 * @param context CTS context.
67 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
79 /** Initialize buffer instance
81 * @param target Buffer target
82 * @param usage Buffer usage enum
83 * @param size <size> parameter
84 * @param data <data> parameter
86 void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data)
88 /* Delete previous buffer instance */
93 const Functions& gl = m_context.getRenderContext().getFunctions();
96 Bind(gl, m_id, m_target);
97 Data(gl, m_target, usage, size, data);
100 /** Release buffer instance
103 void Buffer::Release()
105 if (m_invalid_id != m_id)
107 const Functions& gl = m_context.getRenderContext().getFunctions();
109 gl.deleteBuffers(1, &m_id);
114 /** Binds buffer to its target
117 void Buffer::Bind() const
119 const Functions& gl = m_context.getRenderContext().getFunctions();
121 Bind(gl, m_id, m_target);
124 /** Binds indexed buffer
126 * @param index <index> parameter
128 void Buffer::BindBase(glw::GLuint index) const
130 const Functions& gl = m_context.getRenderContext().getFunctions();
132 BindBase(gl, m_id, m_target, index);
135 /** Bind buffer to given target
137 * @param gl GL functions
138 * @param id Id of buffer
139 * @param target Buffer target
141 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
143 gl.bindBuffer(target, id);
144 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
147 /** Binds indexed buffer
149 * @param gl GL functions
150 * @param id Id of buffer
151 * @param target Buffer target
152 * @param index <index> parameter
154 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
156 gl.bindBufferBase(target, index, id);
157 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
160 /** Allocate memory for buffer and sends initial content
162 * @param gl GL functions
163 * @param target Buffer target
164 * @param usage Buffer usage enum
165 * @param size <size> parameter
166 * @param data <data> parameter
168 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
169 const glw::GLvoid* data)
171 gl.bufferData(target, size, data, usage);
172 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
177 * @param gl GL functions
178 * @param out_id Id of buffer
180 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
182 GLuint id = m_invalid_id;
184 gl.genBuffers(1, &id);
185 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
187 if (m_invalid_id == id)
189 TCU_FAIL("Got invalid id");
195 /** Update range of buffer
197 * @param gl GL functions
198 * @param target Buffer target
199 * @param offset Offset in buffer
200 * @param size <size> parameter
201 * @param data <data> parameter
203 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
206 gl.bufferSubData(target, offset, size, data);
207 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
210 /* Framebuffer constants */
211 const GLuint Framebuffer::m_invalid_id = -1;
215 * @param context CTS context.
217 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
219 /* Nothing to done here */
225 Framebuffer::~Framebuffer()
230 /** Release texture instance
233 void Framebuffer::Release()
235 if (m_invalid_id != m_id)
237 const Functions& gl = m_context.getRenderContext().getFunctions();
239 gl.deleteFramebuffers(1, &m_id);
244 /** Attach texture to specified attachment
246 * @param gl GL functions
247 * @param target Framebuffer target
248 * @param attachment Attachment
249 * @param texture_id Texture id
250 * @param level Level of mipmap
251 * @param width Texture width
252 * @param height Texture height
254 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
255 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height)
257 gl.framebufferTexture(target, attachment, texture_id, level);
258 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
260 gl.viewport(0 /* x */, 0 /* y */, width, height);
261 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
264 /** Binds framebuffer to DRAW_FRAMEBUFFER
266 * @param gl GL functions
267 * @param target Framebuffer target
268 * @param id ID of framebuffer
270 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
272 gl.bindFramebuffer(target, id);
273 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
276 /** Generate framebuffer
279 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
281 GLuint id = m_invalid_id;
283 gl.genFramebuffers(1, &id);
284 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
286 if (m_invalid_id == id)
288 TCU_FAIL("Invalid id");
294 /* Program constants */
295 const GLuint Program::m_invalid_id = 0;
299 * @param context CTS context.
301 Program::Program(deqp::Context& context)
304 , m_fragment(context)
305 , m_geometry(context)
306 , m_tess_ctrl(context)
307 , m_tess_eval(context)
311 /* Nothing to be done here */
322 /** Initialize program instance
324 * @param compute_shader Compute shader source code
325 * @param fragment_shader Fragment shader source code
326 * @param geometry_shader Geometry shader source code
327 * @param tesselation_control_shader Tesselation control shader source code
328 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
329 * @param vertex_shader Vertex shader source code
331 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
332 const std::string& geometry_shader, const std::string& tesselation_control_shader,
333 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
335 /* Delete previous program */
338 /* GL entry points */
339 const Functions& gl = m_context.getRenderContext().getFunctions();
341 /* Initialize shaders */
342 m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
343 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
344 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
345 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
346 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
347 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
349 /* Create program, set up transform feedback and attach shaders */
351 Attach(gl, m_id, m_compute.m_id);
352 Attach(gl, m_id, m_fragment.m_id);
353 Attach(gl, m_id, m_geometry.m_id);
354 Attach(gl, m_id, m_tess_ctrl.m_id);
355 Attach(gl, m_id, m_tess_eval.m_id);
356 Attach(gl, m_id, m_vertex.m_id);
362 /** Release program instance
365 void Program::Release()
367 const Functions& gl = m_context.getRenderContext().getFunctions();
369 if (m_invalid_id != m_id)
371 Use(gl, m_invalid_id);
373 gl.deleteProgram(m_id);
378 m_fragment.Release();
379 m_geometry.Release();
380 m_tess_ctrl.Release();
381 m_tess_eval.Release();
385 /** Set program as active
388 void Program::Use() const
390 const Functions& gl = m_context.getRenderContext().getFunctions();
395 /** Attach shader to program
397 * @param gl GL functions
398 * @param program_id Id of program
399 * @param shader_id Id of shader
401 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
404 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
409 gl.attachShader(program_id, shader_id);
410 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
413 /** Create program instance
415 * @param gl GL functions
416 * @param out_id Id of program
418 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
420 const GLuint id = gl.createProgram();
421 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
423 if (m_invalid_id == id)
425 TCU_FAIL("Failed to create program");
433 * @param gl GL functions
434 * @param id Id of program
436 void Program::Link(const glw::Functions& gl, glw::GLuint id)
438 GLint status = GL_FALSE;
441 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
443 /* Get link status */
444 gl.getProgramiv(id, GL_LINK_STATUS, &status);
445 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
448 if (GL_TRUE != status)
450 glw::GLint length = 0;
453 /* Get error log length */
454 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
455 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
457 message.resize(length, 0);
460 gl.getProgramInfoLog(id, length, 0, &message[0]);
461 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
463 TCU_FAIL(message.c_str());
469 * @param gl GL functions
470 * @param id Id of program
472 void Program::Use(const glw::Functions& gl, glw::GLuint id)
475 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
478 /* Shader's constants */
479 const GLuint Shader::m_invalid_id = 0;
483 * @param context CTS context.
485 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
487 /* Nothing to be done here */
498 /** Initialize shader instance
500 * @param stage Shader stage
501 * @param source Source code
503 void Shader::Init(glw::GLenum stage, const std::string& source)
505 if (true == source.empty())
507 /* No source == no shader */
511 /* Delete any previous shader */
514 /* Create, set source and compile */
515 const Functions& gl = m_context.getRenderContext().getFunctions();
517 Create(gl, stage, m_id);
518 Source(gl, m_id, source);
523 /** Release shader instance
526 void Shader::Release()
528 if (m_invalid_id != m_id)
530 const Functions& gl = m_context.getRenderContext().getFunctions();
532 gl.deleteShader(m_id);
539 * @param gl GL functions
540 * @param id Shader id
542 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
544 GLint status = GL_FALSE;
547 gl.compileShader(id);
548 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
550 /* Get compilation status */
551 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
552 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
554 /* Log compilation error */
555 if (GL_TRUE != status)
557 glw::GLint length = 0;
560 /* Error log length */
561 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
562 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
564 /* Prepare storage */
565 message.resize(length, 0);
568 gl.getShaderInfoLog(id, length, 0, &message[0]);
569 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
571 TCU_FAIL(message.c_str());
577 * @param gl GL functions
578 * @param stage Shader stage
579 * @param out_id Shader id
581 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
583 const GLuint id = gl.createShader(stage);
584 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
586 if (m_invalid_id == id)
588 TCU_FAIL("Failed to create shader");
594 /** Set shader's source code
596 * @param gl GL functions
597 * @param id Shader id
598 * @param source Shader source code
600 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
602 const GLchar* code = source.c_str();
604 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
605 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
608 /* Texture static fields */
609 const GLuint Texture::m_invalid_id = -1;
613 * @param context CTS context.
615 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
617 /* Nothing to done here */
628 /** Release texture instance
631 void Texture::Release()
633 if (m_invalid_id != m_id)
635 const Functions& gl = m_context.getRenderContext().getFunctions();
637 gl.deleteTextures(1, &m_id);
642 /** Bind texture to target
644 * @param gl GL functions
645 * @param id Id of texture
646 * @param tex_type Type of texture
648 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
650 gl.bindTexture(target, id);
651 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
654 /** Set contents of compressed texture
656 * @param gl GL functions
657 * @param target Texture target
658 * @param level Mipmap level
659 * @param internal_format Format of data
660 * @param width Width of texture
661 * @param height Height of texture
662 * @param depth Depth of texture
663 * @param image_size Size of data
664 * @param data Buffer with image data
666 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
667 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
668 glw::GLsizei image_size, const glw::GLvoid* data)
673 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
674 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
676 case GL_TEXTURE_1D_ARRAY:
678 case GL_TEXTURE_RECTANGLE:
679 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
680 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
682 case GL_TEXTURE_CUBE_MAP:
683 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
685 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
687 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
689 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
691 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
693 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
695 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
698 case GL_TEXTURE_2D_ARRAY:
699 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
700 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
703 TCU_FAIL("Invliad enum");
708 /** Generate texture instance
710 * @param gl GL functions
711 * @param out_id Id of texture
713 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
715 GLuint id = m_invalid_id;
717 gl.genTextures(1, &id);
718 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
720 if (m_invalid_id == id)
722 TCU_FAIL("Invalid id");
730 * @param gl GL functions
731 * @param target Texture target
732 * @param format Format of data
733 * @param type Type of data
734 * @param out_data Buffer for data
736 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
737 glw::GLenum type, glw::GLvoid* out_data)
739 gl.getTexImage(target, level, format, type, out_data);
740 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
745 * @param gl GL functions
746 * @param id Texture id
747 * @param level Mipmap level
748 * @param width Texture width
749 * @param height Texture height
750 * @param format Format of data
751 * @param type Type of data
752 * @param out_data Buffer for data
754 void Texture::GetData(const glw::Functions& gl, glw::GLuint id, glw::GLint level, glw::GLuint width, glw::GLuint height,
755 glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data)
758 gl.genFramebuffers(1, &fbo);
759 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
760 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
761 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
762 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, level);
763 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
765 gl.readPixels(0, 0, width, height, format, type, out_data);
766 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
768 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
771 /** Generate texture instance
773 * @param gl GL functions
774 * @param target Texture target
775 * @param level Mipmap level
776 * @param pname Parameter to query
777 * @param param Result of query
779 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
782 gl.getTexLevelParameteriv(target, level, pname, param);
783 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
786 /** Set contents of texture
788 * @param gl GL functions
789 * @param target Texture target
790 * @param level Mipmap level
791 * @param internal_format Format of data
792 * @param width Width of texture
793 * @param height Height of texture
794 * @param depth Depth of texture
795 * @param format Format of data
796 * @param type Type of data
797 * @param data Buffer with image data
799 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
800 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
801 const glw::GLvoid* data)
806 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
807 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
809 case GL_TEXTURE_1D_ARRAY:
811 case GL_TEXTURE_RECTANGLE:
812 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
813 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
815 case GL_TEXTURE_CUBE_MAP:
816 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
818 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
820 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
822 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
824 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
826 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
828 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
831 case GL_TEXTURE_2D_ARRAY:
832 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
833 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
836 TCU_FAIL("Invliad enum");
841 /** Allocate storage for texture
843 * @param gl GL functions
844 * @param target Texture target
845 * @param levels Number of levels
846 * @param internal_format Internal format of texture
847 * @param width Width of texture
848 * @param height Height of texture
849 * @param depth Depth of texture
851 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
852 glw::GLuint width, glw::GLuint height, glw::GLuint depth)
857 gl.texStorage1D(target, levels, internal_format, width);
858 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
860 case GL_TEXTURE_1D_ARRAY:
862 case GL_TEXTURE_RECTANGLE:
863 case GL_TEXTURE_CUBE_MAP:
864 gl.texStorage2D(target, levels, internal_format, width, height);
865 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
867 case GL_TEXTURE_2D_MULTISAMPLE:
868 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
869 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
872 case GL_TEXTURE_2D_ARRAY:
873 gl.texStorage3D(target, levels, internal_format, width, height, depth);
874 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
877 TCU_FAIL("Invliad enum");
882 /** Set contents of texture
884 * @param gl GL functions
885 * @param target Texture target
886 * @param level Mipmap level
890 * @param width Width of texture
891 * @param height Height of texture
892 * @param depth Depth of texture
893 * @param format Format of data
894 * @param type Type of data
895 * @param pixels Buffer with image data
897 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
898 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
899 glw::GLenum type, const glw::GLvoid* pixels)
904 gl.texSubImage1D(target, level, x, width, format, type, pixels);
905 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
907 case GL_TEXTURE_1D_ARRAY:
909 case GL_TEXTURE_RECTANGLE:
910 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
911 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
913 case GL_TEXTURE_CUBE_MAP:
914 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
915 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
916 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
917 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
918 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
919 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
920 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
923 case GL_TEXTURE_2D_ARRAY:
924 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
925 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
928 TCU_FAIL("Invliad enum");
933 /* VertexArray constants */
934 const GLuint VertexArray::m_invalid_id = -1;
938 * @param context CTS context.
940 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
947 VertexArray::~VertexArray()
952 /** Release vertex array object instance
955 void VertexArray::Release()
957 if (m_invalid_id != m_id)
959 const Functions& gl = m_context.getRenderContext().getFunctions();
963 gl.deleteVertexArrays(1, &m_id);
969 /** Binds Vertex array object
971 * @param gl GL functions
972 * @param id ID of vertex array object
974 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
976 gl.bindVertexArray(id);
977 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
980 /** Generates Vertex array object
982 * @param gl GL functions
983 * @param out_id ID of vertex array object
985 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
987 GLuint id = m_invalid_id;
989 gl.genVertexArrays(1, &id);
990 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
992 if (m_invalid_id == id)
994 TCU_FAIL("Invalid id");
1000 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1002 * @param token Token string
1003 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1004 * @param text String that will be used as replacement for <token>
1005 * @param string String to work on
1007 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1009 const size_t text_length = strlen(text);
1010 const size_t token_length = strlen(token);
1011 const size_t token_position = string.find(token, search_position);
1013 string.replace(token_position, token_length, text, text_length);
1015 search_position = token_position + text_length;
1020 * @param context Test context
1022 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context)
1023 : TestCase(context, "vertex_buffer_objects", "Verifies that out-of-bound reads from VB result in zero")
1025 /* Nothing to be done */
1030 * @param context Test context
1032 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context, const char* name, const char* description)
1033 : TestCase(context, name, description)
1035 /* Nothing to be done */
1040 * @return tcu::TestNode::STOP
1042 tcu::TestNode::IterateResult VertexBufferObjectsTest::iterate()
1044 static const GLuint invalid_elements[] = {
1045 9, 1, 2, 10, 2, 3, 11, 3, 4, 12, 4, 5, 13, 5, 6, 14, 6, 7, 15, 7, 8, 16, 8, 1,
1048 static const GLuint valid_elements[] = {
1049 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
1052 static const GLfloat vertices[] = {
1053 0.0f, 0.0f, 0.0f, /* 0 */
1054 -1.0f, 0.0f, 0.0f, /* 1 */
1055 -1.0f, 1.0f, 0.0f, /* 2 */
1056 0.0f, 1.0f, 0.0f, /* 3 */
1057 1.0f, 1.0f, 0.0f, /* 4 */
1058 1.0f, 0.0f, 0.0f, /* 5 */
1059 1.0f, -1.0f, 0.0f, /* 6 */
1060 0.0f, -1.0f, 0.0f, /* 7 */
1061 -1.0f, -1.0f, 0.0f, /* 8 */
1064 static const GLuint height = 8;
1065 static const GLuint n_vertices = 24;
1066 static const GLuint width = 8;
1068 /* GL entry points */
1069 const Functions& gl = m_context.getRenderContext().getFunctions();
1071 /* Test result indicator */
1072 bool test_result = true;
1074 /* Test case objects */
1075 Framebuffer framebuffer(m_context);
1076 Buffer invalid_elements_buffer(m_context);
1077 Program program(m_context);
1078 Texture texture(m_context);
1079 Buffer valid_elements_buffer(m_context);
1080 Buffer vertices_buffer(m_context);
1081 VertexArray vao(m_context);
1084 VertexArray::Generate(gl, vao.m_id);
1085 VertexArray::Bind(gl, vao.m_id);
1087 /* Buffers initialization */
1088 invalid_elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(invalid_elements),
1090 valid_elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(valid_elements), valid_elements);
1091 vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices);
1093 /* Texture initialization */
1094 Texture::Generate(gl, texture.m_id);
1095 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
1096 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0);
1097 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1099 /* Framebuffer initialization*/
1100 Framebuffer::Generate(gl, framebuffer.m_id);
1101 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1102 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
1105 /* Shaders initialization */
1106 program.Init("" /* cs */, getFragmentShader(), "" /* gs */, "" /* tcs */, "" /* tes */, getVertexShader());
1107 Program::Use(gl, program.m_id);
1109 /* Vertex buffer initialization */
1110 vertices_buffer.Bind();
1111 gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 12 /* stride */);
1112 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, NULL);
1113 gl.enableVertexAttribArray(0 /* location */);
1115 /* Binding elements/indices buffer */
1116 valid_elements_buffer.Bind();
1118 cleanTexture(texture.m_id);
1120 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1121 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1123 if (false == verifyValidResults(texture.m_id))
1125 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for valid input"
1126 << tcu::TestLog::EndMessage;
1128 test_result = false;
1131 /* Binding elements/indices buffer */
1132 invalid_elements_buffer.Bind();
1134 cleanTexture(texture.m_id);
1136 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1137 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1139 if (false == verifyInvalidResults(texture.m_id))
1141 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for invalid input"
1142 << tcu::TestLog::EndMessage;
1144 test_result = false;
1148 if (true == test_result)
1150 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1154 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1158 return tcu::TestNode::STOP;
1161 /** Prepare shader for current test case
1165 std::string VertexBufferObjectsTest::getFragmentShader()
1167 return std::string("#version 430 core\n"
1169 "layout (location = 0) out vec4 out_fs_color;\n"
1173 " out_fs_color = vec4(1.0 / 256.0, 1.0, 1.0, 1.0);\n"
1178 /** Prepare shader for current test case
1182 std::string VertexBufferObjectsTest::getVertexShader()
1184 return std::string("#version 430 core\n"
1186 "layout (location = 0) in vec4 in_vs_position;\n"
1190 " gl_Position = in_vs_position;\n"
1195 /** Fill texture with value 128
1197 * @param texture_id Id of texture
1199 void VertexBufferObjectsTest::cleanTexture(glw::GLuint texture_id)
1201 static const GLuint height = 8;
1202 static const GLuint width = 8;
1204 const Functions& gl = m_context.getRenderContext().getFunctions();
1206 GLubyte pixels[width * height];
1207 for (GLuint i = 0; i < width * height; ++i)
1212 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1214 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
1215 GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1218 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1221 /** Verifies that texutre is filled with 1
1223 * @param texture_id Id of texture
1225 * @return true when image is filled with 1, false otherwise
1227 bool VertexBufferObjectsTest::verifyInvalidResults(glw::GLuint texture_id)
1229 return verifyResults(texture_id);
1232 /** Verifies that texutre is filled with 1
1234 * @param texture_id Id of texture
1236 * @return true when image is filled with 1, false otherwise
1238 bool VertexBufferObjectsTest::verifyValidResults(glw::GLuint texture_id)
1240 return verifyResults(texture_id);
1243 /** Verifies that texutre is filled with 1
1245 * @param texture_id Id of texture
1247 * @return true when image is filled with 1, false otherwise
1249 bool VertexBufferObjectsTest::verifyResults(glw::GLuint texture_id)
1251 static const GLuint height = 8;
1252 static const GLuint width = 8;
1254 const Functions& gl = m_context.getRenderContext().getFunctions();
1256 GLubyte pixels[width * height];
1257 for (GLuint i = 0; i < width * height; ++i)
1262 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1264 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1267 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1270 for (GLuint i = 0; i < width * height; ++i)
1272 if (255 != pixels[i])
1274 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
1275 << " at offset: " << i << tcu::TestLog::EndMessage;
1286 * @param context Test context
1288 TexelFetchTest::TexelFetchTest(deqp::Context& context)
1289 : TestCase(context, "texel_fetch", "Verifies that out-of-bound fetches from texture result in zero")
1292 /* Nothing to be done */
1297 * @param context Test context
1299 TexelFetchTest::TexelFetchTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
1300 : TestCase(context, name, description), m_test_case(R8)
1302 /* Nothing to be done */
1307 * @return tcu::TestNode::STOP
1309 tcu::TestNode::IterateResult TexelFetchTest::iterate()
1312 static const GLuint height = 16;
1313 static const GLuint width = 16;
1315 /* GL entry points */
1316 const Functions& gl = m_context.getRenderContext().getFunctions();
1318 /* Test result indicator */
1319 bool test_result = true;
1321 /* Iterate over all cases */
1322 for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
1324 bool case_result = true;
1326 GLenum texture_target = GL_TEXTURE_2D;
1328 if (R32UI_MULTISAMPLE == m_test_case || RG8_SNORM == m_test_case)
1330 // 1. RG8_SNORM case:
1331 // Skip RG8_SNORM format case.
1332 // RG8_SNORM is not required to be used as a render target
1333 // OpenGL 4.5 Core Spec, Page 197
1335 // 2. R32UI_MULTISAMPLE case
1336 // Skip test in multi sample case
1337 // texelFetch with invalid lod plane results undefined value
1338 // OpenGL 4.5 Core Spec, around page 377
1339 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
1344 Texture destination_texture(m_context);
1345 Framebuffer framebuffer(m_context);
1346 Program invalid_program(m_context);
1347 Texture source_texture(m_context);
1348 Program valid_program(m_context);
1349 VertexArray vao(m_context);
1351 const std::string& fs_invalid = getFragmentShader(false);
1352 const std::string& fs_valid = getFragmentShader(true);
1355 VertexArray::Generate(gl, vao.m_id);
1356 VertexArray::Bind(gl, vao.m_id);
1358 /* Prepare textures */
1359 Texture::Generate(gl, destination_texture.m_id);
1360 Texture::Generate(gl, source_texture.m_id);
1362 if (R32UI_MULTISAMPLE == m_test_case)
1364 GLint max_integer_samples;
1365 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
1366 GLint max_image_samples;
1367 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
1368 if (max_integer_samples < 4 || max_image_samples < 4)
1370 /* prepareTexture() hard-codes 4 samples (n_levels) for
1371 * R32UI_MULTISAMPLE case. This value exceeds the required
1372 * min-max value (1 in OpenGL ES 3.2) and is not supported
1373 * by all implementations.
1375 * Also, the test uses a compute shader with images
1376 * to upload the texture so max_image_samples >= 4
1379 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1380 << " not supported" << tcu::TestLog::EndMessage;
1386 prepareTexture(false, destination_texture.m_id);
1387 prepareTexture(true, source_texture.m_id);
1389 /* Select FBO settings */
1390 if (R32UI_MIPMAP == m_test_case)
1394 else if (R32UI_MULTISAMPLE == m_test_case)
1396 texture_target = GL_TEXTURE_2D_MULTISAMPLE;
1400 Framebuffer::Generate(gl, framebuffer.m_id);
1401 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1402 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destination_texture.m_id, level,
1405 /* Prepare programs */
1406 valid_program.Init("" /* cs */, fs_valid, getGeometryShader(), "" /* tcs */, "" /* tes */, getVertexShader());
1407 invalid_program.Init("" /* cs */, fs_invalid, getGeometryShader(), "" /* tcs */, "" /* tes */,
1410 /* Test valid case */
1412 Program::Use(gl, valid_program.m_id);
1415 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1416 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1417 Texture::Bind(gl, source_texture.m_id, texture_target);
1418 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1419 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1421 /* Check if setup is supported */
1422 GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1423 GLU_EXPECT_NO_ERROR(gl.getError(), "CheckFramebufferStatus");
1424 if (GL_FRAMEBUFFER_COMPLETE != fbo_status)
1426 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1427 << " not supported" << tcu::TestLog::EndMessage;
1432 /* Enable multisampling */
1433 if (R32UI_MULTISAMPLE == m_test_case)
1435 gl.enable(GL_MULTISAMPLE);
1436 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
1440 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1442 /* Get error from draw */
1443 GLenum error = gl.getError();
1445 /* Disable multisampling */
1446 if (R32UI_MULTISAMPLE == m_test_case)
1448 gl.disable(GL_MULTISAMPLE);
1449 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
1452 /* Handle error from draw */
1453 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1457 if (false == verifyValidResults(destination_texture.m_id))
1459 case_result = false;
1462 /* Test invalid case */
1464 Program::Use(gl, invalid_program.m_id);
1467 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1468 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1469 Texture::Bind(gl, source_texture.m_id, texture_target);
1470 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1471 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1474 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1476 /* Get error from draw */
1477 GLenum error = gl.getError();
1479 /* Handle error from draw */
1480 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1484 if (false == verifyInvalidResults(destination_texture.m_id))
1486 case_result = false;
1489 /* Set test result */
1490 if (false == case_result)
1492 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1493 << " failed" << tcu::TestLog::EndMessage;
1495 test_result = false;
1500 if (true == test_result)
1502 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1506 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1510 return tcu::TestNode::STOP;
1513 /** Prepares source code for fragment shader
1515 * @param is_case_valid Selects if valid or invalid case is tested
1517 * @return string with prepared code
1519 std::string TexelFetchTest::getFragmentShader(bool is_case_valid)
1521 static const GLchar* plane_0 = " int plane = 0;\n";
1523 static const GLchar* plane_1 = " int plane = 1;\n";
1525 static const GLchar* plane_2 = " int plane = 2;\n";
1527 static const GLchar* plane_sample_invalid = " int plane = 9;\n";
1528 //" int plane = gl_SampleID + 4;\n";
1530 static const GLchar* plane_sample_valid = " int plane = gl_SampleID;\n";
1532 static const GLchar* point_invalid = " ivec2 point = ivec2(gs_fs_tex_coord * 16.0) + ivec2(16, 16);\n";
1534 static const GLchar* point_valid = " ivec2 point = ivec2(gs_fs_tex_coord * 16.0);\n";
1536 static const GLchar* sampler_regular = "sampler2D";
1537 static const GLchar* sampler_regular_u = "usampler2D";
1538 static const GLchar* sampler_multisampled_u = "usampler2DMS";
1540 static const GLchar* template_code = "#version 430 core\n"
1542 " in vec2 gs_fs_tex_coord;\n"
1543 "layout (location = 0) out TYPE out_fs_color;\n"
1544 "layout (location = 0) uniform SAMPLER uni_texture;\n"
1550 " out_fs_color = texelFetch(uni_texture, point, plane);\n"
1554 static const GLchar* type_vec4 = "vec4";
1555 static const GLchar* type_uvec4 = "uvec4";
1557 const GLchar* plane = plane_0;
1558 const GLchar* point = point_valid;
1559 const GLchar* sampler = sampler_regular;
1560 const GLchar* type = type_vec4;
1562 if ((R8 == m_test_case) || (RG8_SNORM == m_test_case) || (RGBA32F == m_test_case))
1564 if (false == is_case_valid)
1566 point = point_invalid;
1569 else if (R32UI_MIPMAP == m_test_case)
1572 sampler = sampler_regular_u;
1575 if (false == is_case_valid)
1580 else if (R32UI_MULTISAMPLE == m_test_case)
1582 plane = plane_sample_valid;
1583 sampler = sampler_multisampled_u;
1586 if (false == is_case_valid)
1588 plane = plane_sample_invalid;
1592 size_t position = 0;
1593 std::string source = template_code;
1594 replaceToken("TYPE", position, type, source);
1595 replaceToken("SAMPLER", position, sampler, source);
1596 replaceToken("PLANE", position, plane, source);
1597 replaceToken("POINT", position, point, source);
1602 /** Prepare shader for current test case
1606 std::string TexelFetchTest::getGeometryShader()
1608 return std::string("#version 430 core\n"
1610 "layout(points) in;\n"
1611 "layout(triangle_strip, max_vertices = 4) out;\n"
1613 "out vec2 gs_fs_tex_coord;\n"
1617 " gs_fs_tex_coord = vec2(0, 0);\n"
1618 " gl_Position = vec4(-1, -1, 0, 1);\n"
1621 " gs_fs_tex_coord = vec2(0, 1);\n"
1622 " gl_Position = vec4(-1, 1, 0, 1);\n"
1625 " gs_fs_tex_coord = vec2(1, 0);\n"
1626 " gl_Position = vec4(1, -1, 0, 1);\n"
1629 " gs_fs_tex_coord = vec2(1, 1);\n"
1630 " gl_Position = vec4(1, 1, 0, 1);\n"
1636 /** Prepare shader for current test case
1640 std::string TexelFetchTest::getVertexShader()
1642 return std::string("#version 430 core\n"
1646 " gl_Position = vec4(0, 0, 0, 1);\n"
1651 /** Returns name of current test case
1653 * @return Name of test case
1655 const glw::GLchar* TexelFetchTest::getTestCaseName() const
1657 const GLchar* name = "";
1659 switch (m_test_case)
1662 name = "\"Sampling GL_R8 texture\"";
1665 name = "\"Sampling GL_RG8_SNORM texture\"";
1668 name = "\"Sampling GL_RGBA32F texture\"";
1671 name = "\"Sampling mipmap of GL_32UI texture\"";
1673 case R32UI_MULTISAMPLE:
1674 name = "\"Sampling GL_32UI multisampled texture\"";
1677 TCU_FAIL("Invalid enum");
1684 /** Prepare a texture
1686 * @param is_source Selects if texutre will be used as source or destination
1687 * @param texture_id Id of texutre
1689 void TexelFetchTest::prepareTexture(bool is_source, glw::GLuint texture_id)
1692 static const GLuint image_height = 16;
1693 static const GLuint image_width = 16;
1695 /* GL entry points */
1696 const Functions& gl = m_context.getRenderContext().getFunctions();
1698 /* Texture storage parameters */
1699 GLuint height = image_height;
1700 GLenum internal_format = 0;
1701 GLsizei n_levels = 1;
1702 GLenum target = GL_TEXTURE_2D;
1703 GLuint width = image_width;
1705 /* Prepare texture storage parameters */
1706 switch (m_test_case)
1709 internal_format = GL_R8;
1712 internal_format = GL_RG8_SNORM;
1715 internal_format = GL_RGBA32F;
1718 height = 2 * image_height;
1719 internal_format = GL_R32UI;
1721 width = 2 * image_width;
1723 case R32UI_MULTISAMPLE:
1724 internal_format = GL_R32UI;
1726 target = GL_TEXTURE_2D_MULTISAMPLE;
1729 TCU_FAIL("Invalid enum");
1732 /* Prepare storage */
1733 Texture::Bind(gl, texture_id, target);
1734 Texture::Storage(gl, target, n_levels, internal_format, width, height, 0);
1736 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1737 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1739 /* Destination image can be left empty */
1740 if (false == is_source)
1742 Texture::Bind(gl, 0, target);
1746 /* Prepare texture */
1747 if (R8 == m_test_case)
1749 GLubyte source_pixels[image_width * image_height];
1750 for (GLuint i = 0; i < image_width * image_height; ++i)
1752 source_pixels[i] = static_cast<GLubyte>(i);
1755 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1756 0 /* depth */, GL_RED, GL_UNSIGNED_BYTE, source_pixels);
1758 else if (RG8_SNORM == m_test_case)
1760 static const GLuint n_components = 2;
1762 GLbyte source_pixels[image_width * image_height * n_components];
1763 for (GLuint i = 0; i < image_width * image_height; ++i)
1765 source_pixels[i * n_components + 0] = static_cast<GLubyte>((i % 16) - 8);
1766 source_pixels[i * n_components + 1] = static_cast<GLubyte>((i / 16) - 8);
1769 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1770 0 /* depth */, GL_RG, GL_BYTE, source_pixels);
1772 else if (RGBA32F == m_test_case)
1774 static const GLuint n_components = 4;
1776 GLfloat source_pixels[image_width * image_height * n_components];
1777 for (GLuint i = 0; i < image_width * image_height; ++i)
1779 source_pixels[i * n_components + 0] = (GLfloat)(i % 16) / 16.0f;
1780 source_pixels[i * n_components + 1] = (GLfloat)(i / 16) / 16.0f;
1781 source_pixels[i * n_components + 2] = (GLfloat)i / 256.0f;
1782 source_pixels[i * n_components + 3] = 1.0f;
1785 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1786 0 /* depth */, GL_RGBA, GL_FLOAT, source_pixels);
1788 else if (R32UI_MIPMAP == m_test_case)
1790 GLuint source_pixels[image_width * image_height];
1791 for (GLuint i = 0; i < image_width * image_height; ++i)
1793 source_pixels[i] = i;
1796 Texture::SubImage(gl, GL_TEXTURE_2D, 1 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, image_width, image_height,
1797 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_INT, source_pixels);
1799 else if (R32UI_MULTISAMPLE == m_test_case)
1801 /* Compute shader */
1802 static const GLchar* cs = "#version 430 core\n"
1804 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1806 "layout (location = 0) writeonly uniform uimage2DMS uni_image;\n"
1810 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
1811 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
1813 " imageStore(uni_image, point, 0, uvec4(index + 0, 0, 0, 0));\n"
1814 " imageStore(uni_image, point, 1, uvec4(index + 1, 0, 0, 0));\n"
1815 " imageStore(uni_image, point, 2, uvec4(index + 2, 0, 0, 0));\n"
1816 " imageStore(uni_image, point, 3, uvec4(index + 3, 0, 0, 0));\n"
1820 Program program(m_context);
1821 program.Init(cs, "", "", "", "", "");
1824 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1825 GL_WRITE_ONLY, GL_R32UI);
1826 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1828 gl.uniform1i(0 /* location */, 0 /* image unit*/);
1829 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1831 gl.dispatchCompute(16, 16, 1);
1832 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1835 Texture::Bind(gl, 0, target);
1838 /** Verifies that texutre is filled with 0 or with (0, 0, 0, x),
1839 * where x may be 0, 1 or the biggest representable integer value.
1841 * @param texture_id Id of texture
1843 * @return true when image is filled with 0, 1 or biggest represetable integer number, false otherwise
1845 bool TexelFetchTest::verifyInvalidResults(glw::GLuint texture_id)
1847 static const GLuint height = 16;
1848 static const GLuint width = 16;
1849 static const GLuint n_pixels = height * width;
1851 const Functions& gl = m_context.getRenderContext().getFunctions();
1855 if (R8 == m_test_case)
1857 static const GLuint n_channels = 1;
1859 std::vector<GLubyte> pixels;
1860 pixels.resize(n_pixels * n_channels);
1861 for (GLuint i = 0; i < n_pixels; ++i)
1863 pixels[i] = static_cast<GLubyte>(i);
1866 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1868 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
1871 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1874 for (GLuint i = 0; i < n_pixels; ++i)
1876 const GLubyte expected_red = 0;
1877 const GLubyte drawn_red = pixels[i];
1879 if (expected_red != drawn_red)
1881 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
1882 << ". Expected value: " << (GLuint)expected_red
1883 << " at offset: " << i << tcu::TestLog::EndMessage;
1890 else if (RG8_SNORM == m_test_case)
1892 static const GLuint n_channels = 2;
1894 std::vector<GLbyte> pixels;
1895 pixels.resize(n_pixels * n_channels);
1896 for (GLuint i = 0; i < n_pixels; ++i)
1898 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
1899 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
1902 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1904 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
1907 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1910 for (GLuint i = 0; i < n_pixels; ++i)
1912 const GLbyte expected_red = 0;
1913 const GLbyte expected_green = 0;
1914 const GLbyte drawn_red = pixels[i * n_channels + 0];
1915 const GLbyte drawn_green = pixels[i * n_channels + 1];
1917 if ((expected_red != drawn_red) || (expected_green != drawn_green))
1919 m_context.getTestContext().getLog()
1920 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
1921 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
1922 << ". At offset: " << i << tcu::TestLog::EndMessage;
1929 else if (RGBA32F == m_test_case)
1931 static const GLuint n_channels = 4;
1933 std::vector<GLfloat> pixels;
1934 pixels.resize(n_pixels * n_channels);
1935 for (GLuint i = 0; i < n_pixels; ++i)
1937 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
1938 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
1939 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
1940 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
1943 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1945 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
1948 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1951 for (GLuint i = 0; i < n_pixels; ++i)
1953 const GLfloat expected_red = 0.0f;
1954 const GLfloat expected_green = 0.0f;
1955 const GLfloat expected_blue = 0.0f;
1956 const GLfloat expected_alpha_0 =
1957 0.0f; /* OpenGL 4.5 (and ES) specifies two possiblities (0 or 1) for alpha channel (Chapter 11.1.3.12). */
1958 const GLfloat expected_alpha_1 = 1.0f;
1959 const GLfloat drawn_red = pixels[i * n_channels + 0];
1960 const GLfloat drawn_green = pixels[i * n_channels + 1];
1961 const GLfloat drawn_blue = pixels[i * n_channels + 2];
1962 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
1964 const GLfloat precision = 0.0009765625; /* (1.f / 1024.f) */
1966 if ((de::abs(expected_red - drawn_red) > precision) ||
1967 (de::abs(expected_green - drawn_green) > precision) ||
1968 (de::abs(expected_blue - drawn_blue) > precision) ||
1969 ((de::abs(expected_alpha_0 - drawn_alpha) > precision) &&
1970 (de::abs(expected_alpha_1 - drawn_alpha) > precision)))
1972 m_context.getTestContext().getLog()
1973 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
1974 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
1975 << expected_green << ", " << expected_blue << ", " << expected_alpha_0 << " or " << expected_alpha_1
1976 << ". At offset: " << i << tcu::TestLog::EndMessage;
1983 else if (R32UI_MIPMAP == m_test_case)
1985 static const GLuint n_channels = 1;
1987 std::vector<GLuint> pixels;
1988 pixels.resize(n_pixels * n_channels);
1989 for (GLuint i = 0; i < n_pixels; ++i)
1994 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1996 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
1999 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2002 for (GLuint i = 0; i < n_pixels; ++i)
2004 const GLuint expected_red = 0;
2005 const GLuint drawn_red = pixels[i];
2007 if (expected_red != drawn_red)
2009 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2010 << ". Expected value: " << expected_red << " at offset: " << i
2011 << tcu::TestLog::EndMessage;
2018 else if (R32UI_MULTISAMPLE == m_test_case)
2020 static const GLuint n_channels = 1;
2022 /* Compute shader */
2023 static const GLchar* cs = "#version 430 core\n"
2025 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2027 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2028 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2032 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2034 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2035 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2036 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2037 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2039 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2041 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2045 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2050 Program program(m_context);
2051 Texture destination_texture(m_context);
2053 Texture::Generate(gl, destination_texture.m_id);
2054 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2055 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2057 program.Init(cs, "", "", "", "", "");
2059 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2060 GL_READ_ONLY, GL_R32UI);
2061 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2062 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2063 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2064 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2066 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2067 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2069 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2070 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2072 gl.dispatchCompute(16, 16, 1);
2073 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2075 /* Pixels buffer initialization */
2076 std::vector<GLuint> pixels;
2077 pixels.resize(n_pixels * n_channels);
2078 for (GLuint i = 0; i < n_pixels; ++i)
2083 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2086 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2089 for (GLuint i = 0; i < n_pixels; ++i)
2091 const GLuint expected_red = 1;
2092 const GLuint drawn_red = pixels[i];
2094 if (expected_red != drawn_red)
2096 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2097 << ". Expected value: " << expected_red << " at offset: " << i
2098 << tcu::TestLog::EndMessage;
2109 /** Verifies that texutre is filled with increasing values
2111 * @param texture_id Id of texture
2113 * @return true when image is filled with increasing values, false otherwise
2115 bool TexelFetchTest::verifyValidResults(glw::GLuint texture_id)
2117 static const GLuint height = 16;
2118 static const GLuint width = 16;
2119 static const GLuint n_pixels = height * width;
2121 const Functions& gl = m_context.getRenderContext().getFunctions();
2125 if (R8 == m_test_case)
2127 static const GLuint n_channels = 1;
2129 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2131 std::vector<GLubyte> pixels;
2132 pixels.resize(n_pixels * n_channels);
2133 for (GLuint i = 0; i < n_pixels; ++i)
2135 pixels[i] = static_cast<GLubyte>(i);
2138 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2141 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2144 for (GLuint i = 0; i < n_pixels; ++i)
2146 const GLubyte expected_red = static_cast<GLubyte>(i);
2147 const GLubyte drawn_red = pixels[i];
2149 if (expected_red != drawn_red)
2151 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2152 << ". Expected value: " << (GLuint)expected_red
2153 << " at offset: " << i << tcu::TestLog::EndMessage;
2160 else if (RG8_SNORM == m_test_case)
2162 static const GLuint n_channels = 2;
2164 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2166 std::vector<GLbyte> pixels;
2167 pixels.resize(n_pixels * n_channels);
2168 for (GLuint i = 0; i < n_pixels; ++i)
2170 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2171 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2174 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2177 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2180 for (GLuint i = 0; i < n_pixels; ++i)
2182 const GLbyte expected_red = static_cast<GLubyte>((i % 16) - 8);
2183 const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
2184 const GLbyte drawn_red = pixels[i * n_channels + 0];
2185 const GLbyte drawn_green = pixels[i * n_channels + 1];
2187 if ((expected_red != drawn_red) || (expected_green != drawn_green))
2189 m_context.getTestContext().getLog()
2190 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2191 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2192 << ". At offset: " << i << tcu::TestLog::EndMessage;
2199 else if (RGBA32F == m_test_case)
2201 static const GLuint n_channels = 4;
2203 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2205 std::vector<GLfloat> pixels;
2206 pixels.resize(n_pixels * n_channels);
2207 for (GLuint i = 0; i < n_pixels; ++i)
2209 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2210 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2211 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2212 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2215 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2218 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2221 for (GLuint i = 0; i < n_pixels; ++i)
2223 const GLfloat expected_red = (GLfloat)(i % 16) / 16.0f;
2224 const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
2225 const GLfloat expected_blue = (GLfloat)i / 256.0f;
2226 const GLfloat expected_alpha = 1.0f;
2227 const GLfloat drawn_red = pixels[i * n_channels + 0];
2228 const GLfloat drawn_green = pixels[i * n_channels + 1];
2229 const GLfloat drawn_blue = pixels[i * n_channels + 2];
2230 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
2232 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2233 (expected_alpha != drawn_alpha))
2235 m_context.getTestContext().getLog()
2236 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2237 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2238 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2239 << tcu::TestLog::EndMessage;
2246 else if (R32UI_MIPMAP == m_test_case)
2248 static const GLuint n_channels = 1;
2250 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2252 std::vector<GLuint> pixels;
2253 pixels.resize(n_pixels * n_channels * 4);
2254 for (GLuint i = 0; i < n_pixels; ++i)
2259 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2262 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2265 for (GLuint i = 0; i < n_pixels; ++i)
2267 const GLuint expected_red = i;
2268 const GLuint drawn_red = pixels[i];
2270 if (expected_red != drawn_red)
2272 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2273 << ". Expected value: " << expected_red << " at offset: " << i
2274 << tcu::TestLog::EndMessage;
2281 else if (R32UI_MULTISAMPLE == m_test_case)
2283 static const GLuint n_channels = 1;
2285 /* Compute shader */
2286 static const GLchar* cs =
2287 "#version 430 core\n"
2289 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2291 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2292 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2296 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2297 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
2299 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2300 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2301 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2302 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2304 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
2306 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2310 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2315 Program program(m_context);
2316 Texture destination_texture(m_context);
2318 Texture::Generate(gl, destination_texture.m_id);
2319 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2320 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2322 program.Init(cs, "", "", "", "", "");
2324 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2325 GL_READ_ONLY, GL_R32UI);
2326 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2327 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2328 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2329 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2331 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2332 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2334 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2335 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2337 gl.dispatchCompute(16, 16, 1);
2338 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2340 /* Pixels buffer initialization */
2341 std::vector<GLuint> pixels;
2342 pixels.resize(n_pixels * n_channels);
2343 for (GLuint i = 0; i < n_pixels; ++i)
2348 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2351 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2354 for (GLuint i = 0; i < n_pixels; ++i)
2356 const GLuint expected_red = 1;
2357 const GLuint drawn_red = pixels[i];
2359 if (expected_red != drawn_red)
2361 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2362 << ". Expected value: " << expected_red << " at offset: " << i
2363 << tcu::TestLog::EndMessage;
2376 * @param context Test context
2378 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context)
2379 : TexelFetchTest(context, "image_load_store", "Verifies that out-of-bound to image result in zero or is discarded")
2381 /* Nothing to be done */
2386 * @param context Test context
2388 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
2389 : TexelFetchTest(context, name, description)
2391 /* Nothing to be done */
2396 * @return tcu::TestNode::STOP
2398 tcu::TestNode::IterateResult ImageLoadStoreTest::iterate()
2401 static const GLuint height = 16;
2402 static const GLuint width = 16;
2404 /* GL entry points */
2405 const Functions& gl = m_context.getRenderContext().getFunctions();
2407 /* Test result indicator */
2408 bool test_result = true;
2410 /* Iterate over all cases */
2411 for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
2413 /* Test case result indicator */
2414 bool case_result = true;
2416 if (R32UI_MULTISAMPLE == m_test_case)
2418 // Skip invalid program test in multi sample case
2419 // texelFetch with invalid lod plane results undefined value
2420 // OpenGL 4.5 Core Spec, around page 377
2421 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
2426 Texture destination_texture(m_context);
2427 Program invalid_destination_program(m_context);
2428 Program invalid_source_program(m_context);
2429 Texture source_texture(m_context);
2430 Program valid_program(m_context);
2432 const std::string& cs_invalid_destination = getComputeShader(DESTINATION_INVALID);
2433 const std::string& cs_invalid_source = getComputeShader(SOURCE_INVALID);
2434 const std::string& cs_valid = getComputeShader(VALID);
2436 /* Prepare textures */
2437 Texture::Generate(gl, destination_texture.m_id);
2438 Texture::Generate(gl, source_texture.m_id);
2440 if (R32UI_MULTISAMPLE == m_test_case)
2442 GLint max_integer_samples;
2443 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
2444 GLint max_image_samples;
2445 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
2446 if (max_integer_samples < 4 || max_image_samples < 4)
2448 /* prepareTexture() hard-codes 4 samples (n_levels) for
2449 * R32UI_MULTISAMPLE case. This value exceeds the required
2450 * min-max value (1 in OpenGL ES 3.2) and is not supported
2451 * by all implementations.
2453 * Also, the test uses a compute shader with images
2454 * to upload the texture so max_image_samples >= 4
2457 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2458 << " not supported" << tcu::TestLog::EndMessage;
2464 prepareTexture(false, destination_texture.m_id);
2465 prepareTexture(true, source_texture.m_id);
2467 /* Prepare programs */
2468 invalid_destination_program.Init(cs_invalid_destination, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
2470 invalid_source_program.Init(cs_invalid_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
2472 valid_program.Init(cs_valid, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
2474 /* Test invalid source case */
2476 invalid_source_program.Use();
2479 setTextures(destination_texture.m_id, source_texture.m_id);
2482 gl.dispatchCompute(width, height, 1 /* depth */);
2483 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2486 if (false == verifyInvalidResults(destination_texture.m_id))
2488 case_result = false;
2491 /* Test valid case */
2493 valid_program.Use();
2496 setTextures(destination_texture.m_id, source_texture.m_id);
2499 gl.dispatchCompute(width, height, 1 /* depth */);
2500 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2503 if (false == verifyValidResults(destination_texture.m_id))
2505 case_result = false;
2508 /* Test invalid destination case */
2510 invalid_destination_program.Use();
2513 setTextures(destination_texture.m_id, source_texture.m_id);
2516 gl.dispatchCompute(width, height, 1 /* depth */);
2517 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2520 if (false == verifyValidResults(destination_texture.m_id))
2522 case_result = false;
2525 /* Set test result */
2526 if (false == case_result)
2528 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2529 << " failed" << tcu::TestLog::EndMessage;
2531 test_result = false;
2536 if (true == test_result)
2538 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2542 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2546 return tcu::TestNode::STOP;
2549 /** Prepare shader for current test case
2551 * @param version Specify which version should be prepared
2555 std::string ImageLoadStoreTest::getComputeShader(VERSION version)
2557 static const GLchar* template_code = "#version 430 core\n"
2559 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2561 "layout (location = 1) writeonly uniform IMAGE uni_destination_image;\n"
2562 "layout (location = 0, FORMAT) readonly uniform IMAGE uni_source_image;\n"
2566 " const ivec2 point_destination = POINT;\n"
2567 " const ivec2 point_source = POINT;\n"
2573 static const GLchar* copy_multisampled =
2574 " const TYPE color_0 = imageLoad(uni_source_image, point_source, 0 + OFFSET);\n"
2575 " const TYPE color_1 = imageLoad(uni_source_image, point_source, 1 + OFFSET);\n"
2576 " const TYPE color_2 = imageLoad(uni_source_image, point_source, 2 + OFFSET);\n"
2577 " const TYPE color_3 = imageLoad(uni_source_image, point_source, 3 + OFFSET);\n"
2578 " imageStore(uni_destination_image, point_destination, 0 + OFFSET, color_0);\n"
2579 " imageStore(uni_destination_image, point_destination, 1 + OFFSET, color_1);\n"
2580 " imageStore(uni_destination_image, point_destination, 2 + OFFSET, color_2);\n"
2581 " imageStore(uni_destination_image, point_destination, 3 + OFFSET, color_3);\n";
2583 static const GLchar* copy_regular =
2584 " const TYPE color = imageLoad(uni_source_image, point_source);\n"
2585 " //imageStore(uni_destination_image, point_destination, vec4(0, 0, 0, 0));\n"
2586 " imageStore(uni_destination_image, point_destination, color);\n";
2588 static const GLchar* format_r8 = "r8";
2589 static const GLchar* format_rg8_snorm = "rg8_snorm";
2590 static const GLchar* format_rgba32f = "rgba32f";
2591 static const GLchar* format_r32ui = "r32ui";
2593 static const GLchar* image_vec4 = "image2D";
2595 static const GLchar* image_uvec4 = "uimage2D";
2597 static const GLchar* image_uvec4_ms = "uimage2DMS";
2599 static const GLchar* offset_invalid = "4";
2600 static const GLchar* offset_valid = "0";
2602 static const GLchar* point_invalid = "ivec2(gl_WorkGroupID.x + 16, gl_WorkGroupID.y + 16)";
2604 static const GLchar* point_valid = "ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
2606 static const GLchar* type_vec4 = "vec4";
2607 static const GLchar* type_uvec4 = "uvec4";
2609 const GLchar* copy = copy_regular;
2610 const GLchar* format = format_r8;
2611 const GLchar* image = image_vec4;
2612 const GLchar* offset_destination = offset_valid;
2613 const GLchar* offset_source = offset_valid;
2614 const GLchar* point_destination = point_valid;
2615 const GLchar* point_source = point_valid;
2616 const GLchar* type = type_vec4;
2622 case SOURCE_INVALID:
2623 point_source = point_invalid;
2624 offset_source = offset_invalid;
2626 case DESTINATION_INVALID:
2627 point_destination = point_invalid;
2628 offset_destination = offset_invalid;
2631 TCU_FAIL("Invalid enum");
2634 switch (m_test_case)
2639 format = format_rg8_snorm;
2642 format = format_rgba32f;
2645 format = format_r32ui;
2646 image = image_uvec4;
2649 case R32UI_MULTISAMPLE:
2650 copy = copy_multisampled;
2651 format = format_r32ui;
2652 image = image_uvec4_ms;
2653 point_destination = point_valid;
2654 point_source = point_valid;
2658 TCU_FAIL("Invalid enum");
2661 size_t position = 0;
2662 std::string source = template_code;
2664 replaceToken("IMAGE", position, image, source);
2665 replaceToken("FORMAT", position, format, source);
2666 replaceToken("IMAGE", position, image, source);
2667 replaceToken("POINT", position, point_destination, source);
2668 replaceToken("POINT", position, point_source, source);
2670 size_t temp_position = position;
2671 replaceToken("COPY", position, copy, source);
2672 position = temp_position;
2674 switch (m_test_case)
2680 replaceToken("TYPE", position, type, source);
2682 case R32UI_MULTISAMPLE:
2683 replaceToken("TYPE", position, type, source);
2684 replaceToken("OFFSET", position, offset_source, source);
2685 replaceToken("TYPE", position, type, source);
2686 replaceToken("OFFSET", position, offset_source, source);
2687 replaceToken("TYPE", position, type, source);
2688 replaceToken("OFFSET", position, offset_source, source);
2689 replaceToken("TYPE", position, type, source);
2690 replaceToken("OFFSET", position, offset_source, source);
2691 replaceToken("OFFSET", position, offset_destination, source);
2692 replaceToken("OFFSET", position, offset_destination, source);
2693 replaceToken("OFFSET", position, offset_destination, source);
2694 replaceToken("OFFSET", position, offset_destination, source);
2697 TCU_FAIL("Invalid enum");
2703 /** Set textures as images
2705 * @param id_destination Id of texture used as destination
2706 * @param id_source Id of texture used as source
2708 void ImageLoadStoreTest::setTextures(glw::GLuint id_destination, glw::GLuint id_source)
2710 const Functions& gl = m_context.getRenderContext().getFunctions();
2715 switch (m_test_case)
2721 format = GL_RG8_SNORM;
2724 format = GL_RGBA32F;
2730 case R32UI_MULTISAMPLE:
2734 TCU_FAIL("Invalid enum");
2737 gl.bindImageTexture(0 /* unit */, id_source, level, GL_FALSE /* layered */, 0 /* layer */, GL_READ_ONLY, format);
2738 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2740 gl.bindImageTexture(1 /* unit */, id_destination, level, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY,
2742 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2744 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2745 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2747 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2748 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2751 /** Verifies that texutre is filled with 0
2753 * @param texture_id Id of texture
2755 * @return true when image is filled with 0, false otherwise
2757 bool ImageLoadStoreTest::verifyInvalidResults(glw::GLuint texture_id)
2759 static const GLuint height = 16;
2760 static const GLuint width = 16;
2761 static const GLuint n_pixels = height * width;
2763 const Functions& gl = m_context.getRenderContext().getFunctions();
2764 gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2765 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2769 if (R8 == m_test_case)
2771 static const GLuint n_channels = 1;
2773 std::vector<GLubyte> pixels;
2774 pixels.resize(n_pixels * n_channels);
2775 for (GLuint i = 0; i < n_pixels; ++i)
2777 pixels[i] = static_cast<GLubyte>(i);
2780 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2782 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2785 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2788 for (GLuint i = 0; i < n_pixels; ++i)
2790 const GLubyte expected_red = 0;
2791 const GLubyte drawn_red = pixels[i];
2793 if (expected_red != drawn_red)
2795 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2796 << ". Expected value: " << (GLuint)expected_red
2797 << " at offset: " << i << tcu::TestLog::EndMessage;
2804 else if (RG8_SNORM == m_test_case)
2806 static const GLuint n_channels = 2;
2808 std::vector<GLbyte> pixels;
2809 pixels.resize(n_pixels * n_channels);
2810 for (GLuint i = 0; i < n_pixels; ++i)
2812 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2813 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2816 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2818 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2821 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2824 for (GLuint i = 0; i < n_pixels; ++i)
2826 const GLbyte expected_red = 0;
2827 const GLbyte expected_green = 0;
2828 const GLbyte drawn_red = pixels[i * n_channels + 0];
2829 const GLbyte drawn_green = pixels[i * n_channels + 1];
2831 if ((expected_red != drawn_red) || (expected_green != drawn_green))
2833 m_context.getTestContext().getLog()
2834 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2835 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2836 << ". At offset: " << i << tcu::TestLog::EndMessage;
2843 else if (RGBA32F == m_test_case)
2845 static const GLuint n_channels = 4;
2847 std::vector<GLfloat> pixels;
2848 pixels.resize(n_pixels * n_channels);
2849 for (GLuint i = 0; i < n_pixels; ++i)
2851 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2852 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2853 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2854 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2857 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2859 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2862 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2865 for (GLuint i = 0; i < n_pixels; ++i)
2867 const GLfloat expected_red = 0.0f;
2868 const GLfloat expected_green = 0.0f;
2869 const GLfloat expected_blue = 0.0f;
2870 const GLfloat expected_alpha = 0.0f;
2871 const GLfloat drawn_red = pixels[i * n_channels + 0];
2872 const GLfloat drawn_green = pixels[i * n_channels + 1];
2873 const GLfloat drawn_blue = pixels[i * n_channels + 2];
2874 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
2876 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2877 (expected_alpha != drawn_alpha))
2879 m_context.getTestContext().getLog()
2880 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2881 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2882 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2883 << tcu::TestLog::EndMessage;
2890 else if (R32UI_MIPMAP == m_test_case)
2892 static const GLuint n_channels = 1;
2894 std::vector<GLuint> pixels;
2895 pixels.resize(n_pixels * n_channels);
2896 for (GLuint i = 0; i < n_pixels; ++i)
2901 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2903 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2906 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2909 for (GLuint i = 0; i < n_pixels; ++i)
2911 const GLuint expected_red = 0;
2912 const GLuint drawn_red = pixels[i];
2914 if (expected_red != drawn_red)
2916 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2917 << ". Expected value: " << expected_red << " at offset: " << i
2918 << tcu::TestLog::EndMessage;
2925 else if (R32UI_MULTISAMPLE == m_test_case)
2927 static const GLuint n_channels = 1;
2929 /* Compute shader */
2930 static const GLchar* cs = "#version 430 core\n"
2932 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2934 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2935 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2939 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2941 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2942 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2943 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2944 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2946 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2948 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2952 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2957 Program program(m_context);
2958 Texture destination_texture(m_context);
2960 Texture::Generate(gl, destination_texture.m_id);
2961 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2962 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2964 program.Init(cs, "", "", "", "", "");
2966 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2967 GL_READ_ONLY, GL_R32UI);
2968 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2969 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2970 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2971 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2973 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2974 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2976 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2977 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2979 gl.dispatchCompute(16, 16, 1);
2980 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2982 /* Pixels buffer initialization */
2983 std::vector<GLuint> pixels;
2984 pixels.resize(n_pixels * n_channels);
2985 for (GLuint i = 0; i < n_pixels; ++i)
2990 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2993 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2996 for (GLuint i = 0; i < n_pixels; ++i)
2998 const GLuint expected_red = 1;
2999 const GLuint drawn_red = pixels[i];
3001 if (expected_red != drawn_red)
3003 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3004 << ". Expected value: " << expected_red << " at offset: " << i
3005 << tcu::TestLog::EndMessage;
3016 /** Verifies that texutre is filled with increasing values
3018 * @param texture_id Id of texture
3020 * @return true when image is filled with increasing values, false otherwise
3022 bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
3024 static const GLuint height = 16;
3025 static const GLuint width = 16;
3026 static const GLuint n_pixels = height * width;
3028 const Functions& gl = m_context.getRenderContext().getFunctions();
3029 gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3030 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3034 if (R8 == m_test_case)
3036 static const GLuint n_channels = 1;
3038 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3040 std::vector<GLubyte> pixels;
3041 pixels.resize(n_pixels * n_channels);
3042 for (GLuint i = 0; i < n_pixels; ++i)
3044 pixels[i] = static_cast<GLubyte>(i);
3047 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
3050 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3053 for (GLuint i = 0; i < n_pixels; ++i)
3055 const GLubyte expected_red = static_cast<GLubyte>(i);
3056 const GLubyte drawn_red = pixels[i];
3058 if (expected_red != drawn_red)
3060 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
3061 << ". Expected value: " << (GLuint)expected_red
3062 << " at offset: " << i << tcu::TestLog::EndMessage;
3069 else if (RG8_SNORM == m_test_case)
3071 static const GLuint n_channels = 2;
3073 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3075 std::vector<GLbyte> pixels;
3076 pixels.resize(n_pixels * n_channels);
3077 for (GLuint i = 0; i < n_pixels; ++i)
3079 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
3080 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
3083 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
3086 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3089 for (GLuint i = 0; i < n_pixels; ++i)
3091 const GLbyte expected_red = static_cast<GLubyte>((i % 16) - 8);
3092 const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
3093 const GLbyte drawn_red = pixels[i * n_channels + 0];
3094 const GLbyte drawn_green = pixels[i * n_channels + 1];
3096 if ((expected_red != drawn_red) || (expected_green != drawn_green))
3098 m_context.getTestContext().getLog()
3099 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
3100 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
3101 << ". At offset: " << i << tcu::TestLog::EndMessage;
3108 else if (RGBA32F == m_test_case)
3110 static const GLuint n_channels = 4;
3112 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3114 std::vector<GLfloat> pixels;
3115 pixels.resize(n_pixels * n_channels);
3116 for (GLuint i = 0; i < n_pixels; ++i)
3118 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
3119 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
3120 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
3121 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
3124 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
3127 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3130 for (GLuint i = 0; i < n_pixels; ++i)
3132 const GLfloat expected_red = (GLfloat)(i % 16) / 16.0f;
3133 const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
3134 const GLfloat expected_blue = (GLfloat)i / 256.0f;
3135 const GLfloat expected_alpha = 1.0f;
3136 const GLfloat drawn_red = pixels[i * n_channels + 0];
3137 const GLfloat drawn_green = pixels[i * n_channels + 1];
3138 const GLfloat drawn_blue = pixels[i * n_channels + 2];
3139 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
3141 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
3142 (expected_alpha != drawn_alpha))
3144 m_context.getTestContext().getLog()
3145 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
3146 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
3147 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
3148 << tcu::TestLog::EndMessage;
3155 else if (R32UI_MIPMAP == m_test_case)
3157 static const GLuint n_channels = 1;
3159 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3161 std::vector<GLuint> pixels;
3162 pixels.resize(n_pixels * n_channels * 4);
3163 for (GLuint i = 0; i < n_pixels; ++i)
3168 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3171 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3174 for (GLuint i = 0; i < n_pixels; ++i)
3176 const GLuint expected_red = i;
3177 const GLuint drawn_red = pixels[i];
3179 if (expected_red != drawn_red)
3181 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3182 << ". Expected value: " << expected_red << " at offset: " << i
3183 << tcu::TestLog::EndMessage;
3190 else if (R32UI_MULTISAMPLE == m_test_case)
3192 static const GLuint n_channels = 1;
3194 /* Compute shader */
3195 static const GLchar* cs =
3196 "#version 430 core\n"
3198 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3200 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
3201 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
3205 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
3206 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
3208 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
3209 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
3210 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
3211 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
3213 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
3215 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
3219 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
3224 Program program(m_context);
3225 Texture destination_texture(m_context);
3227 Texture::Generate(gl, destination_texture.m_id);
3228 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
3229 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
3231 program.Init(cs, "", "", "", "", "");
3233 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3234 GL_READ_ONLY, GL_R32UI);
3235 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3236 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
3237 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
3238 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3240 gl.uniform1i(0 /* location */, 0 /* image unit*/);
3241 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3243 gl.uniform1i(1 /* location */, 1 /* image unit*/);
3244 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3246 gl.dispatchCompute(16, 16, 1);
3247 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3249 /* Pixels buffer initialization */
3250 std::vector<GLuint> pixels;
3251 pixels.resize(n_pixels * n_channels);
3252 for (GLuint i = 0; i < n_pixels; ++i)
3257 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3260 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3263 for (GLuint i = 0; i < n_pixels; ++i)
3265 const GLuint expected_red = 1;
3266 const GLuint drawn_red = pixels[i];
3268 if (expected_red != drawn_red)
3270 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3271 << ". Expected value: " << expected_red << " at offset: " << i
3272 << tcu::TestLog::EndMessage;
3285 * @param context Test context
3287 StorageBufferTest::StorageBufferTest(deqp::Context& context)
3288 : TestCase(context, "storage_buffer", "Verifies that out-of-bound access to SSBO is discared or resutls in 0")
3289 , m_test_case(VALID)
3291 /* Nothing to be done here */
3296 * @param context Test context
3298 StorageBufferTest::StorageBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3299 : TestCase(context, name, description), m_test_case(VALID)
3301 /* Nothing to be done */
3306 * @return tcu::TestNode::STOP
3308 tcu::TestNode::IterateResult StorageBufferTest::iterate()
3310 static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3311 static const GLfloat source_data[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3313 /* GL entry points */
3314 const Functions& gl = m_context.getRenderContext().getFunctions();
3316 /* Test result indicator */
3317 bool test_result = true;
3319 /* Iterate over all cases */
3320 while (LAST != m_test_case)
3322 /* Test case objects */
3323 Buffer destination_buffer(m_context);
3324 Buffer source_buffer(m_context);
3325 Program program(m_context);
3327 /* Compute Shader */
3328 const std::string& cs = getComputeShader();
3330 /* Buffers initialization */
3331 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
3333 source_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
3335 destination_buffer.BindBase(0);
3336 source_buffer.BindBase(1);
3338 /* Shaders initialization */
3339 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3342 /* Dispatch compute */
3343 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3344 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3346 /* Set memory barrier */
3347 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3348 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3350 /* Verify results */
3351 destination_buffer.Bind();
3352 GLfloat* buffer_data =
3353 (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
3354 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3356 test_result = verifyResults(buffer_data);
3358 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3359 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3362 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3366 if (true == test_result)
3368 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3372 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3376 return tcu::TestNode::STOP;
3379 /** Prepare shader for current test case
3383 std::string StorageBufferTest::getComputeShader()
3385 static const GLchar* cs = "#version 430 core\n"
3387 "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3389 "layout (binding = 1, std430) buffer Source {\n"
3393 "layout (binding = 0, std430) buffer Destination {\n"
3399 " const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3400 " const uint index_source = gl_LocalInvocationID.x + OFFSET;\n"
3402 " destination.data[index_destination] = source.data[index_source];\n"
3406 const GLchar* destination_offset;
3407 size_t position = 0;
3408 std::string source = cs;
3409 const GLchar* source_offset;
3411 switch (m_test_case)
3414 destination_offset = "0";
3415 source_offset = "0";
3417 case SOURCE_INVALID:
3418 destination_offset = "0";
3419 source_offset = "16";
3421 case DESTINATION_INVALID:
3422 destination_offset = "16";
3423 source_offset = "0";
3426 TCU_FAIL("Invalid enum");
3429 replaceToken("OFFSET", position, destination_offset, source);
3430 replaceToken("OFFSET", position, source_offset, source);
3435 /** Verify test case results
3437 * @param buffer_data Buffer data to verify
3439 * @return true if buffer_data is as expected, false othrewise
3441 bool StorageBufferTest::verifyResults(GLfloat* buffer_data)
3443 static const GLfloat expected_data_valid[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3444 static const GLfloat expected_data_invalid_destination[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3445 static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3447 int size = static_cast<int>(sizeof(GLfloat) * 4);
3449 /* Prepare expected data const for proper case*/
3450 const GLfloat* expected_data = 0;
3451 const GLchar* name = 0;
3452 switch (m_test_case)
3455 expected_data = expected_data_valid;
3456 name = "valid indices";
3458 case SOURCE_INVALID:
3459 expected_data = expected_data_invalid_source;
3460 name = "invalid source indices";
3462 case DESTINATION_INVALID:
3463 expected_data = expected_data_invalid_destination;
3464 name = "invalid destination indices";
3467 TCU_FAIL("Invalid enum");
3470 /* Verify buffer data */
3471 if (0 != memcmp(expected_data, buffer_data, size))
3473 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3474 << tcu::TestLog::EndMessage;
3483 * @param context Test context
3485 UniformBufferTest::UniformBufferTest(deqp::Context& context)
3486 : TestCase(context, "uniform_buffer", "Verifies that out-of-bound access to UBO resutls in 0"), m_test_case(VALID)
3488 /* Nothing to be done here */
3493 * @param context Test context
3495 UniformBufferTest::UniformBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3496 : TestCase(context, name, description), m_test_case(VALID)
3498 /* Nothing to be done */
3503 * @return tcu::TestNode::STOP
3505 tcu::TestNode::IterateResult UniformBufferTest::iterate()
3507 static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3508 /* The source buffer is packed std140 so we need vec4s */
3509 static const GLfloat source_data[16] = {
3510 2.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 4.0f, 0.0f, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f,
3513 /* GL entry points */
3514 const Functions& gl = m_context.getRenderContext().getFunctions();
3516 /* Test result indicator */
3517 bool test_result = true;
3519 /* Iterate over all cases */
3520 while (LAST != m_test_case)
3522 /* Test case objects */
3523 Buffer destination_buffer(m_context);
3524 Buffer source_buffer(m_context);
3525 Program program(m_context);
3527 /* Compute Shader */
3528 const std::string& cs = getComputeShader();
3530 /* Buffers initialization */
3531 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
3533 source_buffer.InitData(GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
3535 destination_buffer.BindBase(0);
3536 source_buffer.BindBase(0);
3538 /* Shaders initialization */
3539 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3542 /* Dispatch compute */
3543 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3544 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3546 /* Set memory barrier */
3547 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3548 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3550 /* Verify results */
3551 destination_buffer.Bind();
3552 GLfloat* buffer_data =
3553 (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
3554 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3556 test_result = verifyResults(buffer_data);
3558 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3559 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3562 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3566 if (true == test_result)
3568 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3572 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3576 return tcu::TestNode::STOP;
3579 /** Prepare shader for current test case
3583 std::string UniformBufferTest::getComputeShader()
3585 static const GLchar* cs = "#version 430 core\n"
3587 "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3589 "layout (binding = 0, std140) uniform Source {\n"
3590 " float data[16];\n"
3593 "layout (binding = 0, std430) buffer Destination {\n"
3599 " const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3600 " const uint index_source = gl_LocalInvocationID.x + OFFSET;\n"
3602 " destination.data[index_destination] = source.data[index_source];\n"
3606 const GLchar* destination_offset;
3607 size_t position = 0;
3608 std::string source = cs;
3609 const GLchar* source_offset;
3611 switch (m_test_case)
3614 destination_offset = "0";
3615 source_offset = "0";
3617 case SOURCE_INVALID:
3618 destination_offset = "0";
3619 source_offset = "16";
3622 TCU_FAIL("Invalid enum");
3625 replaceToken("OFFSET", position, destination_offset, source);
3626 replaceToken("OFFSET", position, source_offset, source);
3631 /** Verify test case results
3633 * @param buffer_data Buffer data to verify
3635 * @return true if buffer_data is as expected, false othrewise
3637 bool UniformBufferTest::verifyResults(GLfloat* buffer_data)
3639 static const GLfloat expected_data_valid[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3640 static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3642 int size = static_cast<int>(sizeof(GLfloat) * 4);
3644 /* Prepare expected data const for proper case*/
3645 const GLfloat* expected_data = 0;
3646 const GLchar* name = 0;
3647 switch (m_test_case)
3650 expected_data = expected_data_valid;
3651 name = "valid indices";
3653 case SOURCE_INVALID:
3654 expected_data = expected_data_invalid_source;
3655 name = "invalid source indices";
3658 TCU_FAIL("Invalid enum");
3661 /* Verify buffer data */
3662 if (0 != memcmp(expected_data, buffer_data, size))
3664 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3665 << tcu::TestLog::EndMessage;
3671 } /* RobustBufferAccessBehavior */
3675 * @param context Rendering context.
3677 RobustBufferAccessBehaviorTests::RobustBufferAccessBehaviorTests(deqp::Context& context)
3678 : TestCaseGroup(context, "robust_buffer_access_behavior",
3679 "Verifies \"robust buffer access behavior\" functionality")
3681 /* Left blank on purpose */
3684 /** Initializes a multi_bind test group.
3687 void RobustBufferAccessBehaviorTests::init(void)
3689 addChild(new RobustBufferAccessBehavior::VertexBufferObjectsTest(m_context));
3690 addChild(new RobustBufferAccessBehavior::TexelFetchTest(m_context));
3691 addChild(new RobustBufferAccessBehavior::ImageLoadStoreTest(m_context));
3692 addChild(new RobustBufferAccessBehavior::StorageBufferTest(m_context));
3693 addChild(new RobustBufferAccessBehavior::UniformBufferTest(m_context));