| #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 <vector> |
| |
| 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<glw::GLint> 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 |