#ifndef _ESEXTCGEOMETRYSHADERLIMITS_HPP #define _ESEXTCGEOMETRYSHADERLIMITS_HPP /*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2014-2016 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /*! * \file * \brief */ /*-------------------------------------------------------------------*/ /*! * \file esextcGeometryShaderLimits.hpp * \brief Geometry Shader Limits (Test Group 16) */ /*-------------------------------------------------------------------*/ #include "../esextcTestCaseBase.hpp" #include namespace glcts { /** Parent class for geometry shader Test Group 16 tests * based on fetching result via transfrom feedback. **/ class GeometryShaderLimitsTransformFeedbackBase : public TestCaseBase { public: /* Public methods */ virtual void deinit(void); virtual IterateResult iterate(void); protected: /* Protected methods */ GeometryShaderLimitsTransformFeedbackBase(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderLimitsTransformFeedbackBase() { } void initTest(void); /* Methods to be overriden by inheriting test cases */ virtual void clean() = 0; virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, glw::GLuint& out_n_captured_varyings) = 0; virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts) = 0; virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size) = 0; virtual void prepareProgramInput() = 0; virtual bool verifyResult(const void* data) = 0; /* Protected fields */ /* Program and shader ids */ glw::GLuint m_fragment_shader_id; glw::GLuint m_geometry_shader_id; glw::GLuint m_program_object_id; glw::GLuint m_vertex_shader_id; /* Buffer object used in transform feedback */ glw::GLuint m_buffer_object_id; /* Vertex array object */ glw::GLuint m_vertex_array_object_id; private: /* Private fields */ /* Shaders' code */ const glw::GLchar* const* m_fragment_shader_parts; const glw::GLchar* const* m_geometry_shader_parts; const glw::GLchar* const* m_vertex_shader_parts; glw::GLuint m_n_fragment_shader_parts; glw::GLuint m_n_geometry_shader_parts; glw::GLuint m_n_vertex_shader_parts; /* Names of varyings */ const glw::GLchar* const* m_captured_varyings_names; glw::GLuint m_n_captured_varyings; /* Size of buffer used by transform feedback */ glw::GLuint m_buffer_size; }; /** Parent class for geometry shader Test Group 16 tests * based on fetching result via rendering to texture. **/ class GeometryShaderLimitsRenderingBase : public TestCaseBase { public: /* Public methods */ virtual void deinit(void); virtual IterateResult iterate(void); protected: /* Protected methods */ GeometryShaderLimitsRenderingBase(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderLimitsRenderingBase() { } void initTest(void); /* Methods to be overriden by child test cases */ virtual void clean() = 0; virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices) = 0; virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size) = 0; virtual void getRequiredPointSize(glw::GLfloat& out_point_size) = 0; virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts) = 0; virtual void prepareProgramInput() = 0; virtual bool verifyResult(const void* data) = 0; /* Protected fields */ /* Program and shader ids */ glw::GLuint m_fragment_shader_id; glw::GLuint m_geometry_shader_id; glw::GLuint m_program_object_id; glw::GLuint m_vertex_shader_id; /* Framebuffer object id */ glw::GLuint m_framebuffer_object_id; glw::GLuint m_color_texture_id; /* Vertex array object */ glw::GLuint m_vertex_array_object_id; private: /* Private fields */ /* Shaders' code */ const glw::GLchar* const* m_fragment_shader_parts; const glw::GLchar* const* m_geometry_shader_parts; const glw::GLchar* const* m_vertex_shader_parts; glw::GLuint m_n_fragment_shader_parts; glw::GLuint m_n_geometry_shader_parts; glw::GLuint m_n_vertex_shader_parts; /* Framebuffer dimensions */ glw::GLenum m_texture_format; glw::GLuint m_texture_height; glw::GLuint m_texture_pixel_size; glw::GLenum m_texture_read_format; glw::GLenum m_texture_read_type; glw::GLuint m_texture_width; }; /** Implementation of test case 16.1. Test description follows: * * Make sure it is possible to use as many uniform components as defined * by GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT * * Category: API; * Functional Test. * * 1. Create a fragment, geometry and vertex shader objects: * * - Vertex shader code can be boilerplate; * - Geometry shader code should define * floor(GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT / 4) uniform ivec4 * variables. It should take points as input and output, a maximum of * 1 vertex will be written by the shader. In main(), the shader should * set output int variable named result to a sum of all the vectors' * components and emit a vertex. * - Fragment shader code can be boilerplate. * * 2. The program object consisting of these shader objects is expected to * link successfully. * * 3. Configure the uniforms to use subsequently increasing values, starting * from 1 for R component of first vector, 2 for G component of that vector, * 5 for first component of second vector, and so on. * * 4. Configure transform feedback object to capture output from result. * Draw a single point. The test succeeds if first component of the result * vector contains a valid value (bearing potentially minor precision issues * in mind) **/ class GeometryShaderMaxUniformComponentsTest : public GeometryShaderLimitsTransformFeedbackBase { public: /* Public methods */ GeometryShaderMaxUniformComponentsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxUniformComponentsTest() { } protected: /* Overriden from GeometryShaderLimitsTransformFeedbackBase */ virtual void clean(); virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, glw::GLuint& out_n_captured_varyings); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms; static const glw::GLchar* const m_geometry_shader_code_body; static const glw::GLchar* const m_vertex_shader_code; const glw::GLchar* m_geometry_shader_parts[4]; /* String used to store number of uniform vectors */ std::string m_max_uniform_vectors_string; /* Varying names */ static const glw::GLchar* const m_captured_varyings_names; /* Buffer size */ static const glw::GLuint m_buffer_size; /* Max uniform components and vectors */ glw::GLint m_max_uniform_components; glw::GLint m_max_uniform_vectors; /* Uniform location */ glw::GLint m_uniform_location; /* Uniform data */ std::vector m_uniform_data; }; /** Implementation of test case 16.2. Test description follows: * * Make sure it is possible to use as many uniform blocks as defined by * GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT * * Category: API; * Functional Test. * * Slightly modify test case 16.1 to use a similar idea to test if the * value reported for the property by the implementation is reliable: * * - Test case 16.1's ivec4s take form of as many uniform blocks as needed, * each hosting a single int. * - The result value to be calculated in the geometry shader is a sum of * all ints, stored in output int result variable. **/ class GeometryShaderMaxUniformBlocksTest : public GeometryShaderLimitsTransformFeedbackBase { public: /* Public methods */ GeometryShaderMaxUniformBlocksTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxUniformBlocksTest() { } protected: /* Overriden from GeometryShaderLimitsTransformFeedbackBase */ virtual void clean(); virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, glw::GLuint& out_n_captured_varyings); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private type */ struct _uniform_block { glw::GLuint buffer_object_id; glw::GLint data; }; /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms; static const glw::GLchar* const m_geometry_shader_code_body_str; static const glw::GLchar* const m_geometry_shader_code_body_end; static const glw::GLchar* const m_vertex_shader_code; const glw::GLchar* m_geometry_shader_parts[6]; /* String used to store uniform blocks accesses */ std::string m_uniform_block_access_string; /* String used to store number of uniform blocks */ std::string m_max_uniform_blocks_string; /* Varying names */ static const glw::GLchar* const m_captured_varyings_names; /* Buffer size */ static const glw::GLuint m_buffer_size; /* Max uniform blocks */ glw::GLint m_max_uniform_blocks; /* Uniform blocks data */ std::vector<_uniform_block> m_uniform_blocks; }; /** Implementation of test case 16.3. Test description follows: * * Make sure it is possible to use as many input components as defined by * GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT * * Category: API. * * Create a program object, attach a fragment, geometry and a vertex shader to it: * * - Fragment shader can be boilerplate; * - Vertex shader should define exactly * (GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT / 4) ivec4 output variables. * Each of the variables should be assigned a vector value of * (n, n+1, n+2, n+3) where n corresponds to "index" of the variable, * assuming the very first output variable has an "index" of 1. * - Geometry shader should define exactly * (GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT / 4) vec4 input variables. It * should accept input point geometry and output a maximum of 1 point. * It should sum up all components read from input variables and store them * in output int variable called result.. * * The test should then configure the program object to capture values of * "result" variable using transform feedback and link the program object. * * The test should now generate and bind a vertex array object, and then * draw a single point. Test succeeds if the value stored in a buffer object * configured for transform feedback storage is valid. **/ class GeometryShaderMaxInputComponentsTest : public GeometryShaderLimitsTransformFeedbackBase { public: /* Public methods */ GeometryShaderMaxInputComponentsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxInputComponentsTest() { } protected: /* Overriden from GeometryShaderLimitsTransformFeedbackBase */ virtual void clean(); virtual void getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names, glw::GLuint& out_n_captured_varyings); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void getTransformFeedbackBufferSize(glw::GLuint& out_buffer_size); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_number_of_uniforms; static const glw::GLchar* const m_geometry_shader_code_body; static const glw::GLchar* const m_vertex_shader_code_preamble; static const glw::GLchar* const m_vertex_shader_code_number_of_uniforms; static const glw::GLchar* const m_vertex_shader_code_body; const glw::GLchar* m_geometry_shader_parts[4]; const glw::GLchar* m_vertex_shader_parts[4]; /* Max input components and vectors */ glw::GLint m_max_geometry_input_components; glw::GLint m_max_geometry_input_vectors; /* String used to store number of geometry input vectors */ std::string m_max_geometry_input_vectors_string; /* Varying names */ static const glw::GLchar* const m_captured_varyings_names; /* Buffer size */ static const glw::GLuint m_buffer_size; }; /** Implementation of test case 16.4. Test description follows: * * Make sure it is possible to use as many total output components as * defined by GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT. * * Category: API. * * Let n_points be equal to: * * (GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT / GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT) * * Create a fragment, geometry and vertex shader objects: * * - Vertex shader code can be boilerplate; * - Geometry shader code should define: * * floor(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT / 4) * * output ivec4 variables. It should take points as input and output, * a maximum of n_points vertices will be written. In main(), for each * vertex, the shader should set gl_Position to: * * (-1 + (2 * vertex id + 1) / (2 * max vertices) * 2, 0, 0, 1) * * where (vertex id) corresponds to index of about-to-be-emitted vertices, * assuming the indexing starts from 0. * Each vertex should store subsequently increasing, unique values to * components of the output variables. * Geometry shader should emit as many vertices as specified. For each * output point, point size should be set to 2. * - Fragment shader code should take all aforementioned varyings as input * variables, read them, and store result int fragment as sum of all * components for all vectors passed from the geometry shader. * * For rendering, the test should use a framebuffer object, to which * a GL_R32I-based 2D texture object of resolution: * * (2*n_points, 2) * * has been attached to color attachment 0. * * The test should link the program (no linking error should be reported) * and then activate it. Having bound a vertex array object, it should then * draw n_points points. * * The test passes, if the texture attached to color attachment 0 consists * of 2x2 quads filled with the same value, that can be considered valid in * light of the description above. * The program object consisting of these shader objects is expected to link * successfully. **/ class GeometryShaderMaxOutputComponentsTest : public GeometryShaderLimitsRenderingBase { public: /* Public methods */ GeometryShaderMaxOutputComponentsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxOutputComponentsTest() { } protected: /* Methods overriden from GeometryShaderLimitsRenderingBase */ virtual void clean(); virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); virtual void getRequiredPointSize(glw::GLfloat& out_point_size); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private methods */ void prepareFragmentShader(std::string& out_shader_code) const; void prepareGeometryShader(std::string& out_shader_code) const; /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_common_shader_code_gs_fs_out; static const glw::GLchar* const m_common_shader_code_number_of_points; static const glw::GLchar* const m_common_shader_code_gs_fs_out_definitions; static const glw::GLchar* const m_fragment_shader_code_preamble; static const glw::GLchar* const m_fragment_shader_code_flat_in_ivec4; static const glw::GLchar* const m_fragment_shader_code_sum; static const glw::GLchar* const m_fragment_shader_code_body_begin; static const glw::GLchar* const m_fragment_shader_code_body_end; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_layout; static const glw::GLchar* const m_geometry_shader_code_flat_out_ivec4; static const glw::GLchar* const m_geometry_shader_code_assignment; static const glw::GLchar* const m_geometry_shader_code_body_begin; static const glw::GLchar* const m_geometry_shader_code_body_end; static const glw::GLchar* const m_vertex_shader_code; /* Storage for prepared fragment and geometry shader */ std::string m_fragment_shader_code; const glw::GLchar* m_fragment_shader_code_c_str; std::string m_geometry_shader_code; const glw::GLchar* m_geometry_shader_code_c_str; /* Framebuffer dimensions */ glw::GLuint m_texture_width; static const glw::GLuint m_texture_height; static const glw::GLuint m_texture_pixel_size; static const glw::GLuint m_point_size; /* Max number of output components */ glw::GLint m_max_output_components; glw::GLint m_max_output_vectors; glw::GLint m_max_total_output_components; glw::GLint m_n_available_vectors; glw::GLint m_n_output_points; }; /** Implementation of test case 16.5. Test description follows: * * Make sure it possible to request as many output vertices as report for * GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT. Requesting support for larger amount * of output vertices should cause the linking process to fail. * * Category: API; * Negative Test. * * Create two program objects and one boilerplate fragment & one boilerplate * vertex shader objects. * Also create two boilerplate geometry shader objects where: * * a) The first geometry shader object can output up to * GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT vertices. * b) The other geometry shader object can output up to * (GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT+1) vertices. * * 1) Program object A should be attached fragment and vertex shader * objects, as well as geometry shader A. This program object should * link successfully. * 2) Program object B should be attached fragment and vertex shader objects, * as well as geometry shader B. This program object should fail to link. **/ class GeometryShaderMaxOutputVerticesTest : public TestCaseBase { public: /* Public methods */ GeometryShaderMaxOutputVerticesTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxOutputVerticesTest() { } virtual IterateResult iterate(void); private: /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_body; static const glw::GLchar* const m_vertex_shader_code; }; /** Implementation of test case 16.6. Test description follows: * * Make sure it is possible to use as many output components as defined by * GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT * * Category: API. * * Modify test case 16.4, so that: * * * n_points is always 1; **/ class GeometryShaderMaxOutputComponentsSinglePointTest : public GeometryShaderLimitsRenderingBase { public: /* Public methods */ GeometryShaderMaxOutputComponentsSinglePointTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxOutputComponentsSinglePointTest() { } protected: /* Methods overriden from GeometryShaderLimitsRenderingBase */ virtual void clean(); virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); virtual void getRequiredPointSize(glw::GLfloat& out_point_size); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private methods */ void prepareFragmentShader(std::string& out_shader_code) const; void prepareGeometryShader(std::string& out_shader_code) const; /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_common_shader_code_gs_fs_out; static const glw::GLchar* const m_common_shader_code_gs_fs_out_definitions; static const glw::GLchar* const m_fragment_shader_code_preamble; static const glw::GLchar* const m_fragment_shader_code_flat_in_ivec4; static const glw::GLchar* const m_fragment_shader_code_sum; static const glw::GLchar* const m_fragment_shader_code_body_begin; static const glw::GLchar* const m_fragment_shader_code_body_end; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_flat_out_ivec4; static const glw::GLchar* const m_geometry_shader_code_assignment; static const glw::GLchar* const m_geometry_shader_code_body_begin; static const glw::GLchar* const m_geometry_shader_code_body_end; static const glw::GLchar* const m_vertex_shader_code; /* Storage for prepared fragment and geometry shader */ std::string m_fragment_shader_code; std::string m_geometry_shader_code; const glw::GLchar* m_fragment_shader_code_c_str; const glw::GLchar* m_geometry_shader_code_c_str; /* Framebuffer dimensions */ static const glw::GLuint m_texture_width; static const glw::GLuint m_texture_height; static const glw::GLuint m_texture_pixel_size; static const glw::GLuint m_point_size; /* Max number of output components */ glw::GLint m_max_output_components; glw::GLint m_max_output_vectors; glw::GLint m_n_available_vectors; }; /** Implementation of test case 16.7. Test description follows: * * Make sure that it is possible to access as many texture image units from * a geometry shader as reported by GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT * * Category: API; * Functional Test. * * Create as many texture objects as reported by * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT. Each texture should be made an * immutable GL_R32I 2D texture, have 1x1 resolution and be filled with * subsequently increasing intensities (starting from 1, delta: 2). Let's * name these textures "source textures" for the purpose of this test case. * * Create a program object and a fragment/geometry/vertex shader object. * Behavior of the shaders should be as follows: * * 1) Vertex shader should take gl_VertexID and calculate an unique 2D * location, that will later be used to render a 2x2 quad. The calculations * should take quad size into account, note the quads must not overlap. The * result location should be passed to geometry shader by storing it in an * output variable. The shader should also store the vertex id in a * flat-interpolated int output variable called vertex_id. * * 2) Geometry shader should accept points as input types and should emit * triangle strips with a maximum of 4 output vertices. For each output * geometry's vertex, two values should be written: * * * gl_Position obviously; * * color (stored as flat-interpolated integer); * * The shader should define as many 2D samplers as reported for the tested * property. In geometry shader's entry-point, the aforementioned 2D * location should be used to calculate vertices of a quad the shader will * emit (built using a triangle strip). Geometry shader should also write * a result of the following computation to an output color variable: * * sum(i=0..n_samplers)( (vertex_id == i) * (result of sampling 2D texture * at (0,0) using a sampler bound to texture unit i) ); * * 3) Fragment shader should take the color as passed by geometry shader * and write it to output result variable. * * These shader objects should then be compiled, attached to the program * object. The program object should be linked. Each sampler uniform should * be assigned a consecutive texture unit index, starting from 0. * * A framebuffer object should then be created, as well as a 2D GL_R32I * texture of resolution: * * (GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT*2, 2) * * The texture should be attached to the FBO's color attachment. * * A vertex array object should be created and bound. * * "Source textures" are next bound to corresponding texture units, and the * FBO should be made a draw framebuffer. The program object should be made * current and exactly GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points should * be drawn. * * Next, bind the FBO to GL_READ_FRAMEBUFFER target, read the data, and make * sure that consequent 2x2 quads are of expected intensities (epsilon to * consider: +-1). **/ class GeometryShaderMaxTextureUnitsTest : public GeometryShaderLimitsRenderingBase { public: /* Public methods */ GeometryShaderMaxTextureUnitsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxTextureUnitsTest() { } protected: /* Methods overriden from GeometryShaderLimitsRenderingBase */ virtual void clean(); virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); virtual void getRequiredPointSize(glw::GLfloat& out_point_size); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private types */ struct _texture_data { glw::GLuint texture_id; glw::GLint data; }; typedef std::vector<_texture_data> textureContainer; /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_body; static const glw::GLchar* const m_vertex_shader_code_preamble; static const glw::GLchar* const m_vertex_shader_code_body; /* Storage for vertex and geometry shader parts */ const glw::GLchar* m_geometry_shader_parts[3]; const glw::GLchar* m_vertex_shader_parts[3]; /* Framebuffer dimensions */ glw::GLuint m_texture_width; static const glw::GLuint m_texture_height; static const glw::GLuint m_texture_pixel_size; static const glw::GLuint m_point_size; /* Max number of texture units */ glw::GLint m_max_texture_units; std::string m_max_texture_units_string; /* Texture units */ textureContainer m_textures; }; /** Implementation of test case 16.8. Test description follows: * * Make sure it is possible to use as many geometry shader invocations as * defined by GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT. Verify invocation * count defaults to 1 if no number of invocations is defined in the * geometry shader. * * Category: API. * * Create a program object and: * * - A boilerplate vertex shader object; * - A geometry shader object that: * * 1) takes points on input; * 2) outputs a maximum of 3 vertices making up triangles; * 3) uses exactly GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT invocations; * 4) let: * * dx = 2.0 / GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT. * * Emit 3 vertices: * * 4a) (-1+dx*(gl_InvocationID), -1.001, 0, 1) * 4b) (-1+dx*(gl_InvocationID), 1.001, 0, 1) * 4c) (-1+dx*(gl_InvocationID+1), 1.001, 0, 1) * * - A fragment shader object that always sets green color for rasterized * fragments. * * Compile the shaders, attach them to the program object, link the program * object. * * Generate a texture object of type GL_RGBA8 type and of resolution: * * (GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT*9)x9 * * Generate a FBO and attach the texture object to its color attachment. * * Bind the FBO to GL_FRAMEBUFFER target and clear the attachments with red * color. * * Generate a vertex array object, bind it. * * Use the program object and issue a draw call for a single point. * * Read back texture object data. The test succeeds if correct amount of * triangles was rendered at expected locations. To test this: : * * * Let n = (GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT - 1); * * Let (x1, y1) = ((n) * 9, 0); * * Let (x2, y2) = ((n) * 9, 0); * * Let (x3, y3) = ((n + 1) * 9 - 1, 9 - 1); * * Triangle rendered in last invocation is described by vertices at * coordinates (x_i, y_i) where i e {1, 2, 3}. * * Centroid of this triangle is defined by (x', y') where: * * x' = floor( (x1 + x2 + x3) / 3); * y' = floor( (y1 + y2 + y3) / 3); * * * Pixel at (x', y') should be set to (0, 255, 0, 0) (allowed epsilon: 0) * * Pixel at (n*9-1, 9) should be set to red color (allowed epsilon: 0) * * Repeat this test for a geometry shader with no number of invocations * defined, in which case only one triangle should be rendered. **/ class GeometryShaderMaxInvocationsTest : public TestCaseBase { public: /* Public methods */ GeometryShaderMaxInvocationsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxInvocationsTest() { } virtual void deinit(void); virtual IterateResult iterate(void); private: /* Private methods */ void initTest(void); /* Verification of results */ bool verifyResultOfMultipleInvocationsPass(unsigned char* result_image); bool verifyResultOfSingleInvocationPass(unsigned char* result_image); /* Private fields */ /* Program and shader ids for multiple GS invocations */ glw::GLuint m_fragment_shader_id_for_multiple_invocations_pass; glw::GLuint m_geometry_shader_id_for_multiple_invocations_pass; glw::GLuint m_program_object_id_for_multiple_invocations_pass; glw::GLuint m_vertex_shader_id_for_multiple_invocations_pass; /* Program and shader ids for single GS invocation */ glw::GLuint m_fragment_shader_id_for_single_invocation_pass; glw::GLuint m_geometry_shader_id_for_single_invocation_pass; glw::GLuint m_program_object_id_for_single_invocation_pass; glw::GLuint m_vertex_shader_id_for_single_invocation_pass; /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_layout; static const glw::GLchar* const m_geometry_shader_code_layout_invocations; static const glw::GLchar* const m_geometry_shader_code_body; static const glw::GLchar* const m_vertex_shader_code; const glw::GLchar* m_geometry_shader_parts_for_multiple_invocations_pass[16]; const glw::GLchar* m_geometry_shader_parts_for_single_invocation_pass[16]; /* Max GS invocations */ glw::GLint m_max_geometry_shader_invocations; /* String used to store maximum number of GS invocations */ std::string m_max_geometry_shader_invocations_string; /* Framebuffer */ glw::GLuint m_framebuffer_object_id; glw::GLuint m_color_texture_id; /* Framebuffer dimensions */ glw::GLuint m_texture_width; static const glw::GLuint m_triangle_edge_length; static const glw::GLuint m_texture_height; static const glw::GLuint m_texture_pixel_size; /* Vertex array object */ glw::GLuint m_vertex_array_object_id; }; /** Implementation of test case 16.9. Test description follows: * * Make sure it is possible to use up to GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS * texture image units in three different stages, with an assumption that * each access to the same texture unit from a different stage counts as * a separate texture unit access. * * Category: API; * Functional Test. * * Create max(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT, GL_MAX_TEXTURE_IMAGE_UNITS) * immutable texture objects. Each texture should use GL_R32UI internal * format, have 1x1 resolution and contain an unique intensity equal to * index of the texture, where first texture object created is considered * to have index equal to 1. * * We want each stage to use at least one texture unit. Use the following * calculations to determine how many samplers should be defined for each * stage: * * 1) Vertex stage: n_vertex_smpl = max(1, * min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 2, * GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS) ). * 2) Fragment stage: n_frag_smpl = max(1, * min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - n_vertex_smpl - 1, * GL_MAX_TEXTURE_IMAGE_UNITS) ) * 3) Geometry shader: n_geom_smpl = max(1, * min(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - n_vertex_smpl - n_frag_smpl, * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT) ) * * Create a program object and fragment, geometry and vertex shader objects: * * - Vertex shader object should define exactly n_vertex_smpl 2D texture * samplers named samplerX where X stands for texture unit index that * will be accessed. It should set gl_Position to: * * (-1 + gl_VertexID / GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, -1, 0, 1) * * Vertex shader should define int output variable out_vs_vertexid storing * gl_VertexID value, and an output integer variable out_vs_vertex that * should be written result of the following computation: * * sum(i=0..n_vertex_smpl)( (gl_VertexID == i) * (value sampled from the * texture sampler samplerX)) where: X = i; * * - Geometry shader object should define exactly n_geom_smpl 2D texture * samplers named samplerX where X stands for texture unit index that * will be accessed. The geometry shader should define int input variables * out_vs_vertexid, out_vs_vertex and int output variables: * * * out_gs_vertexid - set to the value of out_vs_vertexid; * * out_gs_vertex - set to the value of out_vs_vertex; * * out_geometry that should be written result of the following computation: * * sum(i=0..n_geom_smpl)( (out_vs_vertexid == i) * (value sampled from the * texture sampler samplerX)) where: X = i; * * The geometry shader should emit exactly one point at position configured * by vertex shader. The geometry shader should take points as input. * * - Fragment shader object should define exactly n_frag_smpl 2D texture * samplers named samplerX where X stands for texture unit index that * will be accessed. The fragment shader should define int input variables * out_gs_vertexid, out_gs_vertex and out_geometry. It should define * a single int output variable result which should be written result of * the following computation: * * if (out_gs_vertex == out_geometry) * { * set to sum(i=0..n_frag_smpl)(out_gs_vertex_id == i) * (value sampled * from the texture sampler samplerX)) where: X = i; * } * else * { * set to 0. * } * * The shaders should be attached to the program object and compiled. The * program object should be linked. * * Assume: * * min_texture_image_units = min( * GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, * GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT); * * A framebuffer object should be created, along with a 2D texture object of * min_texture_image_units x 1 resolution. The texture object should be * attached to color attachment point of the FBO. Bind the framebuffer object * to GL_DRAW_FRAMEBUFFER target. * * A vertex array object should be created and bound. * * Configure the program object's uniform samplers to use consecutive texture * image units. Bind the texture objects we created at the beginning to these * texture units. Draw exactly min_texture_image_units points. * * Bind the FBO to GL_READ_FRAMEBUFFER. Read the rendered data and make sure * the result values form a (1, 2, ... min_texture_image_units) set. **/ class GeometryShaderMaxCombinedTextureUnitsTest : public GeometryShaderLimitsRenderingBase { public: /* Public methods */ GeometryShaderMaxCombinedTextureUnitsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GeometryShaderMaxCombinedTextureUnitsTest() { } protected: /* Methods overriden from GeometryShaderLimitsRenderingBase */ virtual void clean(); virtual void getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices); virtual void getFramebufferDetails(glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type, glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, glw::GLuint& out_texture_pixel_size); virtual void getRequiredPointSize(glw::GLfloat& out_point_size); virtual void getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts, glw::GLuint& out_n_fragment_shader_parts, const glw::GLchar* const*& out_geometry_shader_parts, glw::GLuint& out_n_geometry_shader_parts, const glw::GLchar* const*& out_vertex_shader_parts, glw::GLuint& out_n_vertex_shader_parts); virtual void prepareProgramInput(); virtual bool verifyResult(const void* data); private: /* Private types */ struct _texture_data { glw::GLuint texture_id; glw::GLuint data; }; typedef std::vector<_texture_data> textureContainer; /* Private fields */ /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code_preamble; static const glw::GLchar* const m_fragment_shader_code_body; static const glw::GLchar* const m_geometry_shader_code_preamble; static const glw::GLchar* const m_geometry_shader_code_body; static const glw::GLchar* const m_vertex_shader_code_preamble; static const glw::GLchar* const m_vertex_shader_code_body; /* Storage for vertex and geometry shader parts */ const glw::GLchar* m_fragment_shader_parts[3]; const glw::GLchar* m_geometry_shader_parts[3]; const glw::GLchar* m_vertex_shader_parts[3]; /* Framebuffer dimensions */ glw::GLuint m_texture_width; static const glw::GLuint m_texture_height; static const glw::GLuint m_texture_pixel_size; static const glw::GLuint m_point_size; /* Max number of texture units */ glw::GLint m_max_combined_texture_units; glw::GLint m_max_fragment_texture_units; glw::GLint m_max_geometry_texture_units; glw::GLint m_max_vertex_texture_units; glw::GLint m_min_texture_units; glw::GLint m_n_fragment_texture_units; glw::GLint m_n_geometry_texture_units; glw::GLint m_n_texture_units; glw::GLint m_n_vertex_texture_units; std::string m_n_fragment_texture_units_string; std::string m_n_geometry_texture_units_string; std::string m_n_vertex_texture_units_string; /* Texture units */ textureContainer m_textures; }; } /* glcts */ #endif // _ESEXTCGEOMETRYSHADERLIMITS_HPP