blob: 84e2dbf2149951466bc00531b0c32b88294de924 [file] [log] [blame]
#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