1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-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 */ /*-------------------------------------------------------------------*/
25 * \file gl4cShaderSubroutineTests.cpp
26 * \brief Implements conformance tests for "Shader Subroutine" functionality.
27 */ /*-------------------------------------------------------------------*/
29 #include "gl4cShaderSubroutineTests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwEnums.hpp"
32 #include "glwFunctions.hpp"
33 #include "tcuMatrix.hpp"
42 namespace ShaderSubroutine
46 * @param context CTS context.
48 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context)
55 Utils::buffer::~buffer()
59 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
61 gl.deleteBuffers(1, &m_id);
66 /** Execute BindBufferRange
68 * @param target <target> parameter
69 * @param index <index> parameter
70 * @param offset <offset> parameter
71 * @param size <size> parameter
73 void Utils::buffer::bindRange(glw::GLenum target, glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size)
75 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
77 gl.bindBufferRange(target, index, m_id, offset, size);
78 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
84 void Utils::buffer::generate()
86 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
88 gl.genBuffers(1, &m_id);
89 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
92 /** Execute BufferData
94 * @param target <target> parameter
95 * @param size <size> parameter
96 * @param data <data> parameter
97 * @param usage <usage> parameter
99 void Utils::buffer::update(glw::GLenum target, glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage)
101 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
103 gl.bindBuffer(target, m_id);
104 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
106 gl.bufferData(target, size, data, usage);
107 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
112 * @param context CTS context
114 Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context)
116 /* Nothing to be done here */
122 Utils::framebuffer::~framebuffer()
126 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
128 gl.deleteFramebuffers(1, &m_id);
133 /** Attach texture to specified attachment
135 * @param attachment Attachment
136 * @param texture_id Texture id
137 * @param width Texture width
138 * @param height Texture height
140 void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width,
143 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
147 gl.bindTexture(GL_TEXTURE_2D, texture_id);
148 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
150 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture_id, 0 /* level */);
152 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
154 gl.viewport(0 /* x */, 0 /* y */, width, height);
155 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
158 /** Binds framebuffer to DRAW_FRAMEBUFFER
161 void Utils::framebuffer::bind()
163 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
165 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id);
166 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
169 /** Clear framebuffer
171 * @param mask <mask> parameter of glClear. Decides which shall be cleared
173 void Utils::framebuffer::clear(glw::GLenum mask)
175 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
178 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
181 /** Specifie clear color
183 * @param red Red channel
184 * @param green Green channel
185 * @param blue Blue channel
186 * @param alpha Alpha channel
188 void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
190 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
192 gl.clearColor(red, green, blue, alpha);
193 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
196 /** Generate framebuffer
199 void Utils::framebuffer::generate()
201 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
203 gl.genFramebuffers(1, &m_id);
204 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
207 const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9;
211 * @param context CTS context.
213 Utils::program::program(deqp::Context& context)
214 : m_compute_shader_id(0)
215 , m_fragment_shader_id(0)
216 , m_geometry_shader_id(0)
217 , m_program_object_id(0)
218 , m_tesselation_control_shader_id(0)
219 , m_tesselation_evaluation_shader_id(0)
220 , m_vertex_shader_id(0)
223 /* Nothing to be done here */
229 Utils::program::~program()
236 * @param compute_shader_code Compute shader source code
237 * @param fragment_shader_code Fragment shader source code
238 * @param geometry_shader_code Geometry shader source code
239 * @param tesselation_control_shader_code Tesselation control shader source code
240 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
241 * @param vertex_shader_code Vertex shader source code
242 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback
243 * @param n_varying_names Number of varyings to be captured with transfrom feedback
244 * @param is_separable Selects if monolithis or separable program should be built. Defaults to false
246 void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
247 const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
248 const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
249 const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable)
251 /* GL entry points */
252 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
254 /* Create shader objects and compile */
255 if (0 != compute_shader_code)
257 m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
258 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
260 compile(m_compute_shader_id, compute_shader_code);
263 if (0 != fragment_shader_code)
265 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
266 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
268 compile(m_fragment_shader_id, fragment_shader_code);
271 if (0 != geometry_shader_code)
273 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
274 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
276 compile(m_geometry_shader_id, geometry_shader_code);
279 if (0 != tesselation_control_shader_code)
281 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
282 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
284 compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
287 if (0 != tesselation_evaluation_shader_code)
289 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
290 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
292 compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
295 if (0 != vertex_shader_code)
297 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
298 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
300 compile(m_vertex_shader_id, vertex_shader_code);
303 /* Create program object */
304 m_program_object_id = gl.createProgram();
305 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
307 /* Set up captyured varyings' names */
308 if (0 != n_varying_names)
310 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
311 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
314 /* Set separable parameter */
315 if (true == is_separable)
317 gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
318 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
327 * @param shader_id Shader object id
328 * @param shader_code Shader source code
330 void Utils::program::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
332 /* GL entry points */
333 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
335 /* Compilation status */
336 glw::GLint status = GL_FALSE;
338 /* Set source code */
339 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
340 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
343 gl.compileShader(shader_id);
344 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
346 /* Get compilation status */
347 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
348 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
350 /* Log compilation error */
351 if (GL_TRUE != status)
353 glw::GLint length = 0;
354 std::vector<glw::GLchar> message;
356 /* Error log length */
357 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
358 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
360 /* Prepare storage */
361 message.resize(length);
364 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
365 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
368 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
369 << &message[0] << "\nShader source\n"
370 << shader_code << tcu::TestLog::EndMessage;
372 TCU_FAIL("Failed to compile shader");
376 /** Checks whether the tested driver supports GL_ARB_get_program_binary
378 * @return true if the extension is supported and, also, at least one binary format.
380 bool Utils::program::isProgramBinarySupported() const
382 glw::GLint n_program_binary_formats = 0;
384 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
386 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_get_program_binary"))
388 gl.getIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &n_program_binary_formats);
389 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
392 return n_program_binary_formats > 0;
395 /** Create program from provided binary
397 * @param binary Buffer with binary form of program
398 * @param binary_format Format of <binary> data
400 void Utils::program::createFromBinary(const std::vector<GLubyte>& binary, GLenum binary_format)
402 /* GL entry points */
403 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
405 /* Create program object */
406 m_program_object_id = gl.createProgram();
407 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
409 gl.programBinary(m_program_object_id, binary_format, &binary[0], (GLsizei)binary.size());
410 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramBinary");
413 /** Get binary form of program
415 * @param binary Buffer for binary data
416 * @param binary_format Format of binary data
418 void Utils::program::getBinary(std::vector<GLubyte>& binary, GLenum& binary_format) const
420 /* GL entry points */
421 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
423 /* Get binary size */
425 gl.getProgramiv(m_program_object_id, GL_PROGRAM_BINARY_LENGTH, &length);
426 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
428 /* Allocate storage */
429 binary.resize(length);
432 gl.getProgramBinary(m_program_object_id, (GLsizei)binary.size(), &length, &binary_format, &binary[0]);
433 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramBinary");
436 /** Get subroutine index
438 * @param subroutine_name Subroutine name
440 * @return Index of subroutine
442 GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const
444 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
447 index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name);
448 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
450 if (GL_INVALID_INDEX == index)
452 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name
453 << " is not available" << tcu::TestLog::EndMessage;
455 TCU_FAIL("Subroutine is not available");
461 /** Get subroutine uniform location
463 * @param uniform_name Subroutine uniform name
465 * @return Location of subroutine uniform
467 GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const
469 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
472 location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name);
473 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
477 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name
478 << " is not available" << tcu::TestLog::EndMessage;
480 TCU_FAIL("Subroutine uniform is not available");
486 /** Get uniform location
488 * @param uniform_name Subroutine uniform name
490 * @return Location of uniform
492 GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const
494 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
497 location = gl.getUniformLocation(m_program_object_id, uniform_name);
498 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
502 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name
503 << " is not available" << tcu::TestLog::EndMessage;
505 TCU_FAIL("Uniform is not available");
511 /** Attach shaders and link program
514 void Utils::program::link() const
516 /* GL entry points */
517 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
520 glw::GLint status = GL_FALSE;
523 if (0 != m_compute_shader_id)
525 gl.attachShader(m_program_object_id, m_compute_shader_id);
526 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
529 if (0 != m_fragment_shader_id)
531 gl.attachShader(m_program_object_id, m_fragment_shader_id);
532 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
535 if (0 != m_geometry_shader_id)
537 gl.attachShader(m_program_object_id, m_geometry_shader_id);
538 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
541 if (0 != m_tesselation_control_shader_id)
543 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
544 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
547 if (0 != m_tesselation_evaluation_shader_id)
549 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
550 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
553 if (0 != m_vertex_shader_id)
555 gl.attachShader(m_program_object_id, m_vertex_shader_id);
556 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
560 gl.linkProgram(m_program_object_id);
561 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
563 /* Get link status */
564 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
565 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
568 if (GL_TRUE != status)
570 glw::GLint length = 0;
571 std::vector<glw::GLchar> message;
573 /* Get error log length */
574 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
575 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
577 message.resize(length);
580 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
581 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
584 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
585 << &message[0] << tcu::TestLog::EndMessage;
587 TCU_FAIL("Failed to link program");
591 /** Delete program object and all attached shaders
594 void Utils::program::remove()
596 /* GL entry points */
597 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
599 /* Make sure program object is no longer used by GL */
602 /* Clean program object */
603 if (0 != m_program_object_id)
605 gl.deleteProgram(m_program_object_id);
606 m_program_object_id = 0;
610 if (0 != m_compute_shader_id)
612 gl.deleteShader(m_compute_shader_id);
613 m_compute_shader_id = 0;
616 if (0 != m_fragment_shader_id)
618 gl.deleteShader(m_fragment_shader_id);
619 m_fragment_shader_id = 0;
622 if (0 != m_geometry_shader_id)
624 gl.deleteShader(m_geometry_shader_id);
625 m_geometry_shader_id = 0;
628 if (0 != m_tesselation_control_shader_id)
630 gl.deleteShader(m_tesselation_control_shader_id);
631 m_tesselation_control_shader_id = 0;
634 if (0 != m_tesselation_evaluation_shader_id)
636 gl.deleteShader(m_tesselation_evaluation_shader_id);
637 m_tesselation_evaluation_shader_id = 0;
640 if (0 != m_vertex_shader_id)
642 gl.deleteShader(m_vertex_shader_id);
643 m_vertex_shader_id = 0;
647 /** Execute UseProgram
650 void Utils::program::use() const
652 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
654 gl.useProgram(m_program_object_id);
655 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
660 * @param context CTS context.
662 Utils::texture::texture(deqp::Context& context) : m_id(0), m_context(context)
664 /* Nothing to done here */
670 Utils::texture::~texture()
674 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
676 gl.deleteTextures(1, &m_id);
681 /** Bind texture to GL_TEXTURE_2D
684 void Utils::texture::bind()
686 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
688 gl.bindTexture(GL_TEXTURE_2D, m_id);
689 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
692 /** Create 2d texture
694 * @param width Width of texture
695 * @param height Height of texture
696 * @param internal_format Internal format of texture
698 void Utils::texture::create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format)
700 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
702 gl.genTextures(1, &m_id);
703 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
707 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height);
708 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
711 /** Get contents of texture
713 * @param format Format of image
714 * @param type Type of image
715 * @param out_data Buffer for image
717 void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data)
719 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
723 gl.getTexImage(GL_TEXTURE_2D, 0, format, type, out_data);
724 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
727 /** Update contents of texture
729 * @param width Width of texture
730 * @param height Height of texture
731 * @param format Format of data
732 * @param type Type of data
733 * @param data Buffer with image
735 void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLenum format, glw::GLenum type,
738 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
742 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, width, height, format, type, data);
743 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
748 * @param context CTS context.
750 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
757 Utils::vertexArray::~vertexArray()
761 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
763 gl.deleteVertexArrays(1, &m_id);
769 /** Execute BindVertexArray
772 void Utils::vertexArray::bind()
774 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
776 gl.bindVertexArray(m_id);
777 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
780 /** Execute GenVertexArrays
783 void Utils::vertexArray::generate()
785 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
787 gl.genVertexArrays(1, &m_id);
788 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
791 /** Builds a program object consisting of up to 5 shader stages
792 * (vertex/tessellation control/tessellation evaluation/geometry/fragment).
793 * The shaders are attached to the program object, then compiled. Finally,
794 * the program object is linked.
796 * XFB can be optionally configured for the program object.
798 * Should an error be reported by GL implementation, a TestError
799 * exception will be thrown.
801 * @param gl OpenGL functions from the active rendering context.
802 * @param vs_body Body to use for the vertex shader. Can be an empty string.
803 * @param tc_body Body to use for the tessellation control shader. Can be
805 * @param te_body Body to use for the tessellation evaluation shader. Can be
807 * @param gs_body Body to use for the geometry shader. Can be an empty string.
808 * @param fs_body Body to use for the fragment shader. Can be an empty string.
809 * @param xfb_varyings An array of names of varyings to use for XFB. Can be NULL.
810 * @param n_xfb_varyings Amount of XFB varyings defined in @param xfb_varyings.Can be 0.
811 * @param out_vs_id Deref will be used to store GL id of a generated vertex shader.
812 * Can be NULL in which case no vertex shader will be used for the
814 * @param out_tc_id Deref will be used to store GL id of a generated tess control shader.
815 * Can be NULL in which case no tess control shader will be used for the
817 * @param out_te_id Deref will be used to store GL id of a generated tess evaluation shader.
818 * Can be NULL in which case no tess evaluation shader will be used for the
820 * @param out_gs_id Deref will be used to store GL id of a generated geometry shader.
821 * Can be NULL in which case no geometry shader will be used for the
823 * @param out_fs_id Deref will be used to store GL id of a generated fragment shader.
824 * Can be NULL in which case no fragment shader will be used for the
826 * @param out_po_id Deref will be used to store GL id of a generated program object.
829 * @return true if the program was built successfully, false otherwise.
831 bool Utils::buildProgram(const glw::Functions& gl, const std::string& vs_body, const std::string& tc_body,
832 const std::string& te_body, const std::string& gs_body, const std::string& fs_body,
833 const glw::GLchar** xfb_varyings, const unsigned int& n_xfb_varyings, glw::GLuint* out_vs_id,
834 glw::GLuint* out_tc_id, glw::GLuint* out_te_id, glw::GLuint* out_gs_id, glw::GLuint* out_fs_id,
835 glw::GLuint* out_po_id)
839 /* Link the program object */
840 glw::GLint link_status = GL_FALSE;
842 /* Create objects, set up shader bodies and attach all requested shaders to the program object */
843 *out_po_id = gl.createProgram();
844 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
846 if (out_vs_id != DE_NULL)
848 const char* vs_body_raw_ptr = vs_body.c_str();
850 *out_vs_id = gl.createShader(GL_VERTEX_SHADER);
851 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
853 gl.attachShader(*out_po_id, *out_vs_id);
854 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
856 gl.shaderSource(*out_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
857 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
860 if (out_tc_id != DE_NULL)
862 const char* tc_body_raw_ptr = tc_body.c_str();
864 *out_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
865 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
867 gl.attachShader(*out_po_id, *out_tc_id);
868 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
870 gl.shaderSource(*out_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
871 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
874 if (out_te_id != DE_NULL)
876 const char* te_body_raw_ptr = te_body.c_str();
878 *out_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
879 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
881 gl.attachShader(*out_po_id, *out_te_id);
882 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
884 gl.shaderSource(*out_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
885 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
888 if (out_gs_id != DE_NULL)
890 const char* gs_body_raw_ptr = gs_body.c_str();
892 *out_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
893 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
895 gl.attachShader(*out_po_id, *out_gs_id);
896 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
898 gl.shaderSource(*out_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
899 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
902 if (out_fs_id != DE_NULL)
904 const char* fs_body_raw_ptr = fs_body.c_str();
906 *out_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
907 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
909 gl.attachShader(*out_po_id, *out_fs_id);
910 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
912 gl.shaderSource(*out_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
913 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
916 /* Compile all shaders */
917 const glw::GLuint so_ids[] = { (out_vs_id != DE_NULL) ? *out_vs_id : 0, (out_tc_id != DE_NULL) ? *out_tc_id : 0,
918 (out_te_id != DE_NULL) ? *out_te_id : 0, (out_gs_id != DE_NULL) ? *out_gs_id : 0,
919 (out_fs_id != DE_NULL) ? *out_fs_id : 0 };
920 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
922 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
924 glw::GLuint so_id = so_ids[n_so_id];
928 glw::GLint compile_status = GL_FALSE;
930 gl.compileShader(so_id);
931 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
933 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
934 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
936 if (compile_status != GL_TRUE)
940 } /* if (so_id != 0) */
941 } /* for (all shader objects) */
944 if (xfb_varyings != NULL)
946 gl.transformFeedbackVaryings(*out_po_id, n_xfb_varyings, xfb_varyings, GL_INTERLEAVED_ATTRIBS);
947 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
950 gl.linkProgram(*out_po_id);
951 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
953 gl.getProgramiv(*out_po_id, GL_LINK_STATUS, &link_status);
954 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
956 if (link_status != GL_TRUE)
968 /** Retrieves base variable type for user-specified variable type
969 * (eg. float for vec4)
971 * @param variable_type Variable type to use for the query.
973 * @return As per description.
975 Utils::_variable_type Utils::getBaseVariableType(const _variable_type& variable_type)
977 _variable_type result = VARIABLE_TYPE_UNKNOWN;
979 switch (variable_type)
981 case VARIABLE_TYPE_BOOL:
982 case VARIABLE_TYPE_BVEC2:
983 case VARIABLE_TYPE_BVEC3:
984 case VARIABLE_TYPE_BVEC4:
986 result = VARIABLE_TYPE_BOOL;
991 case VARIABLE_TYPE_DOUBLE:
992 case VARIABLE_TYPE_DVEC2:
993 case VARIABLE_TYPE_DVEC3:
994 case VARIABLE_TYPE_DVEC4:
996 result = VARIABLE_TYPE_DOUBLE;
1001 case VARIABLE_TYPE_FLOAT:
1002 case VARIABLE_TYPE_MAT2:
1003 case VARIABLE_TYPE_MAT2X3:
1004 case VARIABLE_TYPE_MAT2X4:
1005 case VARIABLE_TYPE_MAT3:
1006 case VARIABLE_TYPE_MAT3X2:
1007 case VARIABLE_TYPE_MAT3X4:
1008 case VARIABLE_TYPE_MAT4:
1009 case VARIABLE_TYPE_MAT4X2:
1010 case VARIABLE_TYPE_MAT4X3:
1011 case VARIABLE_TYPE_VEC2:
1012 case VARIABLE_TYPE_VEC3:
1013 case VARIABLE_TYPE_VEC4:
1015 result = VARIABLE_TYPE_FLOAT;
1020 case VARIABLE_TYPE_INT:
1021 case VARIABLE_TYPE_IVEC2:
1022 case VARIABLE_TYPE_IVEC3:
1023 case VARIABLE_TYPE_IVEC4:
1025 result = VARIABLE_TYPE_INT;
1030 case VARIABLE_TYPE_UINT:
1031 case VARIABLE_TYPE_UVEC2:
1032 case VARIABLE_TYPE_UVEC3:
1033 case VARIABLE_TYPE_UVEC4:
1035 result = VARIABLE_TYPE_UINT;
1042 TCU_FAIL("Unrecognized variable type");
1044 } /* switch (variable_type) */
1049 /** Retrieves size of a single component (in bytes) for user-specified
1052 * @param variable_type Variable type to use for the query.
1054 * @return As per description.
1056 unsigned int Utils::getComponentSizeForVariableType(const _variable_type& variable_type)
1058 _variable_type base_variable_type = getBaseVariableType(variable_type);
1059 unsigned int result = 0;
1061 switch (base_variable_type)
1063 case VARIABLE_TYPE_BOOL:
1064 result = sizeof(bool);
1066 case VARIABLE_TYPE_DOUBLE:
1067 result = sizeof(double);
1069 case VARIABLE_TYPE_FLOAT:
1070 result = sizeof(float);
1072 case VARIABLE_TYPE_INT:
1073 result = sizeof(int);
1075 case VARIABLE_TYPE_UINT:
1076 result = sizeof(unsigned int);
1081 TCU_FAIL("Unrecognized base variable type");
1083 } /* switch (variable_type) */
1088 /** Retrieves a GLenum value corresponding to internal shader stage
1091 * @param shader_stage Shader stage to user for the query.
1093 * @return Requested value or GL_NONE if the stage was not recognized.
1095 glw::GLenum Utils::getGLenumForShaderStage(const _shader_stage& shader_stage)
1097 glw::GLenum result = GL_NONE;
1099 switch (shader_stage)
1101 case SHADER_STAGE_VERTEX:
1102 result = GL_VERTEX_SHADER;
1104 case SHADER_STAGE_TESSELLATION_CONTROL:
1105 result = GL_TESS_CONTROL_SHADER;
1107 case SHADER_STAGE_TESSELLATION_EVALUATION:
1108 result = GL_TESS_EVALUATION_SHADER;
1110 case SHADER_STAGE_GEOMETRY:
1111 result = GL_GEOMETRY_SHADER;
1113 case SHADER_STAGE_FRAGMENT:
1114 result = GL_FRAGMENT_SHADER;
1119 TCU_FAIL("Unrecognized shader stage requested");
1121 } /* switch (shader_stage) */
1126 /** Retrieves number of components that user-specified variable type supports.
1128 * @param variable_type GLSL variable type to use for the query.
1130 * @return As per description.
1132 unsigned int Utils::getNumberOfComponentsForVariableType(const _variable_type& variable_type)
1134 unsigned int result = 0;
1136 switch (variable_type)
1138 case VARIABLE_TYPE_BOOL:
1139 case VARIABLE_TYPE_DOUBLE:
1140 case VARIABLE_TYPE_FLOAT:
1141 case VARIABLE_TYPE_INT:
1142 case VARIABLE_TYPE_UINT:
1149 case VARIABLE_TYPE_BVEC2:
1150 case VARIABLE_TYPE_DVEC2:
1151 case VARIABLE_TYPE_IVEC2:
1152 case VARIABLE_TYPE_UVEC2:
1153 case VARIABLE_TYPE_VEC2:
1160 case VARIABLE_TYPE_BVEC3:
1161 case VARIABLE_TYPE_DVEC3:
1162 case VARIABLE_TYPE_IVEC3:
1163 case VARIABLE_TYPE_UVEC3:
1164 case VARIABLE_TYPE_VEC3:
1171 case VARIABLE_TYPE_BVEC4:
1172 case VARIABLE_TYPE_DVEC4:
1173 case VARIABLE_TYPE_IVEC4:
1174 case VARIABLE_TYPE_MAT2:
1175 case VARIABLE_TYPE_UVEC4:
1176 case VARIABLE_TYPE_VEC4:
1183 case VARIABLE_TYPE_MAT2X3:
1184 case VARIABLE_TYPE_MAT3X2:
1191 case VARIABLE_TYPE_MAT2X4:
1192 case VARIABLE_TYPE_MAT4X2:
1199 case VARIABLE_TYPE_MAT3:
1206 case VARIABLE_TYPE_MAT3X4:
1207 case VARIABLE_TYPE_MAT4X3:
1214 case VARIABLE_TYPE_MAT4:
1223 } /* switch (variable_type) */
1228 /** Retrieves a literal defining user-specified shader stage enum.
1230 * @param shader_stage Shader stage to use for the query.
1232 * @return Requested string or "?" if the stage was not recognized.
1234 std::string Utils::getShaderStageString(const _shader_stage& shader_stage)
1236 std::string result = "?";
1238 switch (shader_stage)
1240 case SHADER_STAGE_FRAGMENT:
1241 result = "Fragment Shader";
1243 case SHADER_STAGE_GEOMETRY:
1244 result = "Geometry Shader";
1246 case SHADER_STAGE_TESSELLATION_CONTROL:
1247 result = "Tessellation Control Shader";
1249 case SHADER_STAGE_TESSELLATION_EVALUATION:
1250 result = "Tessellation Evaluation Shader";
1252 case SHADER_STAGE_VERTEX:
1253 result = "Vertex Shader";
1258 TCU_FAIL("Unrecognized shader stage");
1260 } /* switch (shader_stage) */
1265 /** Retrieves a literal defining user-specified shader stage enum.
1267 * @param shader_stage_glenum Shader stage to use for the query.
1269 * @return Requested string or "?" if the stage was not recognized.
1271 std::string Utils::getShaderStageStringFromGLEnum(const glw::GLenum shader_stage_glenum)
1273 std::string result = "?";
1275 switch (shader_stage_glenum)
1277 case GL_FRAGMENT_SHADER:
1278 result = "Fragment Shader";
1280 case GL_GEOMETRY_SHADER:
1281 result = "Geometry Shader";
1283 case GL_TESS_CONTROL_SHADER:
1284 result = "Tessellation Control Shader";
1286 case GL_TESS_EVALUATION_SHADER:
1287 result = "Tessellation Evaluation Shader";
1289 case GL_VERTEX_SHADER:
1290 result = "Vertex Shader";
1295 TCU_FAIL("Unrecognized shader string");
1297 } /* switch (shader_stage_glenum) */
1302 /** Returns string that represents program interface name
1304 * @param program_interface Program interface
1306 * @return String representation of known program interface
1308 const GLchar* Utils::programInterfaceToStr(glw::GLenum program_interface)
1310 const GLchar* string = "Unknown program interface";
1312 switch (program_interface)
1314 case GL_VERTEX_SUBROUTINE:
1315 string = "GL_VERTEX_SUBROUTINE";
1317 case GL_VERTEX_SUBROUTINE_UNIFORM:
1318 string = "GL_VERTEX_SUBROUTINE_UNIFORM";
1321 TCU_FAIL("Not implemented");
1328 /** Returns string that represents pname's name
1330 * @param pname pname
1332 * @return String representation of known pnames
1334 const GLchar* Utils::pnameToStr(glw::GLenum pname)
1336 const GLchar* string = "Unknown pname";
1340 case GL_ACTIVE_SUBROUTINE_UNIFORMS:
1341 string = "GL_ACTIVE_SUBROUTINE_UNIFORMS";
1343 case GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS:
1344 string = "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS";
1346 case GL_ACTIVE_SUBROUTINES:
1347 string = "GL_ACTIVE_SUBROUTINES";
1349 case GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH:
1350 string = "GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH";
1352 case GL_ACTIVE_SUBROUTINE_MAX_LENGTH:
1353 string = "GL_ACTIVE_SUBROUTINE_MAX_LENGTH";
1355 case GL_NUM_COMPATIBLE_SUBROUTINES:
1356 string = "GL_NUM_COMPATIBLE_SUBROUTINES";
1358 case GL_UNIFORM_SIZE:
1359 string = "GL_UNIFORM_SIZE";
1361 case GL_COMPATIBLE_SUBROUTINES:
1362 string = "GL_COMPATIBLE_SUBROUTINES";
1364 case GL_UNIFORM_NAME_LENGTH:
1365 string = "GL_UNIFORM_NAME_LENGTH";
1367 case GL_ACTIVE_RESOURCES:
1368 string = "GL_ACTIVE_RESOURCES";
1370 case GL_MAX_NAME_LENGTH:
1371 string = "GL_MAX_NAME_LENGTH";
1373 case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
1374 string = "GL_MAX_NUM_COMPATIBLE_SUBROUTINES";
1376 case GL_NAME_LENGTH:
1377 string = "GL_NAME_LENGTH";
1380 string = "GL_ARRAY_SIZE";
1383 string = "GL_LOCATION";
1386 TCU_FAIL("Not implemented");
1393 bool Utils::compare(const glw::GLfloat& left, const glw::GLfloat& right)
1395 static const glw::GLfloat m_epsilon = 0.00001f;
1397 if (m_epsilon < std::abs(right - left))
1407 /** Returns a variable type enum corresponding to user-specified base variable type
1408 * and the number of components it should support.
1410 * @param base_variable_type Base variable type to use for the query.
1411 * @param n_components Number of components to consider for the query.
1413 * @return As per description.
1415 Utils::_variable_type Utils::getVariableTypeFromProperties(const _variable_type& base_variable_type,
1416 const unsigned int& n_components)
1418 _variable_type result = VARIABLE_TYPE_UNKNOWN;
1420 switch (base_variable_type)
1422 case VARIABLE_TYPE_BOOL:
1424 switch (n_components)
1427 result = VARIABLE_TYPE_BOOL;
1430 result = VARIABLE_TYPE_BVEC2;
1433 result = VARIABLE_TYPE_BVEC3;
1436 result = VARIABLE_TYPE_BVEC4;
1441 TCU_FAIL("Unsupported number of components requested");
1443 } /* switch (n_components) */
1448 case VARIABLE_TYPE_DOUBLE:
1450 switch (n_components)
1453 result = VARIABLE_TYPE_DOUBLE;
1456 result = VARIABLE_TYPE_DVEC2;
1459 result = VARIABLE_TYPE_DVEC3;
1462 result = VARIABLE_TYPE_DVEC4;
1467 TCU_FAIL("Unsupported number of components requested");
1469 } /* switch (n_components) */
1474 case VARIABLE_TYPE_FLOAT:
1476 switch (n_components)
1479 result = VARIABLE_TYPE_FLOAT;
1482 result = VARIABLE_TYPE_VEC2;
1485 result = VARIABLE_TYPE_VEC3;
1488 result = VARIABLE_TYPE_VEC4;
1493 TCU_FAIL("Unsupported number of components requested");
1495 } /* switch (n_components) */
1500 case VARIABLE_TYPE_INT:
1502 switch (n_components)
1505 result = VARIABLE_TYPE_INT;
1508 result = VARIABLE_TYPE_IVEC2;
1511 result = VARIABLE_TYPE_IVEC3;
1514 result = VARIABLE_TYPE_IVEC4;
1519 TCU_FAIL("Unsupported number of components requested");
1521 } /* switch (n_components) */
1526 case VARIABLE_TYPE_UINT:
1528 switch (n_components)
1531 result = VARIABLE_TYPE_UINT;
1534 result = VARIABLE_TYPE_UVEC2;
1537 result = VARIABLE_TYPE_UVEC3;
1540 result = VARIABLE_TYPE_UVEC4;
1545 TCU_FAIL("Unsupported number of components requested");
1547 } /* switch (n_components) */
1554 TCU_FAIL("Unrecognized base variable type");
1556 } /* switch (base_variable_type) */
1561 /** Returns a GLSL literal corresponding to user-specified variable type.
1563 * @param variable_type Variable type to use for the query.
1565 * @return As per description or [?] if @param variable_type was not
1568 std::string Utils::getVariableTypeGLSLString(const _variable_type& variable_type)
1570 std::string result = "[?]";
1572 switch (variable_type)
1574 case VARIABLE_TYPE_BOOL:
1577 case VARIABLE_TYPE_BVEC2:
1580 case VARIABLE_TYPE_BVEC3:
1583 case VARIABLE_TYPE_BVEC4:
1586 case VARIABLE_TYPE_DOUBLE:
1589 case VARIABLE_TYPE_DVEC2:
1592 case VARIABLE_TYPE_DVEC3:
1595 case VARIABLE_TYPE_DVEC4:
1598 case VARIABLE_TYPE_FLOAT:
1601 case VARIABLE_TYPE_INT:
1604 case VARIABLE_TYPE_IVEC2:
1607 case VARIABLE_TYPE_IVEC3:
1610 case VARIABLE_TYPE_IVEC4:
1613 case VARIABLE_TYPE_MAT2:
1616 case VARIABLE_TYPE_MAT2X3:
1619 case VARIABLE_TYPE_MAT2X4:
1622 case VARIABLE_TYPE_MAT3:
1625 case VARIABLE_TYPE_MAT3X2:
1628 case VARIABLE_TYPE_MAT3X4:
1631 case VARIABLE_TYPE_MAT4:
1634 case VARIABLE_TYPE_MAT4X2:
1637 case VARIABLE_TYPE_MAT4X3:
1640 case VARIABLE_TYPE_UINT:
1643 case VARIABLE_TYPE_UVEC2:
1646 case VARIABLE_TYPE_UVEC3:
1649 case VARIABLE_TYPE_UVEC4:
1652 case VARIABLE_TYPE_VEC2:
1655 case VARIABLE_TYPE_VEC3:
1658 case VARIABLE_TYPE_VEC4:
1664 TCU_FAIL("Unrecognized variable type");
1666 } /* switch (variable_type) */
1673 * @param context Rendering context.
1676 APITest1::APITest1(deqp::Context& context)
1677 : TestCase(context, "min_maxes", "Verifies the implementation returns valid GL_MAX_SUBROUTINE* pnames "
1678 "which meet the minimum maximum requirements enforced by the spec.")
1679 , m_has_test_passed(true)
1681 /* Left blank intentionally */
1684 /** Executes test iteration.
1686 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1688 tcu::TestNode::IterateResult APITest1::iterate()
1690 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1692 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1693 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1695 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1698 /* Iterate over all pnames */
1702 const char* pname_string;
1703 glw::GLint min_value;
1704 } pnames[] = { { GL_MAX_SUBROUTINES, "GL_MAX_SUBROUTINES", 256 },
1705 { GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS, "GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS", 1024 } };
1706 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
1708 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
1710 glw::GLboolean bool_value = GL_FALSE;
1711 glw::GLdouble double_value = 0.0;
1712 glw::GLfloat float_value = 0.0f;
1713 glw::GLint int_value = 0;
1714 glw::GLint64 int64_value = 0;
1715 const glw::GLint min_value = pnames[n_pname].min_value;
1716 const glw::GLenum& pname = pnames[n_pname].pname;
1717 const char* pname_string = pnames[n_pname].pname_string;
1719 /* Retrieve the pname values */
1720 gl.getBooleanv(pname, &bool_value);
1721 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() call failed.");
1723 gl.getDoublev(pname, &double_value);
1724 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetDoublev() call failed.");
1726 gl.getFloatv(pname, &float_value);
1727 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed.");
1729 gl.getIntegerv(pname, &int_value);
1730 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1732 gl.getInteger64v(pname, &int64_value);
1733 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v() call failed.");
1735 /* Make sure the value reported meets the min max requirement */
1736 if (int_value < min_value)
1738 m_testCtx.getLog() << tcu::TestLog::Message << "GL implementation reports a value of [" << int_value
1741 << pname_string << "]"
1742 ", whereas the min max for the property is ["
1743 << min_value << "]." << tcu::TestLog::EndMessage;
1745 m_has_test_passed = false;
1748 /* Verify the other getters reported valid values */
1749 const float epsilon = 1e-5f;
1751 if (((int_value == 0) && (bool_value == GL_TRUE)) || ((int_value != 0) && (bool_value != GL_TRUE)))
1753 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid boolean value [" << bool_value
1755 " reported for property ["
1756 << pname_string << "]"
1758 << int_value << "])" << tcu::TestLog::EndMessage;
1760 m_has_test_passed = false;
1763 if (de::abs(double_value - (double)int_value) > epsilon)
1765 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid double value [" << double_value
1767 " reported for property ["
1768 << pname_string << "]"
1770 << int_value << "])" << tcu::TestLog::EndMessage;
1772 m_has_test_passed = false;
1775 if (de::abs(float_value - (float)int_value) > epsilon)
1777 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid float value [" << float_value
1779 " reported for property ["
1780 << pname_string << "]"
1782 << int_value << "])" << tcu::TestLog::EndMessage;
1784 m_has_test_passed = false;
1787 if (int64_value != int_value)
1789 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid 64-bit integer value [" << float_value
1791 " reported for property ["
1792 << pname_string << "]"
1794 << int_value << "])" << tcu::TestLog::EndMessage;
1796 m_has_test_passed = false;
1798 } /* for (all pnames) */
1800 if (m_has_test_passed)
1802 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1806 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1814 * @param context Rendering context.
1817 APITest2::APITest2(deqp::Context& context)
1818 : TestCase(context, "name_getters", "Verifies glGetActiveSubroutineName() and glGetActiveSubroutineUniformName() "
1819 "functions work correctly.")
1821 , m_has_test_passed(true)
1823 , m_subroutine_name1("subroutine1")
1824 , m_subroutine_name2("subroutine2")
1825 , m_subroutine_uniform_name("data_provider")
1828 /* Left blank intentionally */
1831 /** Destroys all ES objects that may have been created during test initialization,
1832 * as well as releases any buffers that may have been allocated during the process.
1834 void APITest2::deinit()
1836 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1838 if (m_buffer != DE_NULL)
1847 gl.deleteProgram(m_po_id);
1854 gl.deleteShader(m_vs_id);
1860 /** Returns body of a vertex shader that should be used for the test.
1862 * @return As per description.
1864 std::string APITest2::getVertexShaderBody()
1866 return "#version 400\n"
1868 "#extension GL_ARB_shader_subroutine : require\n"
1870 "subroutine int ExampleSubroutineType(int example_argument);\n"
1872 "subroutine(ExampleSubroutineType) int subroutine1(int example_argument)\n"
1877 "subroutine(ExampleSubroutineType) int subroutine2(int example_argument)\n"
1882 "subroutine uniform ExampleSubroutineType data_provider;\n"
1886 " gl_Position = vec4(float(data_provider(0)), vec3(1) );\n"
1890 /** Initializes all ES objects required to run the test. */
1891 void APITest2::initTest()
1893 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1895 /* Generate program & shader objects */
1896 m_po_id = gl.createProgram();
1897 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1899 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call(s) failed.");
1901 /* Attach the shader to the program object */
1902 gl.attachShader(m_po_id, m_vs_id);
1903 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
1905 /* Compile the shader */
1906 glw::GLint compile_status = GL_FALSE;
1907 std::string vs_body = getVertexShaderBody();
1908 const char* vs_body_raw_ptr = vs_body.c_str();
1910 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
1911 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1913 gl.compileShader(m_vs_id);
1914 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1916 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1917 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1919 if (compile_status != GL_TRUE)
1921 TCU_FAIL("Shader compilation failed.");
1924 /* Try to link the program object */
1925 glw::GLint link_status = GL_FALSE;
1927 gl.linkProgram(m_po_id);
1928 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1930 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1931 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
1933 if (link_status != GL_TRUE)
1935 TCU_FAIL("Program linking failed.");
1938 /* Perform a few sanity checks */
1939 glw::GLint n_active_subroutines = 0;
1940 glw::GLint n_active_subroutine_uniforms = 0;
1942 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
1943 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
1944 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call failed.");
1946 if (n_active_subroutines != 2 /* subroutines declared in vertex shader */)
1948 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid amount of active subroutines reported; expected: 2,"
1950 << n_active_subroutines << tcu::TestLog::EndMessage;
1952 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINES property value.");
1955 if (n_active_subroutine_uniforms != 1)
1957 m_testCtx.getLog() << tcu::TestLog::Message
1958 << "Invalid amount of active subroutine uniforms reported: expected: 1,"
1960 << n_active_subroutine_uniforms << tcu::TestLog::EndMessage;
1962 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORMS property value.");
1966 /** Executes test iteration.
1968 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1970 tcu::TestNode::IterateResult APITest2::iterate()
1972 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
1973 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
1975 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
1978 /* Initialize a test program object */
1981 /* Verify glGetActiveSubroutineName() works correctly */
1982 verifyGLGetActiveSubroutineNameFunctionality();
1984 /* Verify glGetActiveSubroutineUniformName() works correctly */
1985 verifyGLGetActiveSubroutineUniformNameFunctionality();
1988 if (m_has_test_passed)
1990 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1994 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2000 /** Verifies glGetActiveSubroutineName() behaves as per GL_ARB_shader_subroutine
2003 void APITest2::verifyGLGetActiveSubroutineNameFunctionality()
2005 GLsizei expected_length1 = (GLsizei)strlen(m_subroutine_name1) + 1;
2006 GLsizei expected_length2 = (GLsizei)strlen(m_subroutine_name1) + 1;
2007 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2008 GLsizei reported_length = 0;
2010 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2012 DE_NULL, /* length */
2013 DE_NULL); /* name */
2014 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2016 gl.getProgramInterfaceiv(m_po_id, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, &reported_length);
2017 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2019 if ((reported_length != expected_length1) && (reported_length != expected_length2))
2021 m_testCtx.getLog() << tcu::TestLog::Message
2022 << "Invalid active subroutine name length reported:" << reported_length
2023 << ", instead of: " << expected_length1 << " or " << expected_length2
2024 << tcu::TestLog::EndMessage;
2026 TCU_FAIL("Incorrect length of active subroutine name");
2029 m_buffer = new glw::GLchar[reported_length];
2031 memset(m_buffer, 0, reported_length);
2033 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, 0, reported_length, DE_NULL, /* length */
2035 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineName() call failed.");
2037 if (strcmp(m_buffer, m_subroutine_name1) != 0 && strcmp(m_buffer, m_subroutine_name2) != 0)
2039 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine name reported:[" << m_buffer
2042 << m_subroutine_name1 << "]"
2044 << m_subroutine_name2 << "]." << tcu::TestLog::EndMessage;
2046 TCU_FAIL("Invalid active subroutine name reported.");
2053 /** Verifies glGetActiveSubroutineUniformName() behaves as per GL_ARB_shader_subroutine
2056 void APITest2::verifyGLGetActiveSubroutineUniformNameFunctionality()
2058 GLsizei expected_length = (GLsizei)strlen(m_subroutine_uniform_name);
2059 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2060 GLsizei reported_length = 0;
2062 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2064 DE_NULL, /* length */
2065 DE_NULL); /* name */
2066 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2068 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, /* index */
2070 &reported_length, DE_NULL); /* name */
2071 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveSubroutineUniformName() call failed.");
2073 // reported_length is the actual number of characters written into <name>
2074 // If <bufSize> is 0, reported_length should be 0
2075 if (reported_length != 0)
2077 m_testCtx.getLog() << tcu::TestLog::Message
2078 << "Invalid active subroutine uniform name length reported:" << reported_length
2079 << ", instead of: " << 0 << tcu::TestLog::EndMessage;
2081 TCU_FAIL("Incorrect length of active subroutine uniform name");
2084 m_buffer = new glw::GLchar[expected_length + 1];
2086 memset(m_buffer, 0, expected_length + 1);
2088 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, 0, expected_length + 1, &reported_length, m_buffer);
2089 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformName() call failed.");
2091 if (reported_length != expected_length)
2093 m_testCtx.getLog() << tcu::TestLog::Message
2094 << "Invalid active subroutine uniform name length reported:" << reported_length
2095 << ", instead of: " << expected_length << tcu::TestLog::EndMessage;
2097 TCU_FAIL("Incorrect length of active subroutine uniform name");
2100 if (strcmp(m_buffer, m_subroutine_uniform_name) != 0)
2102 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid active subroutine uniform name reported:[" << m_buffer
2105 << m_subroutine_uniform_name << "]" << tcu::TestLog::EndMessage;
2107 TCU_FAIL("Invalid active subroutine uniform name reported.");
2116 * @param context Rendering context.
2119 FunctionalTest1_2::FunctionalTest1_2(deqp::Context& context)
2120 : TestCase(context, "two_subroutines_single_subroutine_uniform",
2121 "Verifies the subroutines work correctly in a vertex shader for"
2122 " bool/float/int/uint/double/*vec*/*mat* argument and return types")
2123 , m_has_test_passed(true)
2125 , m_po_getter0_subroutine_index(GL_INVALID_INDEX)
2126 , m_po_getter1_subroutine_index(GL_INVALID_INDEX)
2127 , m_po_subroutine_uniform_index(-1)
2132 /* Left blank intentionally */
2135 /** Destroys all ES objects that may have been created during test initialization,
2136 * as well as releases any buffers that may have been allocated during the process.
2138 void FunctionalTest1_2::deinit()
2140 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2142 deinitTestIteration();
2144 if (m_xfb_bo_id != 0)
2146 gl.deleteBuffers(1, &m_xfb_bo_id);
2153 gl.deleteVertexArrays(1, &m_vao_id);
2159 /** Deinitializes GL objects that are iteration-specific */
2160 void FunctionalTest1_2::deinitTestIteration()
2162 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2166 gl.deleteProgram(m_po_id);
2173 gl.deleteShader(m_vs_id);
2179 /** Executes a single test iteration using user-specified test case propertiesz.
2181 * @param test-case Test case descriptor.
2183 * @return true if the test iteration passed, false otherwise.
2185 bool FunctionalTest1_2::executeTestIteration(const _test_case& test_case)
2187 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2190 /* Build the test program */
2191 std::string empty_body;
2192 std::string vs_body = getVertexShaderBody(test_case.variable_type, test_case.array_size);
2193 const glw::GLchar* xfb_varyings[] = { "result" };
2194 const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
2196 if (!Utils::buildProgram(gl, vs_body, empty_body, empty_body, empty_body, empty_body, xfb_varyings, n_xfb_varyings,
2197 &m_vs_id, NULL, /* out_tc_id */
2198 NULL, /* out_te_id */
2199 NULL, /* out_gs_id */
2202 TCU_FAIL("Test program failed to build.");
2205 /* Retrieve subroutine locations */
2206 m_po_getter0_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter0");
2207 m_po_getter1_subroutine_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "getter1");
2209 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
2211 if (m_po_getter0_subroutine_index == GL_INVALID_INDEX || m_po_getter1_subroutine_index == GL_INVALID_INDEX)
2213 TCU_FAIL("At least one subroutine is considered inactive which is invalid.");
2216 /* Retrieve subroutine uniform location */
2217 m_po_subroutine_uniform_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "colorGetterUniform");
2219 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call failed.");
2221 if (m_po_subroutine_uniform_index == -1)
2223 TCU_FAIL("Subroutine uniform is considered inactive which is invalid.");
2226 /* Set up XFB BO storage */
2227 const Utils::_variable_type base_variable_type = Utils::getBaseVariableType(test_case.variable_type);
2228 unsigned int iteration_xfb_bo_size = Utils::getComponentSizeForVariableType(base_variable_type) *
2229 Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
2230 unsigned int total_xfb_bo_size = 0;
2232 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2234 /* Boolean varyings are not supported by OpenGL. Instead, we use ints to output
2235 * boolean values. */
2236 iteration_xfb_bo_size = static_cast<unsigned int>(iteration_xfb_bo_size * sizeof(int));
2239 total_xfb_bo_size = iteration_xfb_bo_size * 2 /* subroutines we will be testing */;
2241 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, total_xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
2242 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2244 /* Activate test program object */
2245 gl.useProgram(m_po_id);
2246 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2248 /* Run two iterations. Each iteration should invoke different subroutine. */
2249 const glw::GLuint subroutine_indices[] = { m_po_getter0_subroutine_index, m_po_getter1_subroutine_index };
2250 const unsigned int n_subroutine_indices = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
2252 for (unsigned int n_subroutine_index = 0; n_subroutine_index < n_subroutine_indices; ++n_subroutine_index)
2254 /* Configure which subroutine should be used for the draw call */
2255 glw::GLuint current_subroutine_index = subroutine_indices[n_subroutine_index];
2257 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, ¤t_subroutine_index);
2258 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
2260 /* Update XFB binding so that we do not overwrite data XFBed in previous iterations */
2261 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2262 m_xfb_bo_id, iteration_xfb_bo_size * n_subroutine_index, iteration_xfb_bo_size);
2263 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() call failed.");
2265 /* Draw a single point */
2266 gl.beginTransformFeedback(GL_POINTS);
2267 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2269 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2270 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
2272 gl.endTransformFeedback();
2273 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2274 } /* for (all subroutine indices) */
2276 /* Map the BO storage into process space */
2277 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2278 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
2280 result &= verifyXFBData(xfb_data_ptr, test_case.variable_type);
2282 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2283 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffeR() call failed.");
2288 /** Retrieves body of a vertex shader that should be used to verify
2289 * subroutine support, given user-specified test iteration properties.
2291 * @param variable_type GLSL type that should be used for argument and
2292 * return type definition in a subroutine. This setting
2293 * also affects type of the only output variable in the shader.
2294 * @param array_size 1 if non-arrayed arguments/return types should be tested;
2295 * 2 if arrayed arguments/return types should be tested.
2297 * @return Requested string.
2299 std::string FunctionalTest1_2::getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size)
2301 Utils::_variable_type base_variable_type = Utils::getBaseVariableType(variable_type);
2302 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2303 std::stringstream result_sstream;
2304 std::string variable_type_glsl = Utils::getVariableTypeGLSLString(variable_type);
2305 std::stringstream variable_type_glsl_array_sstream;
2306 std::stringstream variable_type_glsl_arrayed_sstream;
2308 variable_type_glsl_arrayed_sstream << variable_type_glsl;
2312 variable_type_glsl_array_sstream << "[" << array_size << "]";
2313 variable_type_glsl_arrayed_sstream << variable_type_glsl_array_sstream.str();
2316 /* Form pre-amble */
2317 result_sstream << "#version 400\n"
2319 "#extension GL_ARB_shader_subroutine : require\n";
2321 if (variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2323 result_sstream << "#extension GL_ARB_gpu_shader_fp64 : require\n";
2326 /* Form subroutine type declaration */
2327 result_sstream << "\n"
2329 << variable_type_glsl_arrayed_sstream.str() << " colorGetter(in " << variable_type_glsl
2330 << " in_value" << variable_type_glsl_array_sstream.str() << ");\n"
2333 /* Declare getter functions */
2334 for (int n_getter = 0; n_getter < 2; ++n_getter)
2336 result_sstream << "subroutine(colorGetter) " << variable_type_glsl_arrayed_sstream.str() << " getter"
2337 << n_getter << "(in " << variable_type_glsl << " in_value"
2338 << variable_type_glsl_array_sstream.str() << ")\n"
2343 result_sstream << variable_type_glsl << " temp" << variable_type_glsl_array_sstream.str() << ";\n";
2346 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2350 for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2352 result_sstream << " temp[" << array_index << "]"
2354 << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2355 << "(in_value[" << array_index << "]);\n";
2358 result_sstream << " return temp;\n";
2362 result_sstream << " return "
2363 << ((n_getter == 0) ? ((variable_type_glsl == "bool") ? "!" : "not") : "")
2366 } /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2371 for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2373 result_sstream << " temp[" << array_index << "]"
2375 << array_index << "] + " << (n_getter + 1) << ";\n";
2378 result_sstream << " return temp;\n";
2382 result_sstream << " return (in_value + " << (n_getter + 1) << ");\n";
2386 result_sstream << "}\n";
2387 } /* for (both getter functions) */
2389 /* Declare subroutine uniform */
2390 result_sstream << "subroutine uniform colorGetter colorGetterUniform;\n"
2393 /* Declare output variable */
2394 result_sstream << "out ";
2396 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2398 Utils::_variable_type result_as_int_variable_type =
2399 Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2400 std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2402 result_sstream << variable_type_glsl_as_int;
2406 result_sstream << variable_type_glsl;
2409 result_sstream << " result;\n"
2412 /* Declare main(): prepare input argument for the subroutine function */
2413 result_sstream << "void main()\n"
2416 << variable_type_glsl << " temp";
2420 result_sstream << "[" << array_size << "]";
2423 result_sstream << ";\n";
2425 for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2427 result_sstream << " temp";
2431 result_sstream << "[" << array_index << "]";
2434 result_sstream << " = " << variable_type_glsl << "(";
2436 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2438 result_sstream << "true";
2442 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2444 result_sstream << "3";
2446 if (n_component != (n_variable_type_components - 1))
2448 result_sstream << ", ";
2450 } /* for (all components) */
2453 result_sstream << ");\n";
2454 } /* for (all array indices) */
2456 /* Declare main(): call the subroutine. Verify the input and write the result
2457 * to the output variable.
2459 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2461 Utils::_variable_type result_as_int_variable_type =
2462 Utils::getVariableTypeFromProperties(Utils::VARIABLE_TYPE_INT, n_variable_type_components);
2463 std::string variable_type_glsl_as_int = Utils::getVariableTypeGLSLString(result_as_int_variable_type);
2465 result_sstream << variable_type_glsl_arrayed_sstream.str() << " subroutine_result = colorGetterUniform(temp);\n"
2468 for (unsigned int array_index = 0; array_index < array_size; ++array_index)
2470 if (variable_type_glsl == "bool")
2471 result_sstream << "bool(subroutine_result";
2473 result_sstream << "all(subroutine_result";
2477 result_sstream << "[" << array_index << "]";
2480 result_sstream << ")";
2482 if (array_index != (array_size - 1))
2484 result_sstream << "&& ";
2488 result_sstream << " == true ? " << variable_type_glsl_as_int << "(1) : " << variable_type_glsl_as_int << "(0);";
2494 DE_ASSERT(array_size == 2);
2496 result_sstream << variable_type_glsl << " subroutine_result" << variable_type_glsl_array_sstream.str()
2497 << " = colorGetterUniform(temp);\n"
2499 "if (subroutine_result[0] == subroutine_result[1]) result = subroutine_result[0];\n"
2502 << variable_type_glsl << "(-1);\n";
2506 result_sstream << "result = colorGetterUniform(temp);\n";
2511 result_sstream << "}\n";
2513 return result_sstream.str();
2516 /** Initializes all GL objects required to run the test. */
2517 void FunctionalTest1_2::initTest()
2519 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2521 /* Generate buffer object to hold result XFB data */
2522 gl.genBuffers(1, &m_xfb_bo_id);
2523 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2525 /* Set up XFB BO bindings */
2526 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
2527 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2529 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
2530 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2532 /* Generate VAO to use for the draw calls */
2533 gl.genVertexArrays(1, &m_vao_id);
2534 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2536 gl.bindVertexArray(m_vao_id);
2537 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2540 /** Executes test iteration.
2542 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2544 tcu::TestNode::IterateResult FunctionalTest1_2::iterate()
2546 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2547 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2549 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2552 /* Initialize a test program object */
2555 /* Construct test case descriptors: first, iIerate over all
2556 * variable types we want to cover */
2557 const Utils::_variable_type variable_types[] = {
2558 Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_BVEC2, Utils::VARIABLE_TYPE_BVEC3,
2559 Utils::VARIABLE_TYPE_BVEC4, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT,
2560 Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_IVEC3,
2561 Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_MAT2X3,
2562 Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_MAT3X2,
2563 Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_MAT4X2,
2564 Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_UVEC2,
2565 Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_VEC2,
2566 Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_VEC4
2568 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
2570 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
2572 Utils::_variable_type current_variable_type = variable_types[n_variable_type];
2574 /* We need to test both arrayed and non-arrayed arguments */
2575 for (unsigned int array_size = 1; array_size < 3; ++array_size)
2577 /* Exclude double variables if the relevant extension is unavailable */
2578 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64") &&
2579 current_variable_type == Utils::VARIABLE_TYPE_DOUBLE)
2584 /* Form the descriptor */
2585 _test_case test_case;
2587 test_case.array_size = array_size;
2588 test_case.variable_type = current_variable_type;
2590 /* Store the test case descriptor */
2591 m_test_cases.push_back(test_case);
2592 } /* for (both arrayed and non-arrayed arguments) */
2593 } /* for (all variable types) */
2595 /* Iterate over all test cases and execute the test */
2596 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
2597 ++test_case_iterator)
2599 const _test_case& test_case = *test_case_iterator;
2601 m_has_test_passed &= executeTestIteration(test_case);
2603 /* Release GL objects that were created during the execution */
2604 deinitTestIteration();
2605 } /* for (all test cases) */
2608 if (m_has_test_passed)
2610 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2614 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2620 /** Verifies data that has been XFBed out by the vertex shader.
2622 * @param xfb_data Buffer holding the data.
2623 * @param variable_type GLSL type used for the test iteration
2624 * that generated the data at @param xfb_data.
2626 * @return true if the data was found to be valid, false if it
2627 * was detected to be incorrect.
2629 bool FunctionalTest1_2::verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type)
2631 const Utils::_variable_type base_variable_type = Utils::getBaseVariableType(variable_type);
2632 const float epsilon = 1e-5f;
2633 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
2635 const unsigned char* traveller_ptr = (const unsigned char*)xfb_data;
2637 /* Boolean arguments/return types are tested with a slightly different shader so we
2638 * need to test them in a separate code-path.
2640 if (base_variable_type == Utils::VARIABLE_TYPE_BOOL)
2642 /* 0 should be returned when getter0 is used, 1 otherwise */
2643 const unsigned int ref_values[] = { 0, 1 };
2644 const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2646 for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2648 const unsigned int ref_value = ref_values[n_ref_value];
2650 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2652 int* result_value_ptr = (int*)(traveller_ptr);
2654 if (*result_value_ptr != (int)ref_value)
2656 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2658 << Utils::getVariableTypeGLSLString(variable_type) << "]"
2659 << " argument/return types ("
2661 << ref_value << "], found:[" << *result_value_ptr << "])"
2662 << tcu::TestLog::EndMessage;
2668 traveller_ptr += sizeof(int);
2669 } /* for (all components) */
2670 } /* for (all reference values) */
2671 } /* if (base_variable_type == Utils::VARIABLE_TYPE_BOOL) */
2674 /* 4 should be returned when getter0 is used, 5 otherwise */
2675 const unsigned int ref_values[] = { 4, 5 };
2676 const unsigned int n_ref_values = sizeof(ref_values) / sizeof(ref_values[0]);
2678 for (unsigned int n_ref_value = 0; n_ref_value < n_ref_values; ++n_ref_value)
2680 const unsigned int ref_value = ref_values[n_ref_value];
2683 base_variable_type == Utils::VARIABLE_TYPE_DOUBLE || base_variable_type == Utils::VARIABLE_TYPE_FLOAT ||
2684 base_variable_type == Utils::VARIABLE_TYPE_INT || base_variable_type == Utils::VARIABLE_TYPE_UINT);
2686 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
2688 const double* double_value_ptr = (double*)traveller_ptr;
2689 const float* float_value_ptr = (float*)traveller_ptr;
2690 const int* int_value_ptr = (int*)traveller_ptr;
2692 switch (base_variable_type)
2694 case Utils::VARIABLE_TYPE_DOUBLE:
2696 if (de::abs(*double_value_ptr - (double)ref_value) > epsilon)
2698 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2700 << Utils::getVariableTypeGLSLString(variable_type) << "]"
2701 << " argument/return types ("
2703 << ref_value << "], found:[" << *double_value_ptr << "])"
2704 << tcu::TestLog::EndMessage;
2709 traveller_ptr += sizeof(double);
2713 case Utils::VARIABLE_TYPE_FLOAT:
2715 if (de::abs(*float_value_ptr - (float)ref_value) > epsilon)
2717 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2719 << Utils::getVariableTypeGLSLString(variable_type) << "]"
2720 << " argument/return types ("
2722 << ref_value << "], found:[" << *float_value_ptr << "])"
2723 << tcu::TestLog::EndMessage;
2728 traveller_ptr += sizeof(float);
2732 case Utils::VARIABLE_TYPE_INT:
2733 case Utils::VARIABLE_TYPE_UINT:
2735 if (*int_value_ptr != (int)ref_value)
2737 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported by subroutine using "
2739 << Utils::getVariableTypeGLSLString(variable_type) << "]"
2740 << " argument/return types ("
2742 << ref_value << "], found:[" << *int_value_ptr << "])"
2743 << tcu::TestLog::EndMessage;
2748 traveller_ptr += sizeof(int);
2754 } /* switch (base_variable_type) */
2755 } /* for (all components) */
2756 } /* for (all reference values) */
2764 * @param context CTS context
2766 FunctionalTest3_4::FunctionalTest3_4(deqp::Context& context)
2767 : TestCase(context, "four_subroutines_with_two_uniforms", "Verify Get* API and draw calls")
2768 , m_n_active_subroutine_uniforms(0)
2769 , m_n_active_subroutine_uniform_locations(0)
2770 , m_n_active_subroutines(0)
2771 , m_n_active_subroutine_uniform_name_length(0)
2772 , m_n_active_subroutine_name_length(0)
2773 , m_n_active_subroutine_uniform_size(0)
2775 /* Nothing to be done here */
2780 * @return tcu::TestNode::STOP
2782 tcu::TestNode::IterateResult FunctionalTest3_4::iterate()
2784 static const glw::GLchar* vertex_shader_code =
2785 "#version 400 core\n"
2786 "#extension GL_ARB_shader_subroutine : require\n"
2788 "precision highp float;\n"
2790 "// Sub routine type declaration\n"
2791 "subroutine vec4 routine_type(in vec4 iparam);\n"
2793 "// Sub routine definitions\n"
2794 "subroutine(routine_type) vec4 inverse_order(in vec4 iparam)\n"
2796 " return iparam.wzyx;\n"
2799 "subroutine(routine_type) vec4 negate(in vec4 iparam)\n"
2801 " return -iparam;\n"
2804 "subroutine(routine_type) vec4 inverse(in vec4 iparam)\n"
2806 " return 1 / iparam;\n"
2809 "subroutine(routine_type) vec4 square(in vec4 iparam)\n"
2811 " return iparam * iparam;\n"
2814 "// Sub routine uniforms\n"
2815 "subroutine uniform routine_type first_routine;\n"
2816 "subroutine uniform routine_type second_routine;\n"
2819 "uniform vec4 input_data;\n"
2822 "out vec4 out_input_data;\n"
2823 "out vec4 out_result_from_first_routine;\n"
2824 "out vec4 out_result_from_second_routine;\n"
2825 "out vec4 out_result_from_combined_routines;\n"
2826 "out vec4 out_result_from_routines_combined_in_reveresed_order;\n"
2830 " out_input_data = input_data;\n"
2831 " out_result_from_first_routine = first_routine(input_data);\n"
2832 " out_result_from_second_routine = second_routine(input_data);\n"
2833 " out_result_from_combined_routines = second_routine(first_routine(input_data));\n"
2834 " out_result_from_routines_combined_in_reveresed_order = first_routine(second_routine(input_data));\n"
2838 static const GLchar* varying_names[] = {
2840 "out_result_from_first_routine",
2841 "out_result_from_second_routine",
2842 "out_result_from_combined_routines",
2843 "out_result_from_routines_combined_in_reveresed_order",
2846 static const GLchar* subroutine_uniform_names[] = { "first_routine", "second_routine" };
2848 static const GLchar* subroutine_names[] = { "inverse_order", "negate", "inverse", "square" };
2850 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]);
2851 static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
2853 static const GLuint inverse_order_routine_index = 0;
2854 static const GLuint negate_routine_index = 1;
2855 static const GLuint inverse_routine_index = 2;
2856 static const GLuint square_routine_index = 3;
2859 static const Utils::vec4<GLfloat> inverse_order_negate_data[5] = {
2860 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2861 Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f), Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2862 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f),
2865 static const Utils::vec4<GLfloat> inverse_order_inverse_data[5] = {
2866 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2867 Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2868 Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2871 static const Utils::vec4<GLfloat> inverse_order_square_data[5] = {
2872 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2873 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2874 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2877 static const Utils::vec4<GLfloat> negate_inverse_data[5] = {
2878 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2879 Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f), Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2880 Utils::vec4<GLfloat>(0.5f, 1.0f, -1.0f, -0.5f),
2883 static const Utils::vec4<GLfloat> negate_square_data[5] = {
2884 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(2.0f, 1.0f, -1.0f, -2.0f),
2885 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f),
2886 Utils::vec4<GLfloat>(-4.0f, -1.0f, -1.0f, -4.0f),
2889 static const Utils::vec4<GLfloat> inverse_square_data[5] = {
2890 Utils::vec4<GLfloat>(-2.0f, -1.0f, 1.0f, 2.0f), Utils::vec4<GLfloat>(-0.5f, -1.0f, 1.0f, 0.5f),
2891 Utils::vec4<GLfloat>(4.0f, 1.0f, 1.0f, 4.0f), Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2892 Utils::vec4<GLfloat>(0.25f, 1.0f, 1.0f, 0.25f),
2895 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
2896 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
2898 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
2901 m_n_active_subroutine_uniforms = 2;
2902 m_n_active_subroutine_uniform_locations = 2;
2903 m_n_active_subroutines = 4;
2904 m_n_active_subroutine_uniform_name_length = 0;
2905 m_n_active_subroutine_name_length = 0;
2906 m_n_active_subroutine_uniform_size = 1;
2909 Utils::program program(m_context);
2910 Utils::buffer transform_feedback_buffer(m_context);
2911 Utils::vertexArray vao(m_context);
2915 /* Calculate max name lengths for subroutines and subroutine uniforms */
2916 for (GLint i = 0; i < m_n_active_subroutine_uniforms; ++i)
2918 const GLsizei length = (GLsizei)strlen(subroutine_uniform_names[i]);
2920 if (length > m_n_active_subroutine_uniform_name_length)
2922 m_n_active_subroutine_uniform_name_length = length;
2926 for (GLint i = 0; i < m_n_active_subroutines; ++i)
2928 const GLsizei length = (GLsizei)strlen(subroutine_names[i]);
2930 if (length > m_n_active_subroutine_name_length)
2932 m_n_active_subroutine_name_length = length;
2937 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
2943 transform_feedback_buffer.generate();
2944 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
2946 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
2950 /* Inspect Get* API */
2951 if ((false == inspectProgramStageiv(program.m_program_object_id)) ||
2952 (false == inspectActiveSubroutineUniformiv(program.m_program_object_id, subroutine_uniform_names)) ||
2953 (false == inspectActiveSubroutineUniformName(program.m_program_object_id, subroutine_uniform_names)) ||
2954 (false == inspectActiveSubroutineName(program.m_program_object_id, subroutine_names)) ||
2956 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, false)))
2961 /* Inspect GetProgram* API */
2962 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2964 if ((false == inspectProgramInterfaceiv(program.m_program_object_id)) ||
2966 inspectProgramResourceiv(program.m_program_object_id, subroutine_names, subroutine_uniform_names)) ||
2968 inspectSubroutineBinding(program.m_program_object_id, subroutine_names, subroutine_uniform_names, true)))
2974 /* Test shader execution */
2975 if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2976 subroutine_names[negate_routine_index], subroutine_uniform_names, inverse_order_negate_data,
2978 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2979 subroutine_names[inverse_routine_index], subroutine_uniform_names,
2980 inverse_order_inverse_data, false)) ||
2981 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
2982 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_order_square_data,
2984 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2985 subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
2987 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
2988 subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
2990 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
2991 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
2997 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
2999 if ((false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3000 subroutine_names[negate_routine_index], subroutine_uniform_names,
3001 inverse_order_negate_data, true)) ||
3002 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3003 subroutine_names[inverse_routine_index], subroutine_uniform_names,
3004 inverse_order_inverse_data, true)) ||
3005 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_order_routine_index],
3006 subroutine_names[square_routine_index], subroutine_uniform_names,
3007 inverse_order_square_data, true)) ||
3008 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3009 subroutine_names[inverse_routine_index], subroutine_uniform_names, negate_inverse_data,
3011 (false == testDraw(program.m_program_object_id, subroutine_names[negate_routine_index],
3012 subroutine_names[square_routine_index], subroutine_uniform_names, negate_square_data,
3014 (false == testDraw(program.m_program_object_id, subroutine_names[inverse_routine_index],
3015 subroutine_names[square_routine_index], subroutine_uniform_names, inverse_square_data,
3025 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3029 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3032 return tcu::TestNode::STOP;
3035 /** Verify result of getProgramStageiv
3037 * @param program_id Program object id
3038 * @param pname <pname> parameter for getProgramStageiv
3039 * @param expected Expected value
3041 * @return true if result is equal to expected value, flase otherwise
3043 bool FunctionalTest3_4::checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const
3045 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3048 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, pname, &value);
3049 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3051 if (expected != value)
3053 m_context.getTestContext().getLog() << tcu::TestLog::Message
3054 << "Error. Invalid result. Function: getProgramStageiv. "
3055 << "pname: " << Utils::pnameToStr(pname) << ". "
3056 << "Result: " << value << ". "
3057 << "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3067 /** Verify result of getProgramResourceiv
3069 * @param program_id Program object id
3070 * @param program_interface Program interface
3071 * @param pname <pname> parameter for getProgramStageiv
3072 * @param resource_name Resource name
3073 * @param expected Expected value
3075 * @return true if result is equal to expected value, false otherwise
3077 bool FunctionalTest3_4::checkProgramResourceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3078 const glw::GLchar* resource_name, GLint expected) const
3080 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3081 GLuint index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3084 if (GL_INVALID_INDEX == index)
3089 gl.getProgramResourceiv(program_id, program_interface, index, 1, &pname, 1, 0, &value);
3090 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceiv");
3092 if (expected != value)
3094 m_context.getTestContext().getLog()
3095 << tcu::TestLog::Message << "Error. Invalid result. Function: getProgramResourceiv. "
3096 << "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3097 << "Resource name: " << resource_name << ". "
3098 << "Property: " << Utils::pnameToStr(pname) << ". "
3099 << "Result: " << value << ". "
3100 << "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3110 /** Verify result of getProgramInterfaceiv
3112 * @param program_id Program object id
3113 * @param program_interface Program interface
3114 * @param pname <pname> parameter for getProgramStageiv
3115 * @param expected Expected value
3117 * @return true if result is equal to expected value, flase otherwise
3119 bool FunctionalTest3_4::checkProgramInterfaceiv(GLuint program_id, GLenum program_interface, GLenum pname,
3120 GLint expected) const
3122 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3125 gl.getProgramInterfaceiv(program_id, program_interface, pname, &value);
3126 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInterfaceiv");
3128 if (expected != value)
3130 m_context.getTestContext().getLog()
3131 << tcu::TestLog::Message << "Error. Invalid result. Function: getProgramInterfaceiv. "
3132 << "Program interface: " << Utils::programInterfaceToStr(program_interface) << ". "
3133 << "pname: " << Utils::pnameToStr(pname) << ". "
3134 << "Result: " << value << ". "
3135 << "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3145 /** Verify result of getActiveSubroutineUniformiv
3147 * @param program_id Program object id
3148 * @param index <index> parameter for getActiveSubroutineUniformiv
3149 * @param pname <pname> parameter for getActiveSubroutineUniformiv
3150 * @param expected Expected value
3152 * @return true if result is equal to expected value, flase otherwise
3154 bool FunctionalTest3_4::checkActiveSubroutineUniformiv(GLuint program_id, GLuint index, GLenum pname,
3155 GLint expected) const
3157 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3160 gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, index, pname, &value);
3161 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3163 if (expected != value)
3165 m_context.getTestContext().getLog() << tcu::TestLog::Message
3166 << "Error. Invalid result. Function: getActiveSubroutineUniformiv. "
3167 << "idnex: " << index << ". "
3168 << "pname: " << Utils::pnameToStr(pname) << ". "
3169 << "Result: " << value << ". "
3170 << "Expected: " << expected << "." << tcu::TestLog::EndMessage;
3180 /** Returns index of program resource
3182 * @param program_id Program object id
3183 * @param program_interface Program interface
3184 * @param resource_name Name of resource
3186 * @return Index of specified resource
3188 GLuint FunctionalTest3_4::getProgramResourceIndex(GLuint program_id, GLenum program_interface,
3189 const glw::GLchar* resource_name) const
3191 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3192 GLuint index = gl.getProgramResourceIndex(program_id, program_interface, resource_name);
3194 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramResourceIndex");
3196 if (GL_INVALID_INDEX == index)
3198 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Program resource is not available. "
3199 << "Program interface: " << Utils::programInterfaceToStr(program_interface)
3201 << "Resource name: " << resource_name << "." << tcu::TestLog::EndMessage;
3207 /** Get subroutine index
3209 * @param program_id Program object id
3210 * @param subroutine_name Subroutine name
3211 * @param use_program_query If true getProgramResourceIndex is used, otherwise getSubroutineIndex
3213 * @return Index of subroutine
3215 GLuint FunctionalTest3_4::getSubroutineIndex(GLuint program_id, const glw::GLchar* subroutine_name,
3216 bool use_program_query) const
3218 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3221 if (false == use_program_query)
3223 index = gl.getSubroutineIndex(program_id, GL_VERTEX_SHADER, subroutine_name);
3224 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
3228 index = gl.getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE, subroutine_name);
3229 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3232 if (GL_INVALID_INDEX == index)
3234 TCU_FAIL("Subroutine is not available");
3240 /** Get subroutine uniform location
3242 * @param program_id Program object id
3243 * @param uniform_name Subroutine uniform name
3244 * @param use_program_query If true getProgramResourceLocation is used, otherwise getSubroutineUniformLocation
3246 * @return Location of subroutine uniform
3248 GLint FunctionalTest3_4::getSubroutineUniformLocation(GLuint program_id, const glw::GLchar* uniform_name,
3249 bool use_program_query) const
3251 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3252 GLint location = -1;
3254 if (false == use_program_query)
3256 location = gl.getSubroutineUniformLocation(program_id, GL_VERTEX_SHADER, uniform_name);
3257 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
3261 location = gl.getProgramResourceLocation(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3262 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceLocation");
3267 TCU_FAIL("Subroutine uniform is not available");
3273 /** Test if getProgramStageiv results are as expected
3275 * @param program_id Program object id
3277 * @result false in case of invalid result for any pname, true otherwise
3279 bool FunctionalTest3_4::inspectProgramStageiv(glw::GLuint program_id) const
3283 const inspectionDetails details[] = {
3284 { GL_ACTIVE_SUBROUTINE_UNIFORMS, m_n_active_subroutine_uniforms },
3285 { GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, m_n_active_subroutine_uniform_locations },
3286 { GL_ACTIVE_SUBROUTINES, m_n_active_subroutines },
3287 { GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3288 { GL_ACTIVE_SUBROUTINE_MAX_LENGTH, m_n_active_subroutine_name_length + 1 }
3290 const GLuint n_details = sizeof(details) / sizeof(details[0]);
3292 for (GLuint i = 0; i < n_details; ++i)
3294 if (false == checkProgramStageiv(program_id, details[i].pname, details[i].expected_value))
3303 /** Test if checkProgramInterfaceiv results are as expected
3305 * @param program_id Program object id
3307 * @result false in case of invalid result for any pname, true otherwise
3309 bool FunctionalTest3_4::inspectProgramInterfaceiv(glw::GLuint program_id) const
3313 const inspectionDetailsForProgramInterface details[] = {
3314 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, m_n_active_subroutine_uniforms },
3315 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, m_n_active_subroutine_uniform_name_length + 1 },
3316 { GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3317 { GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, m_n_active_subroutines },
3318 { GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, m_n_active_subroutine_name_length + 1 }
3320 const GLuint n_details = sizeof(details) / sizeof(details[0]);
3322 for (GLuint i = 0; i < n_details; ++i)
3324 if (false == checkProgramInterfaceiv(program_id, details[i].program_interface, details[i].pname,
3325 details[i].expected_value))
3334 /** Test if checkProgramResourceiv results are as expected
3336 * @param program_id Program object id
3337 * @param subroutine_names Array of subroutine names
3338 * @param uniform_names Array of uniform names
3340 * @result false in case of invalid result for any pname, true otherwise
3342 bool FunctionalTest3_4::inspectProgramResourceiv(GLuint program_id, const GLchar** subroutine_names,
3343 const GLchar** uniform_names) const
3345 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3348 for (GLint subroutine = 0; subroutine < m_n_active_subroutines; ++subroutine)
3350 const GLchar* subroutine_name = subroutine_names[subroutine];
3351 const GLint length = (GLint)strlen(subroutine_name) + 1;
3353 if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE, GL_NAME_LENGTH, subroutine_name, length))
3359 inspectionDetails details[] = {
3360 { GL_NAME_LENGTH, 0 },
3361 { GL_ARRAY_SIZE, 1 },
3362 { GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3365 const GLuint n_details = sizeof(details) / sizeof(details[0]);
3367 for (GLint uniform = 0; uniform < m_n_active_subroutine_uniforms; ++uniform)
3369 const GLchar* uniform_name = uniform_names[uniform];
3370 const GLint length = (GLint)strlen(uniform_name) + 1;
3371 const GLint location = getSubroutineUniformLocation(program_id, uniform_name, true);
3373 details[0].expected_value = length;
3374 details[3].expected_value = location;
3376 for (GLuint i = 0; i < n_details; ++i)
3378 if (false == checkProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, details[i].pname,
3379 uniform_name, details[i].expected_value))
3385 /* Check compatible subroutines */
3386 GLuint index = getProgramResourceIndex(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, uniform_name);
3388 if (GL_INVALID_INDEX != index)
3390 std::vector<GLint> compatible_subroutines;
3391 GLint index_sum = 0;
3392 GLenum prop = GL_COMPATIBLE_SUBROUTINES;
3394 compatible_subroutines.resize(m_n_active_subroutines);
3396 gl.getProgramResourceiv(program_id, GL_VERTEX_SUBROUTINE_UNIFORM, index, 1, &prop, m_n_active_subroutines,
3397 0, &compatible_subroutines[0]);
3399 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3401 /* Expected indices are 0, 1, 2, ... N */
3402 for (GLint i = 0; i < m_n_active_subroutines; ++i)
3404 index_sum += compatible_subroutines[i];
3407 /* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3408 if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3410 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3412 message << "Error. Invalid result. Function: getProgramResourceiv. "
3413 << "Program interface: GL_VERTEX_SUBROUTINE_UNIFORM. "
3414 << "Resource name: " << uniform_name << ". "
3415 << "Property: GL_COMPATIBLE_SUBROUTINES. "
3418 for (GLint i = 1; i < m_n_active_subroutines; ++i)
3420 message << compatible_subroutines[i];
3423 message << tcu::TestLog::EndMessage;
3433 /** Test if getActiveSubroutineUniformiv results are as expected
3435 * @param program_id Program object id
3436 * @param uniform_names Array of subroutine uniform names available in program
3438 * @result false in case of invalid result for any pname, true otherwise
3440 bool FunctionalTest3_4::inspectActiveSubroutineUniformiv(GLuint program_id, const GLchar** uniform_names) const
3442 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3444 GLint n_active_subroutine_uniforms = 0;
3446 inspectionDetails details[] = {
3447 { GL_NUM_COMPATIBLE_SUBROUTINES, m_n_active_subroutines },
3448 { GL_UNIFORM_SIZE, m_n_active_subroutine_uniform_size },
3449 { GL_UNIFORM_NAME_LENGTH, 0 },
3451 const GLuint n_details = sizeof(details) / sizeof(details[0]);
3453 /* Get amount of active subroutine uniforms */
3454 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3455 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3457 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3459 GLint name_length = (GLint)strlen(uniform_names[uniform]);
3461 details[2].expected_value = name_length + 1;
3463 /* Checks from "details" */
3464 for (GLuint i = 0; i < n_details; ++i)
3467 checkActiveSubroutineUniformiv(program_id, uniform, details[i].pname, details[i].expected_value))
3473 /* Check compatible subroutines */
3474 std::vector<GLint> compatible_subroutines;
3475 compatible_subroutines.resize(m_n_active_subroutines);
3476 GLint index_sum = 0;
3478 gl.getActiveSubroutineUniformiv(program_id, GL_VERTEX_SHADER, uniform, GL_COMPATIBLE_SUBROUTINES,
3479 &compatible_subroutines[0]);
3480 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineUniformiv");
3482 /* Expected indices are 0, 1, 2, ... N */
3483 for (GLint i = 0; i < m_n_active_subroutines; ++i)
3485 index_sum += compatible_subroutines[i];
3488 /* Sum of E1, ..., EN = (E1 + EN) * N / 2 */
3489 if (((m_n_active_subroutines - 1) * m_n_active_subroutines) / 2 != index_sum)
3491 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3493 message << "Error. Invalid result. Function: getActiveSubroutineUniformiv. idnex: " << uniform
3494 << ". pname: " << Utils::pnameToStr(GL_COMPATIBLE_SUBROUTINES) << ". Results: ";
3496 for (GLint i = 1; i < m_n_active_subroutines; ++i)
3498 message << compatible_subroutines[i];
3501 message << tcu::TestLog::EndMessage;
3510 /** Test if getActiveSubroutineUniformName results are as expected
3512 * @param program_id Program object id
3513 * @param uniform_names Array of subroutine uniform names available in program
3515 * @result false in case of invalid result, true otherwise
3517 bool FunctionalTest3_4::inspectActiveSubroutineUniformName(GLuint program_id, const GLchar** uniform_names) const
3519 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3521 GLint n_active_subroutine_uniforms = 0;
3522 std::vector<GLchar> active_uniform_name;
3524 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3525 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3527 active_uniform_name.resize(m_n_active_subroutine_uniform_name_length + 1);
3529 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3531 bool is_name_ok = false;
3533 gl.getActiveSubroutineUniformName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_uniform_name.size(),
3534 0 /* length */, &active_uniform_name[0]);
3535 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveSubroutineUniformName");
3537 for (GLint name = 0; name < n_active_subroutine_uniforms; ++name)
3539 if (0 == strcmp(uniform_names[name], &active_uniform_name[0]))
3546 if (false == is_name_ok)
3548 m_context.getTestContext().getLog()
3549 << tcu::TestLog::Message
3550 << "Error. Invalid result. Function: getActiveSubroutineUniformName. idnex: " << uniform
3551 << ". Result: " << &active_uniform_name[0] << tcu::TestLog::EndMessage;
3561 /** Test if getActiveSubroutineUniformName results are as expected
3563 * @param program_id Program object id
3564 * @param subroutine_names Array of subroutine names available in program
3566 * @result false in case of invalid result, true otherwise
3568 bool FunctionalTest3_4::inspectActiveSubroutineName(GLuint program_id, const GLchar** subroutine_names) const
3570 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3572 GLint n_active_subroutines = 0;
3573 std::vector<GLchar> active_subroutine_name;
3575 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3576 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3578 active_subroutine_name.resize(m_n_active_subroutine_name_length + 1);
3580 for (GLint uniform = 0; uniform < n_active_subroutines; ++uniform)
3582 bool is_name_ok = false;
3584 gl.getActiveSubroutineName(program_id, GL_VERTEX_SHADER, uniform, (GLsizei)active_subroutine_name.size(),
3585 0 /* length */, &active_subroutine_name[0]);
3586 GLU_EXPECT_NO_ERROR(gl.getError(), "getActiveSubroutineName");
3588 for (GLint name = 0; name < n_active_subroutines; ++name)
3590 if (0 == strcmp(subroutine_names[name], &active_subroutine_name[0]))
3597 if (false == is_name_ok)
3599 m_context.getTestContext().getLog()
3600 << tcu::TestLog::Message
3601 << "Error. Invalid result. Function: getActiveSubroutineName. idnex: " << uniform
3602 << ". Result: " << &active_subroutine_name[0] << tcu::TestLog::EndMessage;
3612 /** Test if it is possible to "bind" all subroutines uniforms with all subroutines
3614 * @param program_id Program object id
3615 * @param subroutine_names Array of subroutine names available in program
3616 * @param uniform_names Array of subroutine uniform names available in program
3618 * @result false in case of invalid result, true otherwise
3620 bool FunctionalTest3_4::inspectSubroutineBinding(GLuint program_id, const GLchar** subroutine_names,
3621 const GLchar** uniform_names, bool use_program_query) const
3623 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3625 GLint n_active_subroutines = 0;
3626 GLint n_active_subroutine_uniforms = 0;
3627 std::vector<GLuint> subroutine_uniforms;
3628 GLuint queried_subroutine_index = 0;
3630 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &n_active_subroutines);
3631 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3633 gl.getProgramStageiv(program_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &n_active_subroutine_uniforms);
3634 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramStageiv");
3636 subroutine_uniforms.resize(n_active_subroutine_uniforms);
3638 for (GLint uniform = 0; uniform < n_active_subroutine_uniforms; ++uniform)
3640 GLuint uniform_location = getSubroutineUniformLocation(program_id, uniform_names[uniform], use_program_query);
3642 for (GLint routine = 0; routine < n_active_subroutines; ++routine)
3644 GLuint routine_index = getSubroutineIndex(program_id, subroutine_names[routine], use_program_query);
3646 subroutine_uniforms[uniform] = routine_index;
3648 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_active_subroutine_uniforms, &subroutine_uniforms[0]);
3649 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3651 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, uniform_location, &queried_subroutine_index);
3652 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
3654 if (queried_subroutine_index != routine_index)
3656 m_context.getTestContext().getLog()
3657 << tcu::TestLog::Message << "Error. Invalid result. Function: gl.getUniformSubroutineuiv."
3658 << " Subroutine uniform: " << uniform << ", name: " << uniform_names[uniform]
3659 << ", location: " << uniform_location << ". Subroutine: " << routine
3660 << ", name: " << subroutine_names[routine] << ", index: " << routine_index
3661 << ". Result: " << queried_subroutine_index << tcu::TestLog::EndMessage;
3671 /** Execute draw call and verify results
3673 * @param program_id Program object id
3674 * @param first_routine_name Name of subroutine that shall be used aas first_routine
3675 * @param second_routine_name Name of subroutine that shall be used aas second_routine
3676 * @param uniform_names Name of uniforms
3677 * @param expected_results Test data. [0] is used as input data. All are used as expected_results
3678 * @param use_program_query If true GetProgram* API will be used
3680 * @return false in case of invalid result, true otherwise
3682 bool FunctionalTest3_4::testDraw(GLuint program_id, const GLchar* first_routine_name, const GLchar* second_routine_name,
3683 const GLchar** uniform_names, const Utils::vec4<GLfloat> expected_results[5],
3684 bool use_program_query) const
3686 static const GLuint n_varyings = 5;
3687 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3689 GLuint subroutine_uniforms[2] = { 0 };
3691 /* Get subroutine uniform locations */
3692 GLint first_routine_location = getSubroutineUniformLocation(program_id, uniform_names[0], use_program_query);
3694 GLint second_routine_location = getSubroutineUniformLocation(program_id, uniform_names[1], use_program_query);
3696 /* Get subroutine indices */
3697 GLuint first_routine_index = getSubroutineIndex(program_id, first_routine_name, use_program_query);
3699 GLuint second_routine_index = getSubroutineIndex(program_id, second_routine_name, use_program_query);
3701 /* Map uniforms with subroutines */
3702 subroutine_uniforms[first_routine_location] = first_routine_index;
3703 subroutine_uniforms[second_routine_location] = second_routine_index;
3705 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 2 /* number of uniforms */, &subroutine_uniforms[0]);
3706 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3708 /* Get location of input_data */
3709 GLint input_data_location = gl.getUniformLocation(program_id, "input_data");
3710 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3712 if (-1 == input_data_location)
3714 TCU_FAIL("Uniform is not available");
3717 /* Set up input_data */
3718 gl.uniform4f(input_data_location, expected_results[0].m_x, expected_results[0].m_y, expected_results[0].m_z,
3719 expected_results[0].m_w);
3720 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
3722 /* Execute draw call with transform feedback */
3723 gl.beginTransformFeedback(GL_POINTS);
3724 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
3726 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
3727 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
3729 gl.endTransformFeedback();
3730 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
3732 /* Verify results */
3733 GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3734 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
3736 Utils::vec4<GLfloat> results[5];
3738 results[0].m_x = feedback_data[0];
3739 results[0].m_y = feedback_data[1];
3740 results[0].m_z = feedback_data[2];
3741 results[0].m_w = feedback_data[3];
3743 results[1].m_x = feedback_data[4];
3744 results[1].m_y = feedback_data[5];
3745 results[1].m_z = feedback_data[6];
3746 results[1].m_w = feedback_data[7];
3748 results[2].m_x = feedback_data[8];
3749 results[2].m_y = feedback_data[9];
3750 results[2].m_z = feedback_data[10];
3751 results[2].m_w = feedback_data[11];
3753 results[3].m_x = feedback_data[12];
3754 results[3].m_y = feedback_data[13];
3755 results[3].m_z = feedback_data[14];
3756 results[3].m_w = feedback_data[15];
3758 results[4].m_x = feedback_data[16];
3759 results[4].m_y = feedback_data[17];
3760 results[4].m_z = feedback_data[18];
3761 results[4].m_w = feedback_data[19];
3763 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3764 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
3766 for (GLuint i = 0; i < n_varyings; ++i)
3768 result = result && (results[i] == expected_results[i]);
3771 if (false == result)
3773 m_context.getTestContext().getLog() << tcu::TestLog::Message
3774 << "Error. Invalid result. First routine: " << first_routine_name
3775 << ". Second routine: " << second_routine_name << tcu::TestLog::EndMessage;
3777 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3779 message << "Results:";
3781 for (GLuint i = 0; i < n_varyings; ++i)
3783 results[i].log(message);
3786 message << tcu::TestLog::EndMessage;
3788 message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
3790 message << "Expected:";
3792 for (GLuint i = 0; i < n_varyings; ++i)
3794 expected_results[i].log(message);
3797 message << tcu::TestLog::EndMessage;
3805 * @param context CTS context
3807 FunctionalTest5::FunctionalTest5(deqp::Context& context)
3808 : TestCase(context, "eight_subroutines_four_uniforms", "Verify multiple subroutine sets")
3814 * @return tcu::TestNode::STOP
3816 tcu::TestNode::IterateResult FunctionalTest5::iterate()
3818 static const GLchar* vertex_shader_code =
3819 "#version 400 core\n"
3820 "#extension GL_ARB_shader_subroutine : require\n"
3822 "precision highp float;\n"
3824 "// Subroutine types\n"
3825 "subroutine vec4 routine_type_1(in vec4 left, in vec4 right);\n"
3826 "subroutine vec4 routine_type_2(in vec4 iparam);\n"
3827 "subroutine vec4 routine_type_3(in vec4 a, in vec4 b, in vec4 c);\n"
3828 "subroutine bvec4 routine_type_4(in vec4 left, in vec4 right);\n"
3830 "// Subroutine definitions\n"
3832 "subroutine(routine_type_1) vec4 add(in vec4 left, in vec4 right)\n"
3834 " return left + right;\n"
3837 "subroutine(routine_type_1) vec4 subtract(in vec4 left, in vec4 right)\n"
3839 " return left - right;\n"
3843 "subroutine(routine_type_2) vec4 square(in vec4 iparam)\n"
3845 " return iparam * iparam;\n"
3848 "subroutine(routine_type_2) vec4 square_root(in vec4 iparam)\n"
3850 " return sqrt(iparam);\n"
3854 "subroutine(routine_type_3) vec4 do_fma(in vec4 a, in vec4 b, in vec4 c)\n"
3856 " return fma(a, b, c);\n"
3859 "subroutine(routine_type_3) vec4 blend(in vec4 a, in vec4 b, in vec4 c)\n"
3861 " return c * a + (vec4(1) - c) * b;\n"
3865 "subroutine(routine_type_4) bvec4 are_equal(in vec4 left, in vec4 right)\n"
3867 " return equal(left, right);\n"
3870 "subroutine(routine_type_4) bvec4 are_greater(in vec4 left, in vec4 right)\n"
3872 " return greaterThan(left, right);\n"
3875 "// Sub routine uniforms\n"
3876 "subroutine uniform routine_type_1 first_routine;\n"
3877 "subroutine uniform routine_type_2 second_routine;\n"
3878 "subroutine uniform routine_type_3 third_routine;\n"
3879 "subroutine uniform routine_type_4 fourth_routine;\n"
3882 "uniform vec4 first_input;\n"
3883 "uniform vec4 second_input;\n"
3884 "uniform vec4 third_input;\n"
3887 "out vec4 out_result_from_first_routine;\n"
3888 "out vec4 out_result_from_second_routine;\n"
3889 "out vec4 out_result_from_third_routine;\n"
3890 "out uvec4 out_result_from_fourth_routine;\n"
3894 " out_result_from_first_routine = first_routine (first_input, second_input);\n"
3895 " out_result_from_second_routine = second_routine(first_input);\n"
3896 " out_result_from_third_routine = third_routine (first_input, second_input, third_input);\n"
3897 " out_result_from_fourth_routine = uvec4(fourth_routine(first_input, second_input));\n"
3901 static const GLchar* subroutine_names[4][2] = {
3902 { "add", "subtract" }, { "square", "square_root" }, { "do_fma", "blend" }, { "are_equal", "are_greater" }
3905 static const GLchar* subroutine_uniform_names[4][1] = {
3906 { "first_routine" }, { "second_routine" }, { "third_routine" }, { "fourth_routine" }
3909 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
3910 static const GLuint n_subroutines_per_type = sizeof(subroutine_names[0]) / sizeof(subroutine_names[0][0]);
3911 static const GLuint n_subroutine_uniforms_per_type =
3912 sizeof(subroutine_uniform_names[0]) / sizeof(subroutine_uniform_names[0][0]);
3914 static const GLchar* uniform_names[] = { "first_input", "second_input", "third_input" };
3915 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
3917 static const GLchar* varying_names[] = { "out_result_from_first_routine", "out_result_from_second_routine",
3918 "out_result_from_third_routine", "out_result_from_fourth_routine" };
3919 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]);
3920 static const GLuint transform_feedback_buffer_size = n_varyings * sizeof(GLfloat) * 4 /* vec4 */;
3923 static const Utils::vec4<GLfloat> input_data[3] = { Utils::vec4<GLfloat>(1.0f, 4.0f, 9.0f, 16.0f),
3924 Utils::vec4<GLfloat>(16.0f, 9.0f, 4.0f, 1.0f),
3925 Utils::vec4<GLfloat>(0.25f, 0.5f, 0.75f, 1.0f) };
3927 static const Utils::vec4<GLfloat> expected_result_from_first_routine[2] = {
3928 Utils::vec4<GLfloat>(17.0f, 13.0f, 13.0f, 17.0f), Utils::vec4<GLfloat>(-15.0f, -5.0f, 5.0f, 15.0f)
3931 static const Utils::vec4<GLfloat> expected_result_from_second_routine[2] = {
3932 Utils::vec4<GLfloat>(1.0f, 16.0f, 81.0f, 256.0f), Utils::vec4<GLfloat>(1.0f, 2.0f, 3.0f, 4.0f)
3935 static const Utils::vec4<GLfloat> expected_result_from_third_routine[2] = {
3936 Utils::vec4<GLfloat>(16.25f, 36.5f, 36.75f, 17.0f), Utils::vec4<GLfloat>(12.25f, 6.5f, 7.75f, 16.0f)
3939 static const Utils::vec4<GLuint> expected_result_from_fourth_routine[2] = { Utils::vec4<GLuint>(0, 0, 0, 0),
3940 Utils::vec4<GLuint>(0, 0, 1, 1) };
3942 /* All combinations of subroutines */
3943 static const GLuint subroutine_combinations[][4] = {
3944 { 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 1, 0 }, { 0, 0, 1, 1 }, { 0, 1, 0, 0 }, { 0, 1, 0, 1 },
3945 { 0, 1, 1, 0 }, { 0, 1, 1, 1 }, { 1, 0, 0, 0 }, { 1, 0, 0, 1 }, { 1, 0, 1, 0 }, { 1, 0, 1, 1 },
3946 { 1, 1, 0, 0 }, { 1, 1, 0, 1 }, { 1, 1, 1, 0 }, { 1, 1, 1, 1 }
3948 static const GLuint n_subroutine_combinations =
3949 sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
3951 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
3952 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
3954 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
3961 Utils::program program(m_context);
3962 Utils::buffer transform_feedback_buffer(m_context);
3963 Utils::vertexArray vao(m_context);
3965 /* Init GL objects */
3966 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
3974 transform_feedback_buffer.generate();
3975 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
3977 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
3979 /* Get subroutine uniform locations and subroutine indices */
3980 for (GLuint type = 0; type < n_subroutine_types; ++type)
3982 for (GLuint uniform = 0; uniform < n_subroutine_uniforms_per_type; ++uniform)
3984 m_subroutine_uniform_locations[type][uniform] =
3985 program.getSubroutineUniformLocation(subroutine_uniform_names[type][uniform], GL_VERTEX_SHADER);
3988 for (GLuint routine = 0; routine < n_subroutines_per_type; ++routine)
3990 m_subroutine_indices[type][routine] =
3991 program.getSubroutineIndex(subroutine_names[type][routine], GL_VERTEX_SHADER);
3995 /* Get uniform locations */
3996 for (GLuint i = 0; i < n_uniform_names; ++i)
3998 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
4001 /* Draw with each routine combination */
4002 for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4004 Utils::vec4<GLfloat> first_routine_result;
4005 Utils::vec4<GLfloat> second_routine_result;
4006 Utils::vec4<GLfloat> third_routine_result;
4007 Utils::vec4<GLuint> fourth_routine_result;
4009 testDraw(subroutine_combinations[i], input_data, first_routine_result, second_routine_result,
4010 third_routine_result, fourth_routine_result);
4012 if (false == verify(first_routine_result, second_routine_result, third_routine_result, fourth_routine_result,
4013 expected_result_from_first_routine[subroutine_combinations[i][0]],
4014 expected_result_from_second_routine[subroutine_combinations[i][1]],
4015 expected_result_from_third_routine[subroutine_combinations[i][2]],
4016 expected_result_from_fourth_routine[subroutine_combinations[i][3]]))
4018 logError(subroutine_names, subroutine_combinations[i], input_data, first_routine_result,
4019 second_routine_result, third_routine_result, fourth_routine_result,
4020 expected_result_from_first_routine[subroutine_combinations[i][0]],
4021 expected_result_from_second_routine[subroutine_combinations[i][1]],
4022 expected_result_from_third_routine[subroutine_combinations[i][2]],
4023 expected_result_from_fourth_routine[subroutine_combinations[i][3]]);
4032 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4036 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4039 return tcu::TestNode::STOP;
4042 /** Log error message
4044 * @param subroutine_names Array of subroutine names
4045 * @param subroutine_combination Combination of subroutines
4046 * @param input_data Input data
4047 * @param first_routine_result Result of first routine
4048 * @param second_routine_result Result of second routine
4049 * @param third_routine_result Result of third routine
4050 * @param fourth_routine_result Result of fourth routine
4051 * @param first_routine_expected_result Expected result of first routine
4052 * @param second_routine_expected_result Expected result of second routine
4053 * @param third_routine_expected_result Expected result of third routine
4054 * @param fourth_routine_expected_result Expected result of fourth routine
4056 void FunctionalTest5::logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4],
4057 const Utils::vec4<glw::GLfloat> input_data[3],
4058 const Utils::vec4<glw::GLfloat>& first_routine_result,
4059 const Utils::vec4<glw::GLfloat>& second_routine_result,
4060 const Utils::vec4<glw::GLfloat>& third_routine_result,
4061 const Utils::vec4<glw::GLuint>& fourth_routine_result,
4062 const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4063 const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4064 const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4065 const Utils::vec4<glw::GLuint>& fourth_routine_expected_result) const
4067 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4068 << tcu::TestLog::EndMessage;
4070 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4072 message << "Function: " << subroutine_names[0][subroutine_combination[0]] << "( ";
4073 input_data[0].log(message);
4075 input_data[1].log(message);
4076 message << " ). Result: ";
4077 first_routine_result.log(message);
4078 message << ". Expected: ";
4079 first_routine_expected_result.log(message);
4081 message << tcu::TestLog::EndMessage;
4083 message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4085 message << "Function: " << subroutine_names[1][subroutine_combination[1]] << "( ";
4086 input_data[0].log(message);
4087 message << " ). Result: ";
4088 second_routine_result.log(message);
4089 message << ". Expected: ";
4090 second_routine_expected_result.log(message);
4092 message << tcu::TestLog::EndMessage;
4094 message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4096 message << "Function: " << subroutine_names[2][subroutine_combination[2]] << "( ";
4097 input_data[0].log(message);
4099 input_data[1].log(message);
4101 input_data[2].log(message);
4102 message << "). Result: ";
4103 third_routine_result.log(message);
4104 message << ". Expected: ";
4105 third_routine_expected_result.log(message);
4107 message << tcu::TestLog::EndMessage;
4109 message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4111 message << "Function: " << subroutine_names[3][subroutine_combination[3]] << "( ";
4112 input_data[0].log(message);
4114 input_data[1].log(message);
4116 message << " ). Result: ";
4117 fourth_routine_result.log(message);
4118 message << ". Expected: ";
4119 fourth_routine_expected_result.log(message);
4121 message << tcu::TestLog::EndMessage;
4124 /** Execute draw call and capture results
4126 * @param subroutine_combination Combination of subroutines
4127 * @param input_data Input data
4128 * @param out_first_routine_result Result of first routine
4129 * @param out_second_routine_result Result of second routine
4130 * @param out_third_routine_result Result of third routine
4131 * @param out_fourth_routine_result Result of fourth routine
4133 void FunctionalTest5::testDraw(const glw::GLuint subroutine_combination[4],
4134 const Utils::vec4<glw::GLfloat> input_data[3],
4135 Utils::vec4<glw::GLfloat>& out_first_routine_result,
4136 Utils::vec4<glw::GLfloat>& out_second_routine_result,
4137 Utils::vec4<glw::GLfloat>& out_third_routine_result,
4138 Utils::vec4<glw::GLuint>& out_fourth_routine_result) const
4140 static const GLuint n_uniforms = sizeof(m_uniform_locations) / sizeof(m_uniform_locations[0]);
4141 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4142 GLuint subroutine_indices[4];
4143 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4145 /* Prepare subroutine uniform data */
4146 for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4148 const GLuint location = m_subroutine_uniform_locations[i][0];
4150 subroutine_indices[location] = m_subroutine_indices[i][subroutine_combination[i]];
4153 /* Set up subroutine uniforms */
4154 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4155 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4157 /* Set up input data uniforms */
4158 for (GLuint i = 0; i < n_uniforms; ++i)
4160 gl.uniform4f(m_uniform_locations[i], input_data[i].m_x, input_data[i].m_y, input_data[i].m_z,
4162 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4165 /* Execute draw call with transform feedback */
4166 gl.beginTransformFeedback(GL_POINTS);
4167 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4169 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4170 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4172 gl.endTransformFeedback();
4173 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4175 /* Capture results */
4176 GLvoid* feedback_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4177 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4179 GLfloat* float_ptr = (GLfloat*)feedback_data;
4182 out_first_routine_result.m_x = float_ptr[0];
4183 out_first_routine_result.m_y = float_ptr[1];
4184 out_first_routine_result.m_z = float_ptr[2];
4185 out_first_routine_result.m_w = float_ptr[3];
4188 out_second_routine_result.m_x = float_ptr[4];
4189 out_second_routine_result.m_y = float_ptr[5];
4190 out_second_routine_result.m_z = float_ptr[6];
4191 out_second_routine_result.m_w = float_ptr[7];
4194 out_third_routine_result.m_x = float_ptr[8];
4195 out_third_routine_result.m_y = float_ptr[9];
4196 out_third_routine_result.m_z = float_ptr[10];
4197 out_third_routine_result.m_w = float_ptr[11];
4200 GLuint* uint_ptr = (GLuint*)(float_ptr + 12);
4201 out_fourth_routine_result.m_x = uint_ptr[0];
4202 out_fourth_routine_result.m_y = uint_ptr[1];
4203 out_fourth_routine_result.m_z = uint_ptr[2];
4204 out_fourth_routine_result.m_w = uint_ptr[3];
4206 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4207 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4210 /** Verify if results match expected results
4212 * @param first_routine_result Result of first routine
4213 * @param second_routine_result Result of second routine
4214 * @param third_routine_result Result of third routine
4215 * @param fourth_routine_result Result of fourth routine
4216 * @param first_routine_expected_result Expected result of first routine
4217 * @param second_routine_expected_result Expected result of second routine
4218 * @param third_routine_expected_result Expected result of third routine
4219 * @param fourth_routine_expected_result Expected result of fourth routine
4221 bool FunctionalTest5::verify(const Utils::vec4<glw::GLfloat>& first_routine_result,
4222 const Utils::vec4<glw::GLfloat>& second_routine_result,
4223 const Utils::vec4<glw::GLfloat>& third_routine_result,
4224 const Utils::vec4<glw::GLuint>& fourth_routine_result,
4225 const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
4226 const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
4227 const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
4228 const Utils::vec4<glw::GLuint>& fourth_routine_expected_result) const
4232 result = result && (first_routine_result == first_routine_expected_result);
4233 result = result && (second_routine_result == second_routine_expected_result);
4234 result = result && (third_routine_result == third_routine_expected_result);
4235 result = result && (fourth_routine_result == fourth_routine_expected_result);
4242 * @param context CTS context
4244 FunctionalTest6::FunctionalTest6(deqp::Context& context)
4245 : TestCase(context, "static_subroutine_call", "Verify that subroutine can be called in a static manner")
4251 * @return tcu::TestNode::STOP
4253 tcu::TestNode::IterateResult FunctionalTest6::iterate()
4255 static const GLchar* vertex_shader_code = "#version 400 core\n"
4256 "#extension GL_ARB_shader_subroutine : require\n"
4258 "precision highp float;\n"
4260 "// Subroutine type\n"
4261 "subroutine vec4 routine_type(in vec4 iparam);\n"
4263 "// Subroutine definition\n"
4264 "subroutine(routine_type) vec4 square(in vec4 iparam)\n"
4266 " return iparam * iparam;\n"
4269 "// Sub routine uniform\n"
4270 "subroutine uniform routine_type routine;\n"
4273 "uniform vec4 input_data;\n"
4276 "out vec4 out_result;\n"
4280 " out_result = square(input_data);\n"
4284 static const GLchar* varying_name = "out_result";
4287 static const Utils::vec4<GLfloat> input_data(1.0f, 4.0f, 9.0f, 16.0f);
4289 static const Utils::vec4<GLfloat> expected_result(1.0f, 16.0f, 81.0f, 256.0f);
4291 static const GLuint transform_feedback_buffer_size = 4 * sizeof(GLfloat);
4293 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4294 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4296 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4300 Utils::program program(m_context);
4301 Utils::buffer transform_feedback_buffer(m_context);
4302 Utils::vertexArray vao(m_context);
4304 /* Init GL objects */
4305 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
4306 1 /* n_varyings */);
4313 transform_feedback_buffer.generate();
4314 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4316 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4320 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4321 const GLint uniform_location = gl.getUniformLocation(program.m_program_object_id, "input_data");
4323 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
4325 if (-1 == uniform_location)
4327 TCU_FAIL("Uniform is not available");
4330 /* Set up input data uniforms */
4331 gl.uniform4f(uniform_location, input_data.m_x, input_data.m_y, input_data.m_z, input_data.m_w);
4332 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4334 /* Execute draw call with transform feedback */
4335 gl.beginTransformFeedback(GL_POINTS);
4336 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4338 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4339 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4341 gl.endTransformFeedback();
4342 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4344 /* Capture results */
4345 GLfloat* feedback_data = (GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4346 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4348 Utils::vec4<GLfloat> result(feedback_data[0], feedback_data[1], feedback_data[2], feedback_data[3]);
4350 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4351 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4354 if (expected_result == result)
4356 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4360 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4361 << tcu::TestLog::EndMessage;
4363 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4365 message << "Function: square( ";
4366 input_data.log(message);
4367 message << " ). Result: ";
4368 result.log(message);
4369 message << ". Expected: ";
4370 expected_result.log(message);
4372 message << tcu::TestLog::EndMessage;
4374 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4379 return tcu::TestNode::STOP;
4384 * @param context CTS context
4386 FunctionalTest7_8::FunctionalTest7_8(deqp::Context& context)
4387 : TestCase(context, "arrayed_subroutine_uniforms", "Verify that subroutine can be called in a static manner")
4393 * @return tcu::TestNode::STOP
4395 tcu::TestNode::IterateResult FunctionalTest7_8::iterate()
4397 static const GLchar* vertex_shader_code =
4398 "#version 400 core\n"
4399 "#extension GL_ARB_shader_subroutine : require\n"
4401 "precision highp float;\n"
4403 "// Subroutine type\n"
4404 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
4406 "// Subroutine definitions\n"
4407 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
4409 " return left + right;\n"
4412 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
4414 " return left * right;\n"
4417 "// Sub routine uniform\n"
4418 "subroutine uniform routine_type routine[4];\n"
4421 "uniform vec4 uni_left;\n"
4422 "uniform vec4 uni_right;\n"
4423 "uniform uvec4 uni_indices;\n"
4426 "out vec4 out_combined;\n"
4427 "out vec4 out_combined_inverted;\n"
4428 "out vec4 out_constant;\n"
4429 "out vec4 out_constant_inverted;\n"
4430 "out vec4 out_dynamic;\n"
4431 "out vec4 out_dynamic_inverted;\n"
4432 "out vec4 out_loop;\n"
4433 "out uint out_array_length;\n"
4437 " out_combined = routine[3](routine[2](routine[1](routine[0](uni_left, uni_right), uni_right), "
4438 "uni_right), uni_right);\n"
4439 " out_combined_inverted = routine[0](routine[1](routine[2](routine[3](uni_left, uni_right), uni_right), "
4440 "uni_right), uni_right);\n"
4442 " out_constant = routine[3](routine[2](routine[1](routine[0](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4443 "-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4444 " out_constant_inverted = routine[0](routine[1](routine[2](routine[3](vec4(1, 2, 3, 4), vec4(-5, -6, -7, "
4445 "-8)), vec4(-1, -2, -3, -4)), vec4(5, 6, 7, 8)), vec4(1, 2, 3, 4));\n"
4448 "routine[uni_indices.w](routine[uni_indices.z](routine[uni_indices.y](routine[uni_indices.x](uni_left, "
4449 "uni_right), uni_right), uni_right), uni_right);\n"
4450 " out_dynamic_inverted = "
4451 "routine[uni_indices.x](routine[uni_indices.y](routine[uni_indices.z](routine[uni_indices.w](uni_left, "
4452 "uni_right), uni_right), uni_right), uni_right);\n"
4454 " out_loop = uni_left;\n"
4455 " for (uint i = 0u; i < routine.length(); ++i)\n"
4457 " out_loop = routine[i](out_loop, uni_right);\n"
4460 " out_array_length = routine.length() + 6 - (uni_indices.x + uni_indices.y + uni_indices.z + "
4465 static const GLchar* subroutine_names[] = {
4468 static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
4470 static const GLchar* subroutine_uniform_names[] = { "routine[0]", "routine[1]", "routine[2]", "routine[3]" };
4471 static const GLuint n_subroutine_uniform_names =
4472 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
4474 static const GLchar* uniform_names[] = {
4475 "uni_left", "uni_right", "uni_indices",
4477 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
4479 static const GLchar* varying_names[] = { "out_combined", "out_combined_inverted",
4480 "out_constant", "out_constant_inverted",
4481 "out_dynamic", "out_dynamic_inverted",
4482 "out_loop", "out_array_length" };
4484 static const GLuint n_varyings = sizeof(varying_names) / sizeof(varying_names[0]);
4485 static const GLuint transform_feedback_buffer_size = n_varyings * 4 * sizeof(GLfloat);
4488 static const Utils::vec4<GLfloat> uni_left(-1.0f, 0.75f, -0.5f, 0.25f);
4489 static const Utils::vec4<GLfloat> uni_right(1.0f, -0.75f, 0.5f, -0.25f);
4490 static const Utils::vec4<GLuint> uni_indices(1, 2, 0, 3);
4492 static const GLuint subroutine_combinations[][4] = {
4493 { 0, 0, 0, 0 }, /* + + + + */
4494 { 0, 0, 0, 1 }, /* + + + * */
4495 { 0, 0, 1, 0 }, /* + + * + */
4496 { 0, 0, 1, 1 }, /* + + * * */
4497 { 0, 1, 0, 0 }, /* + * + + */
4498 { 0, 1, 0, 1 }, /* + * + * */
4499 { 0, 1, 1, 0 }, /* + * * + */
4500 { 0, 1, 1, 1 }, /* + * * * */
4501 { 1, 0, 0, 0 }, /* * + + + */
4502 { 1, 0, 0, 1 }, /* * + + * */
4503 { 1, 0, 1, 0 }, /* * + * + */
4504 { 1, 0, 1, 1 }, /* * + * * */
4505 { 1, 1, 0, 0 }, /* * * + + */
4506 { 1, 1, 0, 1 }, /* * * + * */
4507 { 1, 1, 1, 0 }, /* * * * + */
4508 { 1, 1, 1, 1 } /* * * * * */
4510 static const GLuint n_subroutine_combinations =
4511 sizeof(subroutine_combinations) / sizeof(subroutine_combinations[0]);
4513 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
4514 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
4516 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
4520 Utils::program program(m_context);
4521 Utils::buffer transform_feedback_buffer(m_context);
4522 Utils::vertexArray vao(m_context);
4526 /* Init GL objects */
4527 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, varying_names,
4535 transform_feedback_buffer.generate();
4537 /* Get subroutine indices */
4538 for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
4540 m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
4543 /* Get subroutine uniform locations */
4544 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
4546 m_subroutine_uniform_locations[uniform] =
4547 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
4550 /* Get uniform locations */
4551 for (GLuint i = 0; i < n_uniform_names; ++i)
4553 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
4557 for (GLuint i = 0; i < n_subroutine_combinations; ++i)
4560 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
4562 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
4565 if (false == testDraw(subroutine_combinations[i], uni_left, uni_right, uni_indices))
4573 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4577 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4581 return tcu::TestNode::STOP;
4584 /* Calculate result of function applied to operands
4586 * @param function Function id, 0 is sum, 1 is multiplication
4587 * @param left Left operand
4588 * @param right Right operand
4589 * @param out Function result
4591 void FunctionalTest7_8::calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left,
4592 const Utils::vec4<glw::GLfloat>& right, Utils::vec4<glw::GLfloat>& out) const
4596 out.m_x = left.m_x + right.m_x;
4597 out.m_y = left.m_y + right.m_y;
4598 out.m_z = left.m_z + right.m_z;
4599 out.m_w = left.m_w + right.m_w;
4603 out.m_x = left.m_x * right.m_x;
4604 out.m_y = left.m_y * right.m_y;
4605 out.m_z = left.m_z * right.m_z;
4606 out.m_w = left.m_w * right.m_w;
4610 /** Calculate expected values for all operations
4612 * @param combination Function combination, first applied function is at index [0]
4613 * @param left Left operand
4614 * @param right Right operand
4615 * @param indices Indices used by dynamic calls
4616 * @param out_combined Expected result of "combined" operation
4617 * @param out_combined_inverted Expected result of "combined_inverted" operation
4618 * @param out_constant Expected result of "constant" operation
4619 * @param out_constant_inverted Expected result of "constant_inverted" operation
4620 * @param out_dynamic Expected result of "dynamic" operation
4621 * @param out_dynamic_inverted Expected result of "out_dynamic_inverted" operation
4622 * @param out_loop Expected result of "loop" operation
4624 void FunctionalTest7_8::calculate(
4625 const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right,
4626 const Utils::vec4<glw::GLuint>& indices, Utils::vec4<glw::GLfloat>& out_combined,
4627 Utils::vec4<glw::GLfloat>& out_combined_inverted, Utils::vec4<glw::GLfloat>& out_constant,
4628 Utils::vec4<glw::GLfloat>& out_constant_inverted, Utils::vec4<glw::GLfloat>& out_dynamic,
4629 Utils::vec4<glw::GLfloat>& out_dynamic_inverted, Utils::vec4<glw::GLfloat>& out_loop) const
4631 /* Indices used by "dynamic" operations, range <0..4> */
4632 const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4633 combination[indices.m_z], combination[indices.m_w] };
4635 /* Values used by "constant" operations, come from shader code */
4636 const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4637 Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4638 Utils::vec4<glw::GLfloat>(-1, -2, -3, -4),
4639 Utils::vec4<glw::GLfloat>(5, 6, 7, 8),
4640 Utils::vec4<glw::GLfloat>(1, 2, 3, 4) };
4643 Utils::vec4<glw::GLfloat> combined = left;
4644 Utils::vec4<glw::GLfloat> combined_inverted = left;
4645 Utils::vec4<glw::GLfloat> constant = constant_values[0];
4646 Utils::vec4<glw::GLfloat> constant_inverted = constant_values[0];
4647 Utils::vec4<glw::GLfloat> dynamic = left;
4648 Utils::vec4<glw::GLfloat> dynamic_inverted = left;
4650 /* Calculate expected results */
4651 for (GLuint i = 0; i < 4; ++i)
4653 GLuint function = combination[i];
4654 GLuint function_inverted = combination[3 - i];
4655 GLuint dynamic_function = dynamic_combination[i];
4656 GLuint dynamic_function_inverted = dynamic_combination[3 - i];
4658 calculate(function, combined, right, combined);
4659 calculate(function_inverted, combined_inverted, right, combined_inverted);
4660 calculate(function, constant, constant_values[i + 1], constant);
4661 calculate(function_inverted, constant_inverted, constant_values[i + 1], constant_inverted);
4662 calculate(dynamic_function, dynamic, right, dynamic);
4663 calculate(dynamic_function_inverted, dynamic_inverted, right, dynamic_inverted);
4667 out_combined = combined;
4668 out_combined_inverted = combined_inverted;
4669 out_constant = constant;
4670 out_constant_inverted = constant_inverted;
4671 out_dynamic = dynamic;
4672 out_dynamic_inverted = dynamic_inverted;
4673 out_loop = combined;
4678 * @param combination Operations combination
4679 * @param left Left operand
4680 * @param right Right operand
4681 * @param indices Inidices used by "dynamic" calls
4682 * @param vec4_expected Expected results
4683 * @param vec4_result Results
4684 * @param array_length Length of array
4685 * @param result Comparison results
4687 void FunctionalTest7_8::logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4688 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices,
4689 const Utils::vec4<glw::GLfloat> vec4_expected[7],
4690 const Utils::vec4<glw::GLfloat> vec4_result[7], glw::GLuint array_length,
4691 bool result[7]) const
4693 static const GLuint n_functions = 4;
4694 static const GLuint n_operations = 7;
4696 /* Indices used by "dynamic" operations, range <0..4> */
4697 const GLuint dynamic_combination[4] = { combination[indices.m_x], combination[indices.m_y],
4698 combination[indices.m_z], combination[indices.m_w] };
4700 /* Function symbols */
4701 GLchar functions[4];
4702 GLchar functions_inverted[4];
4703 GLchar functions_dynamic[4];
4704 GLchar functions_dynamic_inverted[4];
4706 for (GLuint i = 0; i < n_functions; ++i)
4708 GLchar function = (0 == combination[i]) ? '+' : '*';
4709 GLchar dynamic_function = (0 == dynamic_combination[i]) ? '+' : '*';
4711 functions[i] = function;
4712 functions_inverted[n_functions - i - 1] = function;
4713 functions_dynamic[i] = dynamic_function;
4714 functions_dynamic_inverted[n_functions - i - 1] = dynamic_function;
4717 /* Values used by "constant" operations, come from shader code */
4718 const Utils::vec4<glw::GLfloat> constant_values[] = { Utils::vec4<glw::GLfloat>(1, 2, 3, 4),
4719 Utils::vec4<glw::GLfloat>(-5, -6, -7, -8),
4720 Utils::vec4<glw::GLfloat>(-1, -2, -3, -4),
4721 Utils::vec4<glw::GLfloat>(5, 6, 7, 8),
4722 Utils::vec4<glw::GLfloat>(1, 2, 3, 4) };
4724 /* Values used by non-"constant" operations */
4725 Utils::vec4<glw::GLfloat> dynamic_values[5];
4726 dynamic_values[0] = left;
4727 dynamic_values[1] = right;
4728 dynamic_values[2] = right;
4729 dynamic_values[3] = right;
4730 dynamic_values[4] = right;
4732 /* For each operation */
4733 for (GLuint i = 0; i < n_operations; ++i)
4735 /* If result is failure */
4736 if (false == result[i])
4738 const GLchar* description = 0;
4739 const Utils::vec4<glw::GLfloat>* input = 0;
4740 const GLchar* operation = 0;
4745 description = "Call made with predefined array indices";
4746 input = dynamic_values;
4747 operation = functions;
4750 description = "Call made with predefined array indices in inverted order";
4751 input = dynamic_values;
4752 operation = functions_inverted;
4755 description = "Call made with predefined array indices, for constant values";
4756 input = constant_values;
4757 operation = functions;
4760 description = "Call made with predefined array indices in inverted order, for constant values";
4761 input = constant_values;
4762 operation = functions_inverted;
4765 description = "Call made with dynamic array indices";
4766 input = dynamic_values;
4767 operation = functions_dynamic;
4770 description = "Call made with dynamic array indices in inverted order";
4771 input = dynamic_values;
4772 operation = functions_dynamic_inverted;
4775 description = "Call made with loop";
4776 input = dynamic_values;
4777 operation = functions;
4781 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
4782 << tcu::TestLog::EndMessage;
4784 m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage;
4786 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4788 message << "Operation: ((((";
4789 input[0].log(message);
4790 for (GLuint function = 0; function < n_functions; ++function)
4792 message << " " << operation[function] << " ";
4794 input[function + 1].log(message);
4799 message << tcu::TestLog::EndMessage;
4801 message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4803 message << "Result: ";
4804 vec4_result[i].log(message);
4806 message << tcu::TestLog::EndMessage;
4808 message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
4810 message << "Expected: ";
4811 vec4_expected[i].log(message);
4813 message << tcu::TestLog::EndMessage;
4816 /* Check array length, it should be 4 */
4817 if (4 != array_length)
4819 m_context.getTestContext().getLog() << tcu::TestLog::Message
4820 << "Error. Invalid array length: " << array_length << ". Expected 4."
4821 << tcu::TestLog::EndMessage;
4826 /** Execute draw call and verifies captrued varyings
4828 * @param combination Function combination, first applied function is at index [0]
4829 * @param left Left operand
4830 * @param right Right operand
4831 * @param indices Indices used by dynamic calls
4833 * @return true if all results match expected values, false otherwise
4835 bool FunctionalTest7_8::testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
4836 const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const
4838 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4839 static const GLuint n_vec4_varyings = 7;
4841 GLuint subroutine_indices[4];
4842 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
4844 /* Prepare expected results */
4845 Utils::vec4<glw::GLfloat> expected_results[7];
4846 calculate(combination, left, right, indices, expected_results[0], expected_results[1], expected_results[2],
4847 expected_results[3], expected_results[4], expected_results[5], expected_results[6]);
4849 /* Set up input data uniforms */
4850 gl.uniform4f(m_uniform_locations[0], left.m_x, left.m_y, left.m_z, left.m_w);
4851 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4853 gl.uniform4f(m_uniform_locations[1], right.m_x, right.m_y, right.m_z, right.m_w);
4854 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
4856 gl.uniform4ui(m_uniform_locations[2], indices.m_x, indices.m_y, indices.m_z, indices.m_w);
4857 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4ui");
4859 /* Prepare subroutine uniform data */
4860 for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
4862 const GLuint location = m_subroutine_uniform_locations[i];
4864 subroutine_indices[location] = m_subroutine_indices[combination[i]];
4867 /* Set up subroutine uniforms */
4868 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
4869 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
4871 /* Execute draw call with transform feedback */
4872 gl.beginTransformFeedback(GL_POINTS);
4873 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4875 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
4876 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4878 gl.endTransformFeedback();
4879 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
4881 /* Capture results */
4882 GLvoid* feedback_data = (GLvoid*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4883 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4885 Utils::vec4<GLfloat> vec4_results[7];
4887 GLfloat* float_data = (GLfloat*)feedback_data;
4888 for (GLuint i = 0; i < n_vec4_varyings; ++i)
4890 vec4_results[i].m_x = float_data[i * 4 + 0];
4891 vec4_results[i].m_y = float_data[i * 4 + 1];
4892 vec4_results[i].m_z = float_data[i * 4 + 2];
4893 vec4_results[i].m_w = float_data[i * 4 + 3];
4896 GLuint* uint_data = (GLuint*)(float_data + (n_vec4_varyings)*4);
4897 GLuint array_length = uint_data[0];
4900 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4901 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4904 for (GLuint i = 0; i < n_vec4_varyings; ++i)
4906 results[i] = (vec4_results[i] == expected_results[i]);
4907 result = result && results[i];
4910 result = result && (4 == array_length);
4912 /* Log error if any */
4913 if (false == result)
4915 logError(combination, left, right, indices, expected_results, vec4_results, array_length, results);
4924 * @param context Rendering context.
4927 FunctionalTest9::FunctionalTest9(deqp::Context& context)
4928 : TestCase(context, "subroutines_3_subroutine_types_and_subroutine_uniforms_one_function",
4929 "Makes sure that program with one function associated with 3 different "
4930 "subroutine types and 3 subroutine uniforms using that function compiles "
4931 "and works as expected")
4932 , m_has_test_passed(true)
4933 , m_n_points_to_draw(16) /* arbitrary value */
4939 /* Left blank intentionally */
4942 /** De-initializes GL objects that may have been created during test execution. */
4943 void FunctionalTest9::deinit()
4945 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4949 gl.deleteProgram(m_po_id);
4956 gl.deleteVertexArrays(1, &m_vao_id);
4963 gl.deleteShader(m_vs_id);
4968 if (m_xfb_bo_id != 0)
4970 gl.deleteBuffers(1, &m_xfb_bo_id);
4976 /** Retrieves body of a vertex shader that should be used
4977 * for the testing purposes.
4979 std::string FunctionalTest9::getVertexShaderBody() const
4981 return "#version 400\n"
4983 "#extension GL_ARB_shader_subroutine : require\n"
4985 "subroutine void subroutineType1(inout float);\n"
4986 "subroutine void subroutineType2(inout float);\n"
4987 "subroutine void subroutineType3(inout float);\n"
4989 "subroutine(subroutineType1, subroutineType2, subroutineType3) void function(inout float result)\n"
4991 " result += float(0.123) + float(gl_VertexID);\n"
4994 "subroutine uniform subroutineType1 subroutine_uniform1;\n"
4995 "subroutine uniform subroutineType2 subroutine_uniform2;\n"
4996 "subroutine uniform subroutineType3 subroutine_uniform3;\n"
4998 "out vec4 result;\n"
5002 " result = vec4(0, 1, 2, 3);\n"
5004 " subroutine_uniform1(result.x);\n"
5005 " subroutine_uniform2(result.y);\n"
5006 " subroutine_uniform3(result.z);\n"
5008 " result.w += result.x + result.y + result.z;\n"
5012 /** Initializes all GL objects required to run the test. */
5013 void FunctionalTest9::initTest()
5015 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5017 /* Set up program object */
5018 const char* xfb_varyings[] = { "result" };
5020 const unsigned int n_xfb_varyings = sizeof(xfb_varyings) / sizeof(xfb_varyings[0]);
5021 if (!Utils::buildProgram(gl, getVertexShaderBody(), "", /* tc_body */
5025 xfb_varyings, n_xfb_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
5026 DE_NULL, /* out_te_id */
5027 DE_NULL, /* out_gs_id */
5028 DE_NULL, /* out_fs_id */
5031 TCU_FAIL("Program failed to link successfully");
5034 /* Set up a buffer object we will use to hold XFB data */
5035 const unsigned int xfb_bo_size = static_cast<unsigned int>(sizeof(float) * 4 /* components */ * m_n_points_to_draw);
5037 gl.genBuffers(1, &m_xfb_bo_id);
5038 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
5040 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
5041 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
5043 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
5044 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
5046 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL, /* data */
5048 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
5050 /* Generate & bind a VAO */
5051 gl.genVertexArrays(1, &m_vao_id);
5052 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
5054 gl.bindVertexArray(m_vao_id);
5055 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
5058 /** Executes test iteration.
5060 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
5062 tcu::TestNode::IterateResult FunctionalTest9::iterate()
5064 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5066 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5067 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5069 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5073 /* Issue a draw call to make use of the three subroutine uniforms that we've defined */
5074 gl.useProgram(m_po_id);
5075 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
5077 gl.beginTransformFeedback(GL_POINTS);
5078 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
5080 gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
5081 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
5083 gl.endTransformFeedback();
5084 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
5086 /* Map the XFB BO storage into process space */
5087 const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5088 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
5090 verifyXFBData(xfb_data_ptr);
5092 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5093 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
5096 if (m_has_test_passed)
5098 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5102 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5108 /** Verifies the data XFBed out by the vertex shader. Should the data
5109 * be found invalid, m_has_test_passed will be set to false.
5111 * @param data_ptr XFB data.
5113 void FunctionalTest9::verifyXFBData(const glw::GLvoid* data_ptr)
5115 const float epsilon = 1e-5f;
5116 bool should_continue = true;
5117 const glw::GLfloat* traveller_ptr = (const glw::GLfloat*)data_ptr;
5119 for (unsigned int n_point = 0; n_point < m_n_points_to_draw && should_continue; ++n_point)
5121 tcu::Vec4 expected_result(0, 1, 2, 3);
5123 for (unsigned int n_component = 0; n_component < 3 /* xyz */; ++n_component)
5125 expected_result[n_component] += 0.123f + float(n_point);
5128 expected_result[3 /* w */] += expected_result[0] + expected_result[1] + expected_result[2];
5130 if (de::abs(expected_result[0] - traveller_ptr[0]) > epsilon ||
5131 de::abs(expected_result[1] - traveller_ptr[1]) > epsilon ||
5132 de::abs(expected_result[2] - traveller_ptr[2]) > epsilon ||
5133 de::abs(expected_result[3] - traveller_ptr[3]) > epsilon)
5135 m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data is invalid. Expected:"
5137 << expected_result[0] << ", " << expected_result[1] << ", " << expected_result[2] << ", "
5138 << expected_result[3] << "), found:(" << traveller_ptr[0] << ", " << traveller_ptr[1]
5139 << ", " << traveller_ptr[2] << ", " << traveller_ptr[3] << ")."
5140 << tcu::TestLog::EndMessage;
5142 m_has_test_passed = false;
5143 should_continue = false;
5146 traveller_ptr += 4; /* xyzw */
5147 } /* for (all rendered points) */
5152 * @param context CTS context
5154 FunctionalTest10::FunctionalTest10(deqp::Context& context)
5155 : TestCase(context, "arrays_of_arrays_of_uniforms", "Verify that arrays of arrays of uniforms works as expected")
5161 * @return tcu::TestNode::STOP
5163 tcu::TestNode::IterateResult FunctionalTest10::iterate()
5165 static const GLchar* vertex_shader_code = "#version 400 core\n"
5166 "#extension GL_ARB_arrays_of_arrays : require\n"
5167 "#extension GL_ARB_shader_subroutine : require\n"
5169 "precision highp float;\n"
5171 "// Subroutine type\n"
5172 "subroutine int routine_type(in int iparam);\n"
5174 "// Subroutine definitions\n"
5175 "subroutine(routine_type) int increment(in int iparam)\n"
5177 " return iparam + 1;\n"
5180 "subroutine(routine_type) int decrement(in int iparam)\n"
5182 " return iparam - 1;\n"
5185 "// Sub routine uniform\n"
5186 "subroutine uniform routine_type routine[4][4];\n"
5189 "out int out_result;\n"
5193 " int result = 0;\n"
5195 " for (uint j = 0; j < routine.length(); ++j)\n"
5197 " for (uint i = 0; i < routine[j].length(); ++i)\n"
5199 " result = routine[j][i](result);\n"
5203 " out_result = result;\n"
5207 static const GLchar* subroutine_names[] = {
5208 "increment", "decrement",
5210 static const GLuint n_subroutine_names = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5212 static const GLchar* subroutine_uniform_names[] = {
5213 "routine[0][0]", "routine[1][0]", "routine[2][0]", "routine[3][0]", "routine[0][1]", "routine[1][1]",
5214 "routine[2][1]", "routine[3][1]", "routine[0][2]", "routine[1][2]", "routine[2][2]", "routine[3][2]",
5215 "routine[0][3]", "routine[1][3]", "routine[2][3]", "routine[3][3]"
5217 static const GLuint n_subroutine_uniform_names =
5218 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5220 static const GLchar* varying_name = "out_result";
5221 static const GLuint transform_feedback_buffer_size = sizeof(GLint);
5223 static const GLuint configuration_increment[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5225 static const GLuint configuration_decrement[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
5227 static const GLuint configuration_mix[16] = { 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1 };
5229 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5230 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5232 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5235 /* Do not execute the test if GL_ARB_arrays_of_arrays is not supported */
5236 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_arrays_of_arrays"))
5238 throw tcu::NotSupportedError("GL_ARB_arrays_of_arrays is not supported.");
5244 Utils::program program(m_context);
5245 Utils::buffer transform_feedback_buffer(m_context);
5246 Utils::vertexArray vao(m_context);
5248 /* Init GL objects */
5249 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code, &varying_name,
5250 1 /* n_varyings */);
5257 transform_feedback_buffer.generate();
5258 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
5260 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
5262 /* Get subroutine indices */
5263 for (GLuint routine = 0; routine < n_subroutine_names; ++routine)
5265 m_subroutine_indices[routine] = program.getSubroutineIndex(subroutine_names[routine], GL_VERTEX_SHADER);
5268 /* Get subroutine uniform locations */
5269 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5271 m_subroutine_uniform_locations[uniform] =
5272 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
5276 GLint increment_result = testDraw(configuration_increment);
5277 GLint decrement_result = testDraw(configuration_decrement);
5278 GLint mix_result = testDraw(configuration_mix);
5281 if (16 != increment_result)
5286 if (-16 != decrement_result)
5290 if (0 != mix_result)
5295 /* Set test result */
5298 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5302 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
5303 << " Incrementation applied 16 times: " << increment_result
5304 << ". Decrementation applied 16 times: " << decrement_result
5305 << ". Incrementation and decrementation applied 8 times: " << mix_result
5306 << tcu::TestLog::EndMessage;
5308 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5312 return tcu::TestNode::STOP;
5315 /** Execute draw call and return captured varying
5317 * @param routine_indices Configuration of subroutine uniforms
5319 * @return Value of varying captured with transform feedback
5321 GLint FunctionalTest10::testDraw(const GLuint routine_indices[16]) const
5323 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5324 GLuint subroutine_indices[16];
5325 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
5327 /* Prepare subroutine uniform data */
5328 for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5330 const GLuint location = m_subroutine_uniform_locations[i];
5332 subroutine_indices[location] = m_subroutine_indices[routine_indices[i]];
5335 /* Set up subroutine uniforms */
5336 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
5337 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5339 /* Execute draw call with transform feedback */
5340 gl.beginTransformFeedback(GL_POINTS);
5341 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5343 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5344 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5346 gl.endTransformFeedback();
5347 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5349 /* Capture results */
5350 GLint* feedback_data = (GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5351 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5353 GLint result = feedback_data[0];
5356 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5357 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5362 /* Definitions of constants used by FunctionalTest11 */
5363 const GLuint FunctionalTest11::m_texture_height = 32;
5364 const GLuint FunctionalTest11::m_texture_width = 32;
5368 * @param context CTS context
5370 FunctionalTest11::FunctionalTest11(deqp::Context& context)
5371 : TestCase(context, "globals_sampling_output_discard_function_calls", "Verify that global variables, texture "
5372 "sampling, fragment output, fragment discard "
5373 "and function calls work as expected")
5379 * @return tcu::TestNode::STOP
5381 tcu::TestNode::IterateResult FunctionalTest11::iterate()
5383 static const GLchar* fragment_shader_code =
5384 "#version 400 core\n"
5385 "#extension GL_ARB_shader_subroutine : require\n"
5387 "precision highp float;\n"
5390 "layout(location = 0) out vec4 out_color;\n"
5392 "// Global variables\n"
5393 "vec4 success_color;\n"
5394 "vec4 failure_color;\n"
5397 "uniform sampler2D sampler_1;\n"
5398 "uniform sampler2D sampler_2;\n"
5401 "bool are_same(in vec4 left, in vec4 right)\n"
5405 " result.x = (left.x == right.x);\n"
5406 " result.y = (left.y == right.y);\n"
5407 " result.z = (left.z == right.z);\n"
5408 " result.w = (left.w == right.w);\n"
5410 " return all(result);\n"
5413 "bool are_different(in vec4 left, in vec4 right)\n"
5417 " result.x = (left.x != right.x);\n"
5418 " result.y = (left.y != right.y);\n"
5419 " result.z = (left.z != right.z);\n"
5420 " result.w = (left.w != right.w);\n"
5422 " return any(result);\n"
5425 "// Subroutine types\n"
5426 "subroutine void discard_fragment_type(void);\n"
5427 "subroutine void set_global_colors_type(void);\n"
5428 "subroutine vec4 sample_texture_type(in vec2);\n"
5429 "subroutine bool comparison_type(in vec4 left, in vec4 right);\n"
5430 "subroutine void test_type(void);\n"
5432 "// Subroutine definitions\n"
5433 "// discard_fragment_type\n"
5434 "subroutine(discard_fragment_type) void discard_yes(void)\n"
5439 "subroutine(discard_fragment_type) void discard_no(void)\n"
5443 "// set_global_colors_type\n"
5444 "subroutine(set_global_colors_type) void red_pass_blue_fail(void)\n"
5446 " success_color = vec4(1, 0, 0, 1);\n"
5447 " failure_color = vec4(0, 0, 1, 1);\n"
5450 "subroutine(set_global_colors_type) void blue_pass_red_fail(void)\n"
5452 " success_color = vec4(0, 0, 1, 1);\n"
5453 " failure_color = vec4(1, 0, 0, 1);\n"
5456 "// sample_texture_type\n"
5457 "subroutine(sample_texture_type) vec4 first_sampler(in vec2 coord)\n"
5459 " return texture(sampler_1, coord);\n"
5462 "subroutine(sample_texture_type) vec4 second_sampler(in vec2 coord)\n"
5464 " return texture(sampler_2, coord);\n"
5467 "// comparison_type\n"
5468 "subroutine(comparison_type) bool check_equal(in vec4 left, in vec4 right)\n"
5470 " return are_same(left, right);\n"
5473 "subroutine(comparison_type) bool check_not_equal(in vec4 left, in vec4 right)\n"
5475 " return are_different(left, right);\n"
5478 "// Subroutine uniforms\n"
5479 "subroutine uniform discard_fragment_type discard_fragment;\n"
5480 "subroutine uniform set_global_colors_type set_global_colors;\n"
5481 "subroutine uniform sample_texture_type sample_texture;\n"
5482 "subroutine uniform comparison_type compare;\n"
5484 "// Subroutine definitions\n"
5486 "subroutine(test_type) void test_with_discard(void)\n"
5488 " discard_fragment();"
5490 " out_color = failure_color;\n"
5492 " set_global_colors();\n"
5494 " vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5496 " bool comparison_result = compare(success_color, sampled_color);\n"
5498 " if (true == comparison_result)\n"
5500 " out_color = success_color;\n"
5504 " out_color = failure_color;\n"
5508 "subroutine(test_type) void test_without_discard(void)\n"
5510 " set_global_colors();\n"
5512 " vec4 sampled_color = sample_texture(gl_PointCoord);\n"
5514 " bool comparison_result = compare(success_color, sampled_color);\n"
5516 " if (true == comparison_result)\n"
5518 " out_color = success_color;\n"
5522 " out_color = failure_color;\n"
5526 "// Subroutine uniforms\n"
5527 "subroutine uniform test_type test;\n"
5532 " success_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5533 " failure_color = vec4(0.5, 0.5, 0.5, 0.5);\n"
5539 static const GLchar* geometry_shader_code = "#version 400 core\n"
5540 "#extension GL_ARB_shader_subroutine : require\n"
5542 "precision highp float;\n"
5544 "layout(points) in;\n"
5545 "layout(triangle_strip, max_vertices = 4) out;\n"
5549 " gl_Position = vec4(-1, -1, 0, 1);\n"
5552 " gl_Position = vec4(-1, 1, 0, 1);\n"
5555 " gl_Position = vec4( 1, -1, 0, 1);\n"
5558 " gl_Position = vec4( 1, 1, 0, 1);\n"
5561 " EndPrimitive();\n"
5565 static const GLchar* vertex_shader_code = "#version 400 core\n"
5566 "#extension GL_ARB_shader_subroutine : require\n"
5568 "precision highp float;\n"
5575 static const GLchar* subroutine_names[][2] = { { "discard_yes", "discard_no" },
5576 { "red_pass_blue_fail", "blue_pass_red_fail" },
5577 { "first_sampler", "second_sampler" },
5578 { "check_equal", "check_not_equal" },
5579 { "test_with_discard", "test_without_discard" } };
5580 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
5582 static const GLchar* subroutine_uniform_names[] = { "discard_fragment", "set_global_colors", "sample_texture",
5583 "compare", "test" };
5584 static const GLuint n_subroutine_uniform_names =
5585 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
5587 static const GLchar* uniform_names[] = {
5588 "sampler_1", "sampler_2",
5590 static const GLuint n_uniform_names = sizeof(uniform_names) / sizeof(uniform_names[0]);
5593 static const GLubyte blue_color[4] = { 0, 0, 255, 255 };
5594 static const GLubyte clean_color[4] = { 0, 0, 0, 0 };
5595 static const GLubyte red_color[4] = { 255, 0, 0, 255 };
5597 /* Configurations */
5598 static const testConfiguration test_configurations[] = {
5600 "Expect red color from 1st sampler", red_color, 1 /* discard_fragment : discard_no */,
5601 0 /* set_global_colors : red_pass_blue_fail */, 0 /* sample_texture : first_sampler */,
5602 0 /* compare : check_equal */, 0 /* test : test_with_discard */, 1 /* red */,
5606 "Test \"without discard\" option, expect no blue color from 2nd sampler", blue_color,
5607 0 /* discard_fragment : discard_yes */, 1 /* set_global_colors : blue_pass_red_fail */,
5608 1 /* sample_texture : second_sampler */, 1 /* compare : check_not_equal */,
5609 1 /* test : test_without_discard */, 0 /* blue */, 1 /* red */),
5611 testConfiguration("Fragment shoud be discarded", clean_color, 0 /* discard_fragment : discard_yes */,
5612 0 /* set_global_colors : red_pass_blue_fail */,
5613 0 /* sample_texture : first_sampler */,
5614 0 /* compare : check_equal */,
5615 0 /* test : test_with_discard */, 1 /* red */, 0 /* blue */),
5618 "Expect blue color from 1st sampler", blue_color, 1 /* discard_fragment : discard_no */,
5619 1 /* set_global_colors : blue_pass_red_fail */, 0 /* sample_texture : first_sampler */,
5620 0 /* compare : check_equal */, 0 /* test : test_with_discard */,
5621 0 /* blue */, 1 /* red */),
5624 "Expect red color from 2nd sampler", red_color, 1 /* discard_fragment : discard_no */,
5625 0 /* set_global_colors : red_pass_blue_fail */, 1 /* sample_texture : second_sampler */,
5626 0 /* compare : check_equal */, 0 /* test : test_with_discard */,
5627 0 /* blue */, 1 /* red */),
5630 "Expect no blue color from 2nd sampler", blue_color, 1 /* discard_fragment : discard_no */,
5631 1 /* set_global_colors : blue_pass_red_fail */, 1 /* sample_texture : second_sampler */,
5632 1 /* compare : check_not_equal */, 0 /* test : test_with_discard */,
5633 0 /* blue */, 1 /* red */),
5635 static const GLuint n_test_cases = sizeof(test_configurations) / sizeof(test_configurations[0]);
5637 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5638 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5640 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5644 Utils::texture blue_texture(m_context);
5645 Utils::texture color_texture(m_context);
5646 Utils::framebuffer framebuffer(m_context);
5647 Utils::program program(m_context);
5648 Utils::texture red_texture(m_context);
5649 Utils::vertexArray vao(m_context);
5651 /* Init GL objects */
5652 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
5653 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
5660 blue_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5661 color_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5662 red_texture.create(m_texture_width, m_texture_height, GL_RGBA8);
5664 framebuffer.generate();
5666 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
5668 /* Get subroutine indices */
5669 for (GLuint type = 0; type < n_subroutine_types; ++type)
5671 m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_FRAGMENT_SHADER);
5672 m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_FRAGMENT_SHADER);
5675 /* Get subroutine uniform locations */
5676 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
5678 m_subroutine_uniform_locations[uniform] =
5679 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_FRAGMENT_SHADER);
5682 /* Get uniform locations */
5683 for (GLuint i = 0; i < n_uniform_names; ++i)
5685 m_uniform_locations[i] = program.getUniformLocation(uniform_names[i]);
5688 /* Prepare textures */
5689 fillTexture(blue_texture, blue_color);
5690 fillTexture(color_texture, clean_color);
5691 fillTexture(red_texture, red_color);
5693 m_source_textures[0] = blue_texture.m_id;
5694 m_source_textures[1] = red_texture.m_id;
5696 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
5700 for (GLuint i = 0; i < n_test_cases; ++i)
5702 /* Clean output texture */
5703 framebuffer.clear(GL_COLOR_BUFFER_BIT);
5706 if (false == testDraw(test_configurations[i].m_routines, test_configurations[i].m_samplers,
5707 test_configurations[i].m_expected_color, color_texture))
5709 m_context.getTestContext().getLog()
5710 << tcu::TestLog::Message << "Error. Failure for configuration: " << test_configurations[i].m_description
5711 << tcu::TestLog::EndMessage;
5720 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5724 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5728 return tcu::TestNode::STOP;
5731 /** Fill texture with specified color
5733 * @param texture Texture instance
5734 * @param color Color
5736 void FunctionalTest11::fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const
5738 std::vector<GLubyte> texture_data;
5740 /* Prepare texture data */
5741 texture_data.resize(m_texture_width * m_texture_height * 4);
5743 for (GLuint y = 0; y < m_texture_height; ++y)
5745 const GLuint line_offset = y * m_texture_width * 4;
5747 for (GLuint x = 0; x < m_texture_width; ++x)
5749 const GLuint point_offset = x * 4 + line_offset;
5751 texture_data[point_offset + 0] = color[0]; /* red */
5752 texture_data[point_offset + 1] = color[1]; /* green */
5753 texture_data[point_offset + 2] = color[2]; /* blue */
5754 texture_data[point_offset + 3] = color[3]; /* alpha */
5758 texture.update(m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
5761 /** Execute draw call and verify results
5763 * @param routine_configuration Configurations of routines to be used
5764 * @param sampler_configuration Configuration of textures to be bound to samplers
5765 * @param expected_color Expected color of result image
5767 * @return true if result image is filled with expected color, false otherwise
5769 bool FunctionalTest11::testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2],
5770 const glw::GLubyte expected_color[4], Utils::texture& color_texture) const
5772 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5773 static const GLint n_samplers = 2;
5774 static const GLint n_subroutine_uniforms = 5;
5775 GLuint subroutine_indices[5];
5778 for (GLuint i = 0; i < n_samplers; ++i)
5780 const GLuint location = m_uniform_locations[i];
5781 const GLuint texture = m_source_textures[sampler_configuration[i]];
5783 gl.activeTexture(GL_TEXTURE0 + i);
5784 GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture");
5786 gl.bindTexture(GL_TEXTURE_2D, texture);
5787 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5789 gl.uniform1i(location, i);
5790 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
5793 gl.activeTexture(GL_TEXTURE0 + 0);
5795 /* Set subroutine uniforms */
5796 for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
5798 const GLuint location = m_subroutine_uniform_locations[i];
5799 const GLuint routine = routine_configuration[i];
5801 subroutine_indices[location] = m_subroutine_indices[i][routine];
5804 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 5, subroutine_indices);
5805 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
5808 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5809 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5811 /* Capture result */
5812 std::vector<GLubyte> captured_data;
5813 captured_data.resize(m_texture_width * m_texture_height * 4);
5815 color_texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &captured_data[0]);
5818 for (GLuint y = 0; y < m_texture_height; ++y)
5820 const GLuint line_offset = y * m_texture_width * 4;
5822 for (GLuint x = 0; x < m_texture_width; ++x)
5824 const GLuint point_offset = x * 4 + line_offset;
5825 bool is_as_expected = true;
5827 is_as_expected = is_as_expected && (expected_color[0] == captured_data[point_offset + 0]); /* red */
5828 is_as_expected = is_as_expected && (expected_color[1] == captured_data[point_offset + 1]); /* green */
5829 is_as_expected = is_as_expected && (expected_color[2] == captured_data[point_offset + 2]); /* blue */
5830 is_as_expected = is_as_expected && (expected_color[3] == captured_data[point_offset + 3]); /* alpha */
5832 if (false == is_as_expected)
5843 /* Constatns used by FunctionalTest12 */
5844 const glw::GLuint FunctionalTest12::m_texture_height = 16;
5845 const glw::GLuint FunctionalTest12::m_texture_width = 16;
5849 * @param context CTS context
5851 FunctionalTest12::FunctionalTest12(deqp::Context& context)
5852 : TestCase(context, "ssbo_atomic_image_load_store",
5853 "Verify that SSBO, atomic counters and image load store work as expected")
5861 * @return tcu::TestNode::STOP
5863 tcu::TestNode::IterateResult FunctionalTest12::iterate()
5865 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
5866 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
5868 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
5873 /* Test atomic counters */
5874 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
5876 if (false == testAtomic())
5882 /* Test shader storage buffer */
5883 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_storage_buffer_object"))
5885 if (false == testSSBO())
5891 /* Test image load store */
5892 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_image_load_store"))
5894 if (false == testImage())
5903 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5907 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5911 return tcu::TestNode::STOP;
5914 /** Fill texture with specified color
5916 * @param texture Texture instance
5917 * @param color Color
5919 void FunctionalTest12::fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const
5921 std::vector<GLuint> texture_data;
5923 /* Prepare texture data */
5924 texture_data.resize(m_texture_width * m_texture_height * 4);
5926 for (GLuint y = 0; y < m_texture_height; ++y)
5928 const GLuint line_offset = y * m_texture_width * 4;
5930 for (GLuint x = 0; x < m_texture_width; ++x)
5932 const GLuint point_offset = x * 4 + line_offset;
5934 texture_data[point_offset + 0] = color[0]; /* red */
5935 texture_data[point_offset + 1] = color[1]; /* green */
5936 texture_data[point_offset + 2] = color[2]; /* blue */
5937 texture_data[point_offset + 3] = color[3]; /* alpha */
5941 texture.update(m_texture_width, m_texture_height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &texture_data[0]);
5944 /** Test atomic counters
5946 * @return true if test pass, false otherwise
5948 bool FunctionalTest12::testAtomic()
5950 static const GLchar* fragment_shader_code = "#version 400 core\n"
5951 "#extension GL_ARB_shader_atomic_counters : require\n"
5952 "#extension GL_ARB_shader_subroutine : require\n"
5954 "precision highp float;\n"
5956 "layout(location = 0) out uint out_color;\n"
5958 "layout(binding = 0, offset = 8) uniform atomic_uint one;\n"
5959 "layout(binding = 0, offset = 4) uniform atomic_uint two;\n"
5960 "layout(binding = 0, offset = 0) uniform atomic_uint three;\n"
5962 "subroutine void atomic_routine(void)\n;"
5964 "subroutine(atomic_routine) void increment_two(void)\n"
5966 " out_color = atomicCounterIncrement(two);\n"
5969 "subroutine(atomic_routine) void decrement_three(void)\n"
5971 " out_color = atomicCounterDecrement(three);\n"
5974 "subroutine(atomic_routine) void read_one(void)\n"
5976 " out_color = atomicCounter(one);\n"
5979 "subroutine uniform atomic_routine routine;\n"
5987 static const GLchar* geometry_shader_code = "#version 400 core\n"
5988 "#extension GL_ARB_shader_subroutine : require\n"
5990 "precision highp float;\n"
5992 "layout(points) in;\n"
5993 "layout(triangle_strip, max_vertices = 4) out;\n"
5997 " gl_Position = vec4(-1, -1, 0, 1);\n"
6000 " gl_Position = vec4(-1, 1, 0, 1);\n"
6003 " gl_Position = vec4( 1, -1, 0, 1);\n"
6006 " gl_Position = vec4( 1, 1, 0, 1);\n"
6009 " EndPrimitive();\n"
6013 static const GLchar* vertex_shader_code = "#version 400 core\n"
6014 "#extension GL_ARB_shader_subroutine : require\n"
6016 "precision highp float;\n"
6023 static const GLchar* subroutine_names[] = { "increment_two", "decrement_three", "read_one" };
6026 static const glw::GLuint atomic_buffer_data[] = { m_texture_width * m_texture_height,
6027 m_texture_width * m_texture_height,
6028 m_texture_width * m_texture_height };
6030 static const glw::GLuint expected_incremented_two[] = { atomic_buffer_data[0], 2 * atomic_buffer_data[1],
6031 atomic_buffer_data[2] };
6033 static const glw::GLuint expected_decremented_three[] = { 0, expected_incremented_two[1],
6034 expected_incremented_two[2] };
6036 static const glw::GLuint expected_read_one[] = { expected_decremented_three[0], expected_decremented_three[1],
6037 expected_decremented_three[2] };
6040 Utils::buffer atomic_buffer(m_context);
6041 Utils::texture color_texture(m_context);
6042 Utils::framebuffer framebuffer(m_context);
6043 Utils::program program(m_context);
6044 Utils::vertexArray vao(m_context);
6046 /* Init GL objects */
6047 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6048 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6055 color_texture.create(m_texture_width, m_texture_height, GL_R32UI);
6057 atomic_buffer.generate();
6058 atomic_buffer.update(GL_ATOMIC_COUNTER_BUFFER, sizeof(atomic_buffer_data), (GLvoid*)atomic_buffer_data,
6060 atomic_buffer.bindRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* index */, 0 /* offset */, sizeof(atomic_buffer_data));
6062 framebuffer.generate();
6064 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6065 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6066 framebuffer.clear(GL_COLOR_BUFFER_BIT);
6068 /* Subroutine indices */
6069 GLuint increment_two = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6070 GLuint decrement_three = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6071 GLuint read_one = program.getSubroutineIndex(subroutine_names[2], GL_FRAGMENT_SHADER);
6076 if (false == testAtomicDraw(increment_two, expected_incremented_two))
6081 if (false == testAtomicDraw(decrement_three, expected_decremented_three))
6086 if (false == testAtomicDraw(read_one, expected_read_one))
6095 /** Execture draw call and verify results
6097 * @param subroutine_index Index of subroutine that shall be used during draw call
6098 * @param expected_results Expected results
6100 * @return true if results are as expected, false otherwise
6102 bool FunctionalTest12::testAtomicDraw(GLuint subroutine_index, const GLuint expected_results[3]) const
6104 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6106 /* Set subroutine uniforms */
6107 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6108 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6111 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6112 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6114 /* Capture results */
6115 GLuint* atomic_results = (GLuint*)gl.mapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);
6116 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6119 bool result = (0 == memcmp(expected_results, atomic_results, 3 * sizeof(GLuint)));
6121 if (false == result)
6123 m_context.getTestContext().getLog()
6124 << tcu::TestLog::Message << "Error. Invalid result. "
6125 << "Result: [ " << atomic_results[0] << ", " << atomic_results[1] << ", " << atomic_results[2] << " ] "
6126 << "Expected: [ " << expected_results[0] << ", " << expected_results[1] << ", " << expected_results[2]
6127 << " ]" << tcu::TestLog::EndMessage;
6131 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
6132 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6138 /** Test image load store
6140 * @return true if test pass, false otherwise
6142 bool FunctionalTest12::testImage()
6144 static const GLchar* fragment_shader_code =
6145 "#version 400 core\n"
6146 "#extension GL_ARB_shader_image_load_store : require\n"
6147 "#extension GL_ARB_shader_subroutine : require\n"
6149 "precision highp float;\n"
6151 "layout(location = 0) out uvec4 out_color;\n"
6153 "layout(rgba32ui) uniform uimage2D left_image;\n"
6154 "layout(rgba32ui) uniform uimage2D right_image;\n"
6156 "subroutine void image_routine(void);\n"
6158 "subroutine(image_routine) void left_to_right(void)\n"
6160 " out_color = imageLoad (left_image, ivec2(gl_FragCoord.xy));\n"
6161 " imageStore(right_image, ivec2(gl_FragCoord.xy), out_color);\n"
6164 "subroutine(image_routine) void right_to_left(void)\n"
6166 " out_color = imageLoad (right_image, ivec2(gl_FragCoord.xy));\n"
6167 " imageStore(left_image, ivec2(gl_FragCoord.xy), out_color);\n"
6170 "subroutine uniform image_routine routine;\n"
6178 static const GLchar* geometry_shader_code = "#version 400 core\n"
6179 "#extension GL_ARB_shader_subroutine : require\n"
6181 "precision highp float;\n"
6183 "layout(points) in;\n"
6184 "layout(triangle_strip, max_vertices = 4) out;\n"
6188 " gl_Position = vec4(-1, -1, 0, 1);\n"
6191 " gl_Position = vec4(-1, 1, 0, 1);\n"
6194 " gl_Position = vec4( 1, -1, 0, 1);\n"
6197 " gl_Position = vec4( 1, 1, 0, 1);\n"
6200 " EndPrimitive();\n"
6204 static const GLchar* vertex_shader_code = "#version 400 core\n"
6205 "#extension GL_ARB_shader_subroutine : require\n"
6207 "precision highp float;\n"
6214 static const GLchar* subroutine_names[] = { "left_to_right", "right_to_left" };
6216 static const GLchar* uniform_names[] = { "left_image", "right_image" };
6219 static const GLuint blue_color[4] = { 0, 0, 255, 255 };
6220 static const GLuint clean_color[4] = { 16, 32, 64, 128 };
6221 static const GLuint red_color[4] = { 255, 0, 0, 255 };
6224 Utils::texture blue_texture(m_context);
6225 Utils::texture destination_texture(m_context);
6226 Utils::texture color_texture(m_context);
6227 Utils::framebuffer framebuffer(m_context);
6228 Utils::program program(m_context);
6229 Utils::texture red_texture(m_context);
6230 Utils::vertexArray vao(m_context);
6232 /* Init GL objects */
6233 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6234 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6241 blue_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6242 destination_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6243 color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6244 red_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6246 fillTexture(blue_texture, blue_color);
6247 fillTexture(destination_texture, clean_color);
6248 fillTexture(red_texture, red_color);
6250 framebuffer.generate();
6252 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6253 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6254 framebuffer.clear(GL_COLOR_BUFFER_BIT);
6256 /* Subroutine indices */
6257 GLuint left_to_right = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6258 GLuint right_to_left = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6260 /* Uniform locations */
6261 m_left_image = program.getUniformLocation(uniform_names[0]);
6262 m_right_image = program.getUniformLocation(uniform_names[1]);
6267 if (false == testImageDraw(left_to_right, blue_texture, destination_texture, blue_color, blue_color))
6272 if (false == testImageDraw(left_to_right, red_texture, destination_texture, red_color, red_color))
6277 if (false == testImageDraw(right_to_left, destination_texture, blue_texture, blue_color, blue_color))
6282 if (false == testImageDraw(right_to_left, destination_texture, red_texture, red_color, red_color))
6287 if (false == testImageDraw(left_to_right, blue_texture, red_texture, blue_color, blue_color))
6296 /** Execute draw call and verifies results
6298 * @param subroutine_index Index of subroutine that shall be used during draw call
6299 * @param left "Left" texture
6300 * @param right "Right" texture
6301 * @param expected_left_color Expected color of "left" texture
6302 * @param expected_right_color Expected color of "right" texture
6304 * @return true if verification result is positive, false otherwise
6306 bool FunctionalTest12::testImageDraw(GLuint subroutine_index, Utils::texture& left, Utils::texture& right,
6307 const GLuint expected_left_color[4], const GLuint expected_right_color[4]) const
6309 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6311 /* Set subroutine uniforms */
6312 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6313 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6315 /* Set up image units */
6316 gl.uniform1i(m_left_image, 0);
6317 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6319 gl.uniform1i(m_right_image, 1);
6320 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
6322 gl.bindImageTexture(0, left.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6323 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6325 gl.bindImageTexture(1, right.m_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
6326 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6329 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6330 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6332 /* Verify results */
6335 if (false == verifyTexture(left, expected_left_color))
6337 m_context.getTestContext().getLog() << tcu::TestLog::Message
6338 << "Error. Invalid result. Left texture is filled with wrong color."
6339 << tcu::TestLog::EndMessage;
6343 if (false == verifyTexture(right, expected_right_color))
6345 m_context.getTestContext().getLog() << tcu::TestLog::Message
6346 << "Error. Invalid result. Right texture is filled with wrong color."
6347 << tcu::TestLog::EndMessage;
6355 /** Test shader storage buffer
6357 * @return true if test pass, false otherwise
6359 bool FunctionalTest12::testSSBO()
6361 static const GLchar* fragment_shader_code = "#version 400 core\n"
6362 "#extension GL_ARB_shader_storage_buffer_object : require\n"
6363 "#extension GL_ARB_shader_subroutine : require\n"
6365 "precision highp float;\n"
6367 "layout(location = 0) out uvec4 out_color;\n"
6369 "layout(std140, binding = 0) buffer Buffer\n"
6374 "subroutine void ssbo_routine(void)\n;"
6376 "subroutine(ssbo_routine) void increment(void)\n"
6378 " out_color.x = atomicAdd(entry.x, 1);\n"
6379 " out_color.y = atomicAdd(entry.y, 1);\n"
6380 " out_color.z = atomicAdd(entry.z, 1);\n"
6381 " out_color.w = atomicAdd(entry.w, 1);\n"
6384 "subroutine(ssbo_routine) void decrement(void)\n"
6386 " out_color.x = atomicAdd(entry.x, -1);\n"
6387 " out_color.y = atomicAdd(entry.y, -1);\n"
6388 " out_color.z = atomicAdd(entry.z, -1);\n"
6389 " out_color.w = atomicAdd(entry.w, -1);\n"
6392 "subroutine uniform ssbo_routine routine;\n"
6400 static const GLchar* geometry_shader_code = "#version 400 core\n"
6401 "#extension GL_ARB_shader_subroutine : require\n"
6403 "precision highp float;\n"
6405 "layout(points) in;\n"
6406 "layout(triangle_strip, max_vertices = 4) out;\n"
6410 " gl_Position = vec4(-1, -1, 0, 1);\n"
6413 " gl_Position = vec4(-1, 1, 0, 1);\n"
6416 " gl_Position = vec4( 1, -1, 0, 1);\n"
6419 " gl_Position = vec4( 1, 1, 0, 1);\n"
6422 " EndPrimitive();\n"
6426 static const GLchar* vertex_shader_code = "#version 400 core\n"
6427 "#extension GL_ARB_shader_subroutine : require\n"
6429 "precision highp float;\n"
6436 static const GLchar* subroutine_names[] = { "increment", "decrement" };
6439 static const glw::GLuint buffer_data[] = { m_texture_width * m_texture_height + 1,
6440 m_texture_width * m_texture_height + 2,
6441 m_texture_width * m_texture_height + 3,
6442 m_texture_width * m_texture_height + 4 };
6444 static const glw::GLuint expected_incremented[] = { m_texture_width * m_texture_height + buffer_data[0],
6445 m_texture_width * m_texture_height + buffer_data[1],
6446 m_texture_width * m_texture_height + buffer_data[2],
6447 m_texture_width * m_texture_height + buffer_data[3] };
6449 static const glw::GLuint expected_decremented[] = { buffer_data[0], buffer_data[1], buffer_data[2],
6453 Utils::buffer buffer(m_context);
6454 Utils::texture color_texture(m_context);
6455 Utils::framebuffer framebuffer(m_context);
6456 Utils::program program(m_context);
6457 Utils::vertexArray vao(m_context);
6459 /* Init GL objects */
6460 program.build(0 /* cs */, fragment_shader_code /* fs */, geometry_shader_code /* gs */, 0 /* tcs */, 0 /* test */,
6461 vertex_shader_code, 0 /* varying_names */, 0 /* n_varyings */);
6468 color_texture.create(m_texture_width, m_texture_height, GL_RGBA32UI);
6471 buffer.update(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), (GLvoid*)buffer_data, GL_STATIC_DRAW);
6472 buffer.bindRange(GL_SHADER_STORAGE_BUFFER, 0 /* index */, 0 /* offset */, sizeof(buffer_data));
6474 framebuffer.generate();
6476 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_texture_width, m_texture_height);
6477 framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
6478 framebuffer.clear(GL_COLOR_BUFFER_BIT);
6480 /* Subroutine indices */
6481 GLuint increment = program.getSubroutineIndex(subroutine_names[0], GL_FRAGMENT_SHADER);
6482 GLuint decrement = program.getSubroutineIndex(subroutine_names[1], GL_FRAGMENT_SHADER);
6487 if (false == testSSBODraw(increment, expected_incremented))
6492 if (false == testSSBODraw(decrement, expected_decremented))
6501 /** Execute draw call and verify results
6503 * @param subroutine_index Index of subroutine that shall be used by draw call
6504 * @param expected_results Expected results
6508 bool FunctionalTest12::testSSBODraw(GLuint subroutine_index, const GLuint expected_results[4]) const
6510 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6512 /* Set subroutine uniforms */
6513 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &subroutine_index);
6514 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
6517 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
6518 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6520 /* Capture results */
6521 GLuint* ssbo_results = (GLuint*)gl.mapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);
6522 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
6525 bool result = (0 == memcmp(expected_results, ssbo_results, 4 * sizeof(GLuint)));
6527 if (false == result)
6529 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result. "
6530 << "Result: [ " << ssbo_results[0] << ", " << ssbo_results[1] << ", "
6531 << ssbo_results[2] << ", " << ssbo_results[3] << " ] "
6532 << "Expected: [ " << expected_results[0] << ", " << expected_results[1]
6533 << ", " << expected_results[2] << ", " << expected_results[3] << " ]"
6534 << tcu::TestLog::EndMessage;
6538 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
6539 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
6545 /** Check if texture is filled with expected color
6547 * @param texture Texture instance
6548 * @param expected_color Expected color
6550 * @return true if texture is filled with specified color, false otherwise
6552 bool FunctionalTest12::verifyTexture(Utils::texture& texture, const GLuint expected_color[4]) const
6554 std::vector<GLuint> results;
6555 results.resize(m_texture_width * m_texture_height * 4);
6557 texture.get(GL_RGBA_INTEGER, GL_UNSIGNED_INT, &results[0]);
6559 for (GLuint y = 0; y < m_texture_height; ++y)
6561 const GLuint line_offset = y * m_texture_width * 4;
6563 for (GLuint x = 0; x < m_texture_width; ++x)
6565 const GLuint point_offset = line_offset + x * 4;
6568 result = result && (results[point_offset + 0] == expected_color[0]);
6569 result = result && (results[point_offset + 1] == expected_color[1]);
6570 result = result && (results[point_offset + 2] == expected_color[2]);
6571 result = result && (results[point_offset + 3] == expected_color[3]);
6573 if (false == result)
6585 * @param context Rendering context.
6588 FunctionalTest13::FunctionalTest13(deqp::Context& context)
6589 : TestCase(context, "subroutines_with_separate_shader_objects",
6590 "Verifies that subroutines work correctly when used in separate "
6594 , m_read_buffer(DE_NULL)
6599 , m_has_test_passed(true)
6601 memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
6602 memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
6603 memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
6604 memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
6605 memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
6608 /** Deinitializes all GL objects that may have been created during test
6609 * execution, as well as releases all process-side buffers that may have
6610 * been allocated during the process.
6611 * The function also restores default GL state configuration.
6613 void FunctionalTest13::deinit()
6615 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6619 gl.deleteFramebuffers(1, &m_fbo_id);
6624 if (m_pipeline_id != 0)
6626 gl.deleteProgramPipelines(1, &m_pipeline_id);
6631 if (m_read_buffer != DE_NULL)
6633 delete[] m_read_buffer;
6635 m_read_buffer = DE_NULL;
6638 for (unsigned int n_id = 0; n_id < 2 /* po id variants */; ++n_id)
6640 if (m_fs_po_ids[n_id] != 0)
6642 gl.deleteProgram(m_fs_po_ids[n_id]);
6644 m_fs_po_ids[n_id] = 0;
6647 if (m_gs_po_ids[n_id] != 0)
6649 gl.deleteProgram(m_gs_po_ids[n_id]);
6651 m_gs_po_ids[n_id] = 0;
6654 if (m_tc_po_ids[n_id] != 0)
6656 gl.deleteProgram(m_tc_po_ids[n_id]);
6658 m_tc_po_ids[n_id] = 0;
6661 if (m_te_po_ids[n_id] != 0)
6663 gl.deleteProgram(m_te_po_ids[n_id]);
6665 m_te_po_ids[n_id] = 0;
6668 if (m_vs_po_ids[n_id] != 0)
6670 gl.deleteProgram(m_vs_po_ids[n_id]);
6672 m_vs_po_ids[n_id] = 0;
6674 } /* for (both shader program object variants) */
6678 gl.deleteTextures(1, &m_to_id);
6685 gl.deleteVertexArrays(1, &m_vao_id);
6690 /* Restore default GL_PATCH_VERTICES setting value */
6691 gl.patchParameteri(GL_PATCH_VERTICES, 3);
6693 /* Restore default GL_PACK_ALIGNMENT setting value */
6694 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
6697 /** Retrieves body of a fragment shader that should be used for the test.
6698 * The subroutine implementations are slightly changed, depending on the
6699 * index of the shader, as specified by the caller.
6701 * @param n_id Index of the shader.
6703 * @return Requested string.
6705 std::string FunctionalTest13::getFragmentShaderBody(unsigned int n_id)
6707 std::stringstream result_sstream;
6710 result_sstream << "#version 400\n"
6712 "#extension GL_ARB_shader_subroutine : require\n"
6715 "subroutine void SubroutineFSType(inout vec4 result);\n"
6717 "subroutine(SubroutineFSType) void SubroutineFS1(inout vec4 result)\n"
6720 << float(n_id + 1) / 10.0f << ", " << float(n_id + 2) / 10.0f << ", " << float(n_id + 3) / 10.0f
6721 << ", " << float(n_id + 4) / 10.0f
6724 "subroutine(SubroutineFSType) void SubroutineFS2(inout vec4 result)\n"
6727 << float(n_id + 1) / 20.0f << ", " << float(n_id + 2) / 20.0f << ", " << float(n_id + 3) / 20.0f
6728 << ", " << float(n_id + 4) / 20.0f << ");\n"
6731 "subroutine uniform SubroutineFSType function;\n"
6739 "out vec4 result;\n"
6740 /* main() declaration */
6743 " vec4 data = in_gs.data;\n"
6744 " function(data);\n"
6749 return result_sstream.str();
6752 /** Retrieves body of a geometry shader that should be used for the test.
6753 * The subroutine implementations are slightly changed, depending on the
6754 * index of the shader, as specified by the caller.
6756 * @param n_id Index of the shader.
6758 * @return Requested string.
6760 std::string FunctionalTest13::getGeometryShaderBody(unsigned int n_id)
6762 std::stringstream result_sstream;
6765 result_sstream << "#version 400\n"
6767 "#extension GL_ARB_shader_subroutine : require\n"
6769 "layout(points) in;\n"
6770 "layout(triangle_strip, max_vertices = 4) out;\n"
6772 "subroutine void SubroutineGSType(inout vec4 result);\n"
6774 "subroutine(SubroutineGSType) void SubroutineGS1(inout vec4 result)\n"
6776 " result += vec4(0, 0, 0, "
6777 << float(n_id + 1) * 0.425f << ");\n"
6779 "subroutine(SubroutineGSType) void SubroutineGS2(inout vec4 result)\n"
6781 " result += vec4(0, 0, 0, "
6782 << float(n_id + 1) * 0.0425f << ");\n"
6785 "subroutine uniform SubroutineGSType function;\n"
6799 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6800 "out gl_PerVertex { vec4 gl_Position; };\n"
6801 /* main() declaration */
6804 " vec4 data = in_te[0].data;\n"
6806 " function(data);\n"
6808 " gl_Position = vec4(1, -1, 0, 1);\n"
6809 " out_gs.data = data;\n"
6812 " gl_Position = vec4(-1, -1, 0, 1);\n"
6813 " out_gs.data = data;\n"
6816 " gl_Position = vec4(1, 1, 0, 1);\n"
6817 " out_gs.data = data;\n"
6820 " gl_Position = vec4(-1, 1, 0, 1);\n"
6821 " out_gs.data = data;\n"
6823 " EndPrimitive();\n"
6826 return result_sstream.str();
6829 /** Retrieves body of a tessellation control shader that should be used for the test.
6830 * The subroutine implementations are slightly changed, depending on the
6831 * index of the shader, as specified by the caller.
6833 * @param n_id Index of the shader.
6835 * @return Requested string.
6837 std::string FunctionalTest13::getTessellationControlShaderBody(unsigned int n_id)
6839 std::stringstream result_sstream;
6842 result_sstream << "#version 400\n"
6844 "#extension GL_ARB_shader_subroutine : require\n"
6846 "layout(vertices = 4) out;\n"
6848 "subroutine void SubroutineTCType(inout vec4 result);\n"
6850 "subroutine(SubroutineTCType) void SubroutineTC1(inout vec4 result)\n"
6852 " result += vec4(0, "
6853 << float(n_id + 1) * 0.25f << ", 0, 0);\n"
6855 "subroutine(SubroutineTCType) void SubroutineTC2(inout vec4 result)\n"
6857 " result += vec4(0, "
6858 << float(n_id + 1) * 0.025f
6862 "subroutine uniform SubroutineTCType function;\n"
6876 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6877 "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n"
6878 /* main() declaration */
6881 " gl_TessLevelOuter[0] = 1.0;\n"
6882 " gl_TessLevelOuter[1] = 1.0;\n"
6883 " gl_TessLevelOuter[2] = 1.0;\n"
6884 " gl_TessLevelOuter[3] = 1.0;\n"
6885 " gl_TessLevelInner[0] = 1.0;\n"
6886 " gl_TessLevelInner[1] = 1.0;\n"
6887 " gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;\n"
6888 " out_tc[gl_InvocationID].data = in_vs[0].data;\n"
6890 " function(out_tc[gl_InvocationID].data);\n"
6893 return result_sstream.str();
6896 /** Retrieves body of a tessellation evaluation shader that should be used for the test.
6897 * The subroutine implementations are slightly changed, depending on the
6898 * index of the shader, as specified by the caller.
6900 * @param n_id Index of the shader.
6902 * @return Requested string.
6904 std::string FunctionalTest13::getTessellationEvaluationShaderBody(unsigned int n_id)
6906 std::stringstream result_sstream;
6909 result_sstream << "#version 400\n"
6911 "#extension GL_ARB_shader_subroutine : require\n"
6913 "layout(quads, point_mode) in;\n"
6915 "subroutine void SubroutineTEType(inout vec4 result);\n"
6917 "subroutine(SubroutineTEType) void SubroutineTE1(inout vec4 result)\n"
6919 " result += vec4(0, 0, "
6920 << float(n_id + 1) * 0.325f << ", 0);\n"
6922 "subroutine(SubroutineTEType) void SubroutineTE2(inout vec4 result)\n"
6924 " result += vec4(0, 0, "
6925 << float(n_id + 1) * 0.0325f << ", 0);\n"
6928 "subroutine uniform SubroutineTEType function;\n"
6942 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
6943 "out gl_PerVertex { vec4 gl_Position; };\n"
6944 /* main() declaration */
6947 " gl_Position = gl_in[0].gl_Position;\n"
6948 " out_te.data = in_tc[0].data;\n"
6950 " function(out_te.data);\n"
6953 return result_sstream.str();
6956 /** Retrieves body of a vertex shader that should be used for the test.
6957 * The subroutine implementations are slightly changed, depending on the
6958 * index of the shader, as specified by the caller.
6960 * @param n_id Index of the shader.
6962 * @return Requested string.
6964 std::string FunctionalTest13::getVertexShaderBody(unsigned int n_id)
6966 std::stringstream result_sstream;
6969 result_sstream << "#version 400\n"
6971 "#extension GL_ARB_shader_subroutine : require\n"
6974 "subroutine void SubroutineVSType(inout vec4 result);\n"
6976 "subroutine(SubroutineVSType) void SubroutineVS1(inout vec4 result)\n"
6979 << float(n_id + 1) * 0.125f << ", 0, 0, 0);\n"
6981 "subroutine(SubroutineVSType) void SubroutineVS2(inout vec4 result)\n"
6984 << float(n_id + 1) * 0.0125f << ", 0, 0, 0);\n"
6987 "subroutine uniform SubroutineVSType function;\n"
6995 "out gl_PerVertex { vec4 gl_Position; };\n"
6996 /* main() declaration */
6999 " gl_Position = vec4(0, 0, 0, 1);\n"
7000 " out_vs.data = vec4(0);\n"
7002 " function(out_vs.data);\n"
7006 return result_sstream.str();
7009 /** Initializes all GL objects required to run the test. Also modifies a few
7010 * GL states in order for the test to run correctly.
7012 void FunctionalTest13::initTest()
7014 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7016 /* Set up viewport */
7017 gl.viewport(0 /* x */, 0 /* y */, m_to_width, m_to_height);
7018 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
7020 /* Make sure no program is used */
7022 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7024 /* Generate a pipeline object */
7025 gl.genProgramPipelines(1, &m_pipeline_id);
7026 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
7028 gl.bindProgramPipeline(m_pipeline_id);
7029 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
7031 /* Initialize all shader programs */
7032 for (unsigned int n_id = 0; n_id < 2 /* variants for each shader type */; ++n_id)
7034 std::string fs_body = getFragmentShaderBody(n_id);
7035 const char* fs_body_raw_ptr = fs_body.c_str();
7036 std::string gs_body = getGeometryShaderBody(n_id);
7037 const char* gs_body_raw_ptr = gs_body.c_str();
7038 std::string tc_body = getTessellationControlShaderBody(n_id);
7039 const char* tc_body_raw_ptr = tc_body.c_str();
7040 std::string te_body = getTessellationEvaluationShaderBody(n_id);
7041 const char* te_body_raw_ptr = te_body.c_str();
7042 std::string vs_body = getVertexShaderBody(n_id);
7043 const char* vs_body_raw_ptr = vs_body.c_str();
7045 m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
7046 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7048 m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
7049 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7051 m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
7052 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7054 m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
7055 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7057 m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
7058 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
7060 /* Verify that all shader program objects have been linked successfully */
7061 const glw::GLuint po_ids[] = {
7062 m_fs_po_ids[n_id], m_gs_po_ids[n_id], m_tc_po_ids[n_id], m_te_po_ids[n_id], m_vs_po_ids[n_id],
7064 const unsigned int n_po_ids = sizeof(po_ids) / sizeof(po_ids[0]);
7066 for (unsigned int n_po_id = 0; n_po_id < n_po_ids; ++n_po_id)
7068 glw::GLint link_status = GL_FALSE;
7069 glw::GLuint po_id = po_ids[n_po_id];
7071 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
7072 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7074 if (link_status != GL_TRUE)
7076 TCU_FAIL("Shader program object linking failed.");
7078 } /* for (all shader program objects) */
7079 } /* for (both shader program object variants) */
7081 /* Generate a texture object. We will use the base mip-map as a render-target */
7082 gl.genTextures(1, &m_to_id);
7083 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
7085 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
7086 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
7088 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA32F, m_to_width, m_to_height);
7089 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed");
7091 /* Generate and configure a FBO we will use for the draw call */
7092 gl.genFramebuffers(1, &m_fbo_id);
7093 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
7095 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
7096 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
7098 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
7099 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
7101 /* Generate & bind a VAO */
7102 gl.genVertexArrays(1, &m_vao_id);
7103 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7105 gl.bindVertexArray(m_vao_id);
7106 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7108 /* Set up tessellation */
7109 gl.patchParameteri(GL_PATCH_VERTICES, 1);
7110 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
7112 /* Set up pixel storage alignment */
7113 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
7114 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
7116 /* Allocate enough space to hold color attachment data */
7117 m_read_buffer = (unsigned char*)new float[m_to_width * m_to_height * 4 /* rgba */];
7120 /** Executes test iteration.
7122 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7124 tcu::TestNode::IterateResult FunctionalTest13::iterate()
7126 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7128 /* Do not execute the test if GL_ARB_shader_subroutine and GL_ARB_separate_shader_objects
7129 * are not supported */
7130 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7132 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7135 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
7137 throw tcu::NotSupportedError("GL_ARB_separate_shader_objects is not supported");
7140 /* Initialize all GL objects before we continue */
7143 /* Iterate over all possible FS/GS/TC/TE/VS permutations */
7144 for (int n_shader_permutation = 0; n_shader_permutation < 32 /* 2^5 */; ++n_shader_permutation)
7146 const unsigned int n_fs_idx = ((n_shader_permutation & (1 << 0)) != 0) ? 1 : 0;
7147 const unsigned int n_gs_idx = ((n_shader_permutation & (1 << 1)) != 0) ? 1 : 0;
7148 const unsigned int n_tc_idx = ((n_shader_permutation & (1 << 2)) != 0) ? 1 : 0;
7149 const unsigned int n_te_idx = ((n_shader_permutation & (1 << 3)) != 0) ? 1 : 0;
7150 const unsigned int n_vs_idx = ((n_shader_permutation & (1 << 4)) != 0) ? 1 : 0;
7151 const unsigned int fs_po_id = m_fs_po_ids[n_fs_idx];
7152 const unsigned int gs_po_id = m_gs_po_ids[n_gs_idx];
7153 const unsigned int tc_po_id = m_tc_po_ids[n_tc_idx];
7154 const unsigned int te_po_id = m_te_po_ids[n_te_idx];
7155 const unsigned int vs_po_id = m_vs_po_ids[n_vs_idx];
7157 /* Configure fragment shader stage */
7158 gl.useProgramStages(m_pipeline_id, GL_FRAGMENT_SHADER_BIT, fs_po_id);
7159 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_FRAGMENT_SHADER_BIT bit");
7161 /* Configure geometry shader stage */
7162 gl.useProgramStages(m_pipeline_id, GL_GEOMETRY_SHADER_BIT, gs_po_id);
7163 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_GEOMETRY_SHADER_BIT bit");
7165 /* Configure tessellation control shader stage */
7166 gl.useProgramStages(m_pipeline_id, GL_TESS_CONTROL_SHADER_BIT, tc_po_id);
7167 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_CONTROL_SHADER_BIT bit");
7169 /* Configure tessellation evaluation shader stage */
7170 gl.useProgramStages(m_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT, te_po_id);
7171 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_TESS_EVALUATION_SHADER_BIT bit");
7173 /* Configure vertex shader stage */
7174 gl.useProgramStages(m_pipeline_id, GL_VERTEX_SHADER_BIT, vs_po_id);
7175 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed for GL_VERTEX_SHADER_BIT bit");
7177 /* Validate the pipeline */
7178 glw::GLint validate_status = GL_FALSE;
7180 gl.validateProgramPipeline(m_pipeline_id);
7181 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgramPipeline() call failed.");
7183 gl.getProgramPipelineiv(m_pipeline_id, GL_VALIDATE_STATUS, &validate_status);
7184 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
7186 if (validate_status != GL_TRUE)
7188 TCU_FAIL("Program pipeline has not been validated successfully.");
7191 /* Retrieve subroutine indices */
7192 GLuint fs_subroutine_indices[2] = { (GLuint)-1 };
7193 GLint fs_subroutine_uniform_index = 0;
7194 GLuint gs_subroutine_indices[2] = { (GLuint)-1 };
7195 GLint gs_subroutine_uniform_index = 0;
7196 GLuint tc_subroutine_indices[2] = { (GLuint)-1 };
7197 GLint tc_subroutine_uniform_index = 0;
7198 GLuint te_subroutine_indices[2] = { (GLuint)-1 };
7199 GLint te_subroutine_uniform_index = 0;
7200 GLuint vs_subroutine_indices[2] = { (GLuint)-1 };
7201 GLint vs_subroutine_uniform_index = 0;
7203 for (unsigned int n_subroutine = 0; n_subroutine < 2; ++n_subroutine)
7205 std::stringstream fs_subroutine_name_sstream;
7206 std::stringstream gs_subroutine_name_sstream;
7207 std::stringstream tc_subroutine_name_sstream;
7208 std::stringstream te_subroutine_name_sstream;
7209 std::stringstream vs_subroutine_name_sstream;
7211 fs_subroutine_name_sstream << "SubroutineFS" << (n_subroutine + 1);
7212 gs_subroutine_name_sstream << "SubroutineGS" << (n_subroutine + 1);
7213 tc_subroutine_name_sstream << "SubroutineTC" << (n_subroutine + 1);
7214 te_subroutine_name_sstream << "SubroutineTE" << (n_subroutine + 1);
7215 vs_subroutine_name_sstream << "SubroutineVS" << (n_subroutine + 1);
7217 fs_subroutine_indices[n_subroutine] =
7218 gl.getSubroutineIndex(fs_po_id, GL_FRAGMENT_SHADER, fs_subroutine_name_sstream.str().c_str());
7219 gs_subroutine_indices[n_subroutine] =
7220 gl.getSubroutineIndex(gs_po_id, GL_GEOMETRY_SHADER, gs_subroutine_name_sstream.str().c_str());
7221 tc_subroutine_indices[n_subroutine] =
7222 gl.getSubroutineIndex(tc_po_id, GL_TESS_CONTROL_SHADER, tc_subroutine_name_sstream.str().c_str());
7223 te_subroutine_indices[n_subroutine] =
7224 gl.getSubroutineIndex(te_po_id, GL_TESS_EVALUATION_SHADER, te_subroutine_name_sstream.str().c_str());
7225 vs_subroutine_indices[n_subroutine] =
7226 gl.getSubroutineIndex(vs_po_id, GL_VERTEX_SHADER, vs_subroutine_name_sstream.str().c_str());
7227 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
7229 if (fs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7230 gs_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7231 tc_subroutine_indices[n_subroutine] == (GLuint)-1 ||
7232 te_subroutine_indices[n_subroutine] == (GLuint)-1 || vs_subroutine_indices[n_subroutine] == (GLuint)-1)
7234 m_testCtx.getLog() << tcu::TestLog::Message
7235 << "At least one subroutine was not recognized by glGetSubroutineIndex() call. "
7237 << fs_subroutine_indices[n_subroutine]
7238 << ", gs:" << gs_subroutine_indices[n_subroutine]
7239 << ", tc:" << tc_subroutine_indices[n_subroutine]
7240 << ", te:" << te_subroutine_indices[n_subroutine]
7241 << ", vs:" << vs_subroutine_indices[n_subroutine] << ")."
7242 << tcu::TestLog::EndMessage;
7244 TCU_FAIL("At least one subroutine was not recognized");
7246 } /* for (both subroutines) */
7248 /* Retrieve subroutine uniform indices */
7249 fs_subroutine_uniform_index = gl.getSubroutineUniformLocation(fs_po_id, GL_FRAGMENT_SHADER, "function");
7250 gs_subroutine_uniform_index = gl.getSubroutineUniformLocation(gs_po_id, GL_GEOMETRY_SHADER, "function");
7251 tc_subroutine_uniform_index = gl.getSubroutineUniformLocation(tc_po_id, GL_TESS_CONTROL_SHADER, "function");
7252 te_subroutine_uniform_index = gl.getSubroutineUniformLocation(te_po_id, GL_TESS_EVALUATION_SHADER, "function");
7253 vs_subroutine_uniform_index = gl.getSubroutineUniformLocation(vs_po_id, GL_VERTEX_SHADER, "function");
7255 if (fs_subroutine_uniform_index == -1 || gs_subroutine_uniform_index == -1 ||
7256 tc_subroutine_uniform_index == -1 || te_subroutine_uniform_index == -1 || vs_subroutine_uniform_index == -1)
7258 m_testCtx.getLog() << tcu::TestLog::Message << "At least one subroutine uniform is considered inactive by "
7259 "glGetSubroutineUniformLocation ("
7261 << fs_subroutine_uniform_index << ", gs:" << gs_subroutine_uniform_index
7262 << ", tc:" << tc_subroutine_uniform_index << ", te:" << te_subroutine_uniform_index
7263 << ", vs:" << vs_subroutine_uniform_index << ")." << tcu::TestLog::EndMessage;
7265 TCU_FAIL("At least one subroutine uniform is considered inactive");
7268 /* Check if both subroutines work correctly in each stage */
7269 for (int n_subroutine_permutation = 0; n_subroutine_permutation < 32; /* 2^5 */
7270 ++n_subroutine_permutation)
7272 unsigned int n_fs_subroutine = ((n_subroutine_permutation & (1 << 0)) != 0) ? 1 : 0;
7273 unsigned int n_gs_subroutine = ((n_subroutine_permutation & (1 << 1)) != 0) ? 1 : 0;
7274 unsigned int n_tc_subroutine = ((n_subroutine_permutation & (1 << 2)) != 0) ? 1 : 0;
7275 unsigned int n_te_subroutine = ((n_subroutine_permutation & (1 << 3)) != 0) ? 1 : 0;
7276 unsigned int n_vs_subroutine = ((n_subroutine_permutation & (1 << 4)) != 0) ? 1 : 0;
7278 /* Configure subroutine uniforms */
7283 glw::GLuint* indices;
7284 } configurations[] = {
7285 { GL_FRAGMENT_SHADER, fs_po_id, fs_subroutine_indices + n_fs_subroutine },
7286 { GL_GEOMETRY_SHADER, gs_po_id, gs_subroutine_indices + n_gs_subroutine },
7287 { GL_TESS_CONTROL_SHADER, tc_po_id, tc_subroutine_indices + n_tc_subroutine },
7288 { GL_TESS_EVALUATION_SHADER, te_po_id, te_subroutine_indices + n_te_subroutine },
7289 { GL_VERTEX_SHADER, vs_po_id, vs_subroutine_indices + n_vs_subroutine },
7292 for (int i = 0; i < 5; ++i)
7294 gl.activeShaderProgram(m_pipeline_id, configurations[i].po_id);
7295 GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveShaderProgram() call failed.");
7297 gl.uniformSubroutinesuiv(configurations[i].stage, 1 /* count */, configurations[i].indices);
7298 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
7301 /* Render a full-screen quad with the pipeline */
7302 gl.clear(GL_COLOR_BUFFER_BIT);
7303 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
7305 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
7306 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7308 /* Read color attachment's contents */
7309 gl.readPixels(0, /* x */
7311 m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_read_buffer);
7312 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
7314 /* Verify the contents */
7315 verifyReadBuffer(n_fs_idx, n_fs_subroutine, n_gs_idx, n_gs_subroutine, n_tc_idx, n_tc_subroutine, n_te_idx,
7316 n_te_subroutine, n_vs_idx, n_vs_subroutine);
7317 } /* for (all subroutine permutations) */
7318 } /* for (all program shader object permutations) */
7321 if (m_has_test_passed)
7323 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7327 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7333 /** Verifies the data that have been rendered using a pipeline object.
7334 * Contents of the data depends on indices of the shaders, as well as
7335 * on the subroutines that have been activated for particular iteration.
7337 * @param n_fs_id Index of the fragment shader used for the iteration;
7338 * @param n_fs_subroutine Index of the subroutine used in the fragment shader
7339 * for the iteration;
7340 * @param n_gs_id Index of the geometry shader used for the iteration;
7341 * @param n_gs_subroutine Index of the subroutine used in the geometry shader
7342 * for the iteration;
7343 * @param n_tc_id Index of the tessellation control shader used for the iteration;
7344 * @param n_tc_subroutine Index of the subroutine used in the tessellation control
7345 * shader for the iteration;
7346 * @param n_te_id Index of the tessellation evaluation shader used for the iteration;
7347 * @param n_te_subroutine Index of the subroutine used in the tessellation evaluation
7348 * shader for the iteration;
7349 * @param n_vs_id Index of the vertex shader used for the iteration;
7350 * @param n_vs_subroutine Index of the subroutine used in the vertex shader for
7353 void FunctionalTest13::verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id,
7354 unsigned int n_gs_subroutine, unsigned int n_tc_id,
7355 unsigned int n_tc_subroutine, unsigned int n_te_id,
7356 unsigned int n_te_subroutine, unsigned int n_vs_id,
7357 unsigned int n_vs_subroutine)
7359 float expected_color[4] = { 0 };
7360 float fs_modifier[4] = { 0 };
7361 float gs_modifier[4] = { 0 };
7362 float tc_modifier[4] = { 0 };
7363 float te_modifier[4] = { 0 };
7364 float vs_modifier[4] = { 0 };
7366 if (n_fs_subroutine == 0)
7368 for (unsigned int n_component = 0; n_component < 4; ++n_component)
7370 fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 10.0f;
7375 for (unsigned int n_component = 0; n_component < 4; ++n_component)
7377 fs_modifier[n_component] = float(n_fs_id + n_component + 1) / 20.0f;
7381 if (n_gs_subroutine == 0)
7383 gs_modifier[3] = float(n_gs_id + 1) * 0.425f;
7387 gs_modifier[3] = float(n_gs_id + 1) * 0.0425f;
7390 if (n_tc_subroutine == 0)
7392 tc_modifier[1] = float(n_tc_id + 1) * 0.25f;
7396 tc_modifier[1] = float(n_tc_id + 1) * 0.025f;
7399 if (n_te_subroutine == 0)
7401 te_modifier[2] = float(n_te_id + 1) * 0.325f;
7405 te_modifier[2] = float(n_te_id + 1) * 0.0325f;
7408 if (n_vs_subroutine == 0)
7410 vs_modifier[0] = float(n_vs_id + 1) * 0.125f;
7414 vs_modifier[0] = float(n_vs_id + 1) * 0.0125f;
7417 /* Determine the expected color */
7418 for (unsigned int n_component = 0; n_component < 4 /* rgba */; ++n_component)
7420 expected_color[n_component] = fs_modifier[n_component] + gs_modifier[n_component] + tc_modifier[n_component] +
7421 te_modifier[n_component] + vs_modifier[n_component];
7424 /* Verify all read texels are valid */
7425 const float epsilon = 1e-5f;
7426 bool should_continue = true;
7428 for (unsigned int y = 0; y < m_to_height && should_continue; ++y)
7430 const float* row_ptr = (const float*)m_read_buffer + y * m_to_width * 4; /* rgba */
7432 for (unsigned int x = 0; x < m_to_width && should_continue; ++x)
7434 const float* texel_ptr = row_ptr + x * 4; /* rgba */
7436 if (de::abs(texel_ptr[0] - expected_color[0]) > epsilon ||
7437 de::abs(texel_ptr[1] - expected_color[1]) > epsilon ||
7438 de::abs(texel_ptr[2] - expected_color[2]) > epsilon ||
7439 de::abs(texel_ptr[3] - expected_color[3]) > epsilon)
7441 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel rendered at (" << x << ", " << y
7443 "the following configuration: "
7445 << n_fs_id << " n_fs_subroutine:" << n_fs_subroutine << " n_gs_id:" << n_gs_id
7446 << " n_gs_subroutine:" << n_gs_subroutine << " n_tc_id:" << n_tc_id
7447 << " n_tc_subroutine:" << n_tc_subroutine << " n_te_id:" << n_te_id
7448 << " n_te_subroutine:" << n_te_subroutine << " n_vs_id:" << n_vs_id
7449 << " n_vs_subroutine:" << n_vs_subroutine << "; expected:"
7451 << expected_color[0] << ", " << expected_color[1] << ", " << expected_color[2]
7452 << ", " << expected_color[3] << "), found:"
7454 << texel_ptr[0] << ", " << texel_ptr[1] << ", " << texel_ptr[2] << ", "
7455 << texel_ptr[3] << ")." << tcu::TestLog::EndMessage;
7457 m_has_test_passed = false;
7458 should_continue = false;
7460 } /* for (all columns) */
7461 } /* for (all rows) */
7466 * @param context CTS context
7468 FunctionalTest14_15::FunctionalTest14_15(deqp::Context& context)
7469 : TestCase(context, "structure_parameters_program_binary", "Verify structures can be used as parameters")
7470 , m_uniform_location(0)
7476 * @return tcu::TestNode::STOP
7478 tcu::TestNode::IterateResult FunctionalTest14_15::iterate()
7480 static const GLchar* vertex_shader_code =
7481 "#version 400 core\n"
7482 "#extension GL_ARB_shader_subroutine : require\n"
7484 "precision highp float;\n"
7494 "subroutine void routine_type_1(in data iparam, out data oparam);\n"
7495 "subroutine void routine_type_2(inout data arg);\n"
7497 "subroutine (routine_type_1) void invert(in data iparam, out data oparam)\n"
7499 " oparam.r = iparam.a;\n"
7500 " oparam.g = iparam.b;\n"
7501 " oparam.b = iparam.g;\n"
7502 " oparam.a = iparam.r;\n"
7505 "subroutine (routine_type_1) void increment(in data iparam, out data oparam)\n"
7507 " oparam.r = 1 + iparam.r;\n"
7508 " oparam.g = 1 + iparam.g;\n"
7509 " oparam.b = 1 + iparam.b;\n"
7510 " oparam.a = 1 + iparam.a;\n"
7513 "subroutine (routine_type_2) void div_by_2(inout data arg)\n"
7515 " arg.r = arg.r / 2;\n"
7516 " arg.g = arg.g / 2;\n"
7517 " arg.b = arg.b / 2;\n"
7518 " arg.a = arg.a / 2;\n"
7521 "subroutine (routine_type_2) void decrement(inout data arg)\n"
7523 " arg.r = arg.r - 1;\n"
7524 " arg.g = arg.g - 1;\n"
7525 " arg.b = arg.b - 1;\n"
7526 " arg.a = arg.a - 1;\n"
7529 "subroutine uniform routine_type_1 routine_1;\n"
7530 "subroutine uniform routine_type_2 routine_2;\n"
7532 "uniform uvec4 uni_input;\n"
7534 "out uvec4 out_routine_1;\n"
7535 "out uvec4 out_routine_2;\n"
7540 " data routine_1_input;\n"
7541 " data routine_1_output;\n"
7542 " data routine_2_arg;\n"
7544 " routine_1_input.r = uni_input.r;\n"
7545 " routine_1_input.g = uni_input.g;\n"
7546 " routine_1_input.b = uni_input.b;\n"
7547 " routine_1_input.a = uni_input.a;\n"
7549 " routine_2_arg.r = uni_input.r;\n"
7550 " routine_2_arg.g = uni_input.g;\n"
7551 " routine_2_arg.b = uni_input.b;\n"
7552 " routine_2_arg.a = uni_input.a;\n"
7554 " routine_1(routine_1_input, routine_1_output);\n"
7555 " routine_2(routine_2_arg);\n"
7557 " out_routine_1.r = routine_1_output.r;\n"
7558 " out_routine_1.g = routine_1_output.g;\n"
7559 " out_routine_1.b = routine_1_output.b;\n"
7560 " out_routine_1.a = routine_1_output.a;\n"
7562 " out_routine_2.r = routine_2_arg.r;\n"
7563 " out_routine_2.g = routine_2_arg.g;\n"
7564 " out_routine_2.b = routine_2_arg.b;\n"
7565 " out_routine_2.a = routine_2_arg.a;\n"
7569 static const GLchar* subroutine_names[][2] = { { "invert", "increment" }, { "div_by_2", "decrement" } };
7570 static const GLuint n_subroutine_types = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
7572 static const GLchar* subroutine_uniform_names[] = { "routine_1", "routine_2" };
7573 static const GLuint n_subroutine_uniform_names =
7574 sizeof(subroutine_uniform_names) / sizeof(subroutine_uniform_names[0]);
7576 static const GLchar* uniform_name = "uni_input";
7577 static const GLchar* varying_names[] = { "out_routine_1", "out_routine_2" };
7579 static const GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
7580 static const GLuint transform_feedback_buffer_size = n_varying_names * 4 * sizeof(GLuint);
7583 static const Utils::vec4<GLuint> uni_input[] = { Utils::vec4<GLuint>(8, 64, 4096, 16777216),
7584 Utils::vec4<GLuint>(8, 64, 4096, 16777216) };
7586 static const Utils::vec4<GLuint> out_routine_1[] = { Utils::vec4<GLuint>(16777216, 4096, 64, 8),
7587 Utils::vec4<GLuint>(9, 65, 4097, 16777217) };
7589 static const Utils::vec4<GLuint> out_routine_2[] = { Utils::vec4<GLuint>(4, 32, 2048, 8388608),
7590 Utils::vec4<GLuint>(7, 63, 4095, 16777215) };
7592 static const GLuint n_test_cases = 2;
7594 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
7595 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
7597 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
7601 Utils::program program(m_context);
7602 Utils::buffer transform_feedback_buffer(m_context);
7603 Utils::vertexArray vao(m_context);
7605 bool is_program_binary_supported = program.isProgramBinarySupported();
7607 /* Init GL objects */
7608 program.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* test */, vertex_shader_code,
7609 varying_names /* varying_names */, n_varying_names /* n_varyings */);
7611 /* Do not execute the test if GL_ARB_get_program_binary is not supported */
7612 if (true == is_program_binary_supported)
7614 /* Get subroutine indices */
7615 for (GLuint type = 0; type < n_subroutine_types; ++type)
7617 m_initial_subroutine_indices[type][0] =
7618 program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7620 m_initial_subroutine_indices[type][1] =
7621 program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7624 /* Get subroutine uniform locations */
7625 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7627 m_initial_subroutine_uniform_locations[uniform] =
7628 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7631 /* Delete program and recreate it from binary */
7632 std::vector<GLubyte> program_binary;
7633 GLenum binary_format;
7635 program.getBinary(program_binary, binary_format);
7637 program.createFromBinary(program_binary, binary_format);
7645 transform_feedback_buffer.generate();
7646 transform_feedback_buffer.update(GL_TRANSFORM_FEEDBACK_BUFFER, transform_feedback_buffer_size, 0 /* data */,
7648 transform_feedback_buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0, transform_feedback_buffer_size);
7650 /* Get subroutine indices */
7651 for (GLuint type = 0; type < n_subroutine_types; ++type)
7653 m_subroutine_indices[type][0] = program.getSubroutineIndex(subroutine_names[type][0], GL_VERTEX_SHADER);
7654 m_subroutine_indices[type][1] = program.getSubroutineIndex(subroutine_names[type][1], GL_VERTEX_SHADER);
7657 /* Get subroutine uniform locations */
7658 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7660 m_subroutine_uniform_locations[uniform] =
7661 program.getSubroutineUniformLocation(subroutine_uniform_names[uniform], GL_VERTEX_SHADER);
7664 /* Get uniform locations */
7665 m_uniform_location = program.getUniformLocation(uniform_name);
7670 /* Test program binary */
7671 if (true == is_program_binary_supported)
7673 /* Test indices and locations */
7674 if (false == testIndicesAndLocations())
7676 static const GLuint n_subroutines_per_type = 2;
7678 m_context.getTestContext().getLog() << tcu::TestLog::Message
7679 << "Error. Subroutine indices or subroutine uniform location changed."
7680 << tcu::TestLog::EndMessage;
7682 for (GLuint type = 0; type < n_subroutine_types; ++type)
7684 for (GLuint i = 0; i < n_subroutines_per_type; ++i)
7686 m_context.getTestContext().getLog()
7687 << tcu::TestLog::Message << "Subroutine: " << subroutine_names[type][i]
7688 << " index: " << m_subroutine_indices[type][i]
7689 << " initial index: " << m_initial_subroutine_indices[type][i] << tcu::TestLog::EndMessage;
7693 for (GLuint uniform = 0; uniform < n_subroutine_uniform_names; ++uniform)
7695 m_context.getTestContext().getLog()
7696 << tcu::TestLog::Message << "Subroutine uniform: " << subroutine_uniform_names[uniform]
7697 << " location: " << m_subroutine_uniform_locations[uniform]
7698 << " initial location: " << m_initial_subroutine_uniform_locations[uniform]
7699 << tcu::TestLog::EndMessage;
7705 /* Test draw with deafult set of subroutines */
7706 if (false == testDefaultSubroutineSet(uni_input[0], out_routine_1, out_routine_2))
7712 for (GLuint i = 0; i < n_test_cases; ++i)
7714 if (false == testDraw(i, uni_input[i], out_routine_1[i], out_routine_2[i]))
7723 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7727 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7731 return tcu::TestNode::STOP;
7734 /** Execute draw call and verify results
7736 * @param uni_input Input data
7737 * @param expected_routine_1_result Set of expected results of "routine_1"
7738 * @param expected_routine_2_result Set of expected results of "routine_2"
7740 * @return true if test pass, false otherwise
7742 bool FunctionalTest14_15::testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input,
7743 const Utils::vec4<glw::GLuint> expected_routine_1_result[2],
7744 const Utils::vec4<glw::GLuint> expected_routine_2_result[2]) const
7746 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7749 /* Set up input data uniforms */
7750 gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7751 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7753 /* Execute draw call with transform feedback */
7754 gl.beginTransformFeedback(GL_POINTS);
7755 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7757 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7758 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7760 gl.endTransformFeedback();
7761 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7763 /* Capture results */
7764 GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7765 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7767 Utils::vec4<GLuint> routine_1_result;
7768 Utils::vec4<GLuint> routine_2_result;
7770 routine_1_result.m_x = feedback_data[0 + 0];
7771 routine_1_result.m_y = feedback_data[0 + 1];
7772 routine_1_result.m_z = feedback_data[0 + 2];
7773 routine_1_result.m_w = feedback_data[0 + 3];
7775 routine_2_result.m_x = feedback_data[4 + 0];
7776 routine_2_result.m_y = feedback_data[4 + 1];
7777 routine_2_result.m_z = feedback_data[4 + 2];
7778 routine_2_result.m_w = feedback_data[4 + 3];
7781 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7782 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7786 ((routine_1_result == expected_routine_1_result[0]) || (routine_1_result == expected_routine_1_result[1]));
7789 ((routine_2_result == expected_routine_2_result[0]) || (routine_2_result == expected_routine_2_result[1]));
7791 /* Log error if any */
7792 if (false == result)
7794 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7795 << tcu::TestLog::EndMessage;
7797 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7799 message << "Routine_1, result: ";
7801 routine_1_result.log(message);
7803 message << "Routine_2, result: ";
7805 routine_2_result.log(message);
7807 message << tcu::TestLog::EndMessage;
7814 /** Execute draw call and verify results
7816 * @param routine_configuration Subroutine "type" ordinal
7817 * @param uni_input Input data
7818 * @param expected_routine_1_result Expected results of "routine_1"
7819 * @param expected_routine_2_result Expected results of "routine_2"
7821 * @return true if test pass, false otherwise
7823 bool FunctionalTest14_15::testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input,
7824 const Utils::vec4<glw::GLuint>& expected_routine_1_result,
7825 const Utils::vec4<glw::GLuint>& expected_routine_2_result) const
7827 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7829 GLuint subroutine_indices[2];
7830 static const GLuint n_subroutine_uniforms = sizeof(subroutine_indices) / sizeof(subroutine_indices[0]);
7832 /* Set up input data uniforms */
7833 gl.uniform4ui(m_uniform_location, uni_input.m_x, uni_input.m_y, uni_input.m_z, uni_input.m_w);
7834 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform4f");
7836 /* Prepare subroutine uniform data */
7837 for (GLuint i = 0; i < n_subroutine_uniforms; ++i)
7839 const GLuint location = m_subroutine_uniform_locations[i];
7841 subroutine_indices[location] = m_subroutine_indices[i][routine_configuration];
7844 /* Set up subroutine uniforms */
7845 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, n_subroutine_uniforms, &subroutine_indices[0]);
7846 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
7848 /* Execute draw call with transform feedback */
7849 gl.beginTransformFeedback(GL_POINTS);
7850 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
7852 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
7853 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
7855 gl.endTransformFeedback();
7856 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
7858 /* Capture results */
7859 GLuint* feedback_data = (GLuint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7860 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
7862 Utils::vec4<GLuint> routine_1_result;
7863 Utils::vec4<GLuint> routine_2_result;
7865 routine_1_result.m_x = feedback_data[0 + 0];
7866 routine_1_result.m_y = feedback_data[0 + 1];
7867 routine_1_result.m_z = feedback_data[0 + 2];
7868 routine_1_result.m_w = feedback_data[0 + 3];
7870 routine_2_result.m_x = feedback_data[4 + 0];
7871 routine_2_result.m_y = feedback_data[4 + 1];
7872 routine_2_result.m_z = feedback_data[4 + 2];
7873 routine_2_result.m_w = feedback_data[4 + 3];
7876 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7877 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
7880 result = result && (routine_1_result == expected_routine_1_result);
7881 result = result && (routine_2_result == expected_routine_2_result);
7883 /* Log error if any */
7884 if (false == result)
7886 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
7887 << tcu::TestLog::EndMessage;
7889 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
7891 message << "Routine_1, result: ";
7893 routine_1_result.log(message);
7895 message << ", expected: ";
7897 expected_routine_1_result.log(message);
7899 message << "Routine_2, result: ";
7901 routine_2_result.log(message);
7903 message << ", expected: ";
7905 expected_routine_2_result.log(message);
7907 message << tcu::TestLog::EndMessage;
7914 /** Verify initial and current values of subroutine indices and subroutines uniform locations
7916 * @return true if test pass, false otherwise
7918 bool FunctionalTest14_15::testIndicesAndLocations() const
7920 static const GLuint n_subroutine_types = 2;
7923 /* Verify subroutine indices */
7924 for (GLuint type = 0; type < n_subroutine_types; ++type)
7926 result = result && (m_subroutine_indices[type][0] == m_initial_subroutine_indices[type][0]);
7927 result = result && (m_subroutine_indices[type][1] == m_initial_subroutine_indices[type][1]);
7930 /* Verify subroutine uniform locations */
7931 for (GLuint uniform = 0; uniform < n_subroutine_types; ++uniform)
7933 result = result && (m_subroutine_uniform_locations[uniform] == m_initial_subroutine_uniform_locations[uniform]);
7941 * @param context Rendering context.
7944 FunctionalTest16::FunctionalTest16(deqp::Context& context)
7945 : TestCase(context, "subroutine_uniform_reset",
7946 "Checks that when the active program for a shader stage is re-linke or "
7947 "changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages,"
7948 " subroutine uniforms for that stage are reset to arbitrarily chosen default "
7949 "functions with compatible subroutine types.")
7950 , m_are_pipeline_objects_supported(false)
7951 , m_has_test_passed(true)
7953 memset(m_fs_ids, 0, sizeof(m_fs_ids));
7954 memset(m_gs_ids, 0, sizeof(m_gs_ids));
7955 memset(m_po_ids, 0, sizeof(m_po_ids));
7956 memset(m_tc_ids, 0, sizeof(m_tc_ids));
7957 memset(m_te_ids, 0, sizeof(m_te_ids));
7958 memset(m_vs_ids, 0, sizeof(m_vs_ids));
7960 memset(m_fs_po_ids, 0, sizeof(m_fs_po_ids));
7961 memset(m_gs_po_ids, 0, sizeof(m_gs_po_ids));
7962 memset(m_pipeline_object_ids, 0, sizeof(m_pipeline_object_ids));
7963 memset(m_tc_po_ids, 0, sizeof(m_tc_po_ids));
7964 memset(m_te_po_ids, 0, sizeof(m_te_po_ids));
7965 memset(m_vs_po_ids, 0, sizeof(m_vs_po_ids));
7968 /** Deinitializes all GL objects that may have been created during test execution. */
7969 void FunctionalTest16::deinit()
7971 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7973 for (unsigned int n_id = 0; n_id < 2; ++n_id)
7975 if (m_fs_ids[n_id] != 0)
7977 gl.deleteShader(m_fs_ids[n_id]);
7982 if (m_fs_po_ids[n_id] != 0)
7984 gl.deleteProgram(m_fs_po_ids[n_id]);
7986 m_fs_po_ids[n_id] = 0;
7989 if (m_gs_ids[n_id] != 0)
7991 gl.deleteShader(m_gs_ids[n_id]);
7996 if (m_gs_po_ids[n_id] != 0)
7998 gl.deleteProgram(m_gs_po_ids[n_id]);
8000 m_gs_po_ids[n_id] = 0;
8003 if (m_pipeline_object_ids[n_id] != 0)
8005 gl.deleteProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8008 if (m_po_ids[n_id] != 0)
8010 gl.deleteProgram(m_po_ids[n_id]);
8015 if (m_tc_ids[n_id] != 0)
8017 gl.deleteShader(m_tc_ids[n_id]);
8022 if (m_tc_po_ids[n_id] != 0)
8024 gl.deleteProgram(m_tc_po_ids[n_id]);
8026 m_tc_po_ids[n_id] = 0;
8029 if (m_te_ids[n_id] != 0)
8031 gl.deleteShader(m_te_ids[n_id]);
8036 if (m_te_po_ids[n_id] != 0)
8038 gl.deleteProgram(m_te_po_ids[n_id]);
8040 m_te_po_ids[n_id] = 0;
8043 if (m_vs_ids[n_id] != 0)
8045 gl.deleteShader(m_vs_ids[n_id]);
8050 if (m_vs_po_ids[n_id] != 0)
8052 gl.deleteProgram(m_vs_po_ids[n_id]);
8054 m_vs_po_ids[n_id] = 0;
8056 } /* for (both IDs) */
8059 /** Retrieves body of a shader that should be used for user-specified shader stage.
8060 * This function returns slightly different implementations, depending on index of
8061 * the program/pipeline object the shader will be used for.
8063 * @param shader_stage Stage the shader body is to be returned for.
8064 * @param n_id Index of the shader (as per description).
8066 * @return Requested string.
8068 std::string FunctionalTest16::getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const
8070 std::stringstream result_sstream;
8072 result_sstream << "#version 400\n"
8074 "#extension GL_ARB_shader_subroutine : require\n"
8077 switch (shader_stage)
8079 case Utils::SHADER_STAGE_VERTEX:
8081 result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8084 case Utils::SHADER_STAGE_GEOMETRY:
8086 result_sstream << "layout(points) in;\n"
8087 "layout(points, max_vertices = 1) out;\n";
8088 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8089 result_sstream << "out gl_PerVertex { vec4 gl_Position; } ;\n";
8093 case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8095 result_sstream << "layout(vertices = 4) out;\n";
8096 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8097 result_sstream << "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
8101 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8103 result_sstream << "layout(quads) in;\n";
8104 result_sstream << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n";
8105 result_sstream << "out gl_PerVertex { vec4 gl_Position; };\n";
8111 } /* switch (shader_stage) */
8113 result_sstream << "\n"
8114 "subroutine void subroutineType (inout vec4 result);\n"
8115 "subroutine vec4 subroutineType2(in vec4 data);\n"
8117 "subroutine(subroutineType) void function1(inout vec4 result)\n"
8120 << (n_id + 1) << ", " << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4)
8123 "subroutine(subroutineType) void function2(inout vec4 result)\n"
8126 << (n_id + 2) << ", " << (n_id + 3) << ", " << (n_id + 4) << ", " << (n_id + 5)
8130 "subroutine(subroutineType2) vec4 function3(in vec4 data)\n"
8132 " return data * data;\n"
8134 "subroutine(subroutineType2) vec4 function4(in vec4 data)\n"
8136 " return data + data;\n"
8139 "subroutine uniform subroutineType subroutine1;\n"
8140 "subroutine uniform subroutineType subroutine2;\n"
8141 "subroutine uniform subroutineType2 subroutine3;\n"
8142 "subroutine uniform subroutineType2 subroutine4;\n"
8145 if (shader_stage == Utils::SHADER_STAGE_FRAGMENT)
8147 result_sstream << "out vec4 result;\n";
8150 result_sstream << "void main()\n"
8153 switch (shader_stage)
8155 case Utils::SHADER_STAGE_FRAGMENT:
8157 result_sstream << " result = vec4(0);\n"
8158 << " subroutine1(result);\n"
8159 " subroutine2(result);\n"
8160 " result = subroutine3(result) + subroutine4(result);\n";
8165 case Utils::SHADER_STAGE_GEOMETRY:
8167 result_sstream << " gl_Position = vec4(0);\n"
8168 " subroutine1(gl_Position);\n"
8169 " subroutine2(gl_Position);\n"
8170 " gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n"
8176 case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
8178 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0);\n"
8179 " subroutine1(gl_out[gl_InvocationID].gl_Position);\n"
8180 " subroutine2(gl_out[gl_InvocationID].gl_Position);\n"
8181 " gl_out[gl_InvocationID].gl_Position = subroutine3(gl_in[0].gl_Position) + "
8182 "subroutine4(gl_in[0].gl_Position);\n";
8187 case Utils::SHADER_STAGE_VERTEX:
8188 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
8190 result_sstream << " gl_Position = vec4(0);\n"
8191 " subroutine1(gl_Position);\n"
8192 " subroutine2(gl_Position);\n"
8193 " gl_Position = subroutine3(gl_Position) + subroutine4(gl_Position);\n";
8200 } /* switch (shader_stage) */
8202 result_sstream << "}\n";
8204 return result_sstream.str();
8207 /** Initializes all objects required to run the test. */
8208 void FunctionalTest16::initTest()
8210 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8212 for (unsigned int n_id = 0; n_id < 2 /* test program/shader objects */; ++n_id)
8214 const std::string fs_body = getShaderBody(Utils::SHADER_STAGE_FRAGMENT, n_id);
8215 const std::string gs_body = getShaderBody(Utils::SHADER_STAGE_GEOMETRY, n_id);
8216 const std::string tc_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_CONTROL, n_id);
8217 const std::string te_body = getShaderBody(Utils::SHADER_STAGE_TESSELLATION_EVALUATION, n_id);
8218 const std::string vs_body = getShaderBody(Utils::SHADER_STAGE_VERTEX, n_id);
8220 if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
8221 DE_NULL, /* n_xfb_varyings */
8222 m_vs_ids + n_id, m_tc_ids + n_id, m_te_ids + n_id, m_gs_ids + n_id, m_fs_ids + n_id,
8225 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build test program object, index:"
8227 << n_id << "]" << tcu::TestLog::EndMessage;
8229 TCU_FAIL("Failed to build a test program");
8232 if (m_are_pipeline_objects_supported)
8234 /* Initialize shader program objects */
8235 const char* fs_body_raw_ptr = fs_body.c_str();
8236 const char* gs_body_raw_ptr = gs_body.c_str();
8237 glw::GLint link_status[5] = { GL_FALSE };
8238 const char* tc_body_raw_ptr = tc_body.c_str();
8239 const char* te_body_raw_ptr = te_body.c_str();
8240 const char* vs_body_raw_ptr = vs_body.c_str();
8242 m_fs_po_ids[n_id] = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1 /* count */, &fs_body_raw_ptr);
8243 m_gs_po_ids[n_id] = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1 /* count */, &gs_body_raw_ptr);
8244 m_tc_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_CONTROL_SHADER, 1 /* count */, &tc_body_raw_ptr);
8245 m_te_po_ids[n_id] = gl.createShaderProgramv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &te_body_raw_ptr);
8246 m_vs_po_ids[n_id] = gl.createShaderProgramv(GL_VERTEX_SHADER, 1 /* count */, &vs_body_raw_ptr);
8247 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
8249 gl.getProgramiv(m_fs_po_ids[n_id], GL_LINK_STATUS, link_status + 0);
8250 gl.getProgramiv(m_gs_po_ids[n_id], GL_LINK_STATUS, link_status + 1);
8251 gl.getProgramiv(m_tc_po_ids[n_id], GL_LINK_STATUS, link_status + 2);
8252 gl.getProgramiv(m_te_po_ids[n_id], GL_LINK_STATUS, link_status + 3);
8253 gl.getProgramiv(m_vs_po_ids[n_id], GL_LINK_STATUS, link_status + 4);
8254 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8256 if (link_status[0] == GL_FALSE)
8257 TCU_FAIL("Fragment shader program failed to link");
8258 if (link_status[1] == GL_FALSE)
8259 TCU_FAIL("Geometry shader program failed to link");
8260 if (link_status[2] == GL_FALSE)
8261 TCU_FAIL("Tessellation control shader program failed to link");
8262 if (link_status[3] == GL_FALSE)
8263 TCU_FAIL("Tessellation evaluation shader program failed to link");
8264 if (link_status[4] == GL_FALSE)
8265 TCU_FAIL("Vertex shader program failed to link");
8267 /* Initialize pipeline program object */
8268 gl.genProgramPipelines(1 /* n */, m_pipeline_object_ids + n_id);
8269 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
8271 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_FRAGMENT_SHADER_BIT, m_fs_po_ids[n_id]);
8272 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_GEOMETRY_SHADER_BIT, m_gs_po_ids[n_id]);
8273 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_CONTROL_SHADER_BIT, m_tc_po_ids[n_id]);
8274 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_TESS_EVALUATION_SHADER_BIT, m_te_po_ids[n_id]);
8275 gl.useProgramStages(m_pipeline_object_ids[n_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_id]);
8276 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8279 /* Retrieve subroutine locations */
8283 _shader_stage& stage;
8285 glw::GLenum so_type;
8287 { m_po_ids[n_id], m_po_descriptors[n_id].fragment, m_fs_ids[n_id], GL_FRAGMENT_SHADER },
8288 { m_po_ids[n_id], m_po_descriptors[n_id].geometry, m_gs_ids[n_id], GL_GEOMETRY_SHADER },
8289 { m_po_ids[n_id], m_po_descriptors[n_id].tess_control, m_tc_ids[n_id], GL_TESS_CONTROL_SHADER },
8290 { m_po_ids[n_id], m_po_descriptors[n_id].tess_evaluation, m_te_ids[n_id], GL_TESS_EVALUATION_SHADER },
8291 { m_po_ids[n_id], m_po_descriptors[n_id].vertex, m_vs_ids[n_id], GL_VERTEX_SHADER },
8293 { m_fs_po_ids[n_id], m_fs_po_descriptors[n_id], m_fs_po_ids[n_id], GL_FRAGMENT_SHADER },
8294 { m_gs_po_ids[n_id], m_gs_po_descriptors[n_id], m_gs_po_ids[n_id], GL_GEOMETRY_SHADER },
8295 { m_tc_po_ids[n_id], m_tc_po_descriptors[n_id], m_tc_po_ids[n_id], GL_TESS_CONTROL_SHADER },
8296 { m_te_po_ids[n_id], m_te_po_descriptors[n_id], m_te_po_ids[n_id], GL_TESS_EVALUATION_SHADER },
8297 { m_vs_po_ids[n_id], m_vs_po_descriptors[n_id], m_vs_po_ids[n_id], GL_VERTEX_SHADER },
8299 const unsigned int n_items = sizeof(items) / sizeof(items[0]);
8301 for (unsigned int n_item = 0; n_item < n_items; ++n_item)
8303 _item& current_item = items[n_item];
8305 current_item.stage.function1_index =
8306 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function1");
8307 current_item.stage.function2_index =
8308 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function2");
8309 current_item.stage.function3_index =
8310 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function3");
8311 current_item.stage.function4_index =
8312 gl.getSubroutineIndex(current_item.po_id, current_item.so_type, "function4");
8313 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
8315 if (current_item.stage.function1_index == GL_INVALID_INDEX ||
8316 current_item.stage.function2_index == GL_INVALID_INDEX ||
8317 current_item.stage.function3_index == GL_INVALID_INDEX ||
8318 current_item.stage.function4_index == GL_INVALID_INDEX)
8320 TCU_FAIL("Subroutine name was not recognized.");
8323 current_item.stage.subroutine1_uniform_location =
8324 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine1");
8325 current_item.stage.subroutine2_uniform_location =
8326 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine2");
8327 current_item.stage.subroutine3_uniform_location =
8328 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine3");
8329 current_item.stage.subroutine4_uniform_location =
8330 gl.getSubroutineUniformLocation(current_item.po_id, current_item.so_type, "subroutine4");
8331 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
8333 if (current_item.stage.subroutine1_uniform_location == -1 ||
8334 current_item.stage.subroutine2_uniform_location == -1 ||
8335 current_item.stage.subroutine3_uniform_location == -1 ||
8336 current_item.stage.subroutine4_uniform_location == -1)
8338 TCU_FAIL("Subroutine uniform name was not recognized.");
8341 if (m_po_ids[n_id] == current_item.po_id)
8343 gl.useProgram(current_item.po_id);
8344 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8348 /* Temporarily bind the program pipeline. */
8349 gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8350 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8353 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine1_uniform_location,
8354 ¤t_item.stage.default_subroutine1_value);
8355 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine2_uniform_location,
8356 ¤t_item.stage.default_subroutine2_value);
8357 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine3_uniform_location,
8358 ¤t_item.stage.default_subroutine3_value);
8359 gl.getUniformSubroutineuiv(current_item.so_type, current_item.stage.subroutine4_uniform_location,
8360 ¤t_item.stage.default_subroutine4_value);
8361 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8363 current_item.stage.gl_stage = current_item.so_type;
8365 if (m_po_ids[n_id] != current_item.po_id)
8367 /* Unbind the program pipeline object */
8368 gl.bindProgramPipeline(0);
8369 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8371 } /* for (all items) */
8373 /* Make sure the default subroutine choices are valid. */
8374 verifySubroutineUniformValues(
8375 TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, /* makes the verification routine use program object descriptor */
8376 n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8378 if (m_are_pipeline_objects_supported)
8381 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8383 gl.bindProgramPipeline(m_pipeline_object_ids[n_id]);
8384 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8386 verifySubroutineUniformValues(
8387 TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT, /* makes the verification routine use pipeline object descriptor */
8388 n_id, SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES);
8390 gl.bindProgramPipeline(0);
8391 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
8393 } /* for (both program descriptors) */
8396 /** Retrieves IDs of shaders OR shader program objects, depending on which of the two
8397 * the caller requests for.
8399 * @param retrieve_program_object_shader_ids true if the caller wishes to retrieve shader object IDs,
8400 * false to return shader program IDs.
8401 * @param n_id Index of the program/pipeline object the shaders
8403 * @param out_shader_stages Deref will be used to store exactly five IDs. Must not
8406 void FunctionalTest16::getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id,
8407 const _shader_stage** out_shader_stages) const
8409 if (retrieve_program_object_shader_ids)
8411 out_shader_stages[0] = &m_po_descriptors[n_id].vertex;
8412 out_shader_stages[1] = &m_po_descriptors[n_id].tess_control;
8413 out_shader_stages[2] = &m_po_descriptors[n_id].tess_evaluation;
8414 out_shader_stages[3] = &m_po_descriptors[n_id].geometry;
8415 out_shader_stages[4] = &m_po_descriptors[n_id].fragment;
8419 out_shader_stages[0] = m_vs_po_descriptors + n_id;
8420 out_shader_stages[1] = m_tc_po_descriptors + n_id;
8421 out_shader_stages[2] = m_te_po_descriptors + n_id;
8422 out_shader_stages[3] = m_gs_po_descriptors + n_id;
8423 out_shader_stages[4] = m_fs_po_descriptors + n_id;
8427 /** Executes test iteration.
8429 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8431 tcu::TestNode::IterateResult FunctionalTest16::iterate()
8433 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8435 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
8436 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
8438 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
8441 m_are_pipeline_objects_supported =
8442 m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects");
8444 /* Initialize GL objects required to run the test */
8447 /* Iterate over both pipelines/programs and verify that calling glUseProgram() /
8448 * glBindProgramPipeline() / glUseProgramStages() resets subroutine uniform configuration.
8450 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
8452 if (static_cast<_test_case>(test_case) != TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT &&
8453 !m_are_pipeline_objects_supported)
8455 /* Current test case requires GL_ARB_separate_shader_objects support which is
8456 * unavaiable on the platform that we're testing
8461 for (unsigned int n_object_id = 0; n_object_id < 2; /* pipeline/program objects allocated for the test */
8464 /* Verify that currently reported subroutine uniform values are equal to default values */
8465 if (test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT)
8467 gl.useProgram(m_po_ids[n_object_id]);
8468 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
8472 gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8473 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed");
8476 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8477 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8479 /* Re-configure subroutine uniforms so that they point to different subroutines than
8482 const _shader_stage* stages[5 /* fs+gs+tc+te+vs */] = { DE_NULL };
8484 getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8485 n_object_id, stages);
8487 for (unsigned int n_stage = 0; n_stage < 5 /* fs+gs+tc+te+vs stages */; ++n_stage)
8489 const _shader_stage& current_stage = *(stages[n_stage]);
8490 glw::GLuint subroutine_configuration[4] = { GL_INVALID_INDEX };
8492 subroutine_configuration[0] =
8493 (current_stage.default_subroutine1_value == current_stage.function1_index) ?
8494 current_stage.function2_index :
8495 current_stage.function1_index;
8496 subroutine_configuration[1] =
8497 (current_stage.default_subroutine2_value == current_stage.function1_index) ?
8498 current_stage.function2_index :
8499 current_stage.function1_index;
8500 subroutine_configuration[2] =
8501 (current_stage.default_subroutine3_value == current_stage.function3_index) ?
8502 current_stage.function4_index :
8503 current_stage.function3_index;
8504 subroutine_configuration[3] =
8505 (current_stage.default_subroutine4_value == current_stage.function3_index) ?
8506 current_stage.function4_index :
8507 current_stage.function3_index;
8509 gl.uniformSubroutinesuiv(current_stage.gl_stage, 4 /* count */, subroutine_configuration);
8510 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed.");
8511 } /* for (all stages) */
8513 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8514 SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8516 /* Execute test case-specific code */
8517 _shader_stage cached_shader_stage_data;
8518 bool stage_reset_status[Utils::SHADER_STAGE_COUNT] = { false, false, false, false, false };
8519 bool uses_stage_reset_status = false;
8523 case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT:
8525 /* Switch to a different program object and then back to current PO.
8526 * Subroutine uniforms should be back at their default settings, instead of
8527 * the ones we've just set.
8529 gl.useProgram(m_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8530 gl.useProgram(m_po_ids[n_object_id]);
8531 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
8536 case TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT:
8538 /* Switch to a different pipeline object and then back to the current one.
8539 * Subroutine uniforms should be back at their default settings, instead of
8540 * the ones we've just set.
8542 gl.bindProgramPipeline(
8543 m_pipeline_object_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8544 gl.bindProgramPipeline(m_pipeline_object_ids[n_object_id]);
8545 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
8550 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8552 /* Change the fragment shader stage to a different one.
8554 * Note: We also need to update internal descriptor since the subroutine/uniform
8555 * locations may be different between the two programs.
8557 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8558 m_fs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8559 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8561 cached_shader_stage_data = m_fs_po_descriptors[n_object_id];
8562 m_fs_po_descriptors[n_object_id] = m_fs_po_descriptors[(n_object_id + 1) % 2];
8564 stage_reset_status[Utils::SHADER_STAGE_FRAGMENT] = true;
8565 uses_stage_reset_status = true;
8570 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8572 /* Change the geometry shader stage to a different one.
8574 * Note: We also need to update internal descriptor since the subroutine/uniform
8575 * locations may be different between the two programs.
8577 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8578 m_gs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8579 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8581 cached_shader_stage_data = m_gs_po_descriptors[n_object_id];
8582 m_gs_po_descriptors[n_object_id] = m_gs_po_descriptors[(n_object_id + 1) % 2];
8584 stage_reset_status[Utils::SHADER_STAGE_GEOMETRY] = true;
8585 uses_stage_reset_status = true;
8590 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8592 /* Change the tessellation control shader stage to a different one.
8594 * Note: We also need to update internal descriptor since the subroutine/uniform
8595 * locations may be different between the two programs.
8597 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8598 m_tc_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8599 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8601 cached_shader_stage_data = m_tc_po_descriptors[n_object_id];
8602 m_tc_po_descriptors[n_object_id] = m_tc_po_descriptors[(n_object_id + 1) % 2];
8604 stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_CONTROL] = true;
8605 uses_stage_reset_status = true;
8610 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8612 /* Change the tessellation evaluation shader stage to a different one.
8614 * Note: We also need to update internal descriptor since the subroutine/uniform
8615 * locations may be different between the two programs.
8617 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8618 m_te_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8619 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8621 cached_shader_stage_data = m_te_po_descriptors[n_object_id];
8622 m_te_po_descriptors[n_object_id] = m_te_po_descriptors[(n_object_id + 1) % 2];
8624 stage_reset_status[Utils::SHADER_STAGE_TESSELLATION_EVALUATION] = true;
8625 uses_stage_reset_status = true;
8630 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8632 /* Change the vertex shader stage to a different one.
8634 * Note: We also need to update internal descriptor since the subroutine/uniform
8635 * locations may be different between the two programs.
8637 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT,
8638 m_vs_po_ids[(n_object_id + 1) % 2 /* objects allocated for the test */]);
8639 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8641 cached_shader_stage_data = m_vs_po_descriptors[n_object_id];
8642 m_vs_po_descriptors[n_object_id] = m_vs_po_descriptors[(n_object_id + 1) % 2];
8644 stage_reset_status[Utils::SHADER_STAGE_VERTEX] = true;
8645 uses_stage_reset_status = true;
8652 TCU_FAIL("Unrecognized test case");
8654 } /* switch (test_case) */
8656 /* Verify the subroutine uniform values are valid */
8657 if (!uses_stage_reset_status)
8659 verifySubroutineUniformValues(static_cast<_test_case>(test_case), n_object_id,
8660 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8664 const _shader_stage* shader_stages[Utils::SHADER_STAGE_COUNT] = { DE_NULL };
8666 getShaderStages(static_cast<_test_case>(test_case) == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT,
8667 n_object_id, shader_stages);
8669 for (unsigned int n_shader_stage = 0; n_shader_stage < Utils::SHADER_STAGE_COUNT; ++n_shader_stage)
8671 const _shader_stage& current_shader_stage = *(shader_stages[n_shader_stage]);
8673 if (stage_reset_status[n_shader_stage])
8675 verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8676 SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES);
8680 verifySubroutineUniformValuesForShaderStage(current_shader_stage,
8681 SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8683 } /* for (all shader stages) */
8686 /* Revert the changes some of the test cases appied */
8689 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE:
8691 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_FRAGMENT_SHADER_BIT,
8692 m_fs_po_ids[n_object_id]);
8693 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8695 m_fs_po_descriptors[n_object_id] = cached_shader_stage_data;
8700 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE:
8702 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_GEOMETRY_SHADER_BIT,
8703 m_gs_po_ids[n_object_id]);
8704 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8706 m_gs_po_descriptors[n_object_id] = cached_shader_stage_data;
8711 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE:
8713 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_CONTROL_SHADER_BIT,
8714 m_tc_po_ids[n_object_id]);
8715 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8717 m_tc_po_descriptors[n_object_id] = cached_shader_stage_data;
8722 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE:
8724 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_TESS_EVALUATION_SHADER_BIT,
8725 m_te_po_ids[n_object_id]);
8726 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8728 m_te_po_descriptors[n_object_id] = cached_shader_stage_data;
8733 case TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE:
8735 gl.useProgramStages(m_pipeline_object_ids[n_object_id], GL_VERTEX_SHADER_BIT, m_vs_po_ids[n_object_id]);
8736 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
8738 m_vs_po_descriptors[n_object_id] = cached_shader_stage_data;
8745 } /* switch (test_case) */
8747 } /* for (all program object descriptors) */
8749 /* Unbind the program object */
8751 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
8752 } /* for (all test cases) */
8754 if (m_has_test_passed)
8756 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8760 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8766 /** Verifies the subroutine uniform values reported by GL implementation. Depending on the test case,
8767 * it will either query program object stages or separate shader objects.
8769 * @param test_case Test case the verification is to be performed for.
8770 * @param n_id Index of the program/pipeline object to use for the verification
8771 * @param verification Verification method.
8773 void FunctionalTest16::verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id,
8774 const _subroutine_uniform_value_verification& verification)
8776 const _shader_stage* stages[] = {
8777 DE_NULL, /* fragment shader stage slot */
8778 DE_NULL, /* geometry shader stage slot */
8779 DE_NULL, /* tess control shader stage slot */
8780 DE_NULL, /* tess eval shader stage slot */
8781 DE_NULL /* vertex shader stage slot */
8783 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
8785 /* Verify that currently reported subroutine uniform values are equal to default values */
8786 getShaderStages(test_case == TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT, n_id, stages);
8788 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
8790 const _shader_stage& current_stage = *(stages[n_stage]);
8792 verifySubroutineUniformValuesForShaderStage(current_stage, verification);
8793 } /* for (all items) */
8796 /** Verifies the subroutine uniform values reported by GL implementation for user-specified
8797 * shader stage. If the verification fails, m_has_test_passed will be set to false.
8799 * @param shader_stage Descriptor of a shader stage that should be used for the process.
8800 * @param verification Type of verification that should be performed.
8803 void FunctionalTest16::verifySubroutineUniformValuesForShaderStage(
8804 const _shader_stage& shader_stage, const _subroutine_uniform_value_verification& verification)
8806 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8807 glw::GLuint result_values[4] = { 0 };
8809 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine1_uniform_location, result_values + 0);
8810 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine2_uniform_location, result_values + 1);
8811 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine3_uniform_location, result_values + 2);
8812 gl.getUniformSubroutineuiv(shader_stage.gl_stage, shader_stage.subroutine4_uniform_location, result_values + 3);
8813 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformSubroutineuiv() call(s) failed.");
8815 if (verification == SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES)
8817 if (!((result_values[0] == (GLuint)shader_stage.subroutine1_uniform_location ||
8818 result_values[0] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8819 (result_values[1] == (GLuint)shader_stage.subroutine1_uniform_location ||
8820 result_values[1] == (GLuint)shader_stage.subroutine2_uniform_location) &&
8821 (result_values[2] == (GLuint)shader_stage.subroutine3_uniform_location ||
8822 result_values[2] == (GLuint)shader_stage.subroutine4_uniform_location) &&
8823 (result_values[3] == (GLuint)shader_stage.subroutine3_uniform_location ||
8824 result_values[3] == (GLuint)shader_stage.subroutine4_uniform_location)))
8826 m_testCtx.getLog() << tcu::TestLog::Message << "SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES validation failed. "
8828 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8830 << shader_stage.subroutine1_uniform_location << " OR "
8831 << shader_stage.subroutine2_uniform_location << " x 2, "
8832 << shader_stage.subroutine3_uniform_location << " OR "
8833 << shader_stage.subroutine4_uniform_location << " x 2], "
8835 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8836 << result_values[3] << "]." << tcu::TestLog::EndMessage;
8838 m_has_test_passed = false;
8841 else if (verification == SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES)
8843 if (result_values[0] != shader_stage.default_subroutine1_value ||
8844 result_values[1] != shader_stage.default_subroutine2_value ||
8845 result_values[2] != shader_stage.default_subroutine3_value ||
8846 result_values[3] != shader_stage.default_subroutine4_value)
8848 m_testCtx.getLog() << tcu::TestLog::Message
8849 << "SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES validation failed. "
8851 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8853 << shader_stage.default_subroutine1_value << ", "
8854 << shader_stage.default_subroutine2_value << ", "
8855 << shader_stage.default_subroutine3_value << ", "
8856 << shader_stage.default_subroutine4_value << "], "
8858 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8859 << result_values[3] << "]." << tcu::TestLog::EndMessage;
8861 m_has_test_passed = false;
8866 DE_ASSERT(verification == SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES);
8868 if (result_values[0] == shader_stage.default_subroutine1_value ||
8869 result_values[1] == shader_stage.default_subroutine2_value ||
8870 result_values[2] == shader_stage.default_subroutine3_value ||
8871 result_values[3] == shader_stage.default_subroutine4_value)
8873 m_testCtx.getLog() << tcu::TestLog::Message
8874 << "SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES validation failed. "
8876 << Utils::getShaderStageStringFromGLEnum(shader_stage.gl_stage) << "], "
8878 << shader_stage.default_subroutine1_value << ", "
8879 << shader_stage.default_subroutine2_value << ", "
8880 << shader_stage.default_subroutine3_value << ", "
8881 << shader_stage.default_subroutine4_value << "], "
8883 << result_values[0] << ", " << result_values[1] << ", " << result_values[2] << ", "
8884 << result_values[3] << "]." << tcu::TestLog::EndMessage;
8886 m_has_test_passed = false;
8893 * @param context Rendering context.
8896 FunctionalTest17::FunctionalTest17(deqp::Context& context)
8897 : TestCase(context, "same_subroutine_and_subroutine_uniform_but_different_type_used_in_all_stages",
8898 "Creates a program which uses the same subroutine and subroutine uniform "
8899 "names for every stage (types of subroutines are different in each stage) "
8900 "and then makes sure that such program compiles and works as expected.")
8904 , m_has_test_passed(true)
8908 , m_to_data(DE_NULL)
8909 , m_to_height(4) /* arbitrary value */
8911 , m_to_width(4) /* arbitrary value */
8915 /* Left blank intentionally */
8918 /** Deinitializes all GL objects that may have been created during test execution. */
8919 void FunctionalTest17::deinit()
8921 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8925 gl.deleteFramebuffers(1, &m_fbo_id);
8932 gl.deleteShader(m_fs_id);
8939 gl.deleteShader(m_gs_id);
8946 gl.deleteProgram(m_po_id);
8953 gl.deleteShader(m_tc_id);
8960 gl.deleteShader(m_te_id);
8965 if (m_to_data != DE_NULL)
8969 m_to_data = DE_NULL;
8974 gl.deleteTextures(1, &m_to_id);
8981 gl.deleteVertexArrays(1, &m_vao_id);
8988 gl.deleteShader(m_vs_id);
8993 /* Restore original GL configuration */
8994 gl.patchParameteri(GL_PATCH_VERTICES, 3);
8995 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
8997 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
8998 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
9001 /** Retrieves body of a fragment shader that should be used by the test program.
9003 * @return Requested string.
9005 std::string FunctionalTest17::getFragmentShaderBody() const
9007 return "#version 400\n"
9009 "#extension GL_ARB_shader_subroutine : require\n"
9019 "out vec4 result;\n"
9021 "subroutine void subroutineTypeFS(out vec4 result);\n"
9023 "subroutine(subroutineTypeFS) void subroutine1(out vec4 result)\n"
9025 " result = vec4(5, 6, 7, 8);\n"
9028 "subroutine uniform subroutineTypeFS function;\n"
9034 " function(fs_data);\n"
9035 " result = gs.gs_data + gs.tc_data + gs.te_data + gs.vs_data + fs_data;\n"
9039 /** Retrieves body of a geometry shader that should be used by the test program.
9041 * @return Requested string.
9043 std::string FunctionalTest17::getGeometryShaderBody() const
9045 return "#version 400\n"
9047 "#extension GL_ARB_shader_subroutine : require\n"
9049 "layout(points) in;\n"
9050 "layout(triangle_strip, max_vertices = 4) out;\n"
9052 "subroutine void subroutineTypeGS(out vec4 result);\n"
9054 "subroutine(subroutineTypeGS) void subroutine1(out vec4 result)\n"
9056 " result = vec4(4, 5, 6, 7);\n"
9059 "subroutine uniform subroutineTypeGS function;\n"
9078 " function(result.gs_data);\n"
9079 " gl_Position = vec4(1, -1, 0, 1);\n"
9080 " result.tc_data = te[0].tc_data;\n"
9081 " result.te_data = te[0].te_data;\n"
9082 " result.vs_data = te[0].vs_data;\n"
9085 " function(result.gs_data);\n"
9086 " gl_Position = vec4(-1, -1, 0, 1);\n"
9087 " result.tc_data = te[0].tc_data;\n"
9088 " result.te_data = te[0].te_data;\n"
9089 " result.vs_data = te[0].vs_data;\n"
9092 " function(result.gs_data);\n"
9093 " gl_Position = vec4(1, 1, 0, 1);\n"
9094 " result.tc_data = te[0].tc_data;\n"
9095 " result.te_data = te[0].te_data;\n"
9096 " result.vs_data = te[0].vs_data;\n"
9099 " function(result.gs_data);\n"
9100 " gl_Position = vec4(-1, 1, 0, 1);\n"
9101 " result.tc_data = te[0].tc_data;\n"
9102 " result.te_data = te[0].te_data;\n"
9103 " result.vs_data = te[0].vs_data;\n"
9105 " EndPrimitive();\n"
9109 /** Retrieves body of a tessellation control shader that should be used by the test program.
9111 * @return Requested string.
9113 std::string FunctionalTest17::getTessellationControlShaderBody() const
9115 return "#version 400\n"
9117 "#extension GL_ARB_shader_subroutine : require\n"
9119 "layout (vertices = 4) out;\n"
9121 "subroutine void subroutineTypeTC(out vec4 result);\n"
9123 "subroutine(subroutineTypeTC) void subroutine1(out vec4 result)\n"
9125 " result = vec4(2, 3, 4, 5);\n"
9128 "subroutine uniform subroutineTypeTC function;\n"
9143 " gl_TessLevelInner[0] = 1.0;\n"
9144 " gl_TessLevelInner[1] = 1.0;\n"
9145 " gl_TessLevelOuter[0] = 1.0;\n"
9146 " gl_TessLevelOuter[1] = 1.0;\n"
9147 " gl_TessLevelOuter[2] = 1.0;\n"
9148 " gl_TessLevelOuter[3] = 1.0;\n"
9150 " function(result[gl_InvocationID].tc_data);\n"
9151 " result[gl_InvocationID].vs_data = vs[gl_InvocationID].vs_data;\n"
9155 /** Retrieves body of a tessellation evaluation shader that should be used
9156 * by the test program.
9158 * @return Requested string.
9160 std::string FunctionalTest17::getTessellationEvaluationShaderBody() const
9162 return "#version 400\n"
9164 "#extension GL_ARB_shader_subroutine : require\n"
9166 "layout (quads, point_mode) in;\n"
9168 "subroutine void subroutineTypeTE(out vec4 result);\n"
9170 "subroutine(subroutineTypeTE) void subroutine1(out vec4 result)\n"
9172 " result = vec4(3, 4, 5, 6);\n"
9175 "subroutine uniform subroutineTypeTE function;\n"
9192 " result.vs_data = tc[0].vs_data;\n"
9193 " result.tc_data = tc[0].tc_data;\n"
9194 " function(result.te_data);\n"
9198 /** Retrieves body of a vertex shader that should be used by the test program.
9200 * @return Requested string.
9202 std::string FunctionalTest17::getVertexShaderBody() const
9204 return "#version 400\n"
9206 "#extension GL_ARB_shader_subroutine : require\n"
9213 "subroutine void subroutineTypeVS(out vec4 result);\n"
9215 "subroutine(subroutineTypeVS) void subroutine1(out vec4 result)\n"
9217 " result = vec4(1, 2, 3, 4);\n"
9220 "subroutine uniform subroutineTypeVS function;\n"
9224 " function(result.vs_data);\n"
9228 /** Initializes all buffers and GL objects required to run the test. */
9229 void FunctionalTest17::initTest()
9231 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9233 /* Configure GL_PATCH_VERTICES so that TC only takes a single patch vertex */
9234 gl.patchParameteri(GL_PATCH_VERTICES, 1);
9235 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
9237 /* Generate & bind a VAO */
9238 gl.genVertexArrays(1, &m_vao_id);
9239 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9241 gl.bindVertexArray(m_vao_id);
9242 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9244 /* Set up test program object */
9245 std::string fs_body = getFragmentShaderBody();
9246 std::string gs_body = getGeometryShaderBody();
9247 std::string tc_body = getTessellationControlShaderBody();
9248 std::string te_body = getTessellationEvaluationShaderBody();
9249 std::string vs_body = getVertexShaderBody();
9251 if (!Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, DE_NULL, /* xfb_varyings */
9252 DE_NULL, /* n_xfb_varyings */
9253 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
9255 TCU_FAIL("Failed to link test program object");
9258 /* Set up a texture object that will be used as a color attachment */
9259 gl.genTextures(1, &m_to_id);
9260 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
9262 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9263 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9265 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
9266 GL_RGBA32F, m_to_width, m_to_height);
9267 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9270 gl.genFramebuffers(1, &m_fbo_id);
9271 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9273 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9274 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
9276 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
9277 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
9279 /* Make sure glReadPixels() does not return misaligned data */
9280 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
9281 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
9283 /* Initialize a buffer that will be used to store rendered data */
9284 m_to_data = new float[m_to_width * m_to_height * 4 /* rgba */];
9287 /** Executes test iteration.
9289 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9291 tcu::TestNode::IterateResult FunctionalTest17::iterate()
9293 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9295 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9296 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9298 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9303 /* Use the test program to render a full-screen test quad */
9304 gl.useProgram(m_po_id);
9305 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9307 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
9308 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9310 /* Read back the data that was rendered */
9311 gl.readPixels(0, /* x */
9313 m_to_width, m_to_height, GL_RGBA, GL_FLOAT, m_to_data);
9314 GLU_EXPECT_NO_ERROR(gl.getError(), "glReaDPixels() call failed.");
9316 /* Verify the data */
9317 verifyRenderedData();
9320 if (m_has_test_passed)
9322 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9326 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9332 /** Verifies the data that have been rendered by the test program.
9334 * It is assumed the rendered data have already been copied to
9337 * If the rendered data is found to be invalid, m_has_test_passed
9338 * will be set to false.
9340 void FunctionalTest17::verifyRenderedData()
9342 const float epsilon = 1e-5f;
9343 const float expected_data[4] = { 15.0f, 20.0f, 25.0f, 30.0f };
9345 for (unsigned int y = 0; y < m_to_height && m_has_test_passed; ++y)
9347 const float* row_ptr = m_to_data + y * 4 /* rgba */ * m_to_width;
9349 for (unsigned int x = 0; x < m_to_width && m_has_test_passed; ++x)
9351 const float* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9353 if (de::abs(pixel_ptr[0] - expected_data[0]) > epsilon ||
9354 de::abs(pixel_ptr[1] - expected_data[1]) > epsilon ||
9355 de::abs(pixel_ptr[2] - expected_data[2]) > epsilon ||
9356 de::abs(pixel_ptr[3] - expected_data[3]) > epsilon)
9358 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel found at (" << x << ", " << y
9361 << expected_data[0] << ", " << expected_data[1] << ", " << expected_data[2] << ", "
9362 << expected_data[3] << "), found:(" << pixel_ptr[0] << ", " << pixel_ptr[1] << ", "
9363 << pixel_ptr[2] << ", " << pixel_ptr[3] << ")." << tcu::TestLog::EndMessage;
9365 m_has_test_passed = false;
9367 } /* for (all columns) */
9368 } /* for (all rows) */
9373 * @param context Rendering context.
9376 FunctionalTest18_19::FunctionalTest18_19(deqp::Context& context)
9377 : TestCase(context, "control_flow_and_returned_subroutine_values_used_as_subroutine_input",
9378 "Makes sure that calling a subroutine with argument value returned by "
9379 "another subroutine works correctly. Also checks that subroutine and "
9380 "subroutine uniforms work as expected when used in connection with control "
9382 , m_has_test_passed(true)
9383 , m_n_points_to_draw(16) /* arbitrary value */
9385 , m_po_subroutine_divide_by_two_location(GL_INVALID_INDEX)
9386 , m_po_subroutine_multiply_by_four_location(GL_INVALID_INDEX)
9387 , m_po_subroutine_returns_false_location(GL_INVALID_INDEX)
9388 , m_po_subroutine_returns_true_location(GL_INVALID_INDEX)
9389 , m_po_subroutine_uniform_bool_operator1(-1)
9390 , m_po_subroutine_uniform_bool_operator2(-1)
9391 , m_po_subroutine_uniform_vec4_processor1(-1)
9392 , m_po_subroutine_uniform_vec4_processor2(-1)
9397 /* Left blank intentionally */
9400 /** De-initializes all GL objects that may have been created during test execution */
9401 void FunctionalTest18_19::deinit()
9403 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9407 gl.deleteProgram(m_po_id);
9414 gl.deleteVertexArrays(1, &m_vao_id);
9421 gl.deleteShader(m_vs_id);
9426 if (m_xfb_bo_id != 0)
9428 gl.deleteBuffers(1, &m_xfb_bo_id);
9434 /** Executes a single test iteration using user-specified properties. If the
9435 * iterations fails, m_has_test_passed is set to false.
9437 * @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9438 * bool_operator1 subroutine uniform.
9439 * @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9440 * bool_operator2 subroutine uniform.
9441 * @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9442 * vec4_operator1 subroutine uniform.
9443 * @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9444 * vec4_operator2 subroutine uniform.
9446 void FunctionalTest18_19::executeTest(glw::GLuint bool_operator1_subroutine_location,
9447 glw::GLuint bool_operator2_subroutine_location,
9448 glw::GLuint vec4_operator1_subroutine_location,
9449 glw::GLuint vec4_operator2_subroutine_location)
9451 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9453 /* Set up subroutines */
9454 glw::GLuint subroutine_configuration[4 /* total number of subroutines */] = { 0 };
9456 subroutine_configuration[m_po_subroutine_uniform_bool_operator1] = bool_operator1_subroutine_location;
9457 subroutine_configuration[m_po_subroutine_uniform_bool_operator2] = bool_operator2_subroutine_location;
9458 subroutine_configuration[m_po_subroutine_uniform_vec4_processor1] = vec4_operator1_subroutine_location;
9459 subroutine_configuration[m_po_subroutine_uniform_vec4_processor2] = vec4_operator2_subroutine_location;
9461 gl.useProgram(m_po_id);
9462 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed");
9464 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 4 /* count */, subroutine_configuration);
9465 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() call failed");
9467 /* Draw test-specific number of points */
9468 gl.beginTransformFeedback(GL_POINTS);
9469 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
9471 gl.drawArrays(GL_POINTS, 0 /* first */, m_n_points_to_draw);
9472 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
9474 gl.endTransformFeedback();
9475 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
9477 /* Map the BO storage into process space */
9478 const glw::GLvoid* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
9479 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
9481 verifyXFBData(xfb_data_ptr, bool_operator1_subroutine_location, bool_operator2_subroutine_location,
9482 vec4_operator1_subroutine_location, vec4_operator2_subroutine_location);
9484 /* Unmap BO storage */
9485 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
9486 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
9489 /** Retrieves body of a vertex shader to be used by the test. */
9490 std::string FunctionalTest18_19::getVertexShaderBody() const
9492 return "#version 400\n"
9494 "subroutine bool bool_processor();\n"
9495 "subroutine vec4 vec4_processor(in vec4 iparam);\n"
9497 "subroutine(bool_processor) bool returnsFalse()\n"
9502 "subroutine(bool_processor) bool returnsTrue()\n"
9507 "subroutine(vec4_processor) vec4 divideByTwo(in vec4 iparam)\n"
9509 " return iparam * vec4(0.5);\n"
9512 "subroutine(vec4_processor) vec4 multiplyByFour(in vec4 iparam)\n"
9514 " return iparam * vec4(4.0);\n"
9517 "subroutine uniform bool_processor bool_operator1;\n"
9518 "subroutine uniform bool_processor bool_operator2;\n"
9519 "subroutine uniform vec4_processor vec4_operator1;\n"
9520 "subroutine uniform vec4_processor vec4_operator2;\n"
9522 "out float result;\n"
9526 " if (bool_operator1() )\n"
9528 " float value = float( (3 * gl_VertexID + 1) * 2);\n"
9530 " while (bool_operator1() )\n"
9532 " value /= float(gl_VertexID + 2);\n"
9534 " if (value <= 1.0f) break;\n"
9537 " result = value;\n"
9541 " vec4 value = vec4(gl_VertexID, gl_VertexID + 1,\n"
9542 " gl_VertexID + 2, gl_VertexID + 3);\n"
9544 " switch (gl_VertexID % 2)\n"
9548 " for (int iteration = 0; iteration < gl_VertexID && bool_operator2(); ++iteration)\n"
9550 " value = vec4_operator2(vec4_operator1(value));\n"
9558 " for (int iteration = 0; iteration < gl_VertexID * 2; ++iteration)\n"
9560 " value = vec4_operator1(vec4_operator2(value));\n"
9567 " result = value.x + value.y + value.z + value.w;\n"
9573 /** Initializes all GL objects required to run the test. */
9574 void FunctionalTest18_19::initTest()
9576 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9577 const char* varyings[1] = { "result" };
9578 std::string vs_body = getVertexShaderBody();
9579 const unsigned int n_varyings = sizeof(varyings) / sizeof(varyings[0]);
9581 if (!Utils::buildProgram(gl, vs_body, "", /* tc_body */
9585 varyings, n_varyings, &m_vs_id, DE_NULL, /* out_tc_id */
9586 DE_NULL, /* out_te_id */
9587 DE_NULL, /* out_gs_id */
9588 DE_NULL, /* out_fs_id */
9591 TCU_FAIL("Failed to build test program object");
9594 /* Retrieve subroutine & subroutine uniform locations */
9595 m_po_subroutine_divide_by_two_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "divideByTwo");
9596 m_po_subroutine_multiply_by_four_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "multiplyByFour");
9597 m_po_subroutine_returns_false_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsFalse");
9598 m_po_subroutine_returns_true_location = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "returnsTrue");
9599 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed");
9601 if (m_po_subroutine_divide_by_two_location == GL_INVALID_INDEX ||
9602 m_po_subroutine_multiply_by_four_location == GL_INVALID_INDEX ||
9603 m_po_subroutine_returns_false_location == GL_INVALID_INDEX ||
9604 m_po_subroutine_returns_true_location == GL_INVALID_INDEX)
9606 TCU_FAIL("glGetSubroutineIndex() returned GL_INVALID_INDEX for a valid subroutine");
9609 m_po_subroutine_uniform_bool_operator1 =
9610 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator1");
9611 m_po_subroutine_uniform_bool_operator2 =
9612 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "bool_operator2");
9613 m_po_subroutine_uniform_vec4_processor1 =
9614 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator1");
9615 m_po_subroutine_uniform_vec4_processor2 =
9616 gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "vec4_operator2");
9617 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed");
9619 if (m_po_subroutine_uniform_bool_operator1 == -1 || m_po_subroutine_uniform_bool_operator2 == -1 ||
9620 m_po_subroutine_uniform_vec4_processor1 == -1 || m_po_subroutine_uniform_vec4_processor2 == -1)
9622 TCU_FAIL("glGetSubroutineUniformLocation() returned -1 for an active subroutine uniform");
9626 const unsigned int bo_size = static_cast<unsigned int>(sizeof(float) * m_n_points_to_draw);
9628 gl.genBuffers(1, &m_xfb_bo_id);
9629 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
9631 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
9632 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
9634 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
9635 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
9637 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_COPY);
9638 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9641 gl.genVertexArrays(1, &m_vao_id);
9642 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9644 gl.bindVertexArray(m_vao_id);
9645 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9648 /** Executes test iteration.
9650 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
9652 tcu::TestNode::IterateResult FunctionalTest18_19::iterate()
9654 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9655 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9657 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9660 /* Initialize all GL objects required to run the test */
9663 /* Iterate over all subroutine permutations */
9664 const glw::GLuint subroutine_bool_operators[] = { m_po_subroutine_returns_false_location,
9665 m_po_subroutine_returns_true_location };
9666 const unsigned int n_subroutine_bool_operators =
9667 sizeof(subroutine_bool_operators) / sizeof(subroutine_bool_operators[0]);
9669 const glw::GLuint subroutine_vec4_operators[] = { m_po_subroutine_divide_by_two_location,
9670 m_po_subroutine_multiply_by_four_location };
9671 const unsigned int n_subroutine_vec4_operators =
9672 sizeof(subroutine_vec4_operators) / sizeof(subroutine_vec4_operators[0]);
9674 for (unsigned int n_subroutine_uniform_bool_operator1 = 0;
9675 n_subroutine_uniform_bool_operator1 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator1)
9677 for (unsigned int n_subroutine_uniform_bool_operator2 = 0;
9678 n_subroutine_uniform_bool_operator2 < n_subroutine_bool_operators; ++n_subroutine_uniform_bool_operator2)
9680 for (unsigned int n_subroutine_uniform_vec4_operator1 = 0;
9681 n_subroutine_uniform_vec4_operator1 < n_subroutine_vec4_operators;
9682 ++n_subroutine_uniform_vec4_operator1)
9684 for (unsigned int n_subroutine_uniform_vec4_operator2 = 0;
9685 n_subroutine_uniform_vec4_operator2 < n_subroutine_vec4_operators;
9686 ++n_subroutine_uniform_vec4_operator2)
9688 executeTest(subroutine_bool_operators[n_subroutine_uniform_bool_operator1],
9689 subroutine_bool_operators[n_subroutine_uniform_bool_operator2],
9690 subroutine_vec4_operators[n_subroutine_uniform_vec4_operator1],
9691 subroutine_vec4_operators[n_subroutine_uniform_vec4_operator2]);
9692 } /* for (all subroutine vec4 operator subroutines used for processor2) */
9693 } /* for (all subroutine vec4 operator subroutines used for processor1) */
9694 } /* for (all subroutine bool operator subroutines used for operator2) */
9695 } /* for (all subroutine bool operator subroutines used for operator1) */
9698 if (m_has_test_passed)
9700 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
9704 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
9710 /** Divides input argument by two. The result value is returned to the
9713 * @param data Input value.
9715 * @return As per description.
9717 tcu::Vec4 FunctionalTest18_19::vec4operator_div2(tcu::Vec4 data)
9722 /** Multiplies input argument by four. The result value is returned to the
9725 * @param data Input value.
9727 * @return As per description.
9729 tcu::Vec4 FunctionalTest18_19::vec4operator_mul4(tcu::Vec4 data)
9734 /** Verifies data XFBed out by the vertex shader. It is assumed the subroutines were configured
9735 * as per passed arguments, prior to the draw call.
9737 * If the result data is found to be invalid, m_has_test_passed is set to false.
9739 * @param data XFBed data.
9740 * @param bool_operator1_subroutine_location Location of a subroutine to be assigned to
9741 * bool_operator1 subroutine uniform.
9742 * @param bool_operator2_subroutine_location Location of a subroutine to be assigned to
9743 * bool_operator2 subroutine uniform.
9744 * @param vec4_operator1_subroutine_location Location of a subroutine to be assigned to
9745 * vec4_operator1 subroutine uniform.
9746 * @param vec4_operator2_subroutine_location Location of a subroutine to be assigned to
9747 * vec4_operator2 subroutine uniform.
9749 void FunctionalTest18_19::verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location,
9750 glw::GLuint bool_operator2_subroutine_location,
9751 glw::GLuint vec4_operator1_subroutine_location,
9752 glw::GLuint vec4_operator2_subroutine_location)
9754 bool bool_operator1_result = false;
9755 bool bool_operator2_result = false;
9756 const float epsilon = 1e-5f;
9757 PFNVEC4OPERATORPROC pVec4Operator1 = NULL;
9758 PFNVEC4OPERATORPROC pVec4Operator2 = NULL;
9759 const glw::GLfloat* traveller_ptr = (const glw::GLfloat*)data;
9761 bool_operator1_result = (bool_operator1_subroutine_location == m_po_subroutine_returns_true_location);
9762 bool_operator2_result = (bool_operator2_subroutine_location == m_po_subroutine_returns_true_location);
9763 pVec4Operator1 = (vec4_operator1_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9766 pVec4Operator2 = (vec4_operator2_subroutine_location == m_po_subroutine_divide_by_two_location) ?
9770 for (unsigned int n_vertex = 0; n_vertex < m_n_points_to_draw; ++n_vertex)
9772 float expected_value = 0.0f;
9774 if (bool_operator1_result)
9776 float value = float((3 * n_vertex + 1) * 2);
9778 while (bool_operator1_result)
9780 value /= float(n_vertex + 2);
9786 expected_value = value;
9790 tcu::Vec4 value((float)n_vertex, (float)n_vertex + 1, (float)n_vertex + 2, (float)n_vertex + 3);
9792 switch (n_vertex % 2)
9796 for (unsigned int iteration = 0; iteration < n_vertex && bool_operator2_result; ++iteration)
9798 value = pVec4Operator2(pVec4Operator1(value));
9806 for (unsigned int iteration = 0; iteration < n_vertex * 2; ++iteration)
9808 value = pVec4Operator1(pVec4Operator2(value));
9813 } /* switch (n_vertex % 2) */
9815 expected_value = value.x() + value.y() + value.z() + value.w();
9818 if (de::abs(expected_value - *traveller_ptr) > epsilon)
9820 m_testCtx.getLog() << tcu::TestLog::Message << "XFBed data was found to be invalid at index [" << n_vertex
9822 "for the following subroutine location configuration:"
9823 " bool_operator1_subroutine_location:["
9824 << bool_operator1_subroutine_location << "]"
9825 " bool_operator2_subroutine_location:["
9826 << bool_operator2_subroutine_location << "]"
9827 " vec4_operator1_subroutine_location:["
9828 << vec4_operator1_subroutine_location << "]"
9829 " vec4_operator2_subroutine_location:["
9830 << vec4_operator2_subroutine_location << "];"
9832 << expected_value << ", found:" << *traveller_ptr << tcu::TestLog::EndMessage;
9834 m_has_test_passed = false;
9838 } /* for (all drawn points) */
9841 /* Constants used by FunctionalTest20_21 */
9842 const GLuint FunctionalTest20_21::m_n_shared_contexts = 4;
9843 const GLuint FunctionalTest20_21::m_fragment_stage_index = 0;
9844 const GLuint FunctionalTest20_21::m_geometry_stage_index = 1;
9845 const GLuint FunctionalTest20_21::m_tesselation_control_stage_index = 2;
9846 const GLuint FunctionalTest20_21::m_tesselation_evaluation_stage_index = 3;
9847 const GLuint FunctionalTest20_21::m_vertex_stage_index = 4;
9849 /** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
9851 * @param bit_field Selects source of of index for each stage
9852 * @param subroutine_indices Array of two indices sets
9854 void FunctionalTest20_21::subroutineUniformSet::set(GLuint bit_field, const subroutineUniformSet subroutine_indices[2])
9856 GLuint vertex_stage = ((bit_field & (0x01 << 0)) >> 0);
9857 GLuint tesselation_control_stage = ((bit_field & (0x01 << 1)) >> 1);
9858 GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2);
9859 GLuint geometry_stage = ((bit_field & (0x01 << 3)) >> 3);
9860 GLuint fragment_stage = ((bit_field & (0x01 << 4)) >> 4);
9862 m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage;
9863 m_tesselation_control_shader_stage =
9864 subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage;
9865 m_tesselation_evaluation_shader_stage =
9866 subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage;
9867 m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage;
9868 m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage;
9871 /** Negated comparison of two sets
9873 * @param arg Instance that will be compared to this
9875 * @return false when both objects are equal, true otherwise
9877 bool FunctionalTest20_21::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
9879 if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) ||
9880 (arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) ||
9881 (arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) ||
9882 (arg.m_geometry_shader_stage != m_geometry_shader_stage) ||
9883 (arg.m_fragment_shader_stage != m_fragment_shader_stage))
9893 * @param context Rendering context.
9896 FunctionalTest20_21::FunctionalTest20_21(deqp::Context& context)
9897 : TestCase(context, "multiple_contexts",
9898 "Verifies that shader uniforms are preserved when rendering context is switched.")
9900 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
9902 m_program_pipelines[i] = 0;
9905 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
9907 m_shared_contexts[i] = 0;
9911 /** Deinitializes all GL objects that may have been created during
9914 void FunctionalTest20_21::deinit()
9916 /* GL entry points */
9917 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9919 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
9921 if (0 != m_program_pipelines[i])
9923 gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
9924 m_program_pipelines[i] = 0;
9928 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
9930 if (0 != m_shared_contexts[i])
9932 delete m_shared_contexts[i];
9933 m_shared_contexts[i] = 0;
9937 m_context.getRenderContext().makeCurrent();
9940 /** Executes test iteration.
9942 * @return Returns STOP
9944 tcu::TestNode::IterateResult FunctionalTest20_21::iterate()
9946 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
9947 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
9949 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
9952 /* Test cases, values stored here are used as bit fields */
9953 static const GLuint test_cases[][m_n_shared_contexts + 1] = {
9954 { 0, 1, 2, 3, 4 }, { 1, 2, 3, 4, 0 }, { 2, 3, 4, 0, 1 }, { 3, 4, 0, 1, 2 },
9955 { 4, 0, 1, 2, 3 }, { 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 },
9956 { 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 },
9958 static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
9960 /* Prepare contexts */
9961 initSharedContexts();
9966 /* Program pointers */
9967 Utils::program* program_pointers[5];
9969 /* Test monolithic program */
9971 /* Prepare program */
9972 Utils::program program(m_context);
9974 program_pointers[m_fragment_stage_index] = &program;
9976 prepareProgram(program_pointers, false);
9979 if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
9981 m_context.getTestContext().getLog() << tcu::TestLog::Message
9982 << "Last error message was caused by monolithic program."
9983 << tcu::TestLog::EndMessage;
9989 /* Test separable programs */
9990 if (true == m_context.getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
9992 /* Prepare programs */
9993 Utils::program vertex_program(m_context);
9994 Utils::program tesselation_control_program(m_context);
9995 Utils::program tesselation_evaluation_program(m_context);
9996 Utils::program geometry_program(m_context);
9997 Utils::program fragment_program(m_context);
9999 program_pointers[m_fragment_stage_index] = &fragment_program;
10000 program_pointers[m_geometry_stage_index] = &geometry_program;
10001 program_pointers[m_tesselation_control_stage_index] = &tesselation_control_program;
10002 program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
10003 program_pointers[m_vertex_stage_index] = &vertex_program;
10005 prepareProgram(program_pointers, true);
10008 if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
10010 m_context.getTestContext().getLog() << tcu::TestLog::Message
10011 << "Last error message was caused by separable program."
10012 << tcu::TestLog::EndMessage;
10018 if (true == result)
10020 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10024 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10027 return tcu::TestNode::STOP;
10030 /** Query state of subroutine uniforms of current program/pipeline
10032 * @param set Storage for results
10034 void FunctionalTest20_21::captureCurrentSubroutineSet(subroutineUniformSet& set)
10036 /* GL entry points */
10037 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10040 gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
10041 &set.m_fragment_shader_stage);
10042 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10045 gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
10046 &set.m_geometry_shader_stage);
10047 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10050 gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
10051 m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
10052 &set.m_tesselation_control_shader_stage);
10053 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10056 gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
10057 m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
10058 &set.m_tesselation_evaluation_shader_stage);
10059 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10062 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
10063 &set.m_vertex_shader_stage);
10064 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
10067 /** Get shaders' source code
10069 * @param out_vertex_shader_code Vertex source code
10070 * @param out_tesselation_control_shader_code Tess ctrl source code
10071 * @param out_tesselation_evaluation_shader_code Tess eval source code
10072 * @param out_geometry_shader_code Geometry source code
10073 * @param out_fragment_shader_code Fragment source code
10075 void FunctionalTest20_21::getShaders(const glw::GLchar*& out_vertex_shader_code,
10076 const glw::GLchar*& out_tesselation_control_shader_code,
10077 const glw::GLchar*& out_tesselation_evaluation_shader_code,
10078 const glw::GLchar*& out_geometry_shader_code,
10079 const glw::GLchar*& out_fragment_shader_code)
10081 static const GLchar* vertex_shader_code = "#version 400 core\n"
10082 "#extension GL_ARB_shader_subroutine : require\n"
10084 "precision highp float;\n"
10086 "// Subroutine type\n"
10087 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10089 "// Subroutine definition\n"
10090 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10092 " return left + right;\n"
10095 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10097 " return left * right;\n"
10100 "// Sub routine uniform\n"
10101 "subroutine uniform routine_type routine;\n"
10104 "uniform vec4 uni_vs_left;\n"
10105 "uniform vec4 uni_vs_right;\n"
10108 "out vec4 vs_tcs_result;\n"
10112 " vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
10116 static const GLchar* tesselation_control_shader_code =
10117 "#version 400 core\n"
10118 "#extension GL_ARB_shader_subroutine : require\n"
10120 "precision highp float;\n"
10122 "layout(vertices = 1) out;\n"
10124 "// Subroutine type\n"
10125 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10127 "// Subroutine definition\n"
10128 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10130 " return left + right;\n"
10133 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10135 " return left * right;\n"
10138 "// Sub routine uniform\n"
10139 "subroutine uniform routine_type routine;\n"
10142 "uniform vec4 uni_tcs_left;\n"
10143 "uniform vec4 uni_tcs_right;\n"
10145 "in vec4 vs_tcs_result[];\n"
10148 "out vec4 tcs_tes_result[];\n"
10152 " gl_TessLevelOuter[0] = 1.0;\n"
10153 " gl_TessLevelOuter[1] = 1.0;\n"
10154 " gl_TessLevelOuter[2] = 1.0;\n"
10155 " gl_TessLevelOuter[3] = 1.0;\n"
10156 " gl_TessLevelInner[0] = 1.0;\n"
10157 " gl_TessLevelInner[1] = 1.0;\n"
10159 " tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
10163 static const GLchar* tesselation_evaluation_shader_code =
10164 "#version 400 core\n"
10165 "#extension GL_ARB_shader_subroutine : require\n"
10167 "precision highp float;\n"
10169 "layout(isolines, point_mode) in;\n"
10171 "// Subroutine type\n"
10172 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10174 "// Subroutine definition\n"
10175 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10177 " return left + right;\n"
10180 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10182 " return left * right;\n"
10185 "// Sub routine uniform\n"
10186 "subroutine uniform routine_type routine;\n"
10189 "uniform vec4 uni_tes_left;\n"
10190 "uniform vec4 uni_tes_right;\n"
10192 "in vec4 tcs_tes_result[];\n"
10195 "out vec4 tes_gs_result;\n"
10199 " tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
10203 static const GLchar* geometry_shader_code =
10204 "#version 400 core\n"
10205 "#extension GL_ARB_shader_subroutine : require\n"
10207 "precision highp float;\n"
10209 "layout(points) in;\n"
10210 "layout(points, max_vertices = 1) out;\n"
10212 "// Subroutine type\n"
10213 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10215 "// Subroutine definition\n"
10216 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10218 " return left + right;\n"
10221 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10223 " return left * right;\n"
10226 "// Sub routine uniform\n"
10227 "subroutine uniform routine_type routine;\n"
10230 "uniform vec4 uni_gs_left;\n"
10231 "uniform vec4 uni_gs_right;\n"
10233 "in vec4 tes_gs_result[];\n"
10236 "out vec4 gs_fs_result;\n"
10240 " gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
10244 static const GLchar* fragmenty_shader_code =
10245 "#version 400 core\n"
10246 "#extension GL_ARB_shader_subroutine : require\n"
10248 "precision highp float;\n"
10250 "// Subroutine type\n"
10251 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
10253 "// Subroutine definition\n"
10254 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
10256 " return left + right;\n"
10259 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
10261 " return left * right;\n"
10264 "// Sub routine uniform\n"
10265 "subroutine uniform routine_type routine;\n"
10268 "uniform vec4 uni_fs_left;\n"
10269 "uniform vec4 uni_fs_right;\n"
10271 "in vec4 gs_fs_result;\n"
10274 "out vec4 fs_out_result;\n"
10278 " fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
10282 out_vertex_shader_code = vertex_shader_code;
10283 out_tesselation_control_shader_code = tesselation_control_shader_code;
10284 out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
10285 out_geometry_shader_code = geometry_shader_code;
10286 out_fragment_shader_code = fragmenty_shader_code;
10289 /** Create <m_n_shared_contexts> shared contexts
10292 void FunctionalTest20_21::initSharedContexts()
10294 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10296 m_shared_contexts[i] = m_context.createSharedContext();
10300 /** Prepare program(s)
10302 * @param programs An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5
10303 * @param is_separable Select if monolithic or separable programs should be prepared
10305 void FunctionalTest20_21::prepareProgram(Utils::program** programs, bool is_separable)
10307 /* Get shader sources */
10308 const GLchar* vertex_shader_code;
10309 const GLchar* tesselation_control_shader_code;
10310 const GLchar* tesselation_evaluation_shader_code;
10311 const GLchar* geometry_shader_code;
10312 const GLchar* fragmenty_shader_code;
10314 getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
10315 geometry_shader_code, fragmenty_shader_code);
10317 /* Subroutines and uniform names */
10318 static const GLchar* subroutine_names[] = { "add", "multiply" };
10319 static const GLuint n_subroutines = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
10321 static const GLchar* subroutine_uniform_name = "routine";
10323 /* Build program */
10324 if (false == is_separable)
10326 programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
10327 tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
10328 0 /* varying_names */, 0 /* n_varying_names */);
10330 programs[m_geometry_stage_index] = programs[m_fragment_stage_index];
10331 programs[m_tesselation_control_stage_index] = programs[m_fragment_stage_index];
10332 programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
10333 programs[m_vertex_stage_index] = programs[m_fragment_stage_index];
10337 programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
10338 programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
10339 programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
10340 programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
10342 programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
10345 /* Get subroutine indices */
10346 for (GLuint i = 0; i < n_subroutines; ++i)
10348 m_subroutine_indices[i].m_fragment_shader_stage =
10349 programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
10351 m_subroutine_indices[i].m_geometry_shader_stage =
10352 programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
10354 m_subroutine_indices[i].m_tesselation_control_shader_stage =
10355 programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
10356 GL_TESS_CONTROL_SHADER);
10358 m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
10359 programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
10360 GL_TESS_EVALUATION_SHADER);
10362 m_subroutine_indices[i].m_vertex_shader_stage =
10363 programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
10366 /* Get subroutine uniform locations */
10367 m_subroutine_uniform_locations.m_fragment_shader_stage =
10368 programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
10370 m_subroutine_uniform_locations.m_geometry_shader_stage =
10371 programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
10373 m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
10374 programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
10375 GL_TESS_CONTROL_SHADER);
10377 m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
10378 programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
10379 GL_TESS_EVALUATION_SHADER);
10381 m_subroutine_uniform_locations.m_vertex_shader_stage =
10382 programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
10385 /** Generate program pipeline for current context and attach separable programs
10387 * @param out_pipeline_id Id of generated pipeline
10388 * @param programs Collection of separable programs
10390 void FunctionalTest20_21::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
10392 /* GL entry points */
10393 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10396 gl.genProgramPipelines(1, &out_pipeline_id);
10397 GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
10400 gl.bindProgramPipeline(out_pipeline_id);
10401 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
10403 /* Set up programs */
10404 gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
10405 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10407 gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
10408 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10410 gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
10411 programs[m_tesselation_control_stage_index]->m_program_object_id);
10412 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10414 gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
10415 programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
10416 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10418 gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
10419 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
10422 /** Test specific case
10424 * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
10426 * @return True if test pass, false otherwise
10428 bool FunctionalTest20_21::testCase(const glw::GLuint bit_field[5])
10430 /* Storage for subroutine indices */
10431 subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
10432 subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
10434 /* Prepare subroutine_indices with bit fields */
10435 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
10437 subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
10440 /* Update subroutine uniforms, each context gets different set */
10441 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10443 m_shared_contexts[i]->makeCurrent();
10444 updateCurrentSubroutineSet(subroutine_indices[i]);
10447 m_context.getRenderContext().makeCurrent();
10448 updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
10450 /* Capture subroutine uniforms */
10451 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10453 m_shared_contexts[i]->makeCurrent();
10454 captureCurrentSubroutineSet(captured_subroutine_indices[i]);
10457 m_context.getRenderContext().makeCurrent();
10458 captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
10460 /* Verify that captured uniforms match expected values */
10461 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
10463 if (subroutine_indices[i] != captured_subroutine_indices[i])
10465 m_context.getTestContext().getLog()
10466 << tcu::TestLog::Message << "Error."
10467 << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
10468 << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
10469 << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
10470 << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
10471 << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
10472 << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
10473 << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
10474 << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
10475 << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
10476 << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage << tcu::TestLog::EndMessage;
10485 /** Test a program or pipeline
10487 * @param programs An array of 5 programs\ pointers, as in preparePrograms
10488 * @param is_separable Selects if monolithic or separable programs should be used
10489 * @param test_cases Collection of test cases
10490 * @param n_test_cases Number of test cases
10492 * @return True if all cases pass, false otherwise
10494 bool FunctionalTest20_21::testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
10495 glw::GLuint n_test_cases)
10497 /* Set program/pipeline as current for all contexts */
10498 if (false == is_separable)
10500 programs[0]->use();
10502 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10504 m_shared_contexts[i]->makeCurrent();
10505 programs[0]->use();
10510 /* GL entry points */
10511 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10513 /* Make sure that program pipeline will be used */
10515 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
10517 prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
10519 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
10521 m_shared_contexts[i]->makeCurrent();
10523 /* Make sure that program pipeline will be used */
10525 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
10527 prepareProgramPipeline(m_program_pipelines[i], programs);
10532 bool result = true;
10533 for (GLuint i = 0; i < n_test_cases; ++i)
10535 if (false == testCase(test_cases[i]))
10545 /** Set up subroutine uniforms for current program or pipeline
10547 * @param set Set of subroutine indices
10549 void FunctionalTest20_21::updateCurrentSubroutineSet(const subroutineUniformSet& set)
10551 /* GL entry points */
10552 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10555 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
10556 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10559 gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
10560 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10563 gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
10564 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10567 gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
10568 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10571 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
10572 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
10577 * @param context Rendering context.
10580 NegativeTest1::NegativeTest1(deqp::Context& context)
10581 : TestCase(context, "subroutine_errors", "Verifies all GL_INVALID_OPERATION, GL_INVALID_VALUE, GL_INVALID ENUM "
10582 "errors related to subroutine usage are properly generated.")
10583 , m_has_test_passed(true)
10584 , m_po_active_subroutine_uniform_locations(0)
10585 , m_po_active_subroutine_uniforms(0)
10586 , m_po_active_subroutines(0)
10587 , m_po_subroutine_uniform_function_index(-1)
10588 , m_po_subroutine_uniform_function2_index(-1)
10589 , m_po_subroutine_test1_index(GL_INVALID_INDEX)
10590 , m_po_subroutine_test2_index(GL_INVALID_INDEX)
10591 , m_po_subroutine_test3_index(GL_INVALID_INDEX)
10592 , m_po_not_linked_id(0)
10596 /* Left blank intentionally */
10599 /** Deinitializes all GL objects that may have been created during
10602 void NegativeTest1::deinit()
10604 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10608 gl.deleteProgram(m_po_id);
10613 if (m_po_not_linked_id != 0)
10615 gl.deleteProgram(m_po_not_linked_id);
10617 m_po_not_linked_id = 0;
10622 gl.deleteShader(m_vs_id);
10628 /** Initializes all GL objects required to run the test. */
10629 void NegativeTest1::initTest()
10631 glw::GLint compile_status = GL_FALSE;
10632 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10634 /* Create program objects */
10635 m_po_not_linked_id = gl.createProgram();
10636 m_po_id = gl.createProgram();
10637 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
10639 /* Create vertex shader object */
10640 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10641 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
10643 /* Set up vertex shader */
10644 const char* vs_body = "#version 400\n"
10646 "#extension GL_ARB_shader_subroutine : require\n"
10648 "subroutine void subroutineType (out ivec2 arg);\n"
10649 "subroutine void subroutineType2(out ivec4 arg);\n"
10651 "subroutine(subroutineType) void test1(out ivec2 arg)\n"
10653 " arg = ivec2(1, 2);\n"
10655 "subroutine(subroutineType) void test2(out ivec2 arg)\n"
10657 " arg = ivec2(3,4);\n"
10659 "subroutine(subroutineType2) void test3(out ivec4 arg)\n"
10661 " arg = ivec4(1, 2, 3, 4);\n"
10664 "subroutine uniform subroutineType function;\n"
10665 "subroutine uniform subroutineType2 function2;\n"
10672 " function(test);\n"
10674 " if (test.x > 2)\n"
10676 " gl_Position = vec4(1);\n"
10680 " function2(test2);\n"
10682 " gl_Position = vec4(float(test2.x) );\n"
10686 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
10687 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
10689 gl.compileShader(m_vs_id);
10690 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
10692 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
10693 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
10695 if (compile_status == GL_FALSE)
10697 TCU_FAIL("Shader compilation failed");
10700 /* Set up & link the test program object */
10701 glw::GLint link_status = GL_FALSE;
10703 gl.attachShader(m_po_id, m_vs_id);
10704 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
10706 gl.linkProgram(m_po_id);
10707 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
10709 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
10710 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
10712 if (link_status == GL_FALSE)
10714 TCU_FAIL("Program linking failed");
10717 /* Query test program object's properties */
10718 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS,
10719 &m_po_active_subroutine_uniform_locations);
10720 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINE_UNIFORMS, &m_po_active_subroutine_uniforms);
10721 gl.getProgramStageiv(m_po_id, GL_VERTEX_SHADER, GL_ACTIVE_SUBROUTINES, &m_po_active_subroutines);
10722 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramStageiv() call(s) failed.");
10724 if (m_po_active_subroutine_uniform_locations != 2)
10726 TCU_FAIL("Invalid GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS value returned");
10729 m_po_subroutine_test1_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test1");
10730 m_po_subroutine_test2_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test2");
10731 m_po_subroutine_test3_index = gl.getSubroutineIndex(m_po_id, GL_VERTEX_SHADER, "test3");
10732 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() call(s) failed.");
10734 if (m_po_subroutine_test1_index == GL_INVALID_INDEX || m_po_subroutine_test2_index == GL_INVALID_INDEX ||
10735 m_po_subroutine_test3_index == GL_INVALID_INDEX)
10737 TCU_FAIL("Invalid subroutine index returned");
10740 m_po_subroutine_uniform_function_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function");
10741 m_po_subroutine_uniform_function2_index = gl.getSubroutineUniformLocation(m_po_id, GL_VERTEX_SHADER, "function2");
10742 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() call(s) failed.");
10744 if (m_po_subroutine_uniform_function_index == -1 || m_po_subroutine_uniform_function2_index == -1)
10746 TCU_FAIL("Invalid subroutine uniform index returned");
10750 /** Executes test iteration.
10752 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10754 tcu::TestNode::IterateResult NegativeTest1::iterate()
10756 glw::GLenum error_code = GL_NO_ERROR;
10757 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10759 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
10760 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
10762 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
10765 /* Initialize GL objects required to run the test */
10768 /* The error INVALID_OPERATION is generated by GetSubroutineUniformLocation
10769 * if the program object identified by <program> has not been successfully
10772 gl.getSubroutineUniformLocation(m_po_not_linked_id, GL_FRAGMENT_SHADER, "subroutine_uniform_name");
10774 error_code = gl.getError();
10776 if (error_code != GL_INVALID_OPERATION)
10778 m_testCtx.getLog() << tcu::TestLog::Message
10779 << "glGetSubroutineUniformLocation() does not generate GL_INVALID_OPERATION "
10780 "error code when called for a non-linked program object."
10781 << tcu::TestLog::EndMessage;
10783 m_has_test_passed = false;
10786 /* The error INVALID_VALUE is generated by GetActiveSubroutineUniformiv or
10787 * GetActiveSubroutineUniformName if <index> is greater than or equal to the
10788 * value of ACTIVE_SUBROUTINE_UNIFORMS for the shader stage.
10790 glw::GLint temp_length = 0;
10791 glw::GLint temp_values = 0;
10793 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms,
10794 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10795 error_code = gl.getError();
10797 if (error_code == GL_INVALID_VALUE)
10799 gl.getActiveSubroutineUniformiv(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10800 GL_NUM_COMPATIBLE_SUBROUTINES, &temp_values);
10802 error_code = gl.getError();
10805 if (error_code != GL_INVALID_VALUE)
10807 m_testCtx.getLog() << tcu::TestLog::Message
10808 << "glGetActiveSubroutineUniformiv() does not generate GL_INVALID_VALUE "
10809 "when passed <index> argument that is greater than or equal to "
10810 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10811 << tcu::TestLog::EndMessage;
10813 m_has_test_passed = false;
10816 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms, 0, /* bufsize */
10817 &temp_length, DE_NULL); /* name */
10818 error_code = gl.getError();
10820 if (error_code == GL_INVALID_VALUE)
10822 gl.getActiveSubroutineUniformName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutine_uniforms + 1,
10824 &temp_length, DE_NULL); /* name */
10826 error_code = gl.getError();
10829 if (error_code != GL_INVALID_VALUE)
10831 m_testCtx.getLog() << tcu::TestLog::Message
10832 << "glGetActiveSubroutineUniformName() does not generate GL_INVALID_VALUE "
10833 "when passed <index> argument that is greater than or equal to "
10834 "the value of GL_ACTIVE_SUBROUTINE_UNIFORMS."
10835 << tcu::TestLog::EndMessage;
10837 m_has_test_passed = false;
10840 /* The error INVALID_VALUE is generated by GetActiveSubroutineName if <index>
10841 * is greater than or equal to the value of ACTIVE_SUBROUTINES for the shader
10844 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines, 0, /* bufsize */
10845 &temp_length, DE_NULL); /* name */
10846 error_code = gl.getError();
10848 if (error_code == GL_INVALID_VALUE)
10850 gl.getActiveSubroutineName(m_po_id, GL_VERTEX_SHADER, m_po_active_subroutines + 1, 0, /* bufsize */
10851 &temp_length, DE_NULL); /* name */
10853 error_code = gl.getError();
10856 if (error_code != GL_INVALID_VALUE)
10858 m_testCtx.getLog() << tcu::TestLog::Message << "glGetActiveSubroutineName() does not generate GL_INVALID_VALUE "
10859 "when passed <index> argument that is greater than or equal to "
10860 "the value of GL_ACTIVE_SUBROUTINES."
10861 << tcu::TestLog::EndMessage;
10863 m_has_test_passed = false;
10866 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if <count>
10867 * is not equal to the value of ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the
10868 * shader stage <shadertype>.
10870 glw::GLuint index = 0;
10872 gl.useProgram(m_po_id);
10873 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10875 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations - 1, &index);
10876 error_code = gl.getError();
10878 if (error_code == GL_INVALID_VALUE)
10880 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &index);
10882 error_code = gl.getError();
10885 if (error_code != GL_INVALID_VALUE)
10887 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesiv() does not generate GL_INVALID_VALUE "
10888 "when passed <count> argument that is not equal to the value of "
10889 "GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10890 << tcu::TestLog::EndMessage;
10892 m_has_test_passed = false;
10895 /* The error INVALID_VALUE is generated by UniformSubroutinesuiv if any value
10896 * in <indices> is greater than or equal to the value of ACTIVE_SUBROUTINES
10897 * for the shader stage.
10899 glw::GLuint invalid_subroutine_indices[4] = { (GLuint)m_po_active_subroutines, (GLuint)m_po_active_subroutines,
10900 (GLuint)m_po_active_subroutines + 1,
10901 (GLuint)m_po_active_subroutines + 1 };
10903 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, /* count */
10904 invalid_subroutine_indices + 0);
10905 error_code = gl.getError();
10907 if (error_code == GL_INVALID_VALUE)
10909 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations,
10910 invalid_subroutine_indices + 2);
10912 error_code = gl.getError();
10915 if (error_code != GL_INVALID_VALUE)
10917 m_testCtx.getLog() << tcu::TestLog::Message << "glUniformSubroutinesuiv() does not generate GL_INVALID_VALUE "
10918 "when the value passed via <indices> argument is greater than "
10919 "or equal to the value of GL_ACTIVE_SUBROUTINES."
10920 << tcu::TestLog::EndMessage;
10922 m_has_test_passed = false;
10925 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv() if any
10926 * subroutine index in <indices> identifies a subroutine not associated with
10927 * the type of the subroutine uniform variable assigned to the corresponding
10930 glw::GLuint invalid_subroutine_indices2[2] = { m_po_subroutine_test1_index, m_po_subroutine_test1_index };
10932 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, invalid_subroutine_indices2);
10933 error_code = gl.getError();
10935 if (error_code != GL_INVALID_OPERATION)
10937 m_testCtx.getLog() << tcu::TestLog::Message
10938 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10939 "when the subroutine index passed via <indices> argument identifies"
10940 "a subroutine not associated with the type of the subroutine uniform "
10941 "assigned to the corresponding location."
10942 << tcu::TestLog::EndMessage;
10944 m_has_test_passed = false;
10947 /* The error INVALID_OPERATION is generated by UniformSubroutinesuiv if no
10948 * program is active.
10950 glw::GLuint valid_subroutine_locations[2] = { 0 };
10952 valid_subroutine_locations[m_po_subroutine_uniform_function_index] = m_po_subroutine_test1_index;
10953 valid_subroutine_locations[m_po_subroutine_uniform_function2_index] = m_po_subroutine_test3_index;
10956 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10958 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, valid_subroutine_locations);
10959 error_code = gl.getError();
10961 if (error_code != GL_INVALID_OPERATION)
10963 m_testCtx.getLog() << tcu::TestLog::Message
10964 << "glUniformSubroutinesuiv() does not generate GL_INVALID_OPERATION "
10965 "when called without an active program object."
10966 << tcu::TestLog::EndMessage;
10968 m_has_test_passed = false;
10971 /* The error INVALID_VALUE is generated by GetUniformSubroutineuiv if
10972 * <location> is greater than or equal to the value of
10973 * ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS for the shader stage.
10975 glw::GLuint temp_value = 0;
10977 gl.useProgram(m_po_id);
10978 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
10980 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations, &temp_value);
10981 error_code = gl.getError();
10983 if (error_code == GL_INVALID_VALUE)
10985 gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_po_active_subroutine_uniform_locations + 1, &temp_value);
10986 error_code = gl.getError();
10989 if (error_code != GL_INVALID_VALUE)
10991 m_testCtx.getLog() << tcu::TestLog::Message
10992 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_VALUE "
10993 "when called for location that is greater than or equal to the value "
10994 "of GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS."
10995 << tcu::TestLog::EndMessage;
10997 m_has_test_passed = false;
11000 /* The error INVALID_OPERATION is generated by GetUniformSubroutineuiv if no
11001 * program is active for the shader stage identified by <shadertype>.
11003 const glw::GLenum undefined_shader_stages[] = { GL_FRAGMENT_SHADER, GL_GEOMETRY_SHADER, GL_TESS_CONTROL_SHADER,
11004 GL_TESS_EVALUATION_SHADER };
11005 const unsigned int n_undefined_shader_stages = sizeof(undefined_shader_stages) / sizeof(undefined_shader_stages[0]);
11007 for (unsigned int n_undefined_shader_stage = 0; n_undefined_shader_stage < n_undefined_shader_stages;
11008 ++n_undefined_shader_stage)
11010 glw::GLenum shader_stage = undefined_shader_stages[n_undefined_shader_stage];
11012 gl.getUniformSubroutineuiv(shader_stage, 0, /* location */
11014 error_code = gl.getError();
11016 if (error_code != GL_INVALID_OPERATION)
11018 m_testCtx.getLog() << tcu::TestLog::Message
11019 << "glGetUniformSubroutineuiv() does not generate GL_INVALID_OPERATION "
11020 "when called for a shader stage that is not defined for active "
11022 << tcu::TestLog::EndMessage;
11024 m_has_test_passed = false;
11026 } /* for (all undefined shader stages) */
11029 if (m_has_test_passed)
11031 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11035 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11043 * @param context Rendering context.
11046 NegativeTest2::NegativeTest2(deqp::Context& context)
11047 : TestCase(context, "subroutine_uniform_scope", "Verifies subroutine uniforms declared in shader stage A"
11048 "cannot be accessed from a different stage.")
11051 , m_has_test_passed(true)
11057 /* Left blank intentionally */
11060 /** Deinitializes all GL objects that may have been created during test execution */
11061 void NegativeTest2::deinit()
11066 /** Deinitializes all GL objects that may have been created during test execution */
11067 void NegativeTest2::deinitGLObjects()
11069 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11073 gl.deleteShader(m_fs_id);
11080 gl.deleteShader(m_gs_id);
11087 gl.deleteShader(m_tc_id);
11094 gl.deleteShader(m_te_id);
11101 gl.deleteShader(m_vs_id);
11108 gl.deleteProgram(m_po_id);
11114 /** Builds an offending program object and tries to link it. We're either expecting
11115 * a compile-time or link-time error here.
11117 * If the program object builds successfully, the test has failed.
11119 * @param referencing_stage Shader stage which defines a subroutine uniform that
11120 * should be called from fragment/geometry/tess control/
11121 * tess evaluation/vertex shader stages.
11124 void NegativeTest2::executeTestCase(const Utils::_shader_stage& referencing_stage)
11126 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11128 const std::string fs_body = getFragmentShaderBody(referencing_stage);
11129 const std::string gs_body = getGeometryShaderBody(referencing_stage);
11130 const std::string tc_body = getTessellationControlShaderBody(referencing_stage);
11131 const std::string te_body = getTessellationEvaluationShaderBody(referencing_stage);
11132 const std::string vs_body = getVertexShaderBody(referencing_stage);
11134 if (Utils::buildProgram(gl, vs_body, tc_body, te_body, gs_body, fs_body, NULL, /* xfb_varyings */
11135 0, /* n_xfb_varyings */
11136 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
11138 /* Test program should not have built correctly ! */
11139 m_testCtx.getLog() << tcu::TestLog::Message << "In the following program, one of the stages references "
11140 "a subroutine that is defined in another stage. This "
11141 "is forbidden by the specification.\n"
11143 "Vertex shader:\n\n"
11144 << vs_body.c_str() << "\n\nTessellation control shader:\n\n"
11145 << tc_body.c_str() << "\n\nTessellation evaluation shader:\n\n"
11146 << te_body.c_str() << "\n\nGeometry shader:\n\n"
11147 << gs_body.c_str() << "\n\nFragment shader:\n\n"
11148 << fs_body.c_str() << tcu::TestLog::EndMessage;
11150 m_has_test_passed = false;
11151 } /* if (test program was built successfully) */
11153 /* Release the shaders & the program object that buildProgram() created */
11157 /** Retrieves an offending fragment shader body.
11159 * @param referencing_stage Shader stage which defines the subroutine uniform that
11160 * will be called from fragment shader.
11162 * @return Requested string.
11164 std::string NegativeTest2::getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const
11166 std::stringstream result;
11168 /* Form the pre-amble */
11169 result << "#version 400\n"
11171 "#extension GL_ARB_shader_subroutine : require\n"
11173 "subroutine void testSubroutineType(out vec4 test_argument);\n"
11175 /* Define a subroutine */
11176 "subroutine(testSubroutineType) void fs_subroutine(out vec4 test_argument)\n"
11178 " test_argument = vec4(1, 0, 0, 0);\n"
11181 /* Define output variables */
11182 "out vec4 result;\n"
11184 /* Define uniforms */
11185 "subroutine uniform testSubroutineType test_fs_subroutine;\n"
11187 /* Define main() */
11191 << getSubroutineUniformName(referencing_stage) << "(result);\n"
11194 return result.str();
11197 /** Retrieves an offending geometry shader body.
11199 * @param referencing_stage Shader stage which defines the subroutine uniform that
11200 * will be called from geometry shader.
11202 * @return Requested string.
11204 std::string NegativeTest2::getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const
11206 std::stringstream result;
11208 /* Form the pre-amble */
11209 result << "#version 400\n"
11211 "#extension GL_ARB_shader_subroutine : require\n"
11213 "subroutine void testSubroutineType(out vec4 test_argument);\n"
11215 "layout(points) in;\n"
11216 "layout(points, max_vertices = 1) out;\n"
11218 /* Define a subroutine */
11219 "subroutine(testSubroutineType) void gs_subroutine(out vec4 test_argument)\n"
11221 " test_argument = vec4(0, 1, 1, 1);\n"
11224 /* Define output variables */
11225 "out vec4 result;\n"
11227 /* Define uniforms */
11228 "subroutine uniform testSubroutineType test_gs_subroutine;\n"
11230 /* Define main() */
11234 << getSubroutineUniformName(referencing_stage) << "(result);\n"
11237 return result.str();
11240 /** Retrieves name of the subroutine uniform that is defined in user-specified
11243 * @param stage Shader stage to retrieve the subroutine uniform name for.
11245 * @return As per description.
11247 std::string NegativeTest2::getSubroutineUniformName(const Utils::_shader_stage& stage) const
11249 std::string result = "?";
11253 case Utils::SHADER_STAGE_FRAGMENT:
11255 result = "test_fs_subroutine";
11260 case Utils::SHADER_STAGE_GEOMETRY:
11262 result = "test_gs_subroutine";
11267 case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11269 result = "test_tc_subroutine";
11274 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11276 result = "test_te_subroutine";
11281 case Utils::SHADER_STAGE_VERTEX:
11283 result = "test_vs_subroutine";
11290 TCU_FAIL("Unrecognized shader stage requested");
11292 } /* switch (stage) */
11297 /** Retrieves an offending tessellation control shader body.
11299 * @param referencing_stage Shader stage which defines the subroutine uniform that
11300 * will be called from tessellation control shader.
11302 * @return Requested string.
11304 std::string NegativeTest2::getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const
11306 std::stringstream result;
11308 /* Form the pre-amble */
11309 result << "#version 400\n"
11311 "#extension GL_ARB_shader_subroutine : require\n"
11313 "layout(vertices = 4) out;\n"
11315 "subroutine void testSubroutineType(out vec4 test_argument);\n"
11317 /* Define a subroutine */
11318 "subroutine(testSubroutineType) void tc_subroutine(out vec4 test_argument)\n"
11320 " test_argument = vec4(0, 0, 1, 0);\n"
11323 /* Define uniforms */
11324 "subroutine uniform testSubroutineType test_tc_subroutine;\n"
11326 /* Define main() */
11330 << getSubroutineUniformName(referencing_stage) << "(gl_out[gl_InvocationID].gl_Position);\n"
11333 return result.str();
11336 /** Retrieves an offending tessellation evaluation shader body.
11338 * @param referencing_stage Shader stage which defines the subroutine uniform that
11339 * will be called from tessellation evaluation shader.
11341 * @return Requested string.
11343 std::string NegativeTest2::getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const
11345 std::stringstream result;
11347 /* Form the pre-amble */
11348 result << "#version 400\n"
11350 "#extension GL_ARB_shader_subroutine : require\n"
11352 "layout(quads) in;\n"
11354 "subroutine void testSubroutineType(out vec4 test_argument);\n"
11356 /* Define a subroutine */
11357 "subroutine(testSubroutineType) void te_subroutine(out vec4 test_argument)\n"
11359 " test_argument = vec4(1, 1, 1, 1);\n"
11362 /* Define uniforms */
11363 "subroutine uniform testSubroutineType test_te_subroutine;\n"
11365 /* Define main() */
11369 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
11372 return result.str();
11375 /** Retrieves an offending vertex shader body.
11377 * @param referencing_stage Shader stage which defines the subroutine uniform that
11378 * will be called from vertex shader.
11380 * @return Requested string.
11382 std::string NegativeTest2::getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const
11384 std::stringstream result;
11386 /* Form the pre-amble */
11387 result << "#version 400\n"
11389 "#extension GL_ARB_shader_subroutine : require\n"
11391 "subroutine void testSubroutineType(out vec4 test_argument);\n"
11393 /* Define a subroutine */
11394 "subroutine(testSubroutineType) void vs_subroutine(out vec4 test_argument)\n"
11396 " test_argument = vec4(0, 1, 0, 0);\n"
11399 /* Define uniforms */
11400 "subroutine uniform testSubroutineType test_vs_subroutine;\n"
11402 /* Define main() */
11406 << getSubroutineUniformName(referencing_stage) << "(gl_Position);\n"
11409 return result.str();
11412 /** Executes test iteration.
11414 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11416 tcu::TestNode::IterateResult NegativeTest2::iterate()
11418 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11419 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11421 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11424 /* Iterate over all shader stages and execute the checks */
11425 for (int referencing_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11426 referencing_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++referencing_stage)
11428 executeTestCase(static_cast<Utils::_shader_stage>(referencing_stage));
11429 } /* for (all test cases) */
11432 if (m_has_test_passed)
11434 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11438 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11446 * @param context Rendering context.
11449 NegativeTest3::NegativeTest3(deqp::Context& context)
11450 : TestCase(context, "missing_subroutine_keyword", "Verifies that subroutine keyword is necessary when declaring a "
11451 "subroutine uniforn and a compilation error occurs without it.")
11452 , m_has_test_passed(true)
11455 /* Left blank intentionally */
11458 /** Deinitializes all GL objects that may have been created during test execution */
11459 void NegativeTest3::deinit()
11461 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11465 gl.deleteShader(m_so_id);
11471 /** Verifies that broken shader (for user-specified shader stage) does not compile.
11473 * @param shader_stage Shader stage to use for the test.
11475 void NegativeTest3::executeTest(const Utils::_shader_stage& shader_stage)
11477 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11479 /* Generate a new shader object */
11480 m_so_id = gl.createShader(Utils::getGLenumForShaderStage(shader_stage));
11481 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
11483 /* Assign body to the shader */
11485 const char* body_raw_ptr = DE_NULL;
11487 switch (shader_stage)
11489 case Utils::SHADER_STAGE_VERTEX:
11490 body = getVertexShaderBody();
11492 case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11493 body = getTessellationControlShaderBody();
11495 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11496 body = getTessellationEvaluationShaderBody();
11498 case Utils::SHADER_STAGE_GEOMETRY:
11499 body = getGeometryShaderBody();
11501 case Utils::SHADER_STAGE_FRAGMENT:
11502 body = getFragmentShaderBody();
11507 TCU_FAIL("Unrecognized shader stage requested");
11509 } /* switch (shader_stage) */
11511 body_raw_ptr = body.c_str();
11513 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
11514 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11516 /* Try to compile the shader */
11517 glw::GLint compile_status = 0;
11519 gl.compileShader(m_so_id);
11520 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11522 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11523 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11525 if (compile_status == GL_TRUE)
11527 m_testCtx.getLog() << tcu::TestLog::Message << "The following shader was expected to fail to compile but was "
11528 "accepted by the compiler:\n"
11530 << body.c_str() << tcu::TestLog::EndMessage;
11532 m_has_test_passed = false;
11535 /* Good to release the shader at this point */
11536 gl.deleteShader(m_so_id);
11537 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11540 /** Retrieves body of a broken fragment shader.
11542 * @return Requested string.
11544 std::string NegativeTest3::getFragmentShaderBody() const
11546 return "#version 400\n"
11548 "#extension GL_ARB_shader_subroutine : require\n"
11550 "subroutine void testSubroutineType(inout vec4 test);\n"
11552 "void testSubroutine1(inout vec4 test)\n"
11554 " test += vec4(3, 4, 5, 6);\n"
11557 "uniform testSubroutineType subroutineFunction;\n"
11558 "out vec4 result;\n"
11562 " vec4 test = vec4(2, 3, 4, 5);\n"
11564 " subroutineFunction(test);\n"
11566 " result = test;\n"
11570 /** Retrieves body of a broken geometry shader.
11572 * @return Requested string.
11574 std::string NegativeTest3::getGeometryShaderBody() const
11576 return "#version 400\n"
11578 "#extension GL_ARB_shader_subroutine : require\n"
11580 "layout(points) in;\n"
11581 "layout(points, max_vertices = 1) out;\n"
11583 "subroutine void testSubroutineType(inout vec4 test);\n"
11585 "void testSubroutine1(inout vec4 test)\n"
11587 " test += vec4(3, 4, 5, 6);\n"
11590 "uniform testSubroutineType subroutineFunction;\n"
11594 " vec4 test = vec4(2, 3, 4, 5);\n"
11596 " subroutineFunction(test);\n"
11598 " gl_Position = test;\n"
11603 /** Retrieves body of a broken tessellation control shader.
11605 * @return Requested string.
11607 std::string NegativeTest3::getTessellationControlShaderBody() const
11609 return "#version 400\n"
11611 "#extension GL_ARB_shader_subroutine : require\n"
11613 "layout(vertices=4) out;\n"
11615 "subroutine void testSubroutineType(inout vec4 test);\n"
11617 "void testSubroutine1(inout vec4 test)\n"
11619 " test += vec4(1, 2, 3, 4);\n"
11622 "uniform testSubroutineType subroutineFunction;\n"
11626 " vec4 test = vec4(0, 1, 2, 3);\n"
11628 " subroutineFunction(test);\n"
11630 " gl_out[gl_InvocationID].gl_Position = test;\n"
11634 /** Retrieves body of a broken tessellation evaluation shader.
11636 * @return Requested string.
11638 std::string NegativeTest3::getTessellationEvaluationShaderBody() const
11640 return "#version 400\n"
11642 "#extension GL_ARB_shader_subroutine : require\n"
11644 "layout(quads) in;\n"
11646 "subroutine void testSubroutineType(inout vec4 test);\n"
11648 "void testSubroutine1(inout vec4 test)\n"
11650 " test += vec4(2, 3, 4, 5);\n"
11653 "uniform testSubroutineType subroutineFunction;\n"
11657 " vec4 test = vec4(1, 2, 3, 4);\n"
11659 " subroutineFunction(test);\n"
11661 " gl_Position = test;\n"
11665 /** Retrieves body of a broken vertex shader.
11667 * @return Requested string.
11669 std::string NegativeTest3::getVertexShaderBody() const
11671 return "#version 400\n"
11673 "#extension GL_ARB_shader_subroutine : require\n"
11675 "subroutine void testSubroutineType(inout vec4 test);\n"
11677 "void testSubroutine1(inout vec4 test)\n"
11679 " test += vec4(0, 1, 2, 3);\n"
11682 "uniform testSubroutineType subroutineFunction;\n"
11686 " subroutineFunction(gl_Position);\n"
11690 /** Executes test iteration.
11692 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11694 tcu::TestNode::IterateResult NegativeTest3::iterate()
11696 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11697 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11699 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11702 /* Iterate over all shader stages */
11703 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11704 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11706 executeTest(static_cast<Utils::_shader_stage>(shader_stage));
11707 } /* for (all shader stages) */
11710 if (m_has_test_passed)
11712 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11716 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11724 * @param context Rendering context.
11727 NegativeTest4::NegativeTest4(deqp::Context& context)
11728 : TestCase(context, "subroutines_incompatible_with_subroutine_type",
11729 "Verifies that a compile-time error is generated when arguments and "
11730 "return type do not match beween the function and each associated "
11731 "subroutine type.")
11732 , m_has_test_passed(true)
11735 /* Left blank intentionally */
11738 /** Deinitializes GL objects that may have been created during test
11741 void NegativeTest4::deinit()
11743 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11747 gl.deleteShader(m_so_id);
11753 /** Retrieves body of a shader of user-specified type that should be used
11754 * for a single test iteration. The shader will define user-specified number
11755 * of subroutine types, with the last type either defining an additional argument
11756 * or using a different return type.
11757 * A subroutine (claimed compatible with *all* subroutine types) will also be
11758 * defined in the shader.
11760 * @param shader_stage Shader stage to use for the query.
11761 * @param n_subroutine_types Overall number of subroutine types that will be
11762 * declared & used in the shader. Please see description
11763 * for more details.
11765 * @return Requested string.
11767 std::string NegativeTest4::getShaderBody(const Utils::_shader_stage& shader_stage,
11768 const unsigned int& n_subroutine_types, const _test_case& test_case) const
11770 std::stringstream result_sstream;
11772 /* Form the pre-amble */
11773 result_sstream << "#version 400\n"
11775 "#extension GL_ARB_shader_subroutine : require\n"
11778 /* Inject stage-specific code */
11779 switch (shader_stage)
11781 case Utils::SHADER_STAGE_GEOMETRY:
11783 result_sstream << "layout (points) in;\n"
11784 "layout (points, max_vertices = 1) out;\n"
11790 case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11792 result_sstream << "layout (vertices = 4) out;\n"
11798 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11800 result_sstream << "layout (quads) in;\n"
11808 } /* switch (shader_stage) */
11810 /* Insert subroutine type declarations */
11811 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types - 1; ++n_subroutine_type)
11813 result_sstream << "subroutine void subroutineType" << n_subroutine_type << "(inout vec3 argument);\n";
11814 } /* for (all subroutine types) */
11818 case TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST:
11820 result_sstream << "subroutine void subroutineType" << (n_subroutine_types - 1)
11821 << "(inout vec3 argument, out vec4 argument2);\n";
11826 case TEST_CASE_INCOMPATIBLE_RETURN_TYPE:
11828 result_sstream << "subroutine int subroutineType" << (n_subroutine_types - 1) << "(inout vec3 argument);\n";
11835 TCU_FAIL("Unrecognized test case");
11837 } /* switch (test_case) */
11839 /* Insert subroutine declarations */
11840 result_sstream << "subroutine(";
11842 for (unsigned int n_subroutine_type = 0; n_subroutine_type < n_subroutine_types; ++n_subroutine_type)
11844 result_sstream << "subroutineType" << n_subroutine_type;
11846 if (n_subroutine_type != (n_subroutine_types - 1))
11848 result_sstream << ", ";
11850 } /* for (all subroutine types) */
11852 result_sstream << ") void function(inout vec3 argument)\n"
11854 " argument = vec3(1, 2, 3);\n"
11858 /* Insert remaining required stage-specific bits */
11859 switch (shader_stage)
11861 case Utils::SHADER_STAGE_FRAGMENT:
11863 result_sstream << "out vec4 result;\n"
11867 " result = vec4(1, 2, 3, 4);\n"
11873 case Utils::SHADER_STAGE_GEOMETRY:
11875 result_sstream << "void main()\n"
11877 " gl_Position = vec4(1, 2, 3, 4);\n"
11884 case Utils::SHADER_STAGE_TESSELLATION_CONTROL:
11886 result_sstream << "void main()\n"
11888 " gl_TessLevelInner[0] = 1;\n"
11889 " gl_TessLevelInner[1] = 1;\n"
11890 " gl_TessLevelOuter[0] = 1;\n"
11891 " gl_TessLevelOuter[1] = 1;\n"
11892 " gl_TessLevelOuter[2] = 1;\n"
11893 " gl_TessLevelOuter[3] = 1;\n"
11894 " gl_out[gl_InvocationID].gl_Position = vec4(2, 3, 4, 5);\n"
11900 case Utils::SHADER_STAGE_TESSELLATION_EVALUATION:
11901 case Utils::SHADER_STAGE_VERTEX:
11903 result_sstream << "void main()\n"
11905 " gl_Position = vec4(1, 2, 3, 4);\n"
11913 TCU_FAIL("Unrecognized shader stage");
11915 } /* switch (shader_stage) */
11917 return result_sstream.str();
11920 /** Executes test iteration.
11922 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11924 tcu::TestNode::IterateResult NegativeTest4::iterate()
11926 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11928 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
11929 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
11931 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
11934 /* Iterate over all shader stages.. */
11935 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
11936 shader_stage != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
11938 /* For each shader stage, we will be trying to compile a number of invalid shaders.
11939 * Each shader defines N different subroutine types. (N-1) of them are compatible
11940 * with a subroutine, but exactly 1 will be mismatched. The test passes if GLSL
11941 * compiler correctly detects that all shaders we will be trying to compile are
11944 const glw::GLenum shader_type = Utils::getGLenumForShaderStage(static_cast<Utils::_shader_stage>(shader_stage));
11946 for (unsigned int n_subroutine_types = 1; n_subroutine_types < 6; /* arbitrary number */
11947 ++n_subroutine_types)
11949 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT);
11953 const char* body_raw_ptr = NULL;
11954 glw::GLint compile_status = GL_FALSE;
11956 body = getShaderBody(static_cast<Utils::_shader_stage>(shader_stage), n_subroutine_types,
11957 static_cast<_test_case>(test_case));
11958 body_raw_ptr = body.c_str();
11960 /* Try to compile the shader */
11961 m_so_id = gl.createShader(shader_type);
11962 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed");
11964 gl.shaderSource(m_so_id, 1 /* count */, &body_raw_ptr, DE_NULL);
11965 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
11967 gl.compileShader(m_so_id);
11968 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
11970 gl.getShaderiv(m_so_id, GL_COMPILE_STATUS, &compile_status);
11971 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11973 if (compile_status == GL_TRUE)
11975 m_testCtx.getLog() << tcu::TestLog::Message << "A malformed "
11976 << Utils::getShaderStageString(static_cast<Utils::_shader_stage>(shader_stage))
11977 << " compiled successfully "
11979 << n_subroutine_types << " subroutine types "
11981 << tcu::TestLog::EndMessage;
11983 m_has_test_passed = false;
11986 /* Release the object */
11987 gl.deleteShader(m_so_id);
11988 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader() call failed.");
11989 } /* for (all test cases) */
11990 } /* for (a number of different subroutine type declarations) */
11991 } /* for (all shader stages) */
11994 if (m_has_test_passed)
11996 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12000 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12008 * @param context Rendering context.
12011 NegativeTest5::NegativeTest5(deqp::Context& context)
12012 : TestCase(context, "subroutine_uniform_wo_matching_subroutines",
12013 "Verifies that a link- or compile-time error occurs when "
12014 "trying to link a program with no subroutine for subroutine "
12015 "uniform variable.")
12018 , m_has_test_passed(true)
12024 /* Left blank intentionally */
12027 /** Deinitializes all GL objects that may have been created during test execution */
12028 void NegativeTest5::deinit()
12033 /** Deinitializes all GL objects that may have been created during a single test
12036 void NegativeTest5::deinitIteration()
12038 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12042 gl.deleteShader(m_fs_id);
12049 gl.deleteShader(m_gs_id);
12056 gl.deleteProgram(m_po_id);
12063 gl.deleteShader(m_tc_id);
12070 gl.deleteShader(m_te_id);
12077 gl.deleteShader(m_vs_id);
12083 /** Executes a single test iteration.
12085 * If the iteration fails, m_has_test_passed will be set to false.
12087 * @param shader_stage Shader stage, for which a subroutine uniform should be
12088 * declared in the shader without a matching subroutine.
12090 void NegativeTest5::executeIteration(const Utils::_shader_stage& shader_stage)
12092 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12093 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12094 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12095 std::string te_body =
12096 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12097 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12099 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12100 DE_NULL, /* xfb_varyings */
12101 DE_NULL, /* n_xfb_varyings */
12102 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12104 /* None of the test programs should ever build successfully */
12105 m_testCtx.getLog() << tcu::TestLog::Message
12106 << "A program object, consisting of the following shaders, has linked"
12107 " correctly. One of the shaders defines a subroutine uniform but does "
12108 "not implement any function that matches subroutine type of the uniform."
12109 " This should have resulted in a compilation/link-time error.\n"
12114 "Tessellation control shader:\n"
12117 "Tessellation evaluation shader:\n"
12120 "Geometry shader:\n"
12123 "Fragment shader:\n"
12125 << fs_body << tcu::TestLog::EndMessage;
12127 m_has_test_passed = false;
12131 /** Retrieves fragment shader body.
12133 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12134 * a subroutine uniform without
12135 * a matching subroutine, false otherwise.
12137 * @return Requested string.
12139 std::string NegativeTest5::getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12141 std::stringstream result_sstream;
12143 result_sstream << "#version 400\n"
12145 "#extension GL_ARB_shader_subroutine : require\n"
12148 if (include_invalid_subroutine_uniform_declaration)
12150 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12152 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12155 result_sstream << "\n"
12156 "out vec4 result;\n"
12161 if (include_invalid_subroutine_uniform_declaration)
12163 result_sstream << " test_subroutineFS(result);\n";
12167 result_sstream << " result = vec4(0, 1, 2, 3);\n";
12170 result_sstream << "}\n";
12172 return result_sstream.str();
12175 /** Retrieves geometry shader body.
12177 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12178 * a subroutine uniform without
12179 * a matching subroutine, false otherwise.
12181 * @return Requested string.
12183 std::string NegativeTest5::getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12185 std::stringstream result_sstream;
12187 result_sstream << "#version 400\n"
12189 "#extension GL_ARB_shader_subroutine : require\n"
12191 "layout (points) in;\n"
12192 "layout (points, max_vertices = 1) out;\n"
12195 if (include_invalid_subroutine_uniform_declaration)
12197 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12199 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12202 result_sstream << "\n"
12206 if (include_invalid_subroutine_uniform_declaration)
12208 result_sstream << " test_subroutineGS(gl_Position);\n";
12212 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
12215 result_sstream << "EmitVertex();\n"
12218 return result_sstream.str();
12221 /** Retrieves tessellation control shader body.
12223 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12224 * a subroutine uniform without
12225 * a matching subroutine, false otherwise.
12227 * @return Requested string.
12229 std::string NegativeTest5::getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12231 std::stringstream result_sstream;
12233 result_sstream << "#version 400\n"
12235 "#extension GL_ARB_shader_subroutine : require\n"
12237 "layout (vertices = 4) out;\n"
12240 if (include_invalid_subroutine_uniform_declaration)
12242 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12244 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12247 result_sstream << "\n"
12251 if (include_invalid_subroutine_uniform_declaration)
12253 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12257 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12260 result_sstream << "}\n";
12262 return result_sstream.str();
12265 /** Retrieves tessellation evaluation body.
12267 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12268 * a subroutine uniform without
12269 * a matching subroutine, false otherwise.
12271 * @return Requested string.
12273 std::string NegativeTest5::getTessellationEvaluationShaderBody(
12274 bool include_invalid_subroutine_uniform_declaration) const
12276 std::stringstream result_sstream;
12278 result_sstream << "#version 400\n"
12280 "#extension GL_ARB_shader_subroutine : require\n"
12282 "layout (quads) in;\n"
12285 if (include_invalid_subroutine_uniform_declaration)
12287 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12289 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12292 result_sstream << "\n"
12296 if (include_invalid_subroutine_uniform_declaration)
12298 result_sstream << " test_subroutineTE(gl_Position);\n";
12302 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
12305 result_sstream << "}\n";
12307 return result_sstream.str();
12310 /** Retrieves vertex shader body.
12312 * @param include_invalid_subroutine_uniform_declaration true if the shader should declare
12313 * a subroutine uniform without
12314 * a matching subroutine, false otherwise.
12316 * @return Requested string.
12318 std::string NegativeTest5::getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const
12320 std::stringstream result_sstream;
12322 result_sstream << "#version 400\n"
12324 "#extension GL_ARB_shader_subroutine : require\n"
12327 if (include_invalid_subroutine_uniform_declaration)
12329 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12331 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12334 result_sstream << "\n"
12338 if (include_invalid_subroutine_uniform_declaration)
12340 result_sstream << " test_subroutineVS(gl_Position);\n";
12344 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
12347 result_sstream << "}\n";
12349 return result_sstream.str();
12352 /** Executes test iteration.
12354 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12356 tcu::TestNode::IterateResult NegativeTest5::iterate()
12358 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12359 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12361 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12364 /* Iterate over all shader stages. Iteration-specific shader stage defines a subroutine type &
12365 * a corresponding subroutine uniform, for which no compatible subroutines are available. All
12366 * other shader stages are defined correctly.
12368 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12369 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12371 executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12373 } /* for (all shader stages) */
12376 if (m_has_test_passed)
12378 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12382 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12390 * @param context Rendering context.
12393 NegativeTest6::NegativeTest6(deqp::Context& context)
12394 : TestCase(context, "two_duplicate_functions_one_being_a_subroutine",
12395 "Verifies that a link- or compile-time error occurs if any shader in "
12396 "a program object includes two functions with the same name and one "
12397 "of which is associated with a subroutine type.")
12400 , m_has_test_passed(true)
12406 /* Left blank intentionally */
12409 /** Deinitializes all GL objects that may have been created during test execution */
12410 void NegativeTest6::deinit()
12415 /** Deinitializes all GL objects that may have been created during a single test
12418 void NegativeTest6::deinitIteration()
12420 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12424 gl.deleteShader(m_fs_id);
12431 gl.deleteShader(m_gs_id);
12438 gl.deleteProgram(m_po_id);
12445 gl.deleteShader(m_tc_id);
12452 gl.deleteShader(m_te_id);
12459 gl.deleteShader(m_vs_id);
12465 /** Executes a single test iteration.
12467 * If the iteration fails, m_has_test_passed will be set to false.
12469 * @param shader_stage Shader stage, for which two duplicate functions
12470 * (one additionally marked as subroutine) should
12473 void NegativeTest6::executeIteration(const Utils::_shader_stage& shader_stage)
12475 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
12476 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
12477 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
12478 std::string te_body =
12479 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
12480 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
12482 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
12483 DE_NULL, /* xfb_varyings */
12484 DE_NULL, /* n_xfb_varyings */
12485 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
12487 /* None of the test programs should ever build successfully */
12488 m_testCtx.getLog() << tcu::TestLog::Message
12489 << "A program object, consisting of the following shaders, has linked"
12490 " correctly. This is invalid, because one of the shaders defines two"
12491 " functions with the same name, with an exception that one of the"
12492 " functions is marked as a subroutine.\n"
12497 "Tessellation control shader:\n"
12500 "Tessellation evaluation shader:\n"
12503 "Geometry shader:\n"
12506 "Fragment shader:\n"
12508 << fs_body << tcu::TestLog::EndMessage;
12510 m_has_test_passed = false;
12514 /** Retrieves fragment shader body.
12516 * @param include_invalid_declaration true if the shader should include duplicate function
12519 * @return Requested string.
12521 std::string NegativeTest6::getFragmentShaderBody(bool include_invalid_declaration) const
12523 std::stringstream result_sstream;
12525 result_sstream << "#version 400\n"
12527 "#extension GL_ARB_shader_subroutine : require\n"
12530 if (include_invalid_declaration)
12532 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
12534 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test)\n"
12536 " test = vec4(1, 2, 3, 4);\n"
12539 "void test_impl1(out vec4 test)\n"
12541 " test = vec4(2, 3, 4, 5);\n"
12544 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
12547 result_sstream << "\n"
12548 "out vec4 result;\n"
12553 if (include_invalid_declaration)
12555 result_sstream << " test_subroutineFS(result);\n";
12559 result_sstream << " result = vec4(0, 1, 2, 3);\n";
12562 result_sstream << "}\n";
12564 return result_sstream.str();
12567 /** Retrieves geometry shader body.
12569 * @param include_invalid_declaration true if the shader should include duplicate function
12572 * @return Requested string.
12574 std::string NegativeTest6::getGeometryShaderBody(bool include_invalid_declaration) const
12576 std::stringstream result_sstream;
12578 result_sstream << "#version 400\n"
12580 "#extension GL_ARB_shader_subroutine : require\n"
12582 "layout (points) in;\n"
12583 "layout (points, max_vertices = 1) out;\n"
12586 if (include_invalid_declaration)
12588 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
12590 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test)\n"
12592 " test = vec4(1, 2, 3, 4);\n"
12595 "void test_impl1(out vec4 test)\n"
12597 " test = vec4(2, 3, 4, 5);\n"
12600 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
12603 result_sstream << "\n"
12607 if (include_invalid_declaration)
12609 result_sstream << " test_subroutineGS(gl_Position);\n";
12613 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
12616 result_sstream << "EmitVertex();\n"
12619 return result_sstream.str();
12622 /** Retrieves tessellation control shader body.
12624 * @param include_invalid_declaration true if the shader should include duplicate function
12627 * @return Requested string.
12629 std::string NegativeTest6::getTessellationControlShaderBody(bool include_invalid_declaration) const
12631 std::stringstream result_sstream;
12633 result_sstream << "#version 400\n"
12635 "#extension GL_ARB_shader_subroutine : require\n"
12637 "layout (vertices = 4) out;\n"
12640 if (include_invalid_declaration)
12642 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
12644 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test)\n"
12646 " test = vec4(1, 2, 3, 4);\n"
12649 "void test_impl1(out vec4 test)\n"
12651 " test = vec4(2, 3, 4, 5);\n"
12654 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
12657 result_sstream << "\n"
12661 if (include_invalid_declaration)
12663 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
12667 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
12670 result_sstream << "}\n";
12672 return result_sstream.str();
12675 /** Retrieves tessellation evaluation body.
12677 * @param include_invalid_declaration true if the shader should include duplicate function
12680 * @return Requested string.
12682 std::string NegativeTest6::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
12684 std::stringstream result_sstream;
12686 result_sstream << "#version 400\n"
12688 "#extension GL_ARB_shader_subroutine : require\n"
12690 "layout (quads) in;\n"
12693 if (include_invalid_declaration)
12695 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
12697 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test)\n"
12699 " test = vec4(1, 2, 3, 4);\n"
12702 "void test_impl1(out vec4 test)\n"
12704 " test = vec4(2, 3, 4, 5);\n"
12707 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
12710 result_sstream << "\n"
12714 if (include_invalid_declaration)
12716 result_sstream << " test_subroutineTE(gl_Position);\n";
12720 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
12723 result_sstream << "}\n";
12725 return result_sstream.str();
12728 /** Retrieves vertex shader body.
12730 * @param include_invalid_declaration true if the shader should include duplicate function
12733 * @return Requested string.
12735 std::string NegativeTest6::getVertexShaderBody(bool include_invalid_declaration) const
12737 std::stringstream result_sstream;
12739 result_sstream << "#version 400\n"
12741 "#extension GL_ARB_shader_subroutine : require\n"
12744 if (include_invalid_declaration)
12746 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
12748 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test)\n"
12750 " test = vec4(1, 2, 3, 4);\n"
12753 "void test_impl1(out vec4 test)\n"
12755 " test = vec4(2, 3, 4, 5);\n"
12758 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
12761 result_sstream << "\n"
12765 if (include_invalid_declaration)
12767 result_sstream << " test_subroutineVS(gl_Position);\n";
12771 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
12774 result_sstream << "}\n";
12776 return result_sstream.str();
12779 /** Executes test iteration.
12781 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12783 tcu::TestNode::IterateResult NegativeTest6::iterate()
12785 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
12786 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
12788 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
12791 /* Iterate over all shader stages. In each iteration, we will inject invalid
12792 * duplicate function declarations to iteration-specific shader stage. All other
12793 * shader stages will be assigned valid bodies. Test should fail if the program
12794 * links successfully.
12796 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
12797 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
12799 executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
12801 } /* for (all shader stages) */
12804 if (m_has_test_passed)
12806 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
12810 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
12818 * @param context CTS context
12820 NegativeTest7::NegativeTest7(deqp::Context& context)
12821 : TestCase(context, "recursion", "Verify that it is not possible to build program with recursing subroutines")
12823 , m_vertex_shader_id(0)
12825 /* Nothing to be done here */
12828 /** Deinitializes all GL objects that may have been created during test execution
12831 void NegativeTest7::deinit()
12833 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
12835 if (m_program_id != 0)
12837 gl.deleteProgram(m_program_id);
12842 if (m_vertex_shader_id != 0)
12844 gl.deleteShader(m_vertex_shader_id);
12846 m_vertex_shader_id = 0;
12850 /** Executes test iteration.
12852 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
12854 tcu::TestNode::IterateResult NegativeTest7::iterate()
12856 static const GLchar* vertex_shader_with_static_recursion =
12859 "#extension GL_ARB_shader_subroutine : require\n"
12861 "precision highp float;\n"
12863 "subroutine vec4 routine_type(in vec4 data, in uint control);\n"
12865 "subroutine (routine_type) vec4 power_routine(in vec4 data, in uint control)\n"
12867 " if (0 != control)\n"
12869 " return data * power_routine(data, control - 1);\n"
12873 " return vec4(1, 1, 1, 1);\n"
12877 "subroutine (routine_type) vec4 select_routine(in vec4 data, in uint control)\n"
12879 " if (0 == control)\n"
12881 " return data.rrrr;\n"
12883 " else if (1 == control)\n"
12885 " return data.gggg;\n"
12887 " else if (2 == control)\n"
12889 " return data.bbbb;\n"
12893 " return data.aaaa;\n"
12897 "subroutine uniform routine_type routine;\n"
12899 "uniform vec4 uni_value;\n"
12900 "uniform uint uni_control;\n"
12902 "out vec4 out_result;\n"
12906 " out_result = routine(uni_value, uni_control);\n"
12910 static const GLchar* vertex_shader_with_dynamic_recursion =
12913 "#extension GL_ARB_shader_subroutine : require\n"
12915 "precision highp float;\n"
12917 "subroutine vec4 routine_type(in vec4 data);\n"
12919 "subroutine uniform routine_type routine;\n"
12921 "subroutine (routine_type) vec4 div_by_2(in vec4 data)\n"
12923 " return data / 2;\n"
12926 "subroutine (routine_type) vec4 div_routine_result_by_2(in vec4 data)\n"
12928 " return routine(data) / 2;\n"
12931 "uniform vec4 uni_value;\n"
12933 "out vec4 out_result;\n"
12937 " out_result = routine(uni_value);\n"
12941 static const GLchar* vertex_shader_with_subroutine_function_recursion =
12944 "#extension GL_ARB_shader_subroutine : require\n"
12946 "precision highp float;\n"
12948 "subroutine vec4 routine_type(in vec4 data);\n"
12950 "subroutine uniform routine_type routine;\n"
12952 "vec4 function(in vec4 data)\n"
12954 " return routine(data) + vec4(0.5, 0.5, 0.5, 0.5);\n"
12957 "subroutine (routine_type) vec4 routine_a(in vec4 data)\n"
12959 " return function(data) / 2;\n"
12962 "subroutine (routine_type) vec4 routine_b(in vec4 data)\n"
12964 " return routine_a(data) * 2;\n"
12967 "uniform vec4 uni_value;\n"
12969 "out vec4 out_result;\n"
12973 " out_result = routine(uni_value);\n"
12977 bool result = true;
12979 if (false == test(vertex_shader_with_subroutine_function_recursion, "routine_a"))
12984 if (false == test(vertex_shader_with_dynamic_recursion, "div_routine_result_by_2"))
12989 if (false == test(vertex_shader_with_static_recursion, "power_routine"))
12995 if (true == result)
12997 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13001 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13005 return tcu::TestNode::STOP;
13008 /** Try to build program from vertex shader code.
13010 * @param vertex_shader_code Source code of vertex shader
13011 * @param name_of_recursive_routine Name of subroutine that should cause link failure due to recursion
13013 * @return true build process failed, false otherwise
13015 bool NegativeTest7::test(const GLchar* vertex_shader_code, const GLchar* name_of_recursive_routine)
13017 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13018 bool result = true;
13019 static const GLchar* varying_name = "out_result";
13021 /* Try to build program */
13022 if (true == Utils::buildProgram(gl, vertex_shader_code, "", "", "", "", &varying_name /* varying_names */,
13023 1 /* n_varyings */, &m_vertex_shader_id, 0, 0, 0, 0, &m_program_id))
13025 /* Success is considered an error */
13027 Utils::program program(m_context);
13030 program.build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0);
13032 /* Verify that recursive subroutine is active */
13035 index = program.getSubroutineIndex(name_of_recursive_routine, GL_VERTEX_SHADER);
13037 catch (const std::exception& exc)
13039 /* Something wrong with shader or compilation */
13040 m_context.getTestContext().getLog()
13041 << tcu::TestLog::Message << "It is expected that subroutine: \n"
13042 << name_of_recursive_routine
13043 << " is considered active. This subroutine is potentially recursive and should cause link failure."
13044 << tcu::TestLog::EndMessage;
13049 /* Subsoutine is active, however linking should fail */
13050 m_context.getTestContext().getLog()
13051 << tcu::TestLog::Message << "Error. Program with potentially recursive subroutine, "
13052 << name_of_recursive_routine << ", which is active, index: " << index << ", has been built successfully.\n"
13053 << vertex_shader_code << tcu::TestLog::EndMessage;
13058 /* Delete program and shader */
13067 * @param context Rendering context.
13070 NegativeTest8::NegativeTest8(deqp::Context& context)
13071 : TestCase(context, "subroutine_wo_body", "Verifies that a compile- or link-time error occurs if a function "
13072 "declared as a subroutine does not include a body.")
13075 , m_has_test_passed(true)
13081 /* Left blank intentionally */
13084 /** Deinitializes all GL objects that may have been created during test execution */
13085 void NegativeTest8::deinit()
13090 /** Deinitializes all GL objects that may have been created during a single test
13093 void NegativeTest8::deinitIteration()
13095 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13099 gl.deleteShader(m_fs_id);
13106 gl.deleteShader(m_gs_id);
13113 gl.deleteProgram(m_po_id);
13120 gl.deleteShader(m_tc_id);
13127 gl.deleteShader(m_te_id);
13134 gl.deleteShader(m_vs_id);
13140 /** Executes a single test iteration.
13142 * If the iteration fails, m_has_test_passed will be set to false.
13144 * @param shader_stage Shader stage, for which two duplicate functions
13145 * (one additionally marked as subroutine) should
13148 void NegativeTest8::executeIteration(const Utils::_shader_stage& shader_stage)
13150 std::string fs_body = getFragmentShaderBody(shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13151 std::string gs_body = getGeometryShaderBody(shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13152 std::string tc_body = getTessellationControlShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13153 std::string te_body =
13154 getTessellationEvaluationShaderBody(shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13155 std::string vs_body = getVertexShaderBody(shader_stage == Utils::SHADER_STAGE_VERTEX);
13157 if (Utils::buildProgram(m_context.getRenderContext().getFunctions(), vs_body, tc_body, te_body, gs_body, fs_body,
13158 DE_NULL, /* xfb_varyings */
13159 DE_NULL, /* n_xfb_varyings */
13160 &m_vs_id, &m_tc_id, &m_te_id, &m_gs_id, &m_fs_id, &m_po_id))
13162 /* None of the test programs should ever build successfully */
13163 m_testCtx.getLog() << tcu::TestLog::Message
13164 << "A program object consisting of FS+GS+TC+TE+VS stages has linked successfully, "
13165 "even though one of the shaders only defines a subroutine that lacks any body."
13170 "Tessellation control shader:\n"
13173 "Tessellation evaluation shader:\n"
13176 "Geometry shader:\n"
13179 "Fragment shader:\n"
13181 << fs_body << tcu::TestLog::EndMessage;
13183 m_has_test_passed = false;
13187 /** Retrieves fragment shader body.
13189 * @param include_invalid_declaration true if a subroutine prototype should be included in
13190 * the shader, false to skip it.
13192 * @return Requested string.
13194 std::string NegativeTest8::getFragmentShaderBody(bool include_invalid_declaration) const
13196 std::stringstream result_sstream;
13198 result_sstream << "#version 400\n"
13200 "#extension GL_ARB_shader_subroutine : require\n"
13203 if (include_invalid_declaration)
13205 result_sstream << "subroutine void subroutineTestTypeFS(out vec4 test);\n"
13207 "subroutine(subroutineTestTypeFS) void test_impl1(out vec4 test);\n"
13209 "subroutine uniform subroutineTestTypeFS test_subroutineFS;\n";
13212 result_sstream << "\n"
13213 "out vec4 result;\n"
13218 if (include_invalid_declaration)
13220 result_sstream << " test_subroutineFS(result);\n";
13224 result_sstream << " result = vec4(0, 1, 2, 3);\n";
13227 result_sstream << "}\n";
13229 return result_sstream.str();
13232 /** Retrieves geometry shader body.
13234 * @param include_invalid_declaration true if a subroutine prototype should be included in
13235 * the shader, false to skip it.
13237 * @return Requested string.
13239 std::string NegativeTest8::getGeometryShaderBody(bool include_invalid_declaration) const
13241 std::stringstream result_sstream;
13243 result_sstream << "#version 400\n"
13245 "#extension GL_ARB_shader_subroutine : require\n"
13247 "layout (points) in;\n"
13248 "layout (points, max_vertices = 1) out;\n"
13251 if (include_invalid_declaration)
13253 result_sstream << "subroutine void subroutineTestTypeGS(out vec4 test);\n"
13255 "subroutine(subroutineTestTypeGS) void test_impl1(out vec4 test);\n"
13257 "subroutine uniform subroutineTestTypeGS test_subroutineGS;\n";
13260 result_sstream << "\n"
13264 if (include_invalid_declaration)
13266 result_sstream << " test_subroutineGS(gl_Position);\n";
13270 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
13273 result_sstream << "EmitVertex();\n"
13276 return result_sstream.str();
13279 /** Retrieves tessellation control shader body.
13281 * @param include_invalid_declaration true if a subroutine prototype should be included in
13282 * the shader, false to skip it.
13284 * @return Requested string.
13286 std::string NegativeTest8::getTessellationControlShaderBody(bool include_invalid_declaration) const
13288 std::stringstream result_sstream;
13290 result_sstream << "#version 400\n"
13292 "#extension GL_ARB_shader_subroutine : require\n"
13294 "layout (vertices = 4) out;\n"
13297 if (include_invalid_declaration)
13299 result_sstream << "subroutine void subroutineTestTypeTC(out vec4 test);\n"
13301 "subroutine(subroutineTestTypeTC) void test_impl1(out vec4 test);\n"
13303 "subroutine uniform subroutineTestTypeTC test_subroutineTC;\n";
13306 result_sstream << "\n"
13310 if (include_invalid_declaration)
13312 result_sstream << " test_subroutineTC(gl_out[gl_InvocationID].gl_Position);\n";
13316 result_sstream << " gl_out[gl_InvocationID].gl_Position = vec4(0, 1, 2, 3);\n";
13319 result_sstream << "}\n";
13321 return result_sstream.str();
13324 /** Retrieves tessellation evaluation body.
13326 * @param include_invalid_declaration true if a subroutine prototype should be included in
13327 * the shader, false to skip it.
13329 * @return Requested string.
13331 std::string NegativeTest8::getTessellationEvaluationShaderBody(bool include_invalid_declaration) const
13333 std::stringstream result_sstream;
13335 result_sstream << "#version 400\n"
13337 "#extension GL_ARB_shader_subroutine : require\n"
13339 "layout (quads) in;\n"
13342 if (include_invalid_declaration)
13344 result_sstream << "subroutine void subroutineTestTypeTE(out vec4 test);\n"
13346 "subroutine(subroutineTestTypeTE) void test_impl1(out vec4 test);\n"
13348 "subroutine uniform subroutineTestTypeTE test_subroutineTE;\n";
13351 result_sstream << "\n"
13355 if (include_invalid_declaration)
13357 result_sstream << " test_subroutineTE(gl_Position);\n";
13361 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
13364 result_sstream << "}\n";
13366 return result_sstream.str();
13369 /** Retrieves vertex shader body.
13371 * @param include_invalid_declaration true if a subroutine prototype should be included in
13372 * the shader, false to skip it.
13374 * @return Requested string.
13376 std::string NegativeTest8::getVertexShaderBody(bool include_invalid_declaration) const
13378 std::stringstream result_sstream;
13380 result_sstream << "#version 400\n"
13382 "#extension GL_ARB_shader_subroutine : require\n"
13385 if (include_invalid_declaration)
13387 result_sstream << "subroutine void subroutineTestTypeVS(out vec4 test);\n"
13389 "subroutine(subroutineTestTypeVS) void test_impl1(out vec4 test);\n"
13391 "subroutine uniform subroutineTestTypeVS test_subroutineVS;\n";
13394 result_sstream << "\n"
13398 if (include_invalid_declaration)
13400 result_sstream << " test_subroutineVS(gl_Position);\n";
13404 result_sstream << " gl_Position = vec4(0, 1, 2, 3);\n";
13407 result_sstream << "}\n";
13409 return result_sstream.str();
13412 /** Executes test iteration.
13414 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13416 tcu::TestNode::IterateResult NegativeTest8::iterate()
13418 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13419 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13421 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13424 /* Iterate over all shader stages. For each iteration, iteration-specific shader stage
13425 * will feature an invalid subroutine definition. Other shader stages will be assigned
13426 * valid bodies. The test fails if a program built of such shaders links successfully.
13428 for (int shader_stage = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13429 shader_stage < static_cast<int>(Utils::SHADER_STAGE_COUNT); ++shader_stage)
13431 executeIteration(static_cast<Utils::_shader_stage>(shader_stage));
13433 } /* for (all shader stages) */
13436 if (m_has_test_passed)
13438 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13442 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13450 * @param context Rendering context.
13452 NegativeTest9::NegativeTest9(deqp::Context& context)
13453 : TestCase(context, "subroutines_cannot_be_assigned_float_int_values_or_be_compared",
13454 "Make sure it is not possible to assign float/int to subroutine "
13455 "uniform and that subroutine uniform values cannot be compared.")
13456 , m_has_test_passed(true)
13460 /* Left blank intentionally */
13463 /** Deinitializes any GL objects that may have been created during
13466 void NegativeTest9::deinit()
13468 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13472 gl.deleteProgram(m_po_id);
13479 gl.deleteShader(m_vs_id);
13485 /** Returns a literal corresponding to user-specified test case enum.
13487 * @param test_case As per description.
13489 * @return Requested string.
13491 std::string NegativeTest9::getTestCaseString(const _test_case& test_case)
13493 std::string result = "?";
13497 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13498 result = "TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
13500 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13501 result = "TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT";
13503 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
13504 result = "TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON";
13513 /** Retrieves vertex shader body for user-specified test case.
13515 * @param test_case As per description.
13517 * @return Requested string.
13519 std::string NegativeTest9::getVertexShader(const _test_case& test_case)
13521 std::stringstream result_sstream;
13523 /* Form pre-amble */
13524 result_sstream << "#version 400\n"
13526 "#extension GL_ARB_shader_subroutine : require\n"
13528 /* Define a subroutine */
13529 "subroutine void subroutineType(inout vec4 test);\n"
13531 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13533 " test += vec4(0, 1, 2, 3);\n"
13536 "subroutine uniform subroutineType function;\n"
13539 /* Include case-specific implementation */
13542 case TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13544 result_sstream << "void main()\n"
13546 " function = 1.0f;\n"
13548 " function(gl_Position);\n"
13554 case TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT:
13556 result_sstream << "void main()\n"
13560 " function(gl_Position);\n"
13566 case TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON:
13568 result_sstream << "subroutine uniform subroutineType function2;\n"
13572 " if (function == function2)\n"
13574 " function(gl_Position);\n"
13578 " function2(gl_Position);\n"
13587 } /* switch (test_case) */
13590 return result_sstream.str();
13593 /** Executes test iteration.
13595 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13597 tcu::TestNode::IterateResult NegativeTest9::iterate()
13599 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13601 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13602 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13604 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
13607 /* Iterate over all test cases */
13608 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
13610 /* Try to build a program object using invalid vertex shader, specific to the
13611 * iteration we're currently in */
13612 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
13614 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */
13618 DE_NULL, /* xfb_varyings */
13619 0, /* n_xfb_varyings */
13620 &m_vs_id, DE_NULL, /* out_tc_id */
13621 DE_NULL, /* out_te_id */
13622 DE_NULL, /* out_gs_id */
13623 DE_NULL, /* out_fs_id */
13626 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
13627 << getTestCaseString(static_cast<_test_case>(test_case))
13628 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
13630 m_has_test_passed = false;
13633 /* Delete any objects that may have been created */
13635 } /* for (all test cases) */
13638 if (m_has_test_passed)
13640 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
13644 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13652 * @param context Rendering context.
13654 NegativeTest10::NegativeTest10(deqp::Context& context)
13655 : TestCase(context, "function_overloading_forbidden_for_subroutines",
13656 "Check that an overloaded function cannot be declared with subroutine and "
13657 "a program will fail to compile or link if any shader or stage contains"
13658 " two or more functions with the same name if the name is associated with"
13659 " a subroutine type.")
13660 , m_has_test_passed(true)
13668 /* Left blank intentionally */
13671 /** Deinitializes any GL objects that may have been created during
13674 void NegativeTest10::deinit()
13676 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13680 gl.deleteShader(m_fs_id);
13687 gl.deleteShader(m_gs_id);
13694 gl.deleteProgram(m_po_id);
13701 gl.deleteShader(m_tc_id);
13708 gl.deleteShader(m_te_id);
13715 gl.deleteShader(m_vs_id);
13721 /** Retrieves fragment shader that should be used for the purpose of the test.
13722 * An overloaded version of a subroutine function is inserted if
13723 * @param include_duplicate_function flag is set to true.
13725 * @param include_duplicate_function As per description.
13727 * @return Requested string.
13729 std::string NegativeTest10::getFragmentShader(bool include_duplicate_function)
13731 std::stringstream result_sstream;
13733 result_sstream << "#version 400\n"
13735 "#extension GL_ARB_shader_subroutine : require\n"
13737 "subroutine void subroutineType(inout vec4 test);\n"
13739 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13741 " test = vec4(2, 3, 4, 5);\n"
13744 "subroutine uniform subroutineType function;\n"
13745 "out vec4 result;\n"
13748 if (include_duplicate_function)
13750 result_sstream << "void test_function(inout vec4 test)\n"
13752 " test = vec4(3, 4, 5, 6);\n"
13757 result_sstream << "void main()\n"
13759 " test_function(result);\n"
13762 return result_sstream.str();
13765 /** Retrieves geometry shader that should be used for the purpose of the test.
13766 * An overloaded version of a subroutine function is inserted if
13767 * @param include_duplicate_function flag is set to true.
13769 * @param include_duplicate_function As per description.
13771 * @return Requested string.
13773 std::string NegativeTest10::getGeometryShader(bool include_duplicate_function)
13775 std::stringstream result_sstream;
13777 result_sstream << "#version 400\n"
13779 "#extension GL_ARB_shader_subroutine : require\n"
13781 "layout (triangles) in;\n"
13782 "layout (triangle_strip, max_vertices = 4) out;\n"
13784 "subroutine void subroutineType(inout vec4 test);\n"
13786 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13788 " test = vec4(2, 3, 4, 5);\n"
13791 "subroutine uniform subroutineType function;\n"
13794 if (include_duplicate_function)
13796 result_sstream << "void test_function(inout vec4 test)\n"
13798 " test = vec4(3, 4, 5, 6);\n"
13803 result_sstream << "void main()\n"
13805 " function(gl_Position);\n"
13807 " EndPrimitive();\n"
13810 return result_sstream.str();
13813 /** Retrieves tess control shader that should be used for the purpose of the test.
13814 * An overloaded version of a subroutine function is inserted if
13815 * @param include_duplicate_function flag is set to true.
13817 * @param include_duplicate_function As per description.
13819 * @return Requested string.
13821 std::string NegativeTest10::getTessellationControlShader(bool include_duplicate_function)
13823 std::stringstream result_sstream;
13825 result_sstream << "#version 400\n"
13827 "#extension GL_ARB_shader_subroutine : require\n"
13829 "layout (vertices = 4) out;\n"
13831 "subroutine void subroutineType(inout vec4 test);\n"
13833 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13835 " test = vec4(2, 3, 4, 5);\n"
13838 "subroutine uniform subroutineType function;\n"
13841 if (include_duplicate_function)
13843 result_sstream << "void test_function(inout vec4 test)\n"
13845 " test = vec4(3, 4, 5, 6);\n"
13850 result_sstream << "void main()\n"
13854 " function(temp);\n"
13856 " gl_out[gl_InvocationID].gl_Position = temp;\n"
13857 " gl_TessLevelInner[0] = temp.x;\n"
13858 " gl_TessLevelInner[1] = temp.y;\n"
13859 " gl_TessLevelOuter[0] = temp.z;\n"
13860 " gl_TessLevelOuter[1] = temp.w;\n"
13861 " gl_TessLevelOuter[2] = temp.x;\n"
13862 " gl_TessLevelOuter[3] = temp.y;\n"
13865 return result_sstream.str();
13868 /** Retrieves tess evaluation shader that should be used for the purpose of the test.
13869 * An overloaded version of a subroutine function is inserted if
13870 * @param include_duplicate_function flag is set to true.
13872 * @param include_duplicate_function As per description.
13874 * @return Requested string.
13876 std::string NegativeTest10::getTessellationEvaluationShader(bool include_duplicate_function)
13878 std::stringstream result_sstream;
13880 result_sstream << "#version 400\n"
13882 "#extension GL_ARB_shader_subroutine : require\n"
13884 "layout (quads) in;\n"
13886 "subroutine void subroutineType(inout vec4 test);\n"
13888 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13890 " test = vec4(2, 3, 4, 5);\n"
13893 "subroutine uniform subroutineType function;\n"
13896 if (include_duplicate_function)
13898 result_sstream << "void test_function(inout vec4 test)\n"
13900 " test = vec4(3, 4, 5, 6);\n"
13905 result_sstream << "void main()\n"
13909 " function(temp);\n"
13911 " gl_Position = temp;\n"
13914 return result_sstream.str();
13917 /** Retrieves vertex shader that should be used for the purpose of the test.
13918 * An overloaded version of a subroutine function is inserted if
13919 * @param include_duplicate_function flag is set to true.
13921 * @param include_duplicate_function As per description.
13923 * @return Requested string.
13925 std::string NegativeTest10::getVertexShader(bool include_duplicate_function)
13927 std::stringstream result_sstream;
13929 result_sstream << "#version 400\n"
13931 "#extension GL_ARB_shader_subroutine : require\n"
13933 "subroutine void subroutineType(inout vec4 test);\n"
13935 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
13937 " test = vec4(2, 3, 4, 5);\n"
13940 "subroutine uniform subroutineType function;\n"
13943 if (include_duplicate_function)
13945 result_sstream << "void test_function(inout vec4 test)\n"
13947 " test = vec4(3, 4, 5, 6);\n"
13952 result_sstream << "void main()\n"
13954 " function(gl_Position);\n"
13957 return result_sstream.str();
13960 /** Fills m_test_cases field with test case descriptors */
13961 void NegativeTest10::initTestCases()
13963 /* For each test case, only one shader stage should define a function that
13964 * has already been defined as a subroutine. */
13965 for (int offending_shader_stage_it = static_cast<int>(Utils::SHADER_STAGE_FIRST);
13966 offending_shader_stage_it != static_cast<int>(Utils::SHADER_STAGE_COUNT); ++offending_shader_stage_it)
13968 Utils::_shader_stage offending_shader_stage = static_cast<Utils::_shader_stage>(offending_shader_stage_it);
13969 /* Form the test case descriptor */
13970 std::stringstream name_sstream;
13971 _test_case test_case;
13973 name_sstream << "Broken shader stage:" << Utils::getShaderStageString(offending_shader_stage);
13975 test_case.fs_body = getFragmentShader(offending_shader_stage == Utils::SHADER_STAGE_FRAGMENT);
13976 test_case.gs_body = getGeometryShader(offending_shader_stage == Utils::SHADER_STAGE_GEOMETRY);
13977 test_case.name = name_sstream.str();
13978 test_case.tc_body =
13979 getTessellationControlShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_CONTROL);
13980 test_case.te_body =
13981 getTessellationEvaluationShader(offending_shader_stage == Utils::SHADER_STAGE_TESSELLATION_EVALUATION);
13982 test_case.vs_body = getVertexShader(offending_shader_stage == Utils::SHADER_STAGE_VERTEX);
13984 m_test_cases.push_back(test_case);
13988 /** Executes test iteration.
13990 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
13992 tcu::TestNode::IterateResult NegativeTest10::iterate()
13994 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13996 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
13997 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
13999 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14002 /* Form test cases */
14005 /* Iterate over all test cases */
14006 for (_test_cases_const_iterator test_case_iterator = m_test_cases.begin(); test_case_iterator != m_test_cases.end();
14007 ++test_case_iterator)
14009 const _test_case& test_case = *test_case_iterator;
14011 /* Try to build the program object */
14012 if (ShaderSubroutine::Utils::buildProgram(gl, test_case.vs_body, test_case.tc_body, test_case.te_body,
14013 test_case.gs_body, test_case.fs_body, DE_NULL, /* xfb_varyings */
14014 0, /* n_xfb_varyings */
14015 &m_vs_id, (test_case.tc_body.length() > 0) ? &m_tc_id : DE_NULL,
14016 (test_case.te_body.length() > 0) ? &m_te_id : DE_NULL,
14017 (test_case.gs_body.length() > 0) ? &m_gs_id : DE_NULL,
14018 (test_case.fs_body.length() > 0) ? &m_fs_id : DE_NULL, &m_po_id))
14020 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14021 << test_case.name << "] test case, even though it was invalid."
14022 << tcu::TestLog::EndMessage;
14024 m_has_test_passed = false;
14027 /* Delete any objects that may have been created */
14029 } /* for (all test cases) */
14032 if (m_has_test_passed)
14034 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14038 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14046 * @param context Rendering context.
14048 NegativeTest11::NegativeTest11(deqp::Context& context)
14049 : TestCase(context, "subroutine_uniforms_used_for_sampling_atomic_image_functions",
14050 "Tries to use subroutine uniforms in invalid way in sampling, "
14051 "atomic and image functions. Verifies that compile- or link-time "
14053 , m_has_test_passed(true)
14057 /* Left blank intentionally */
14060 /** Deinitializes any GL objects that may have been created during
14063 void NegativeTest11::deinit()
14065 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14069 gl.deleteProgram(m_po_id);
14076 gl.deleteShader(m_vs_id);
14082 /** Returns a literal corresponding to user-specified test case enum.
14084 * @param test_case As per description.
14086 * @return Requested string.
14088 std::string NegativeTest11::getTestCaseString(const _test_case& test_case)
14090 std::string result = "?";
14094 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
14095 result = "TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT";
14097 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
14098 result = "TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT";
14100 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
14101 result = "TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT";
14110 /** Retrieves vertex shader body for user-specified test case.
14112 * @param test_case As per description.
14114 * @return Requested string.
14116 std::string NegativeTest11::getVertexShader(const _test_case& test_case)
14118 std::stringstream result_sstream;
14120 /* Form pre-amble */
14121 result_sstream << "#version 400\n"
14123 "#extension GL_ARB_shader_subroutine : require\n";
14125 if (test_case == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT)
14127 result_sstream << "#extension GL_ARB_shader_atomic_counters : require\n";
14130 result_sstream << "\n"
14131 /* Define a subroutine */
14132 "subroutine void subroutineType(inout vec4 test);\n"
14134 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
14136 " test += vec4(0, 1, 2, 3);\n"
14139 "subroutine uniform subroutineType function;\n"
14142 /* Define main() body */
14146 /* Implement case-specific behavior */
14149 case TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT:
14151 result_sstream << "if (atomicCounter(function) > 2)\n"
14153 " gl_Position = vec4(1);\n"
14159 case TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT:
14161 result_sstream << "imageStore(function, vec2(0.0, 1.0), vec4(1.0) );\n";
14166 case TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT:
14168 result_sstream << "gl_Position = texture(function, vec2(1.0) );\n";
14175 } /* switch (test_case) */
14177 /* Close main() body */
14178 result_sstream << "}\n";
14181 return result_sstream.str();
14184 /** Executes test iteration.
14186 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
14188 tcu::TestNode::IterateResult NegativeTest11::iterate()
14190 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14192 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
14193 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
14195 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14198 /* Iterate over all test cases */
14199 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
14201 if (static_cast<_test_case>(test_case) == TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT &&
14202 !m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_atomic_counters"))
14204 /* This iteration requires atomic counter support that this GL implementation
14205 * is not capable of. Skip the iteration
14210 /* Try to build a program object using invalid vertex shader, specific to the
14211 * iteration we're currently in */
14212 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
14214 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */
14218 DE_NULL, /* xfb_varyings */
14219 0, /* n_xfb_varyings */
14220 &m_vs_id, DE_NULL, /* out_tc_id */
14221 DE_NULL, /* out_te_id */
14222 DE_NULL, /* out_gs_id */
14223 DE_NULL, /* out_fs_id */
14226 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14227 << getTestCaseString(static_cast<_test_case>(test_case))
14228 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
14230 m_has_test_passed = false;
14233 /* Delete any objects that may have been created */
14235 } /* for (all test cases) */
14238 if (m_has_test_passed)
14240 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14244 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14252 * @param context Rendering context.
14254 NegativeTest12::NegativeTest12(deqp::Context& context)
14255 : TestCase(context, "subroutines_not_allowed_as_variables_constructors_and_argument_or_return_types",
14256 "Verifies that it is not allowed to use subroutine type for "
14257 "local/global variables, constructors or argument/return type.")
14258 , m_has_test_passed(true)
14262 /* Left blank intentionally */
14265 /** Deinitializes any GL objects that may have been created during
14268 void NegativeTest12::deinit()
14270 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14274 gl.deleteProgram(m_po_id);
14281 gl.deleteShader(m_vs_id);
14287 /** Returns a literal corresponding to user-specified test case enum.
14289 * @param test_case As per description.
14291 * @return Requested string.
14293 std::string NegativeTest12::getTestCaseString(const _test_case& test_case)
14295 std::string result = "?";
14299 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
14300 result = "TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE";
14302 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
14303 result = "TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE";
14305 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
14306 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR";
14308 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
14309 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT";
14311 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
14312 result = "TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE";
14321 /** Retrieves vertex shader body for user-specified test case.
14323 * @param test_case As per description.
14325 * @return Requested string.
14327 std::string NegativeTest12::getVertexShader(const _test_case& test_case)
14329 std::stringstream result_sstream;
14331 /* Form pre-amble */
14332 result_sstream << "#version 400\n"
14334 "#extension GL_ARB_shader_subroutine : require\n"
14336 /* Define a subroutine */
14337 "subroutine void subroutineType(inout vec4 test);\n"
14339 "subroutine(subroutineType) void test_function(inout vec4 test)\n"
14341 " test += vec4(0, 1, 2, 3);\n"
14344 "subroutine uniform subroutineType function;\n"
14347 /* Include case-specific implementation */
14350 case TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE:
14352 result_sstream << "void main()\n"
14354 " subroutine subroutineType function2;\n"
14357 " function2(result);\n"
14358 " gl_Position = result;\n"
14364 case TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE:
14366 result_sstream << "subroutine subroutineType function2;\n"
14372 " function2(result);\n"
14373 " gl_Position = result;\n"
14379 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR:
14381 result_sstream << "void main()\n"
14383 " subroutineType(function);\n"
14389 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT:
14391 result_sstream << "vec4 test_function(subroutineType argument)\n"
14393 " vec4 result = vec4(1, 2, 3, 4);\n"
14395 " argument(result);\n"
14397 " return result;\n"
14402 " test_function(function);\n"
14408 case TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE:
14410 result_sstream << "subroutineType test_function()\n"
14412 " return function;\n"
14417 " test_function()(gl_Position);\n"
14425 } /* switch (test_case) */
14428 return result_sstream.str();
14431 /** Executes test iteration.
14433 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
14435 tcu::TestNode::IterateResult NegativeTest12::iterate()
14437 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14439 /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
14440 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
14442 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
14445 /* Iterate over all test cases */
14446 for (int test_case = static_cast<int>(TEST_CASE_FIRST); test_case != static_cast<int>(TEST_CASE_COUNT); ++test_case)
14448 /* Try to build a program object using invalid vertex shader, specific to the
14449 * iteration we're currently in */
14450 std::string vs_body = getVertexShader(static_cast<_test_case>(test_case));
14452 if (ShaderSubroutine::Utils::buildProgram(gl, vs_body, "", /* tc_body */
14456 DE_NULL, /* xfb_varyings */
14457 0, /* n_xfb_varyings */
14458 &m_vs_id, DE_NULL, /* out_tc_id */
14459 DE_NULL, /* out_te_id */
14460 DE_NULL, /* out_gs_id */
14461 DE_NULL, /* out_fs_id */
14464 m_testCtx.getLog() << tcu::TestLog::Message << "A program object was successfully built for ["
14465 << getTestCaseString(static_cast<_test_case>(test_case))
14466 << "] test case, even though it was invalid." << tcu::TestLog::EndMessage;
14468 m_has_test_passed = false;
14471 /* Delete any objects that may have been created */
14473 } /* for (all test cases) */
14476 if (m_has_test_passed)
14478 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
14482 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
14488 } /* ShaderSubroutine */
14492 * @param context Rendering context.
14494 ShaderSubroutineTests::ShaderSubroutineTests(deqp::Context& context)
14495 : TestCaseGroup(context, "shader_subroutine", "Verifies \"shader_subroutine\" functionality")
14497 /* Left blank on purpose */
14500 /** Initializes a texture_storage_multisample test group.
14503 void ShaderSubroutineTests::init(void)
14505 addChild(new ShaderSubroutine::APITest1(m_context));
14506 addChild(new ShaderSubroutine::APITest2(m_context));
14507 addChild(new ShaderSubroutine::FunctionalTest1_2(m_context));
14508 addChild(new ShaderSubroutine::FunctionalTest3_4(m_context));
14509 addChild(new ShaderSubroutine::FunctionalTest5(m_context));
14510 addChild(new ShaderSubroutine::FunctionalTest6(m_context));
14511 addChild(new ShaderSubroutine::FunctionalTest7_8(m_context));
14512 addChild(new ShaderSubroutine::FunctionalTest9(m_context));
14513 addChild(new ShaderSubroutine::FunctionalTest10(m_context));
14514 addChild(new ShaderSubroutine::FunctionalTest11(m_context));
14515 addChild(new ShaderSubroutine::FunctionalTest12(m_context));
14516 addChild(new ShaderSubroutine::FunctionalTest13(m_context));
14517 addChild(new ShaderSubroutine::FunctionalTest14_15(m_context));
14518 addChild(new ShaderSubroutine::FunctionalTest16(m_context));
14519 addChild(new ShaderSubroutine::FunctionalTest17(m_context));
14520 addChild(new ShaderSubroutine::FunctionalTest18_19(m_context));
14521 addChild(new ShaderSubroutine::FunctionalTest20_21(m_context));
14522 addChild(new ShaderSubroutine::NegativeTest1(m_context));
14523 addChild(new ShaderSubroutine::NegativeTest2(m_context));
14524 addChild(new ShaderSubroutine::NegativeTest3(m_context));
14525 addChild(new ShaderSubroutine::NegativeTest4(m_context));
14526 addChild(new ShaderSubroutine::NegativeTest5(m_context));
14527 addChild(new ShaderSubroutine::NegativeTest6(m_context));
14528 addChild(new ShaderSubroutine::NegativeTest7(m_context));
14529 addChild(new ShaderSubroutine::NegativeTest8(m_context));
14530 addChild(new ShaderSubroutine::NegativeTest9(m_context));
14531 addChild(new ShaderSubroutine::NegativeTest10(m_context));
14532 addChild(new ShaderSubroutine::NegativeTest11(m_context));
14533 addChild(new ShaderSubroutine::NegativeTest12(m_context));
14536 } /* glcts namespace */