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 "gluContextInfo.hpp"
31 #include "gluDefs.hpp"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 #include "tcuTestLog.hpp"
43 namespace RobustBufferAccessBehavior
45 /* Buffer constants */
46 const GLuint Buffer::m_invalid_id = -1;
48 const GLenum Buffer::m_targets[Buffer::m_n_targets] = {
49 GL_ARRAY_BUFFER, /* 0 */
50 GL_ATOMIC_COUNTER_BUFFER, /* 1 */
51 GL_COPY_READ_BUFFER, /* 2 */
52 GL_COPY_WRITE_BUFFER, /* 3 */
53 GL_DISPATCH_INDIRECT_BUFFER, /* 4 */
54 GL_DRAW_INDIRECT_BUFFER, /* 5 */
55 GL_ELEMENT_ARRAY_BUFFER, /* 6 */
56 GL_PIXEL_PACK_BUFFER, /* 7 */
57 GL_PIXEL_UNPACK_BUFFER, /* 8 */
58 GL_QUERY_BUFFER, /* 9 */
59 GL_SHADER_STORAGE_BUFFER, /* 10 */
60 GL_TRANSFORM_FEEDBACK_BUFFER, /* 11 */
61 GL_UNIFORM_BUFFER, /* 12 */
66 * @param context CTS context.
68 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_target(GL_ARRAY_BUFFER)
80 /** Initialize buffer instance
82 * @param target Buffer target
83 * @param usage Buffer usage enum
84 * @param size <size> parameter
85 * @param data <data> parameter
87 void Buffer::InitData(glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size, const glw::GLvoid* data)
89 /* Delete previous buffer instance */
94 const Functions& gl = m_context.getRenderContext().getFunctions();
97 Bind(gl, m_id, m_target);
98 Data(gl, m_target, usage, size, data);
101 /** Release buffer instance
104 void Buffer::Release()
106 if (m_invalid_id != m_id)
108 const Functions& gl = m_context.getRenderContext().getFunctions();
110 gl.deleteBuffers(1, &m_id);
115 /** Binds buffer to its target
118 void Buffer::Bind() const
120 const Functions& gl = m_context.getRenderContext().getFunctions();
122 Bind(gl, m_id, m_target);
125 /** Binds indexed buffer
127 * @param index <index> parameter
129 void Buffer::BindBase(glw::GLuint index) const
131 const Functions& gl = m_context.getRenderContext().getFunctions();
133 BindBase(gl, m_id, m_target, index);
136 /** Bind buffer to given target
138 * @param gl GL functions
139 * @param id Id of buffer
140 * @param target Buffer target
142 void Buffer::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
144 gl.bindBuffer(target, id);
145 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
148 /** Binds indexed buffer
150 * @param gl GL functions
151 * @param id Id of buffer
152 * @param target Buffer target
153 * @param index <index> parameter
155 void Buffer::BindBase(const glw::Functions& gl, glw::GLuint id, glw::GLenum target, glw::GLuint index)
157 gl.bindBufferBase(target, index, id);
158 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
161 /** Allocate memory for buffer and sends initial content
163 * @param gl GL functions
164 * @param target Buffer target
165 * @param usage Buffer usage enum
166 * @param size <size> parameter
167 * @param data <data> parameter
169 void Buffer::Data(const glw::Functions& gl, glw::GLenum target, glw::GLenum usage, glw::GLsizeiptr size,
170 const glw::GLvoid* data)
172 gl.bufferData(target, size, data, usage);
173 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
178 * @param gl GL functions
179 * @param out_id Id of buffer
181 void Buffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
183 GLuint id = m_invalid_id;
185 gl.genBuffers(1, &id);
186 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
188 if (m_invalid_id == id)
190 TCU_FAIL("Got invalid id");
196 /** Update range of buffer
198 * @param gl GL functions
199 * @param target Buffer target
200 * @param offset Offset in buffer
201 * @param size <size> parameter
202 * @param data <data> parameter
204 void Buffer::SubData(const glw::Functions& gl, glw::GLenum target, glw::GLintptr offset, glw::GLsizeiptr size,
207 gl.bufferSubData(target, offset, size, data);
208 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
211 /* Framebuffer constants */
212 const GLuint Framebuffer::m_invalid_id = -1;
216 * @param context CTS context.
218 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
220 /* Nothing to done here */
226 Framebuffer::~Framebuffer()
231 /** Release texture instance
234 void Framebuffer::Release()
236 if (m_invalid_id != m_id)
238 const Functions& gl = m_context.getRenderContext().getFunctions();
240 gl.deleteFramebuffers(1, &m_id);
245 /** Attach texture to specified attachment
247 * @param gl GL functions
248 * @param target Framebuffer target
249 * @param attachment Attachment
250 * @param texture_id Texture id
251 * @param level Level of mipmap
252 * @param width Texture width
253 * @param height Texture height
255 void Framebuffer::AttachTexture(const glw::Functions& gl, glw::GLenum target, glw::GLenum attachment,
256 glw::GLuint texture_id, glw::GLint level, glw::GLuint width, glw::GLuint height)
258 gl.framebufferTexture(target, attachment, texture_id, level);
259 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
261 gl.viewport(0 /* x */, 0 /* y */, width, height);
262 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
265 /** Binds framebuffer to DRAW_FRAMEBUFFER
267 * @param gl GL functions
268 * @param target Framebuffer target
269 * @param id ID of framebuffer
271 void Framebuffer::Bind(const glw::Functions& gl, glw::GLenum target, glw::GLuint id)
273 gl.bindFramebuffer(target, id);
274 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
277 /** Generate framebuffer
280 void Framebuffer::Generate(const glw::Functions& gl, glw::GLuint& out_id)
282 GLuint id = m_invalid_id;
284 gl.genFramebuffers(1, &id);
285 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
287 if (m_invalid_id == id)
289 TCU_FAIL("Invalid id");
295 /* Program constants */
296 const GLuint Program::m_invalid_id = 0;
300 * @param context CTS context.
302 Program::Program(deqp::Context& context)
305 , m_fragment(context)
306 , m_geometry(context)
307 , m_tess_ctrl(context)
308 , m_tess_eval(context)
312 /* Nothing to be done here */
323 /** Initialize program instance
325 * @param compute_shader Compute shader source code
326 * @param fragment_shader Fragment shader source code
327 * @param geometry_shader Geometry shader source code
328 * @param tesselation_control_shader Tesselation control shader source code
329 * @param tesselation_evaluation_shader Tesselation evaluation shader source code
330 * @param vertex_shader Vertex shader source code
332 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
333 const std::string& geometry_shader, const std::string& tesselation_control_shader,
334 const std::string& tesselation_evaluation_shader, const std::string& vertex_shader)
336 /* Delete previous program */
339 /* GL entry points */
340 const Functions& gl = m_context.getRenderContext().getFunctions();
342 /* Initialize shaders */
343 m_compute.Init(GL_COMPUTE_SHADER, compute_shader);
344 m_fragment.Init(GL_FRAGMENT_SHADER, fragment_shader);
345 m_geometry.Init(GL_GEOMETRY_SHADER, geometry_shader);
346 m_tess_ctrl.Init(GL_TESS_CONTROL_SHADER, tesselation_control_shader);
347 m_tess_eval.Init(GL_TESS_EVALUATION_SHADER, tesselation_evaluation_shader);
348 m_vertex.Init(GL_VERTEX_SHADER, vertex_shader);
350 /* Create program, set up transform feedback and attach shaders */
352 Attach(gl, m_id, m_compute.m_id);
353 Attach(gl, m_id, m_fragment.m_id);
354 Attach(gl, m_id, m_geometry.m_id);
355 Attach(gl, m_id, m_tess_ctrl.m_id);
356 Attach(gl, m_id, m_tess_eval.m_id);
357 Attach(gl, m_id, m_vertex.m_id);
363 /** Release program instance
366 void Program::Release()
368 const Functions& gl = m_context.getRenderContext().getFunctions();
370 if (m_invalid_id != m_id)
372 Use(gl, m_invalid_id);
374 gl.deleteProgram(m_id);
379 m_fragment.Release();
380 m_geometry.Release();
381 m_tess_ctrl.Release();
382 m_tess_eval.Release();
386 /** Set program as active
389 void Program::Use() const
391 const Functions& gl = m_context.getRenderContext().getFunctions();
396 /** Attach shader to program
398 * @param gl GL functions
399 * @param program_id Id of program
400 * @param shader_id Id of shader
402 void Program::Attach(const glw::Functions& gl, glw::GLuint program_id, glw::GLuint shader_id)
405 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
410 gl.attachShader(program_id, shader_id);
411 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
414 /** Create program instance
416 * @param gl GL functions
417 * @param out_id Id of program
419 void Program::Create(const glw::Functions& gl, glw::GLuint& out_id)
421 const GLuint id = gl.createProgram();
422 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
424 if (m_invalid_id == id)
426 TCU_FAIL("Failed to create program");
434 * @param gl GL functions
435 * @param id Id of program
437 void Program::Link(const glw::Functions& gl, glw::GLuint id)
439 GLint status = GL_FALSE;
442 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
444 /* Get link status */
445 gl.getProgramiv(id, GL_LINK_STATUS, &status);
446 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
449 if (GL_TRUE != status)
451 glw::GLint length = 0;
454 /* Get error log length */
455 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
456 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
458 message.resize(length, 0);
461 gl.getProgramInfoLog(id, length, 0, &message[0]);
462 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
464 TCU_FAIL(message.c_str());
470 * @param gl GL functions
471 * @param id Id of program
473 void Program::Use(const glw::Functions& gl, glw::GLuint id)
476 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
479 /* Shader's constants */
480 const GLuint Shader::m_invalid_id = 0;
484 * @param context CTS context.
486 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
488 /* Nothing to be done here */
499 /** Initialize shader instance
501 * @param stage Shader stage
502 * @param source Source code
504 void Shader::Init(glw::GLenum stage, const std::string& source)
506 if (true == source.empty())
508 /* No source == no shader */
512 /* Delete any previous shader */
515 /* Create, set source and compile */
516 const Functions& gl = m_context.getRenderContext().getFunctions();
518 Create(gl, stage, m_id);
519 Source(gl, m_id, source);
524 /** Release shader instance
527 void Shader::Release()
529 if (m_invalid_id != m_id)
531 const Functions& gl = m_context.getRenderContext().getFunctions();
533 gl.deleteShader(m_id);
540 * @param gl GL functions
541 * @param id Shader id
543 void Shader::Compile(const glw::Functions& gl, glw::GLuint id)
545 GLint status = GL_FALSE;
548 gl.compileShader(id);
549 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
551 /* Get compilation status */
552 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
553 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
555 /* Log compilation error */
556 if (GL_TRUE != status)
558 glw::GLint length = 0;
561 /* Error log length */
562 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
563 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
565 /* Prepare storage */
566 message.resize(length, 0);
569 gl.getShaderInfoLog(id, length, 0, &message[0]);
570 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
572 TCU_FAIL(message.c_str());
578 * @param gl GL functions
579 * @param stage Shader stage
580 * @param out_id Shader id
582 void Shader::Create(const glw::Functions& gl, glw::GLenum stage, glw::GLuint& out_id)
584 const GLuint id = gl.createShader(stage);
585 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
587 if (m_invalid_id == id)
589 TCU_FAIL("Failed to create shader");
595 /** Set shader's source code
597 * @param gl GL functions
598 * @param id Shader id
599 * @param source Shader source code
601 void Shader::Source(const glw::Functions& gl, glw::GLuint id, const std::string& source)
603 const GLchar* code = source.c_str();
605 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
606 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
609 /* Texture static fields */
610 const GLuint Texture::m_invalid_id = -1;
614 * @param context CTS context.
616 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
618 /* Nothing to done here */
629 /** Release texture instance
632 void Texture::Release()
634 if (m_invalid_id != m_id)
636 const Functions& gl = m_context.getRenderContext().getFunctions();
638 gl.deleteTextures(1, &m_id);
643 /** Bind texture to target
645 * @param gl GL functions
646 * @param id Id of texture
647 * @param tex_type Type of texture
649 void Texture::Bind(const glw::Functions& gl, glw::GLuint id, glw::GLenum target)
651 gl.bindTexture(target, id);
652 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
655 /** Set contents of compressed texture
657 * @param gl GL functions
658 * @param target Texture target
659 * @param level Mipmap level
660 * @param internal_format Format of data
661 * @param width Width of texture
662 * @param height Height of texture
663 * @param depth Depth of texture
664 * @param image_size Size of data
665 * @param data Buffer with image data
667 void Texture::CompressedImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level,
668 glw::GLenum internal_format, glw::GLuint width, glw::GLuint height, glw::GLuint depth,
669 glw::GLsizei image_size, const glw::GLvoid* data)
674 gl.compressedTexImage1D(target, level, internal_format, width, 0 /* border */, image_size, data);
675 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage1D");
677 case GL_TEXTURE_1D_ARRAY:
679 case GL_TEXTURE_RECTANGLE:
680 gl.compressedTexImage2D(target, level, internal_format, width, height, 0 /* border */, image_size, data);
681 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
683 case GL_TEXTURE_CUBE_MAP:
684 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */,
686 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */,
688 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */,
690 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */,
692 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */,
694 gl.compressedTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */,
696 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage2D");
699 case GL_TEXTURE_2D_ARRAY:
700 gl.compressedTexImage3D(target, level, internal_format, width, height, depth, 0 /* border */, image_size, data);
701 GLU_EXPECT_NO_ERROR(gl.getError(), "CompressedTexImage3D");
704 TCU_FAIL("Invliad enum");
709 /** Generate texture instance
711 * @param gl GL functions
712 * @param out_id Id of texture
714 void Texture::Generate(const glw::Functions& gl, glw::GLuint& out_id)
716 GLuint id = m_invalid_id;
718 gl.genTextures(1, &id);
719 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
721 if (m_invalid_id == id)
723 TCU_FAIL("Invalid id");
731 * @param gl GL functions
732 * @param target Texture target
733 * @param format Format of data
734 * @param type Type of data
735 * @param out_data Buffer for data
737 void Texture::GetData(const glw::Functions& gl, glw::GLint level, glw::GLenum target, glw::GLenum format,
738 glw::GLenum type, glw::GLvoid* out_data)
740 gl.getTexImage(target, level, format, type, out_data);
741 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
746 * @param gl GL functions
747 * @param id Texture id
748 * @param level Mipmap level
749 * @param width Texture width
750 * @param height Texture height
751 * @param format Format of data
752 * @param type Type of data
753 * @param out_data Buffer for data
755 void Texture::GetData(const glw::Functions& gl, glw::GLuint id, glw::GLint level, glw::GLuint width, glw::GLuint height,
756 glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data)
759 gl.genFramebuffers(1, &fbo);
760 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
761 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
762 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
763 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, level);
764 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
766 gl.readPixels(0, 0, width, height, format, type, out_data);
767 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
769 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
772 /** Generate texture instance
774 * @param gl GL functions
775 * @param target Texture target
776 * @param level Mipmap level
777 * @param pname Parameter to query
778 * @param param Result of query
780 void Texture::GetLevelParameter(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum pname,
783 gl.getTexLevelParameteriv(target, level, pname, param);
784 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
787 /** Set contents of texture
789 * @param gl GL functions
790 * @param target Texture target
791 * @param level Mipmap level
792 * @param internal_format Format of data
793 * @param width Width of texture
794 * @param height Height of texture
795 * @param depth Depth of texture
796 * @param format Format of data
797 * @param type Type of data
798 * @param data Buffer with image data
800 void Texture::Image(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLenum internal_format,
801 glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type,
802 const glw::GLvoid* data)
807 gl.texImage1D(target, level, internal_format, width, 0 /* border */, format, type, data);
808 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage1D");
810 case GL_TEXTURE_1D_ARRAY:
812 case GL_TEXTURE_RECTANGLE:
813 gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
814 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
816 case GL_TEXTURE_CUBE_MAP:
817 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, internal_format, width, height, 0 /* border */, format,
819 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, internal_format, width, height, 0 /* border */, format,
821 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, internal_format, width, height, 0 /* border */, format,
823 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internal_format, width, height, 0 /* border */, format,
825 gl.texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, internal_format, width, height, 0 /* border */, format,
827 gl.texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internal_format, width, height, 0 /* border */, format,
829 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage2D");
832 case GL_TEXTURE_2D_ARRAY:
833 gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
834 GLU_EXPECT_NO_ERROR(gl.getError(), "TexImage3D");
837 TCU_FAIL("Invliad enum");
842 /** Allocate storage for texture
844 * @param gl GL functions
845 * @param target Texture target
846 * @param levels Number of levels
847 * @param internal_format Internal format of texture
848 * @param width Width of texture
849 * @param height Height of texture
850 * @param depth Depth of texture
852 void Texture::Storage(const glw::Functions& gl, glw::GLenum target, glw::GLsizei levels, glw::GLenum internal_format,
853 glw::GLuint width, glw::GLuint height, glw::GLuint depth)
858 gl.texStorage1D(target, levels, internal_format, width);
859 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
861 case GL_TEXTURE_1D_ARRAY:
863 case GL_TEXTURE_RECTANGLE:
864 case GL_TEXTURE_CUBE_MAP:
865 gl.texStorage2D(target, levels, internal_format, width, height);
866 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
868 case GL_TEXTURE_2D_MULTISAMPLE:
869 gl.texStorage2DMultisample(target, levels, internal_format, width, height, GL_FALSE);
870 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2DMultisample");
873 case GL_TEXTURE_2D_ARRAY:
874 gl.texStorage3D(target, levels, internal_format, width, height, depth);
875 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
878 TCU_FAIL("Invliad enum");
883 /** Set contents of texture
885 * @param gl GL functions
886 * @param target Texture target
887 * @param level Mipmap level
891 * @param width Width of texture
892 * @param height Height of texture
893 * @param depth Depth of texture
894 * @param format Format of data
895 * @param type Type of data
896 * @param pixels Buffer with image data
898 void Texture::SubImage(const glw::Functions& gl, glw::GLenum target, glw::GLint level, glw::GLint x, glw::GLint y,
899 glw::GLint z, glw::GLsizei width, glw::GLsizei height, glw::GLsizei depth, glw::GLenum format,
900 glw::GLenum type, const glw::GLvoid* pixels)
905 gl.texSubImage1D(target, level, x, width, format, type, pixels);
906 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage1D");
908 case GL_TEXTURE_1D_ARRAY:
910 case GL_TEXTURE_RECTANGLE:
911 gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
912 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
914 case GL_TEXTURE_CUBE_MAP:
915 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, x, y, width, height, format, type, pixels);
916 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, x, y, width, height, format, type, pixels);
917 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, x, y, width, height, format, type, pixels);
918 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, x, y, width, height, format, type, pixels);
919 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, x, y, width, height, format, type, pixels);
920 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, x, y, width, height, format, type, pixels);
921 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
924 case GL_TEXTURE_2D_ARRAY:
925 gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
926 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
929 TCU_FAIL("Invliad enum");
934 /* VertexArray constants */
935 const GLuint VertexArray::m_invalid_id = -1;
939 * @param context CTS context.
941 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
948 VertexArray::~VertexArray()
953 /** Release vertex array object instance
956 void VertexArray::Release()
958 if (m_invalid_id != m_id)
960 const Functions& gl = m_context.getRenderContext().getFunctions();
964 gl.deleteVertexArrays(1, &m_id);
970 /** Binds Vertex array object
972 * @param gl GL functions
973 * @param id ID of vertex array object
975 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
977 gl.bindVertexArray(id);
978 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
981 /** Generates Vertex array object
983 * @param gl GL functions
984 * @param out_id ID of vertex array object
986 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
988 GLuint id = m_invalid_id;
990 gl.genVertexArrays(1, &id);
991 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
993 if (m_invalid_id == id)
995 TCU_FAIL("Invalid id");
1001 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1003 * @param token Token string
1004 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1005 * @param text String that will be used as replacement for <token>
1006 * @param string String to work on
1008 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1010 const size_t text_length = strlen(text);
1011 const size_t token_length = strlen(token);
1012 const size_t token_position = string.find(token, search_position);
1014 string.replace(token_position, token_length, text, text_length);
1016 search_position = token_position + text_length;
1021 * @param context Test context
1023 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context)
1024 : TestCase(context, "vertex_buffer_objects", "Verifies that out-of-bound reads from VB result in zero")
1026 /* Nothing to be done */
1031 * @param context Test context
1033 VertexBufferObjectsTest::VertexBufferObjectsTest(deqp::Context& context, const char* name, const char* description)
1034 : TestCase(context, name, description)
1036 /* Nothing to be done */
1041 * @return tcu::TestNode::STOP
1043 tcu::TestNode::IterateResult VertexBufferObjectsTest::iterate()
1045 static const GLuint invalid_elements[] = {
1046 9, 1, 2, 10, 2, 3, 11, 3, 4, 12, 4, 5, 13, 5, 6, 14, 6, 7, 15, 7, 8, 16, 8, 1,
1049 static const GLuint valid_elements[] = {
1050 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1,
1053 static const GLfloat vertices[] = {
1054 0.0f, 0.0f, 0.0f, /* 0 */
1055 -1.0f, 0.0f, 0.0f, /* 1 */
1056 -1.0f, 1.0f, 0.0f, /* 2 */
1057 0.0f, 1.0f, 0.0f, /* 3 */
1058 1.0f, 1.0f, 0.0f, /* 4 */
1059 1.0f, 0.0f, 0.0f, /* 5 */
1060 1.0f, -1.0f, 0.0f, /* 6 */
1061 0.0f, -1.0f, 0.0f, /* 7 */
1062 -1.0f, -1.0f, 0.0f, /* 8 */
1065 static const GLuint height = 8;
1066 static const GLuint n_vertices = 24;
1067 static const GLuint width = 8;
1069 /* GL entry points */
1070 const Functions& gl = m_context.getRenderContext().getFunctions();
1072 /* Test result indicator */
1073 bool test_result = true;
1075 /* Test case objects */
1076 Framebuffer framebuffer(m_context);
1077 Buffer invalid_elements_buffer(m_context);
1078 Program program(m_context);
1079 Texture texture(m_context);
1080 Buffer valid_elements_buffer(m_context);
1081 Buffer vertices_buffer(m_context);
1082 VertexArray vao(m_context);
1085 VertexArray::Generate(gl, vao.m_id);
1086 VertexArray::Bind(gl, vao.m_id);
1088 /* Buffers initialization */
1089 invalid_elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(invalid_elements),
1091 valid_elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(valid_elements), valid_elements);
1092 vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices);
1094 /* Texture initialization */
1095 Texture::Generate(gl, texture.m_id);
1096 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D);
1097 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0);
1098 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1100 /* Framebuffer initialization*/
1101 Framebuffer::Generate(gl, framebuffer.m_id);
1102 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1103 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture.m_id, 0 /* level */, width,
1106 /* Shaders initialization */
1107 program.Init("" /* cs */, getFragmentShader(), "" /* gs */, "" /* tcs */, "" /* tes */, getVertexShader());
1108 Program::Use(gl, program.m_id);
1110 /* Vertex buffer initialization */
1111 vertices_buffer.Bind();
1112 gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 12 /* stride */);
1113 gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12, NULL);
1114 gl.enableVertexAttribArray(0 /* location */);
1116 /* Binding elements/indices buffer */
1117 valid_elements_buffer.Bind();
1119 cleanTexture(texture.m_id);
1121 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1122 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1124 if (false == verifyValidResults(texture.m_id))
1126 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for valid input"
1127 << tcu::TestLog::EndMessage;
1129 test_result = false;
1132 /* Binding elements/indices buffer */
1133 invalid_elements_buffer.Bind();
1135 cleanTexture(texture.m_id);
1137 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */);
1138 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
1140 if (false == verifyInvalidResults(texture.m_id))
1142 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result for invalid input"
1143 << tcu::TestLog::EndMessage;
1145 test_result = false;
1149 if (true == test_result)
1151 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1155 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1159 return tcu::TestNode::STOP;
1162 /** Prepare shader for current test case
1166 std::string VertexBufferObjectsTest::getFragmentShader()
1168 return std::string("#version 430 core\n"
1170 "layout (location = 0) out vec4 out_fs_color;\n"
1174 " out_fs_color = vec4(1.0 / 256.0, 1.0, 1.0, 1.0);\n"
1179 /** Prepare shader for current test case
1183 std::string VertexBufferObjectsTest::getVertexShader()
1185 return std::string("#version 430 core\n"
1187 "layout (location = 0) in vec4 in_vs_position;\n"
1191 " gl_Position = in_vs_position;\n"
1196 /** Fill texture with value 128
1198 * @param texture_id Id of texture
1200 void VertexBufferObjectsTest::cleanTexture(glw::GLuint texture_id)
1202 static const GLuint height = 8;
1203 static const GLuint width = 8;
1205 const Functions& gl = m_context.getRenderContext().getFunctions();
1207 GLubyte pixels[width * height];
1208 for (GLuint i = 0; i < width * height; ++i)
1213 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1215 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */,
1216 GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1219 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1222 /** Verifies that texutre is filled with 1
1224 * @param texture_id Id of texture
1226 * @return true when image is filled with 1, false otherwise
1228 bool VertexBufferObjectsTest::verifyInvalidResults(glw::GLuint texture_id)
1230 return verifyResults(texture_id);
1233 /** Verifies that texutre is filled with 1
1235 * @param texture_id Id of texture
1237 * @return true when image is filled with 1, false otherwise
1239 bool VertexBufferObjectsTest::verifyValidResults(glw::GLuint texture_id)
1241 return verifyResults(texture_id);
1244 /** Verifies that texutre is filled with 1
1246 * @param texture_id Id of texture
1248 * @return true when image is filled with 1, false otherwise
1250 bool VertexBufferObjectsTest::verifyResults(glw::GLuint texture_id)
1252 static const GLuint height = 8;
1253 static const GLuint width = 8;
1255 const Functions& gl = m_context.getRenderContext().getFunctions();
1257 GLubyte pixels[width * height];
1258 for (GLuint i = 0; i < width * height; ++i)
1263 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1265 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels);
1268 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1271 for (GLuint i = 0; i < width * height; ++i)
1273 if (255 != pixels[i])
1275 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)pixels[i]
1276 << " at offset: " << i << tcu::TestLog::EndMessage;
1287 * @param context Test context
1289 TexelFetchTest::TexelFetchTest(deqp::Context& context)
1290 : TestCase(context, "texel_fetch", "Verifies that out-of-bound fetches from texture result in zero")
1293 /* Nothing to be done */
1298 * @param context Test context
1300 TexelFetchTest::TexelFetchTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
1301 : TestCase(context, name, description), m_test_case(R8)
1303 /* Nothing to be done */
1308 * @return tcu::TestNode::STOP
1310 tcu::TestNode::IterateResult TexelFetchTest::iterate()
1313 static const GLuint height = 16;
1314 static const GLuint width = 16;
1316 /* GL entry points */
1317 const Functions& gl = m_context.getRenderContext().getFunctions();
1319 /* Test result indicator */
1320 bool test_result = true;
1322 /* Iterate over all cases */
1323 for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
1325 bool case_result = true;
1327 GLenum texture_target = GL_TEXTURE_2D;
1329 if (R32UI_MULTISAMPLE == m_test_case || RG8_SNORM == m_test_case)
1331 // 1. RG8_SNORM case:
1332 // Skip RG8_SNORM format case.
1333 // RG8_SNORM is not required to be used as a render target
1334 // OpenGL 4.5 Core Spec, Page 197
1336 // 2. R32UI_MULTISAMPLE case
1337 // Skip test in multi sample case
1338 // texelFetch with invalid lod plane results undefined value
1339 // OpenGL 4.5 Core Spec, around page 377
1340 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
1345 Texture destination_texture(m_context);
1346 Framebuffer framebuffer(m_context);
1347 Program invalid_program(m_context);
1348 Texture source_texture(m_context);
1349 Program valid_program(m_context);
1350 VertexArray vao(m_context);
1352 const std::string& fs_invalid = getFragmentShader(false);
1353 const std::string& fs_valid = getFragmentShader(true);
1356 VertexArray::Generate(gl, vao.m_id);
1357 VertexArray::Bind(gl, vao.m_id);
1359 /* Prepare textures */
1360 Texture::Generate(gl, destination_texture.m_id);
1361 Texture::Generate(gl, source_texture.m_id);
1363 if (R32UI_MULTISAMPLE == m_test_case)
1365 GLint max_integer_samples;
1366 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
1367 GLint max_image_samples;
1368 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
1369 if (max_integer_samples < 4 || max_image_samples < 4)
1371 /* prepareTexture() hard-codes 4 samples (n_levels) for
1372 * R32UI_MULTISAMPLE case. This value exceeds the required
1373 * min-max value (1 in OpenGL ES 3.2) and is not supported
1374 * by all implementations.
1376 * Also, the test uses a compute shader with images
1377 * to upload the texture so max_image_samples >= 4
1380 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1381 << " not supported" << tcu::TestLog::EndMessage;
1387 prepareTexture(false, destination_texture.m_id);
1388 prepareTexture(true, source_texture.m_id);
1390 /* Select FBO settings */
1391 if (R32UI_MIPMAP == m_test_case)
1395 else if (R32UI_MULTISAMPLE == m_test_case)
1397 texture_target = GL_TEXTURE_2D_MULTISAMPLE;
1401 Framebuffer::Generate(gl, framebuffer.m_id);
1402 Framebuffer::Bind(gl, GL_DRAW_FRAMEBUFFER, framebuffer.m_id);
1403 Framebuffer::AttachTexture(gl, GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, destination_texture.m_id, level,
1406 /* Prepare programs */
1407 valid_program.Init("" /* cs */, fs_valid, getGeometryShader(), "" /* tcs */, "" /* tes */, getVertexShader());
1408 invalid_program.Init("" /* cs */, fs_invalid, getGeometryShader(), "" /* tcs */, "" /* tes */,
1411 /* Test valid case */
1413 Program::Use(gl, valid_program.m_id);
1416 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1417 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1418 Texture::Bind(gl, source_texture.m_id, texture_target);
1419 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1420 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1422 /* Check if setup is supported */
1423 GLenum fbo_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1424 GLU_EXPECT_NO_ERROR(gl.getError(), "CheckFramebufferStatus");
1425 if (GL_FRAMEBUFFER_COMPLETE != fbo_status)
1427 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1428 << " not supported" << tcu::TestLog::EndMessage;
1433 /* Enable multisampling */
1434 if (R32UI_MULTISAMPLE == m_test_case)
1436 gl.enable(GL_MULTISAMPLE);
1437 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
1441 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1443 /* Get error from draw */
1444 GLenum error = gl.getError();
1446 /* Disable multisampling */
1447 if (R32UI_MULTISAMPLE == m_test_case)
1449 gl.disable(GL_MULTISAMPLE);
1450 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
1453 /* Handle error from draw */
1454 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1458 if (false == verifyValidResults(destination_texture.m_id))
1460 case_result = false;
1463 /* Test invalid case */
1465 Program::Use(gl, invalid_program.m_id);
1468 gl.activeTexture(GL_TEXTURE0); /* location = 0 */
1469 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
1470 Texture::Bind(gl, source_texture.m_id, texture_target);
1471 gl.uniform1i(0 /* location */, 0 /* texture unit */);
1472 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1475 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1477 /* Get error from draw */
1478 GLenum error = gl.getError();
1480 /* Handle error from draw */
1481 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
1485 if (false == verifyInvalidResults(destination_texture.m_id))
1487 case_result = false;
1490 /* Set test result */
1491 if (false == case_result)
1493 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
1494 << " failed" << tcu::TestLog::EndMessage;
1496 test_result = false;
1501 if (true == test_result)
1503 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1507 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1511 return tcu::TestNode::STOP;
1514 /** Prepares source code for fragment shader
1516 * @param is_case_valid Selects if valid or invalid case is tested
1518 * @return string with prepared code
1520 std::string TexelFetchTest::getFragmentShader(bool is_case_valid)
1522 static const GLchar* plane_0 = " int plane = 0;\n";
1524 static const GLchar* plane_1 = " int plane = 1;\n";
1526 static const GLchar* plane_2 = " int plane = 2;\n";
1528 static const GLchar* plane_sample_invalid = " int plane = 9;\n";
1529 //" int plane = gl_SampleID + 4;\n";
1531 static const GLchar* plane_sample_valid = " int plane = gl_SampleID;\n";
1533 static const GLchar* point_invalid = " ivec2 point = ivec2(gs_fs_tex_coord * 16.0) + ivec2(16, 16);\n";
1535 static const GLchar* point_valid = " ivec2 point = ivec2(gs_fs_tex_coord * 16.0);\n";
1537 static const GLchar* sampler_regular = "sampler2D";
1538 static const GLchar* sampler_regular_u = "usampler2D";
1539 static const GLchar* sampler_multisampled_u = "usampler2DMS";
1541 static const GLchar* template_code = "#version 430 core\n"
1543 " in vec2 gs_fs_tex_coord;\n"
1544 "layout (location = 0) out TYPE out_fs_color;\n"
1545 "layout (location = 0) uniform SAMPLER uni_texture;\n"
1551 " out_fs_color = texelFetch(uni_texture, point, plane);\n"
1555 static const GLchar* type_vec4 = "vec4";
1556 static const GLchar* type_uvec4 = "uvec4";
1558 const GLchar* plane = plane_0;
1559 const GLchar* point = point_valid;
1560 const GLchar* sampler = sampler_regular;
1561 const GLchar* type = type_vec4;
1563 if ((R8 == m_test_case) || (RG8_SNORM == m_test_case) || (RGBA32F == m_test_case))
1565 if (false == is_case_valid)
1567 point = point_invalid;
1570 else if (R32UI_MIPMAP == m_test_case)
1573 sampler = sampler_regular_u;
1576 if (false == is_case_valid)
1581 else if (R32UI_MULTISAMPLE == m_test_case)
1583 plane = plane_sample_valid;
1584 sampler = sampler_multisampled_u;
1587 if (false == is_case_valid)
1589 plane = plane_sample_invalid;
1593 size_t position = 0;
1594 std::string source = template_code;
1595 replaceToken("TYPE", position, type, source);
1596 replaceToken("SAMPLER", position, sampler, source);
1597 replaceToken("PLANE", position, plane, source);
1598 replaceToken("POINT", position, point, source);
1603 /** Prepare shader for current test case
1607 std::string TexelFetchTest::getGeometryShader()
1609 return std::string("#version 430 core\n"
1611 "layout(points) in;\n"
1612 "layout(triangle_strip, max_vertices = 4) out;\n"
1614 "out vec2 gs_fs_tex_coord;\n"
1618 " gs_fs_tex_coord = vec2(0, 0);\n"
1619 " gl_Position = vec4(-1, -1, 0, 1);\n"
1622 " gs_fs_tex_coord = vec2(0, 1);\n"
1623 " gl_Position = vec4(-1, 1, 0, 1);\n"
1626 " gs_fs_tex_coord = vec2(1, 0);\n"
1627 " gl_Position = vec4(1, -1, 0, 1);\n"
1630 " gs_fs_tex_coord = vec2(1, 1);\n"
1631 " gl_Position = vec4(1, 1, 0, 1);\n"
1637 /** Prepare shader for current test case
1641 std::string TexelFetchTest::getVertexShader()
1643 return std::string("#version 430 core\n"
1647 " gl_Position = vec4(0, 0, 0, 1);\n"
1652 /** Returns name of current test case
1654 * @return Name of test case
1656 const glw::GLchar* TexelFetchTest::getTestCaseName() const
1658 const GLchar* name = "";
1660 switch (m_test_case)
1663 name = "\"Sampling GL_R8 texture\"";
1666 name = "\"Sampling GL_RG8_SNORM texture\"";
1669 name = "\"Sampling GL_RGBA32F texture\"";
1672 name = "\"Sampling mipmap of GL_32UI texture\"";
1674 case R32UI_MULTISAMPLE:
1675 name = "\"Sampling GL_32UI multisampled texture\"";
1678 TCU_FAIL("Invalid enum");
1685 /** Prepare a texture
1687 * @param is_source Selects if texutre will be used as source or destination
1688 * @param texture_id Id of texutre
1690 void TexelFetchTest::prepareTexture(bool is_source, glw::GLuint texture_id)
1693 static const GLuint image_height = 16;
1694 static const GLuint image_width = 16;
1696 /* GL entry points */
1697 const Functions& gl = m_context.getRenderContext().getFunctions();
1699 /* Texture storage parameters */
1700 GLuint height = image_height;
1701 GLenum internal_format = 0;
1702 GLsizei n_levels = 1;
1703 GLenum target = GL_TEXTURE_2D;
1704 GLuint width = image_width;
1706 /* Prepare texture storage parameters */
1707 switch (m_test_case)
1710 internal_format = GL_R8;
1713 internal_format = GL_RG8_SNORM;
1716 internal_format = GL_RGBA32F;
1719 height = 2 * image_height;
1720 internal_format = GL_R32UI;
1722 width = 2 * image_width;
1724 case R32UI_MULTISAMPLE:
1725 internal_format = GL_R32UI;
1727 target = GL_TEXTURE_2D_MULTISAMPLE;
1730 TCU_FAIL("Invalid enum");
1733 /* Prepare storage */
1734 Texture::Bind(gl, texture_id, target);
1735 Texture::Storage(gl, target, n_levels, internal_format, width, height, 0);
1737 gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1738 gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1740 /* Destination image can be left empty */
1741 if (false == is_source)
1743 Texture::Bind(gl, 0, target);
1747 /* Prepare texture */
1748 if (R8 == m_test_case)
1750 GLubyte source_pixels[image_width * image_height];
1751 for (GLuint i = 0; i < image_width * image_height; ++i)
1753 source_pixels[i] = static_cast<GLubyte>(i);
1756 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1757 0 /* depth */, GL_RED, GL_UNSIGNED_BYTE, source_pixels);
1759 else if (RG8_SNORM == m_test_case)
1761 static const GLuint n_components = 2;
1763 GLbyte source_pixels[image_width * image_height * n_components];
1764 for (GLuint i = 0; i < image_width * image_height; ++i)
1766 source_pixels[i * n_components + 0] = static_cast<GLubyte>((i % 16) - 8);
1767 source_pixels[i * n_components + 1] = static_cast<GLubyte>((i / 16) - 8);
1770 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1771 0 /* depth */, GL_RG, GL_BYTE, source_pixels);
1773 else if (RGBA32F == m_test_case)
1775 static const GLuint n_components = 4;
1777 GLfloat source_pixels[image_width * image_height * n_components];
1778 for (GLuint i = 0; i < image_width * image_height; ++i)
1780 source_pixels[i * n_components + 0] = (GLfloat)(i % 16) / 16.0f;
1781 source_pixels[i * n_components + 1] = (GLfloat)(i / 16) / 16.0f;
1782 source_pixels[i * n_components + 2] = (GLfloat)i / 256.0f;
1783 source_pixels[i * n_components + 3] = 1.0f;
1786 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height,
1787 0 /* depth */, GL_RGBA, GL_FLOAT, source_pixels);
1789 else if (R32UI_MIPMAP == m_test_case)
1791 GLuint source_pixels[image_width * image_height];
1792 for (GLuint i = 0; i < image_width * image_height; ++i)
1794 source_pixels[i] = i;
1797 Texture::SubImage(gl, GL_TEXTURE_2D, 1 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, image_width, image_height,
1798 0 /* depth */, GL_RED_INTEGER, GL_UNSIGNED_INT, source_pixels);
1800 else if (R32UI_MULTISAMPLE == m_test_case)
1802 /* Compute shader */
1803 static const GLchar* cs = "#version 430 core\n"
1805 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1807 "layout (location = 0) writeonly uniform uimage2DMS uni_image;\n"
1811 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
1812 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
1814 " imageStore(uni_image, point, 0, uvec4(index + 0, 0, 0, 0));\n"
1815 " imageStore(uni_image, point, 1, uvec4(index + 1, 0, 0, 0));\n"
1816 " imageStore(uni_image, point, 2, uvec4(index + 2, 0, 0, 0));\n"
1817 " imageStore(uni_image, point, 3, uvec4(index + 3, 0, 0, 0));\n"
1821 Program program(m_context);
1822 program.Init(cs, "", "", "", "", "");
1825 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
1826 GL_WRITE_ONLY, GL_R32UI);
1827 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
1829 gl.uniform1i(0 /* location */, 0 /* image unit*/);
1830 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
1832 gl.dispatchCompute(16, 16, 1);
1833 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
1836 Texture::Bind(gl, 0, target);
1839 /** Verifies that texutre is filled with 0 or with (0, 0, 0, x),
1840 * where x may be 0, 1 or the biggest representable integer value.
1842 * @param texture_id Id of texture
1844 * @return true when image is filled with 0, 1 or biggest represetable integer number, false otherwise
1846 bool TexelFetchTest::verifyInvalidResults(glw::GLuint texture_id)
1848 static const GLuint height = 16;
1849 static const GLuint width = 16;
1850 static const GLuint n_pixels = height * width;
1852 const Functions& gl = m_context.getRenderContext().getFunctions();
1856 if (R8 == m_test_case)
1858 static const GLuint n_channels = 1;
1860 std::vector<GLubyte> pixels;
1861 pixels.resize(n_pixels * n_channels);
1862 for (GLuint i = 0; i < n_pixels; ++i)
1864 pixels[i] = static_cast<GLubyte>(i);
1867 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1869 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
1872 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1875 for (GLuint i = 0; i < n_pixels; ++i)
1877 const GLubyte expected_red = 0;
1878 const GLubyte drawn_red = pixels[i];
1880 if (expected_red != drawn_red)
1882 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
1883 << ". Expected value: " << (GLuint)expected_red
1884 << " at offset: " << i << tcu::TestLog::EndMessage;
1891 else if (RG8_SNORM == m_test_case)
1893 static const GLuint n_channels = 2;
1895 std::vector<GLbyte> pixels;
1896 pixels.resize(n_pixels * n_channels);
1897 for (GLuint i = 0; i < n_pixels; ++i)
1899 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
1900 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
1903 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1905 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
1908 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1911 for (GLuint i = 0; i < n_pixels; ++i)
1913 const GLbyte expected_red = 0;
1914 const GLbyte expected_green = 0;
1915 const GLbyte drawn_red = pixels[i * n_channels + 0];
1916 const GLbyte drawn_green = pixels[i * n_channels + 1];
1918 if ((expected_red != drawn_red) || (expected_green != drawn_green))
1920 m_context.getTestContext().getLog()
1921 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
1922 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
1923 << ". At offset: " << i << tcu::TestLog::EndMessage;
1930 else if (RGBA32F == m_test_case)
1932 static const GLuint n_channels = 4;
1934 std::vector<GLfloat> pixels;
1935 pixels.resize(n_pixels * n_channels);
1936 for (GLuint i = 0; i < n_pixels; ++i)
1938 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
1939 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
1940 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
1941 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
1944 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1946 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
1949 Texture::Bind(gl, 0, GL_TEXTURE_2D);
1952 for (GLuint i = 0; i < n_pixels; ++i)
1954 const GLfloat expected_red = 0.0f;
1955 const GLfloat expected_green = 0.0f;
1956 const GLfloat expected_blue = 0.0f;
1957 const GLfloat expected_alpha_0 =
1958 0.0f; /* OpenGL 4.5 (and ES) specifies two possiblities (0 or 1) for alpha channel (Chapter 11.1.3.12). */
1959 const GLfloat expected_alpha_1 = 1.0f;
1960 const GLfloat drawn_red = pixels[i * n_channels + 0];
1961 const GLfloat drawn_green = pixels[i * n_channels + 1];
1962 const GLfloat drawn_blue = pixels[i * n_channels + 2];
1963 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
1965 const GLfloat precision = 0.0009765625; /* (1.f / 1024.f) */
1967 if ((de::abs(expected_red - drawn_red) > precision) ||
1968 (de::abs(expected_green - drawn_green) > precision) ||
1969 (de::abs(expected_blue - drawn_blue) > precision) ||
1970 ((de::abs(expected_alpha_0 - drawn_alpha) > precision) &&
1971 (de::abs(expected_alpha_1 - drawn_alpha) > precision)))
1973 m_context.getTestContext().getLog()
1974 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
1975 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
1976 << expected_green << ", " << expected_blue << ", " << expected_alpha_0 << " or " << expected_alpha_1
1977 << ". At offset: " << i << tcu::TestLog::EndMessage;
1984 else if (R32UI_MIPMAP == m_test_case)
1986 static const GLuint n_channels = 1;
1988 std::vector<GLuint> pixels;
1989 pixels.resize(n_pixels * n_channels);
1990 for (GLuint i = 0; i < n_pixels; ++i)
1995 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
1997 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2000 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2003 for (GLuint i = 0; i < n_pixels; ++i)
2005 const GLuint expected_red = 0;
2006 const GLuint drawn_red = pixels[i];
2008 if (expected_red != drawn_red)
2010 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2011 << ". Expected value: " << expected_red << " at offset: " << i
2012 << tcu::TestLog::EndMessage;
2019 else if (R32UI_MULTISAMPLE == m_test_case)
2021 static const GLuint n_channels = 1;
2023 /* Compute shader */
2024 static const GLchar* cs = "#version 430 core\n"
2026 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2028 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2029 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2033 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2035 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2036 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2037 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2038 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2040 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2042 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2046 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2051 Program program(m_context);
2052 Texture destination_texture(m_context);
2054 Texture::Generate(gl, destination_texture.m_id);
2055 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2056 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2058 program.Init(cs, "", "", "", "", "");
2060 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2061 GL_READ_ONLY, GL_R32UI);
2062 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2063 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2064 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2065 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2067 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2068 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2070 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2071 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2073 gl.dispatchCompute(16, 16, 1);
2074 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2076 /* Pixels buffer initialization */
2077 std::vector<GLuint> pixels;
2078 pixels.resize(n_pixels * n_channels);
2079 for (GLuint i = 0; i < n_pixels; ++i)
2084 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2087 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2090 for (GLuint i = 0; i < n_pixels; ++i)
2092 const GLuint expected_red = 1;
2093 const GLuint drawn_red = pixels[i];
2095 if (expected_red != drawn_red)
2097 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2098 << ". Expected value: " << expected_red << " at offset: " << i
2099 << tcu::TestLog::EndMessage;
2110 /** Verifies that texutre is filled with increasing values
2112 * @param texture_id Id of texture
2114 * @return true when image is filled with increasing values, false otherwise
2116 bool TexelFetchTest::verifyValidResults(glw::GLuint texture_id)
2118 static const GLuint height = 16;
2119 static const GLuint width = 16;
2120 static const GLuint n_pixels = height * width;
2122 const Functions& gl = m_context.getRenderContext().getFunctions();
2126 if (R8 == m_test_case)
2128 static const GLuint n_channels = 1;
2130 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2132 std::vector<GLubyte> pixels;
2133 pixels.resize(n_pixels * n_channels);
2134 for (GLuint i = 0; i < n_pixels; ++i)
2136 pixels[i] = static_cast<GLubyte>(i);
2139 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2142 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2145 for (GLuint i = 0; i < n_pixels; ++i)
2147 const GLubyte expected_red = static_cast<GLubyte>(i);
2148 const GLubyte drawn_red = pixels[i];
2150 if (expected_red != drawn_red)
2152 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2153 << ". Expected value: " << (GLuint)expected_red
2154 << " at offset: " << i << tcu::TestLog::EndMessage;
2161 else if (RG8_SNORM == m_test_case)
2163 static const GLuint n_channels = 2;
2165 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2167 std::vector<GLbyte> pixels;
2168 pixels.resize(n_pixels * n_channels);
2169 for (GLuint i = 0; i < n_pixels; ++i)
2171 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2172 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2175 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2178 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2181 for (GLuint i = 0; i < n_pixels; ++i)
2183 const GLbyte expected_red = static_cast<GLubyte>((i % 16) - 8);
2184 const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
2185 const GLbyte drawn_red = pixels[i * n_channels + 0];
2186 const GLbyte drawn_green = pixels[i * n_channels + 1];
2188 if ((expected_red != drawn_red) || (expected_green != drawn_green))
2190 m_context.getTestContext().getLog()
2191 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2192 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2193 << ". At offset: " << i << tcu::TestLog::EndMessage;
2200 else if (RGBA32F == m_test_case)
2202 static const GLuint n_channels = 4;
2204 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2206 std::vector<GLfloat> pixels;
2207 pixels.resize(n_pixels * n_channels);
2208 for (GLuint i = 0; i < n_pixels; ++i)
2210 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2211 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2212 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2213 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2216 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2219 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2222 for (GLuint i = 0; i < n_pixels; ++i)
2224 const GLfloat expected_red = (GLfloat)(i % 16) / 16.0f;
2225 const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
2226 const GLfloat expected_blue = (GLfloat)i / 256.0f;
2227 const GLfloat expected_alpha = 1.0f;
2228 const GLfloat drawn_red = pixels[i * n_channels + 0];
2229 const GLfloat drawn_green = pixels[i * n_channels + 1];
2230 const GLfloat drawn_blue = pixels[i * n_channels + 2];
2231 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
2233 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2234 (expected_alpha != drawn_alpha))
2236 m_context.getTestContext().getLog()
2237 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2238 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2239 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2240 << tcu::TestLog::EndMessage;
2247 else if (R32UI_MIPMAP == m_test_case)
2249 static const GLuint n_channels = 1;
2251 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2253 std::vector<GLuint> pixels;
2254 pixels.resize(n_pixels * n_channels * 4);
2255 for (GLuint i = 0; i < n_pixels; ++i)
2260 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2263 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2266 for (GLuint i = 0; i < n_pixels; ++i)
2268 const GLuint expected_red = i;
2269 const GLuint drawn_red = pixels[i];
2271 if (expected_red != drawn_red)
2273 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2274 << ". Expected value: " << expected_red << " at offset: " << i
2275 << tcu::TestLog::EndMessage;
2282 else if (R32UI_MULTISAMPLE == m_test_case)
2284 static const GLuint n_channels = 1;
2286 /* Compute shader */
2287 static const GLchar* cs =
2288 "#version 430 core\n"
2290 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2292 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2293 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2297 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2298 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
2300 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2301 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2302 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2303 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2305 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
2307 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2311 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2316 Program program(m_context);
2317 Texture destination_texture(m_context);
2319 Texture::Generate(gl, destination_texture.m_id);
2320 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2321 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2323 program.Init(cs, "", "", "", "", "");
2325 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2326 GL_READ_ONLY, GL_R32UI);
2327 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2328 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2329 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2330 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2332 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2333 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2335 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2336 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2338 gl.dispatchCompute(16, 16, 1);
2339 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2341 /* Pixels buffer initialization */
2342 std::vector<GLuint> pixels;
2343 pixels.resize(n_pixels * n_channels);
2344 for (GLuint i = 0; i < n_pixels; ++i)
2349 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2352 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2355 for (GLuint i = 0; i < n_pixels; ++i)
2357 const GLuint expected_red = 1;
2358 const GLuint drawn_red = pixels[i];
2360 if (expected_red != drawn_red)
2362 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2363 << ". Expected value: " << expected_red << " at offset: " << i
2364 << tcu::TestLog::EndMessage;
2377 * @param context Test context
2379 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context)
2380 : TexelFetchTest(context, "image_load_store", "Verifies that out-of-bound to image result in zero or is discarded")
2382 /* Nothing to be done */
2387 * @param context Test context
2389 ImageLoadStoreTest::ImageLoadStoreTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
2390 : TexelFetchTest(context, name, description)
2392 /* Nothing to be done */
2397 * @return tcu::TestNode::STOP
2399 tcu::TestNode::IterateResult ImageLoadStoreTest::iterate()
2402 static const GLuint height = 16;
2403 static const GLuint width = 16;
2405 /* GL entry points */
2406 const Functions& gl = m_context.getRenderContext().getFunctions();
2408 /* Test result indicator */
2409 bool test_result = true;
2411 /* Iterate over all cases */
2412 for (; m_test_case < LAST; m_test_case = (TEST_CASES)((GLuint)m_test_case + 1))
2414 /* Test case result indicator */
2415 bool case_result = true;
2417 if (R32UI_MULTISAMPLE == m_test_case)
2419 // Skip invalid program test in multi sample case
2420 // texelFetch with invalid lod plane results undefined value
2421 // OpenGL 4.5 Core Spec, around page 377
2422 m_test_case = (TEST_CASES)((GLuint)m_test_case + 1);
2427 Texture destination_texture(m_context);
2428 Program invalid_destination_program(m_context);
2429 Program invalid_source_program(m_context);
2430 Texture source_texture(m_context);
2431 Program valid_program(m_context);
2433 const std::string& cs_invalid_destination = getComputeShader(DESTINATION_INVALID);
2434 const std::string& cs_invalid_source = getComputeShader(SOURCE_INVALID);
2435 const std::string& cs_valid = getComputeShader(VALID);
2437 /* Prepare textures */
2438 Texture::Generate(gl, destination_texture.m_id);
2439 Texture::Generate(gl, source_texture.m_id);
2441 if (R32UI_MULTISAMPLE == m_test_case)
2443 GLint max_integer_samples;
2444 gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &max_integer_samples);
2445 GLint max_image_samples;
2446 gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
2447 if (max_integer_samples < 4 || max_image_samples < 4)
2449 /* prepareTexture() hard-codes 4 samples (n_levels) for
2450 * R32UI_MULTISAMPLE case. This value exceeds the required
2451 * min-max value (1 in OpenGL ES 3.2) and is not supported
2452 * by all implementations.
2454 * Also, the test uses a compute shader with images
2455 * to upload the texture so max_image_samples >= 4
2458 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2459 << " not supported" << tcu::TestLog::EndMessage;
2465 prepareTexture(false, destination_texture.m_id);
2466 prepareTexture(true, source_texture.m_id);
2468 /* Prepare programs */
2469 invalid_destination_program.Init(cs_invalid_destination, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
2471 invalid_source_program.Init(cs_invalid_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */,
2473 valid_program.Init(cs_valid, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
2475 /* Test invalid source case */
2477 invalid_source_program.Use();
2480 setTextures(destination_texture.m_id, source_texture.m_id);
2483 gl.dispatchCompute(width, height, 1 /* depth */);
2484 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2487 if (false == verifyInvalidResults(destination_texture.m_id))
2489 case_result = false;
2492 /* Test valid case */
2494 valid_program.Use();
2497 setTextures(destination_texture.m_id, source_texture.m_id);
2500 gl.dispatchCompute(width, height, 1 /* depth */);
2501 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2504 if (false == verifyValidResults(destination_texture.m_id))
2506 case_result = false;
2509 /* Test invalid destination case */
2511 invalid_destination_program.Use();
2514 setTextures(destination_texture.m_id, source_texture.m_id);
2517 gl.dispatchCompute(width, height, 1 /* depth */);
2518 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2521 if (false == verifyValidResults(destination_texture.m_id))
2523 case_result = false;
2526 /* Set test result */
2527 if (false == case_result)
2529 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << getTestCaseName()
2530 << " failed" << tcu::TestLog::EndMessage;
2532 test_result = false;
2537 if (true == test_result)
2539 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2543 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2547 return tcu::TestNode::STOP;
2550 /** Prepare shader for current test case
2552 * @param version Specify which version should be prepared
2556 std::string ImageLoadStoreTest::getComputeShader(VERSION version)
2558 static const GLchar* template_code = "#version 430 core\n"
2560 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2562 "layout (location = 1) writeonly uniform IMAGE uni_destination_image;\n"
2563 "layout (location = 0, FORMAT) readonly uniform IMAGE uni_source_image;\n"
2567 " const ivec2 point_destination = POINT;\n"
2568 " const ivec2 point_source = POINT;\n"
2574 static const GLchar* copy_multisampled =
2575 " const TYPE color_0 = imageLoad(uni_source_image, point_source, 0 + OFFSET);\n"
2576 " const TYPE color_1 = imageLoad(uni_source_image, point_source, 1 + OFFSET);\n"
2577 " const TYPE color_2 = imageLoad(uni_source_image, point_source, 2 + OFFSET);\n"
2578 " const TYPE color_3 = imageLoad(uni_source_image, point_source, 3 + OFFSET);\n"
2579 " imageStore(uni_destination_image, point_destination, 0 + OFFSET, color_0);\n"
2580 " imageStore(uni_destination_image, point_destination, 1 + OFFSET, color_1);\n"
2581 " imageStore(uni_destination_image, point_destination, 2 + OFFSET, color_2);\n"
2582 " imageStore(uni_destination_image, point_destination, 3 + OFFSET, color_3);\n";
2584 static const GLchar* copy_regular =
2585 " const TYPE color = imageLoad(uni_source_image, point_source);\n"
2586 " //imageStore(uni_destination_image, point_destination, vec4(0, 0, 0, 0));\n"
2587 " imageStore(uni_destination_image, point_destination, color);\n";
2589 static const GLchar* format_r8 = "r8";
2590 static const GLchar* format_rg8_snorm = "rg8_snorm";
2591 static const GLchar* format_rgba32f = "rgba32f";
2592 static const GLchar* format_r32ui = "r32ui";
2594 static const GLchar* image_vec4 = "image2D";
2596 static const GLchar* image_uvec4 = "uimage2D";
2598 static const GLchar* image_uvec4_ms = "uimage2DMS";
2600 static const GLchar* offset_invalid = "4";
2601 static const GLchar* offset_valid = "0";
2603 static const GLchar* point_invalid = "ivec2(gl_WorkGroupID.x + 16, gl_WorkGroupID.y + 16)";
2605 static const GLchar* point_valid = "ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y)";
2607 static const GLchar* type_vec4 = "vec4";
2608 static const GLchar* type_uvec4 = "uvec4";
2610 const GLchar* copy = copy_regular;
2611 const GLchar* format = format_r8;
2612 const GLchar* image = image_vec4;
2613 const GLchar* offset_destination = offset_valid;
2614 const GLchar* offset_source = offset_valid;
2615 const GLchar* point_destination = point_valid;
2616 const GLchar* point_source = point_valid;
2617 const GLchar* type = type_vec4;
2623 case SOURCE_INVALID:
2624 point_source = point_invalid;
2625 offset_source = offset_invalid;
2627 case DESTINATION_INVALID:
2628 point_destination = point_invalid;
2629 offset_destination = offset_invalid;
2632 TCU_FAIL("Invalid enum");
2635 switch (m_test_case)
2640 format = format_rg8_snorm;
2643 format = format_rgba32f;
2646 format = format_r32ui;
2647 image = image_uvec4;
2650 case R32UI_MULTISAMPLE:
2651 copy = copy_multisampled;
2652 format = format_r32ui;
2653 image = image_uvec4_ms;
2654 point_destination = point_valid;
2655 point_source = point_valid;
2659 TCU_FAIL("Invalid enum");
2662 size_t position = 0;
2663 std::string source = template_code;
2665 replaceToken("IMAGE", position, image, source);
2666 replaceToken("FORMAT", position, format, source);
2667 replaceToken("IMAGE", position, image, source);
2668 replaceToken("POINT", position, point_destination, source);
2669 replaceToken("POINT", position, point_source, source);
2671 size_t temp_position = position;
2672 replaceToken("COPY", position, copy, source);
2673 position = temp_position;
2675 switch (m_test_case)
2681 replaceToken("TYPE", position, type, source);
2683 case R32UI_MULTISAMPLE:
2684 replaceToken("TYPE", position, type, source);
2685 replaceToken("OFFSET", position, offset_source, source);
2686 replaceToken("TYPE", position, type, source);
2687 replaceToken("OFFSET", position, offset_source, source);
2688 replaceToken("TYPE", position, type, source);
2689 replaceToken("OFFSET", position, offset_source, source);
2690 replaceToken("TYPE", position, type, source);
2691 replaceToken("OFFSET", position, offset_source, source);
2692 replaceToken("OFFSET", position, offset_destination, source);
2693 replaceToken("OFFSET", position, offset_destination, source);
2694 replaceToken("OFFSET", position, offset_destination, source);
2695 replaceToken("OFFSET", position, offset_destination, source);
2698 TCU_FAIL("Invalid enum");
2704 /** Set textures as images
2706 * @param id_destination Id of texture used as destination
2707 * @param id_source Id of texture used as source
2709 void ImageLoadStoreTest::setTextures(glw::GLuint id_destination, glw::GLuint id_source)
2711 const Functions& gl = m_context.getRenderContext().getFunctions();
2716 switch (m_test_case)
2722 format = GL_RG8_SNORM;
2725 format = GL_RGBA32F;
2731 case R32UI_MULTISAMPLE:
2735 TCU_FAIL("Invalid enum");
2738 gl.bindImageTexture(0 /* unit */, id_source, level, GL_FALSE /* layered */, 0 /* layer */, GL_READ_ONLY, format);
2739 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2741 gl.bindImageTexture(1 /* unit */, id_destination, level, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY,
2743 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2745 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2746 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2748 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2749 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2752 /** Verifies that texutre is filled with 0
2754 * @param texture_id Id of texture
2756 * @return true when image is filled with 0, false otherwise
2758 bool ImageLoadStoreTest::verifyInvalidResults(glw::GLuint texture_id)
2760 static const GLuint height = 16;
2761 static const GLuint width = 16;
2762 static const GLuint n_pixels = height * width;
2764 const Functions& gl = m_context.getRenderContext().getFunctions();
2765 gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2766 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
2770 if (R8 == m_test_case)
2772 static const GLuint n_channels = 1;
2774 std::vector<GLubyte> pixels;
2775 pixels.resize(n_pixels * n_channels);
2776 for (GLuint i = 0; i < n_pixels; ++i)
2778 pixels[i] = static_cast<GLubyte>(i);
2781 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2783 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
2786 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2789 for (GLuint i = 0; i < n_pixels; ++i)
2791 const GLubyte expected_red = 0;
2792 const GLubyte drawn_red = pixels[i];
2794 if (expected_red != drawn_red)
2796 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
2797 << ". Expected value: " << (GLuint)expected_red
2798 << " at offset: " << i << tcu::TestLog::EndMessage;
2805 else if (RG8_SNORM == m_test_case)
2807 static const GLuint n_channels = 2;
2809 std::vector<GLbyte> pixels;
2810 pixels.resize(n_pixels * n_channels);
2811 for (GLuint i = 0; i < n_pixels; ++i)
2813 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
2814 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
2817 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2819 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
2822 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2825 for (GLuint i = 0; i < n_pixels; ++i)
2827 const GLbyte expected_red = 0;
2828 const GLbyte expected_green = 0;
2829 const GLbyte drawn_red = pixels[i * n_channels + 0];
2830 const GLbyte drawn_green = pixels[i * n_channels + 1];
2832 if ((expected_red != drawn_red) || (expected_green != drawn_green))
2834 m_context.getTestContext().getLog()
2835 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
2836 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
2837 << ". At offset: " << i << tcu::TestLog::EndMessage;
2844 else if (RGBA32F == m_test_case)
2846 static const GLuint n_channels = 4;
2848 std::vector<GLfloat> pixels;
2849 pixels.resize(n_pixels * n_channels);
2850 for (GLuint i = 0; i < n_pixels; ++i)
2852 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
2853 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
2854 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
2855 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
2858 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2860 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
2863 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2866 for (GLuint i = 0; i < n_pixels; ++i)
2868 const GLfloat expected_red = 0.0f;
2869 const GLfloat expected_green = 0.0f;
2870 const GLfloat expected_blue = 0.0f;
2871 const GLfloat expected_alpha = 0.0f;
2872 const GLfloat drawn_red = pixels[i * n_channels + 0];
2873 const GLfloat drawn_green = pixels[i * n_channels + 1];
2874 const GLfloat drawn_blue = pixels[i * n_channels + 2];
2875 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
2877 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
2878 (expected_alpha != drawn_alpha))
2880 m_context.getTestContext().getLog()
2881 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
2882 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
2883 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
2884 << tcu::TestLog::EndMessage;
2891 else if (R32UI_MIPMAP == m_test_case)
2893 static const GLuint n_channels = 1;
2895 std::vector<GLuint> pixels;
2896 pixels.resize(n_pixels * n_channels);
2897 for (GLuint i = 0; i < n_pixels; ++i)
2902 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
2904 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2907 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2910 for (GLuint i = 0; i < n_pixels; ++i)
2912 const GLuint expected_red = 0;
2913 const GLuint drawn_red = pixels[i];
2915 if (expected_red != drawn_red)
2917 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
2918 << ". Expected value: " << expected_red << " at offset: " << i
2919 << tcu::TestLog::EndMessage;
2926 else if (R32UI_MULTISAMPLE == m_test_case)
2928 static const GLuint n_channels = 1;
2930 /* Compute shader */
2931 static const GLchar* cs = "#version 430 core\n"
2933 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2935 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
2936 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
2940 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
2942 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
2943 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
2944 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
2945 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
2947 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(0))))\n"
2949 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
2953 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
2958 Program program(m_context);
2959 Texture destination_texture(m_context);
2961 Texture::Generate(gl, destination_texture.m_id);
2962 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
2963 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
2965 program.Init(cs, "", "", "", "", "");
2967 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
2968 GL_READ_ONLY, GL_R32UI);
2969 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2970 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
2971 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
2972 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
2974 gl.uniform1i(0 /* location */, 0 /* image unit*/);
2975 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2977 gl.uniform1i(1 /* location */, 1 /* image unit*/);
2978 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
2980 gl.dispatchCompute(16, 16, 1);
2981 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
2983 /* Pixels buffer initialization */
2984 std::vector<GLuint> pixels;
2985 pixels.resize(n_pixels * n_channels);
2986 for (GLuint i = 0; i < n_pixels; ++i)
2991 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
2994 Texture::Bind(gl, 0, GL_TEXTURE_2D);
2997 for (GLuint i = 0; i < n_pixels; ++i)
2999 const GLuint expected_red = 1;
3000 const GLuint drawn_red = pixels[i];
3002 if (expected_red != drawn_red)
3004 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3005 << ". Expected value: " << expected_red << " at offset: " << i
3006 << tcu::TestLog::EndMessage;
3017 /** Verifies that texutre is filled with increasing values
3019 * @param texture_id Id of texture
3021 * @return true when image is filled with increasing values, false otherwise
3023 bool ImageLoadStoreTest::verifyValidResults(glw::GLuint texture_id)
3025 static const GLuint height = 16;
3026 static const GLuint width = 16;
3027 static const GLuint n_pixels = height * width;
3029 const Functions& gl = m_context.getRenderContext().getFunctions();
3030 gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
3031 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3035 if (R8 == m_test_case)
3037 static const GLuint n_channels = 1;
3039 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3041 std::vector<GLubyte> pixels;
3042 pixels.resize(n_pixels * n_channels);
3043 for (GLuint i = 0; i < n_pixels; ++i)
3045 pixels[i] = static_cast<GLubyte>(i);
3048 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED, GL_UNSIGNED_BYTE, &pixels[0]);
3051 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3054 for (GLuint i = 0; i < n_pixels; ++i)
3056 const GLubyte expected_red = static_cast<GLubyte>(i);
3057 const GLubyte drawn_red = pixels[i];
3059 if (expected_red != drawn_red)
3061 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << (GLuint)drawn_red
3062 << ". Expected value: " << (GLuint)expected_red
3063 << " at offset: " << i << tcu::TestLog::EndMessage;
3070 else if (RG8_SNORM == m_test_case)
3072 static const GLuint n_channels = 2;
3074 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3076 std::vector<GLbyte> pixels;
3077 pixels.resize(n_pixels * n_channels);
3078 for (GLuint i = 0; i < n_pixels; ++i)
3080 pixels[i * n_channels + 0] = static_cast<GLubyte>(i);
3081 pixels[i * n_channels + 1] = static_cast<GLubyte>(i);
3084 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RG, GL_BYTE, &pixels[0]);
3087 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3090 for (GLuint i = 0; i < n_pixels; ++i)
3092 const GLbyte expected_red = static_cast<GLubyte>((i % 16) - 8);
3093 const GLbyte expected_green = static_cast<GLubyte>((i / 16) - 8);
3094 const GLbyte drawn_red = pixels[i * n_channels + 0];
3095 const GLbyte drawn_green = pixels[i * n_channels + 1];
3097 if ((expected_red != drawn_red) || (expected_green != drawn_green))
3099 m_context.getTestContext().getLog()
3100 << tcu::TestLog::Message << "Invalid value: " << (GLint)drawn_red << ", " << (GLint)drawn_green
3101 << ". Expected value: " << (GLint)expected_red << ", " << (GLint)expected_green
3102 << ". At offset: " << i << tcu::TestLog::EndMessage;
3109 else if (RGBA32F == m_test_case)
3111 static const GLuint n_channels = 4;
3113 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3115 std::vector<GLfloat> pixels;
3116 pixels.resize(n_pixels * n_channels);
3117 for (GLuint i = 0; i < n_pixels; ++i)
3119 pixels[i * n_channels + 0] = (GLfloat)i / (GLfloat)n_pixels;
3120 pixels[i * n_channels + 1] = (GLfloat)i / (GLfloat)n_pixels;
3121 pixels[i * n_channels + 2] = (GLfloat)i / (GLfloat)n_pixels;
3122 pixels[i * n_channels + 3] = (GLfloat)i / (GLfloat)n_pixels;
3125 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RGBA, GL_FLOAT, &pixels[0]);
3128 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3131 for (GLuint i = 0; i < n_pixels; ++i)
3133 const GLfloat expected_red = (GLfloat)(i % 16) / 16.0f;
3134 const GLfloat expected_green = (GLfloat)(i / 16) / 16.0f;
3135 const GLfloat expected_blue = (GLfloat)i / 256.0f;
3136 const GLfloat expected_alpha = 1.0f;
3137 const GLfloat drawn_red = pixels[i * n_channels + 0];
3138 const GLfloat drawn_green = pixels[i * n_channels + 1];
3139 const GLfloat drawn_blue = pixels[i * n_channels + 2];
3140 const GLfloat drawn_alpha = pixels[i * n_channels + 3];
3142 if ((expected_red != drawn_red) || (expected_green != drawn_green) || (expected_blue != drawn_blue) ||
3143 (expected_alpha != drawn_alpha))
3145 m_context.getTestContext().getLog()
3146 << tcu::TestLog::Message << "Invalid value: " << drawn_red << ", " << drawn_green << ", "
3147 << drawn_blue << ", " << drawn_alpha << ". Expected value: " << expected_red << ", "
3148 << expected_green << ", " << expected_blue << ", " << expected_alpha << ". At offset: " << i
3149 << tcu::TestLog::EndMessage;
3156 else if (R32UI_MIPMAP == m_test_case)
3158 static const GLuint n_channels = 1;
3160 Texture::Bind(gl, texture_id, GL_TEXTURE_2D);
3162 std::vector<GLuint> pixels;
3163 pixels.resize(n_pixels * n_channels * 4);
3164 for (GLuint i = 0; i < n_pixels; ++i)
3169 Texture::GetData(gl, 1 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3172 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3175 for (GLuint i = 0; i < n_pixels; ++i)
3177 const GLuint expected_red = i;
3178 const GLuint drawn_red = pixels[i];
3180 if (expected_red != drawn_red)
3182 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3183 << ". Expected value: " << expected_red << " at offset: " << i
3184 << tcu::TestLog::EndMessage;
3191 else if (R32UI_MULTISAMPLE == m_test_case)
3193 static const GLuint n_channels = 1;
3195 /* Compute shader */
3196 static const GLchar* cs =
3197 "#version 430 core\n"
3199 "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
3201 "layout (location = 1) writeonly uniform uimage2D uni_destination_image;\n"
3202 "layout (location = 0, r32ui) readonly uniform uimage2DMS uni_source_image;\n"
3206 " const ivec2 point = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n"
3207 " const uint index = gl_WorkGroupID.y * 16 + gl_WorkGroupID.x;\n"
3209 " const uvec4 color_0 = imageLoad(uni_source_image, point, 0);\n"
3210 " const uvec4 color_1 = imageLoad(uni_source_image, point, 1);\n"
3211 " const uvec4 color_2 = imageLoad(uni_source_image, point, 2);\n"
3212 " const uvec4 color_3 = imageLoad(uni_source_image, point, 3);\n"
3214 " if (any(equal(uvec4(color_0.r, color_1.r, color_2.r, color_3.r), uvec4(index + 3))))\n"
3216 " imageStore(uni_destination_image, point, uvec4(1, 1, 1, 1));\n"
3220 " imageStore(uni_destination_image, point, uvec4(0, 0, 0, 0));\n"
3225 Program program(m_context);
3226 Texture destination_texture(m_context);
3228 Texture::Generate(gl, destination_texture.m_id);
3229 Texture::Bind(gl, destination_texture.m_id, GL_TEXTURE_2D);
3230 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R32UI, width, height, 0 /* depth */);
3232 program.Init(cs, "", "", "", "", "");
3234 gl.bindImageTexture(0 /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3235 GL_READ_ONLY, GL_R32UI);
3236 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3237 gl.bindImageTexture(1 /* unit */, destination_texture.m_id, 0 /* level */, GL_FALSE /* layered */,
3238 0 /* layer */, GL_WRITE_ONLY, GL_R32UI);
3239 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
3241 gl.uniform1i(0 /* location */, 0 /* image unit*/);
3242 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3244 gl.uniform1i(1 /* location */, 1 /* image unit*/);
3245 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3247 gl.dispatchCompute(16, 16, 1);
3248 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3250 /* Pixels buffer initialization */
3251 std::vector<GLuint> pixels;
3252 pixels.resize(n_pixels * n_channels);
3253 for (GLuint i = 0; i < n_pixels; ++i)
3258 Texture::GetData(gl, 0 /* level */, GL_TEXTURE_2D, GL_RED_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
3261 Texture::Bind(gl, 0, GL_TEXTURE_2D);
3264 for (GLuint i = 0; i < n_pixels; ++i)
3266 const GLuint expected_red = 1;
3267 const GLuint drawn_red = pixels[i];
3269 if (expected_red != drawn_red)
3271 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid value: " << drawn_red
3272 << ". Expected value: " << expected_red << " at offset: " << i
3273 << tcu::TestLog::EndMessage;
3284 /* StorageBufferTest constants */
3285 const GLfloat StorageBufferTest::m_destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3286 const GLfloat StorageBufferTest::m_source_data[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3290 * @param context Test context
3292 StorageBufferTest::StorageBufferTest(deqp::Context& context)
3293 : TestCase(context, "storage_buffer", "Verifies that out-of-bound access to SSBO is discared or resutls in 0")
3294 , m_test_case(VALID)
3295 , m_hasKhrRobustBufferAccess(false)
3297 /* Nothing to be done here */
3302 * @param context Test context
3304 StorageBufferTest::StorageBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3305 : TestCase(context, name, description), m_test_case(VALID)
3307 /* Nothing to be done */
3312 * @return tcu::TestNode::STOP
3314 tcu::TestNode::IterateResult StorageBufferTest::iterate()
3317 /* GL entry points */
3318 const Functions& gl = m_context.getRenderContext().getFunctions();
3320 m_hasKhrRobustBufferAccess = m_context.getContextInfo().isExtensionSupported("GL_KHR_robust_buffer_access_behavior") ||
3321 contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5));
3323 /* Test result indicator */
3324 bool test_result = true;
3326 /* Iterate over all cases */
3327 while (LAST != m_test_case)
3329 /* Test case objects */
3330 Buffer destination_buffer(m_context);
3331 Buffer source_buffer(m_context);
3332 Program program(m_context);
3334 /* Compute Shader */
3335 const std::string& cs = getComputeShader();
3337 /* Buffers initialization */
3338 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(m_destination_data),
3339 m_destination_data);
3340 source_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(m_source_data), m_source_data);
3342 destination_buffer.BindBase(0);
3343 source_buffer.BindBase(1);
3345 /* Shaders initialization */
3346 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3349 /* Dispatch compute */
3350 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3351 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3353 /* Set memory barrier */
3354 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3355 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3357 /* Verify results */
3358 destination_buffer.Bind();
3359 GLfloat* buffer_data =
3360 (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(m_destination_data), GL_MAP_READ_BIT);
3361 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3363 test_result = verifyResults(buffer_data);
3365 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3366 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3369 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3373 if (true == test_result)
3375 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3379 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3383 return tcu::TestNode::STOP;
3386 /** Prepare shader for current test case
3390 std::string StorageBufferTest::getComputeShader()
3392 static const GLchar* cs = "#version 430 core\n"
3394 "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3396 "layout (binding = 1, std430) buffer Source {\n"
3400 "layout (binding = 0, std430) buffer Destination {\n"
3406 " const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3407 " const uint index_source = gl_LocalInvocationID.x + OFFSET;\n"
3409 " destination.data[index_destination] = source.data[index_source];\n"
3413 const GLchar* destination_offset;
3414 size_t position = 0;
3415 std::string source = cs;
3416 const GLchar* source_offset;
3418 switch (m_test_case)
3421 destination_offset = "0";
3422 source_offset = "0";
3424 case SOURCE_INVALID:
3425 destination_offset = "0";
3426 source_offset = "16";
3428 case DESTINATION_INVALID:
3429 destination_offset = "16";
3430 source_offset = "0";
3433 TCU_FAIL("Invalid enum");
3436 replaceToken("OFFSET", position, destination_offset, source);
3437 replaceToken("OFFSET", position, source_offset, source);
3442 /** Verify test case results
3444 * @param buffer_data Buffer data to verify
3446 * @return true if buffer_data is as expected, false othrewise
3448 bool StorageBufferTest::verifyResults(GLfloat* buffer_data)
3450 /* KHR_robust_buffer_access_behavior (and also GL 4.5 and later) states
3451 * which values can be expected when reading or writing outside of a
3452 * buffer's range. If supported, we will compare results against those
3455 * Otherwise, we will attempt to match results against previously observed
3456 * and valid behavior.
3458 static const GLfloat expected_data_valid[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3459 static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3460 static const GLfloat expected_data_invalid_destination[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3462 /* Prepare expected data const for proper case*/
3463 const GLchar* name = 0;
3464 bool check_expected_data = false;
3465 const GLfloat* expected_data = 0;
3466 switch (m_test_case)
3469 name = "valid indices";
3470 check_expected_data = true;
3471 expected_data = expected_data_valid;
3473 case SOURCE_INVALID:
3474 name = "invalid source indices";
3475 if (m_hasKhrRobustBufferAccess)
3477 for (int b = 0; b < 4; b++)
3479 /* Each out-of-range read can either be 0 or any value within
3480 * the source buffer.
3483 if (buffer_data[b] == 0.0f)
3489 for (int c = 0; c < 4 && !valid; c++)
3491 if (buffer_data[b] == m_source_data[c])
3499 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3500 << tcu::TestLog::EndMessage;
3506 check_expected_data = true;
3507 expected_data = expected_data_invalid_source;
3510 case DESTINATION_INVALID:
3511 name = "invalid destination indices";
3512 if (m_hasKhrRobustBufferAccess)
3514 for (int b = 0; b < 4; b++)
3517 /* Each out-of-range write can either be discarded (in which
3518 * case it would have the original destination value) or it
3519 * could write any value within the buffer (so we need to check
3520 * against each possible source value).
3522 if (buffer_data[b] == m_destination_data[b])
3528 for (int c = 0; c < 4 && !valid; c++)
3530 if (buffer_data[b] == m_source_data[c])
3538 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3539 << tcu::TestLog::EndMessage;
3545 check_expected_data = true;
3546 expected_data = expected_data_invalid_destination;
3550 TCU_FAIL("Invalid enum");
3553 if (check_expected_data)
3555 /* Verify buffer data */
3556 int size = static_cast<int>(sizeof(GLfloat) * 4);
3557 if (0 != memcmp(expected_data, buffer_data, size))
3559 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3560 << tcu::TestLog::EndMessage;
3570 * @param context Test context
3572 UniformBufferTest::UniformBufferTest(deqp::Context& context)
3573 : TestCase(context, "uniform_buffer", "Verifies that out-of-bound access to UBO resutls in 0"), m_test_case(VALID)
3575 /* Nothing to be done here */
3580 * @param context Test context
3582 UniformBufferTest::UniformBufferTest(deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
3583 : TestCase(context, name, description), m_test_case(VALID)
3585 /* Nothing to be done */
3590 * @return tcu::TestNode::STOP
3592 tcu::TestNode::IterateResult UniformBufferTest::iterate()
3594 static const GLfloat destination_data[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
3595 /* The source buffer is packed std140 so we need vec4s */
3596 static const GLfloat source_data[16] = {
3597 2.0f, 0.0f, 0.0f, 0.0f, 3.0f, 0.0f, 0.0f, 0.0f, 4.0f, 0.0f, 0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f,
3600 /* GL entry points */
3601 const Functions& gl = m_context.getRenderContext().getFunctions();
3603 /* Test result indicator */
3604 bool test_result = true;
3606 /* Iterate over all cases */
3607 while (LAST != m_test_case)
3609 /* Test case objects */
3610 Buffer destination_buffer(m_context);
3611 Buffer source_buffer(m_context);
3612 Program program(m_context);
3614 /* Compute Shader */
3615 const std::string& cs = getComputeShader();
3617 /* Buffers initialization */
3618 destination_buffer.InitData(GL_SHADER_STORAGE_BUFFER, GL_DYNAMIC_COPY, sizeof(destination_data),
3620 source_buffer.InitData(GL_UNIFORM_BUFFER, GL_DYNAMIC_COPY, sizeof(source_data), source_data);
3622 destination_buffer.BindBase(0);
3623 source_buffer.BindBase(0);
3625 /* Shaders initialization */
3626 program.Init(cs, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */);
3629 /* Dispatch compute */
3630 gl.dispatchCompute(1 /* x */, 1 /* y */, 1 /* z */);
3631 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
3633 /* Set memory barrier */
3634 gl.memoryBarrier(GL_ALL_BARRIER_BITS);
3635 GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier");
3637 /* Verify results */
3638 destination_buffer.Bind();
3639 GLfloat* buffer_data =
3640 (GLfloat*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(destination_data), GL_MAP_READ_BIT);
3641 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange");
3643 test_result = verifyResults(buffer_data);
3645 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
3646 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3649 m_test_case = (VERSION)((GLuint)m_test_case + 1);
3653 if (true == test_result)
3655 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3659 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3663 return tcu::TestNode::STOP;
3666 /** Prepare shader for current test case
3670 std::string UniformBufferTest::getComputeShader()
3672 static const GLchar* cs = "#version 430 core\n"
3674 "layout (local_size_x = 4, local_size_y = 1, local_size_z = 1) in;\n"
3676 "layout (binding = 0, std140) uniform Source {\n"
3677 " float data[16];\n"
3680 "layout (binding = 0, std430) buffer Destination {\n"
3686 " const uint index_destination = gl_LocalInvocationID.x + OFFSET;\n"
3687 " const uint index_source = gl_LocalInvocationID.x + OFFSET;\n"
3689 " destination.data[index_destination] = source.data[index_source];\n"
3693 const GLchar* destination_offset;
3694 size_t position = 0;
3695 std::string source = cs;
3696 const GLchar* source_offset;
3698 switch (m_test_case)
3701 destination_offset = "0";
3702 source_offset = "0";
3704 case SOURCE_INVALID:
3705 destination_offset = "0";
3706 source_offset = "16";
3709 TCU_FAIL("Invalid enum");
3712 replaceToken("OFFSET", position, destination_offset, source);
3713 replaceToken("OFFSET", position, source_offset, source);
3718 /** Verify test case results
3720 * @param buffer_data Buffer data to verify
3722 * @return true if buffer_data is as expected, false othrewise
3724 bool UniformBufferTest::verifyResults(GLfloat* buffer_data)
3726 static const GLfloat expected_data_valid[4] = { 2.0f, 3.0f, 4.0f, 5.0f };
3727 static const GLfloat expected_data_invalid_source[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3729 int size = static_cast<int>(sizeof(GLfloat) * 4);
3731 /* Prepare expected data const for proper case*/
3732 const GLfloat* expected_data = 0;
3733 const GLchar* name = 0;
3734 switch (m_test_case)
3737 expected_data = expected_data_valid;
3738 name = "valid indices";
3740 case SOURCE_INVALID:
3741 expected_data = expected_data_invalid_source;
3742 name = "invalid source indices";
3745 TCU_FAIL("Invalid enum");
3748 /* Verify buffer data */
3749 if (0 != memcmp(expected_data, buffer_data, size))
3751 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << name << " failed"
3752 << tcu::TestLog::EndMessage;
3758 } /* RobustBufferAccessBehavior */
3762 * @param context Rendering context.
3764 RobustBufferAccessBehaviorTests::RobustBufferAccessBehaviorTests(deqp::Context& context)
3765 : TestCaseGroup(context, "robust_buffer_access_behavior",
3766 "Verifies \"robust buffer access behavior\" functionality")
3768 /* Left blank on purpose */
3771 /** Initializes a multi_bind test group.
3774 void RobustBufferAccessBehaviorTests::init(void)
3776 addChild(new RobustBufferAccessBehavior::VertexBufferObjectsTest(m_context));
3777 addChild(new RobustBufferAccessBehavior::TexelFetchTest(m_context));
3778 addChild(new RobustBufferAccessBehavior::ImageLoadStoreTest(m_context));
3779 addChild(new RobustBufferAccessBehavior::StorageBufferTest(m_context));
3780 addChild(new RobustBufferAccessBehavior::UniformBufferTest(m_context));