blob: 31ba85c78b3a5c3965da4a8eb87b2f9b29c67d30 [file] [log] [blame]
#ifndef _GL3CTRANSFORMFEEDBACKTESTS_HPP
#define _GL3CTRANSFORMFEEDBACKTESTS_HPP
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2015-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 gl3cTransformFeedback.hpp
* \brief Transform Feedback Test Suite Interface
*/ /*-------------------------------------------------------------------*/
#include "glcTestCase.hpp"
#include "glwDefs.hpp"
#include "tcuDefs.hpp"
/* Includes. */
#include <map>
#include <string>
#include <typeinfo>
#include <vector>
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
namespace gl3cts
{
namespace TransformFeedback
{
class Tests : public deqp::TestCaseGroup
{
public:
Tests(deqp::Context& context);
~Tests(void);
virtual void init(void);
private:
Tests(const Tests& other);
Tests& operator=(const Tests& other);
};
/** APIErrors
*
* Verifies if errors are generated as specified.
* Four test shall be run:
* - Test api errors defined in GL_EXT_transform_feedback.
* - Test api errors defined in GL_ARB_transform_feedback2.
* - Test api errors defined in GL_ARB_transform_feedback3.
* - Test api errors defined in GL_ARB_transform_feedback_instanced.
*/
class APIErrors : public deqp::TestCase
{
public:
APIErrors(deqp::Context& context);
~APIErrors(void);
IterateResult iterate(void);
private:
deqp::Context& m_context;
static const glw::GLchar* m_tessellation_control_shader;
static const glw::GLchar* m_tessellation_evaluation_shader;
static const glw::GLchar* m_geometry_shader;
static const glw::GLchar* s_vertex_shader_with_input_output;
static const glw::GLchar* s_vertex_shader_with_output;
static const glw::GLchar* s_vertex_shader_without_output;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* m_varying_name;
static const glw::GLfloat m_buffer_1_data[];
static const glw::GLsizei m_buffer_1_size;
glw::GLuint m_buffer_0;
glw::GLuint m_buffer_1;
glw::GLuint m_vertex_array_object;
glw::GLuint m_transform_feedback_object_0;
glw::GLuint m_transform_feedback_object_1;
glw::GLuint m_query_object;
glw::GLuint m_program_id_with_input_output;
glw::GLuint m_program_id_with_output;
glw::GLuint m_program_id_without_output;
glw::GLuint m_program_id_with_geometry_shader;
glw::GLuint m_program_id_with_tessellation_shaders;
/** Check the following if EXT_transform_feedback is supported or context is
* at least 3.0:
*
* - INVALID_VALUE is generated by BindBufferRange, BindBufferOffset and
* BindBufferBase when <index> is greater or equal to
* MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS;
* - INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
* when <size> is less or equal to zero;
* - INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
* when <offset> is not word-aligned;
* - INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
* when <size> is not word-aligned;
* - INVALID_OPERATION is generated by BindBufferRange, BindBufferOffset and
* BindBufferBase when <target> is TRANSFORM_FEEDBACK_BUFFER and transform
* feedback is active;
* - INVALID_OPERATION is generated by UseProgram when transform feedback is
* active;
* - INVALID_OPERATION is generated by LinkProgram when <program> is currently
* active and transform feedback is active;
* - INVALID_OPERATION is generated by BeginTransformFeedback when transform
* feedback is active;
* - INVALID_OPERATION is generated by EndTransformFeedback when transform
* feedback is inactive;
* - INVALID_OPERATION is generated by draw command when generated primitives
* type does not match <primitiveMode>;
* - INVALID_OPERATION is generated by BeginTransformFeedback when any binding
* point used by XFB does not have buffer bound;
* - INVALID_OPERATION is generated by BeginTransformFeedback when no program
* is active;
* - INVALID_OPERATION is generated by BeginTransformFeedback when no variable
* are specified to be captured in the active program;
* - INVALID_VALUE is generated by TransformFeedbackVaryings when <program> is
* not id of the program object;
* - INVALID_VALUE is generated by TransformFeedbackVaryings when <bufferMode>
* is SEPARATE_ATTRIBS and <count> is exceeds limits;
* - IVALID_VALUE is generated by GetTransformFeedbackVarying when <index> is
* greater than or equal to TRANSFORM_FEEDBACK_VARYINGS;
* - INVALID_VALUE is generated by GetIntegerIndexdv when <index> exceeds the
* limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is one of the
* following:
* * TRANSFORM_FEEDBACK_BUFFER_BINDING,
* * TRANSFORM_FEEDBACK_BUFFER_START,
* * TRANSFORM_FEEDBACK_BUFFER_SIZE;
* - INVALID_VALUE is generated by GetBooleanIndexedv when <index> exceeds the
* limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is
* TRANSFORM_FEEDBACK_BUFFER_BINDING.
*/
bool testExtension1(void);
/** Check the following if ARB_transform_feedback2 is supported or context is
* at least 4.0:
*
* - INVALID_OPERATION is generated by BindTransformFeedback if current
* transform feedback is active and not paused;
* - INVALID_OPERATION is generated by DeleteTransformFeedbacks if any of <ids>
* is active;
* - INVALID_OPERATION is generated by PauseTransformFeedback if current
* transform feedback is not active or paused;
* - INVALID_OPERATION is generated by ResumeTransformFeedback if current
* transform feedback is not active or not paused;
* - No error is generated by draw command when transform feedback is paused
* and primitive modes do not match;
* - No error is generated by UseProgram when transform feedback is paused;
* - INVALID_OPERATION is generated by LinkProgram when <program> is used by
* some transform feedback object that is currently not active;
* - INVALID_VALUE is generated by DrawTransformFeedback if <id> is not name of
* transform feedback object;
* - INVALID_OPERATION is generated by DrawTransformFeedback when
* EndTransformFeedback was never called for the object named <id>.
*/
bool testExtension2(void);
/** Check the following if ARB_transform_feedback3 is supported or context is
* at least 4.0:
*
* - INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
* GetQueryIndexediv when <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN and
* <index> exceeds limits of MAX_VERTEX_STREAMS;
* - INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
* GetQueryIndexediv when <target> is PRIMITIVES_GENERATED and <index> exceeds
* limits of MAX_VERTEX_STREAMS;
* - INVALID_OPERATION is generated by EndQueryIndexed when name of active
* query at <index> of <target> is zero;
* - INVALID_VALUE is generated by DrawTransformFeedbackStream when <stream>
* exceeds limits of MAX_VERTEX_STREAMS;
* - INVALID_OPERATION is generated by TransformFeedbackVaryings when
* <varyings> contains any of the special names while <bufferMode> is not
* INTERLEAVED_ATTRIBS;
* - INVALID_OPERATION is generated by TransformFeedbackVaryings when
* <varyings> contains more "gl_NextBuffer" entries than allowed limit of
* MAX_TRANSFORM_FEEDBACK_BUFFERS;
*/
bool testExtension3(void);
/** Check the following if ARB_transform_feedback_instanced is supported or
* context is at least 4.2:
*
* - INVALID_ENUM is generated by DrawTransformFeedbackInstanced and
* DrawTransformFeedbackStreamInstanced if <mode> is invalid;
* - INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
* DrawTransformFeedbackStreamInstanced if <mode> does not match geometry
* shader;
* - INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
* DrawTransformFeedbackStreamInstanced if <mode> does not match tessellation;
* - INVALID_VALUE is generated by DrawTransformFeedbackStreamInstanced if
* <stream> is greater than or equal to MAX_VERTEX_STREAMS;
* - INVALID_VALUE is generated by DrawTransformFeedbackInstanced and
* DrawTransformFeedbackStreamInstanced if <id> is not name of transform
* feedback object;
* - INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
* DrawTransformFeedbackStreamInstanced if a non-zero buffer object name is
* bound to an enabled array and the buffer object's data store is currently
* mapped;
* - INVALID_OPERATION is generated if by DrawTransformFeedbackStreamInstanced
* if EndTransformFeedback was never called for the object named <id>.
*/
bool testInstanced(void);
typedef GLW_APICALL void (GLW_APIENTRY *BindBufferOffsetEXT_ProcAddress)(glw::GLenum target, glw::GLuint index, glw::GLuint buffer,
glw::GLintptr offset);
typedef GLW_APICALL void (GLW_APIENTRY *GetIntegerIndexedvEXT_ProcAddress)(glw::GLenum param, glw::GLuint index, glw::GLint* values);
typedef GLW_APICALL void (GLW_APIENTRY *GetBooleanIndexedvEXT_ProcAddress)(glw::GLenum param, glw::GLuint index, glw::GLboolean* values);
BindBufferOffsetEXT_ProcAddress m_glBindBufferOffsetEXT;
GetIntegerIndexedvEXT_ProcAddress m_glGetIntegerIndexedvEXT;
GetBooleanIndexedvEXT_ProcAddress m_glGetBooleanIndexedvEXT;
};
/** LinkingErrors
*
* Verifies that linker reports errors as specified.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Check if link process fails under the following conditions:
* - <count> specified by TransformFeedbackVaryings is non-zero and program has
* neither vertex nor geometry shader;
* - <varyings> specified by TransformFeedbackVaryings contains name of
* variable that is not available for capture;
* - <varyings> specified by TransformFeedbackVaryings contains name of
* variable more than once;
* - number of components specified to capture exceeds limits
* MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or
* MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS.
*/
class LinkingErrors : public deqp::TestCase
{
public:
LinkingErrors(deqp::Context& context);
~LinkingErrors(void);
IterateResult iterate(void);
private:
deqp::Context& m_context;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* s_vertex_shader_template;
static const glw::GLchar* s_valid_transform_feedback_varying;
static const glw::GLchar* s_invalid_transform_feedback_varying;
static const glw::GLchar* s_repeated_transform_feedback_varying[];
static const glw::GLsizei s_repeated_transform_feedback_varying_count;
bool testNoVertexNoGeometry(void);
bool testInvalidVarying(void);
bool testRepeatedVarying(void);
bool testTooManyVaryings(void);
};
/** Limits
*
* Verifies that limits reported by API are as expected.
*
* Check the following if EXT_transform_feedback is supported or context is at
* least 3.0:
* - MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64,
* - MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4,
* - MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4.
*
* Check the following if ARB_transform_feedback3 is supported or context is at
* least 4.0:
* - MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4,
* - MAX_VERTEX_STREAMS is at least 1.
*/
class Limits : public deqp::TestCase
{
public:
Limits(deqp::Context& context);
~Limits(void);
IterateResult iterate(void);
private:
deqp::Context& m_context;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* s_vertex_shader;
static const glw::GLint s_min_value_of_max_transform_feedback_interleaved_components;
static const glw::GLint s_min_value_of_max_transform_feedback_separate_attribs;
static const glw::GLint s_min_value_of_max_transform_feedback_separate_components;
static const glw::GLint s_min_value_of_max_transform_feedback_buffers;
static const glw::GLint s_min_value_of_max_vertex_streams;
bool test_max_transform_feedback_interleaved_components(void);
bool test_max_transform_feedback_separate_attribs(void);
bool test_max_transform_feedback_separate_components(void);
bool test_max_transform_feedback_buffers(void);
bool test_max_vertex_streams(void);
};
/** CaptureVertexInterleaved
*
* Verifies if geometry processed with vertex shader is captured as expected in
* interleaved mode.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Steps:
* - prepare program consisting of vertex and fragment shader; Vertex shader
* should assign all MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS components;
* One of the variables must be a position; Position should be set to one of
* corners, based on gl_VertexID: 0 - top left, 1 - top right, 2 - bottom left
* and 3 - bottom right; Rest of components should be covered with output
* variables of type vec4; Fragment shader should accept all outputs from
* vertex shader as inputs and use them to calculate non-black output color;
* - instruct implementation to capture all outputs defined by vertex shader;
* Use interleaved mode;
* - prepare and set buffer to store captured geometry;
* - prepare, set and clean frame-buffer with black color;
* - execute BeginTransformFeedback;
* - execute DrawElements;
* - execute EndTransformFeedback;
* - inspect contents of frame-buffer to check if rasterization was done
* correctly;
* - inspect TRANSFORM_FEEDBACK_BUFFER_START and
* TRANSFORM_FEEDBACK_BUFFER_SIZE;
* - inspect contents of the buffer to check if geometry was captured
* correctly.
*
* Test the following BindBuffer routines:
* - BindBufferRange - use non-zero offset,
* - BindBufferOffset - use non-zero offset,
* - BindBufferBase.
*
* Test the following primitive types:
* - GL_POINTS - use these indices: [0, 1, 2, 3]; All corner pixels should be
* set to specific colors; XFB should contain four vertices;
* - GL_LINES - use these indices: [0, 1, 2, 3]; Top and bottom edges should be
* drawn; XFB should contain four vertices;
* - GL_LINE_LOOP - use these indices: [0, 1, 3, 2]; All four edges should be
* drawn; XFB should contain eight vertices;
* - GL_LINE_STRIP - use these indices: [0, 1, 3, 2]; Top, right and bottom
* edge should be drawn; XFB should contain six vertices;
* - GL_TRIANGLES - use these indices: [2, 0, 1, 2, 1, 3]; Whole image should
* be drawn; XFB should contain six vertices;
* - GL_TRIANGLE_STRIP - use these indices: [0, 1, 2, 3]; Whole image should
* be drawn; XFB should contain six vertices;
* - GL_TRIANGLE_FAN - use these indices: [2, 0, 1, 3]; Whole image should
* be drawn; XFB should contain six vertices.
*
* Number of components that can be passed to rasterization must not exceed
* MAX_VARYING_COMPONENTS.
*/
class CaptureVertexInterleaved : public deqp::TestCase
{
public:
CaptureVertexInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
~CaptureVertexInterleaved(void);
virtual IterateResult iterate(void);
protected:
deqp::Context& m_context;
glw::GLuint m_program;
glw::GLuint m_framebuffer;
glw::GLuint m_renderbuffer;
glw::GLuint m_buffer;
glw::GLuint m_buffer_size;
glw::GLuint m_vertex_array_object;
glw::GLint m_max_transform_feedback_components;
glw::GLenum m_attrib_type;
glw::GLuint m_max_vertices_drawn;
typedef GLW_APICALL void (GLW_APIENTRY *BindBufferOffsetEXT_ProcAddress)(glw::GLenum target, glw::GLuint index, glw::GLuint buffer,
glw::GLintptr offset);
BindBufferOffsetEXT_ProcAddress m_glBindBufferOffsetEXT;
static const glw::GLchar* s_vertex_shader_source_code_template;
static const glw::GLchar* s_fragment_shader_source_code;
static const glw::GLuint s_max_element_indices_count = 6;
static const glw::GLuint s_element_indices[][s_max_element_indices_count];
static const glw::GLuint s_primitive_cases_count;
static const glw::GLuint s_element_indices_counts[];
static const glw::GLenum s_primitive_cases[];
static const glw::GLenum s_primitive_cases_xfb[];
static const glw::GLuint s_framebuffer_size;
static const glw::GLfloat s_rasterization_epsilon;
static const glw::GLuint s_max_vertex_id = 4;
enum BindBufferCase
{
BIND_BUFFER_BASE_CASE,
BIND_BUFFER_RANGE_CASE,
BIND_BUFFER_OFFSET_CASE,
BIND_BUFFER_CASES_COUNT
};
virtual void fetchLimits(void);
virtual void buildProgram(void);
void createFramebuffer(void);
virtual void createTransformFeedbackBuffer(void);
void createVertexArrayObject(void);
virtual void draw(glw::GLuint primitive_case);
virtual bool checkFramebuffer(glw::GLuint primitive_case);
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
virtual void bindBuffer(BindBufferCase bind_case);
virtual void clean(void);
virtual void cleanBuffer(void);
};
/** CaptureGeometryInterleaved
*
* Verifies if geometry processed with geometry shader is captured as expected
* in interleaved mode.
*
* Test should be run if either EXT_transform_feedback is supported or context
* is at least 3.0 and either ARB_geometry_shader4 is supported or context is
* at least 3.2.
*
* Modify CaptureVertexInterleaved test in the following aspects:
* - outputs definition and assignment is done in geometry instead of
* vertex shader;
* - vertex shader can be blank;
* - use DrawArrays instead of DrawElements, draw single vertex with GL_POINTS.
*
* Test the following output primitive types for geometry shader:
* - points - emit vertices as in GL_POINTS case;
* - line_strip - emit vertices as in GL_LINE_STRIP case;
* - triangle_strip - emit vertices as in GL_TRIANGLE_STRIP case.
*
* Number of components written by geometry shader must not exceed
* MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS.
*/
class CaptureGeometryInterleaved : virtual public CaptureVertexInterleaved
{
public:
CaptureGeometryInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
~CaptureGeometryInterleaved(void);
virtual IterateResult iterate(void);
protected:
virtual void fetchLimits(void);
using CaptureVertexInterleaved::buildProgram;
virtual void buildProgram(glw::GLuint primitive_case);
virtual void draw(glw::GLuint primitive_case);
static const glw::GLchar* s_geometry_shader_source_code_template;
static const glw::GLchar* s_blank_vertex_shader_source_code;
static const glw::GLchar* s_geometry_interleaved_primitive_cases[];
static const glw::GLenum s_geometry_interleaved_primitive_cases_xfb[];
static const glw::GLuint s_geometry_interleaved_primitive_cases_count;
};
/** CaptureVertexSeparate
*
* Verifies if geometry processed with vertex shader is captured as expected in
* separate mode.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Modify CaptureVertexInterleaved test in the following aspects:
* - use transform feedback in separate mode.
*
* Separate mode require one buffer per captured variable.
*
* Number of attributes and components that can be captured is limited by:
* - MAX TRANSFORM FEEDBACK SEPARATE ATTRIBS,
* - MAX TRANSFORM FEEDBACK SEPARATE COMPONENTS.
*/
class CaptureVertexSeparate : virtual public CaptureVertexInterleaved
{
public:
CaptureVertexSeparate(deqp::Context& context, const char* test_name, const char* test_description);
protected:
glw::GLuint* m_buffers;
glw::GLint m_max_transform_feedback_separate_attribs;
virtual void fetchLimits(void);
virtual void createTransformFeedbackBuffer(void);
virtual void bindBuffer(BindBufferCase bind_case);
virtual void cleanBuffer(void);
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
};
/** CaptureGeometrySeparate
*
* Verifies if geometry processed with geometry shader is captured as expected
* in separate mode.
*
* Test should be run if either EXT_transform_feedback is supported or context
* is at least 3.0 and either ARB_geometry_shader4 is supported or context is
* at least 3.2.
*
* Modify CaptureGeometryInterleaved test in the following aspects:
* - use transform feedback in separate mode.
*
* Separate mode require one buffer per captured variable.
*
* Number of attributes and components that can be captured is limited by:
* - MAX TRANSFORM FEEDBACK SEPARATE ATTRIBS,
* - MAX TRANSFORM FEEDBACK SEPARATE COMPONENTS.
*/
class CaptureGeometrySeparate : public CaptureGeometryInterleaved, virtual public CaptureVertexSeparate
{
public:
CaptureGeometrySeparate(deqp::Context& context, const char* test_name, const char* test_description);
virtual IterateResult iterate(void)
{
return CaptureGeometryInterleaved::iterate();
};
protected:
glw::GLuint* m_buffers;
glw::GLint m_max_transform_feedback_separate_attribs;
virtual void draw(glw::GLenum primitive_type)
{
CaptureGeometryInterleaved::draw(primitive_type);
};
virtual void fetchLimits(void)
{
CaptureVertexSeparate::fetchLimits();
};
virtual void createTransformFeedbackBuffer(void)
{
CaptureVertexSeparate::createTransformFeedbackBuffer();
};
virtual void bindBuffer(BindBufferCase bind_case)
{
CaptureVertexSeparate::bindBuffer(bind_case);
};
virtual void cleanBuffer(void)
{
CaptureVertexSeparate::cleanBuffer();
};
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type)
{
return CaptureVertexSeparate::checkTransformFeedbackBuffer(bind_case, primitive_type);
};
};
/** GetXFBVaryingVertexInterleaved
*
* Verifies if varyings captured from vertex stage are correctly reported in
* interleaved mode.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Steps:
* - prepare program consisting of vertex and fragment shader; Vertex shader
* should define and assign maximum allowed number of varyings of tested type;
* Fragment shader can be blank;
* - instruct implementation to capture all outputs defined by vertex shader;
* Use interleaved mode;
* - inspect all captured varying with GetTransformFeedbackVarying;
* - inspect TRANSFORM_FEEDBACK_VARYINGS;
* - inspect TRANSFORM_FEEDBACK_BUFFER_MODE;
* - inspect TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH.
*
* Test all valid types.
*
*
* GetXFBVaryingGeometryInterleaved
*
* Verifies if varyings captured from geometry stage are correctly reported in
* interleaved mode.
*
* Test should be run if either EXT_transform_feedback is supported or context
* is at least 3.0 and either ARB_geometry_shader4 is supported or context is
* at least 3.2.
*
* Modify GetXFBVaryingVertexInterleaved test in the following aspects:
* - outputs definition and assignment is done in geometry instead of
* vertex shader;
* - vertex shader can be blank;
*
*
* GetXFBVaryingVertexSeparate
*
* Verifies if varyings captured from vertex stage are correctly reported in
* separate mode.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Modify CaptureGeometryInterleaved test in the following aspects:
* - use transform feedback in separate mode.
*
* Separate mode require one buffer per captured variable.
*
*
* GetXFBVaryingGeometrySeparate
*
* Verifies if varyings captured from geometry stage are correctly reported in
* separate mode.
*
* Test should be run if either EXT_transform_feedback is supported or context
* is at least 3.0 and either ARB_geometry_shader4 is supported or context is
* at least 3.2.
*
* Modify GetXFBVaryingGeometryInterleaved test in the following aspects:
* - use transform feedback in separate mode.
*
* Separate mode require one buffer per captured variable.
*/
class CheckGetXFBVarying : public deqp::TestCase
{
public:
CheckGetXFBVarying(deqp::Context& context, const char* test_name, const char* test_description);
~CheckGetXFBVarying(void);
virtual IterateResult iterate(void);
private:
deqp::Context& m_context;
glw::GLint m_max_xfb_interleaved_components;
glw::GLint m_max_xfb_separate_attributes;
glw::GLint m_max_xfb_separate_components;
glw::GLint m_max_varying_components;
glw::GLint m_max_varying_vectors;
glw::GLint m_max_geometry_total_output_components;
void fetchLimits(void);
glw::GLuint numberOfAttributes(glw::GLuint capture_way, glw::GLuint shader_case, glw::GLuint varying_type);
glw::GLuint buildProgram(glw::GLuint capture_way, glw::GLuint shader_case, glw::GLuint varying_type,
glw::GLuint number_of_attributes);
bool check(glw::GLuint program, glw::GLuint capture_way, glw::GLuint shader_case, glw::GLuint varying_type,
glw::GLuint number_of_attributes);
static const glw::GLchar* s_generic_fragment_shader;
static const struct ShaderCase
{
const glw::GLchar* vertex_shader;
const glw::GLchar* geometry_shader;
} s_shader_cases[];
static const glw::GLuint s_shader_cases_count;
static const struct VaryingType
{
const glw::GLenum type;
const glw::GLchar* name;
const glw::GLuint components_count;
const bool float_component;
} s_varying_types[];
static const glw::GLuint s_varying_types_count;
static const glw::GLenum s_capture_ways[];
static const glw::GLuint s_capture_ways_count;
};
/** QueryVertexInterleaved
*
* Verifies if queries are performed as expected when geometry is captured from
* vertex stage in interleaved mode.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Modify CaptureVertexInterleaved test in the following aspects:
* - buffer used as storage for captured geometry should be too small to fit
* all emitted vertices;
* - execute BeginQuery for PRIMITIVES_GENERATED and
* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
* after draw call.
*
* Test pass if results of queries are correct.
*/
class QueryVertexInterleaved : public CaptureVertexInterleaved
{
public:
QueryVertexInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
protected:
glw::GLuint m_query_object;
virtual void createTransformFeedbackBuffer(void);
virtual void draw(glw::GLuint primitive_case);
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
virtual void clean(void);
};
/** QueryGeometryInterleaved
*
* Verifies if queries are performed as expected when geometry is captured from
* geometry stage in interleaved mode.
*
* Test should be run if either EXT_transform_feedback is supported or context
* is at least 3.0 and either ARB_geometry_shader4 is supported or context is
* at least 3.2.
*
* Modify CaptureGeometryInterleaved test in the following aspects:
* - buffer used as storage for captured geometry should be too small to fit
* all emitted vertices;
* - execute BeginQuery for PRIMITIVES_GENERATED and
* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
* after draw call.
*
* Test pass if results of queries are correct.
*/
class QueryGeometryInterleaved : public CaptureGeometryInterleaved
{
public:
QueryGeometryInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
protected:
glw::GLuint m_query_object;
virtual void createTransformFeedbackBuffer(void);
virtual void draw(glw::GLuint primitive_case);
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
virtual void clean(void);
};
/** QueryVertexSeparate
*
* Verifies if queries are performed as expected when geometry is captured from
* vertex stage in separate mode.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Modify CaptureVertexSeparate test in the following aspects:
* - buffers used as storage for captured geometry should be too small to fit
* all emitted vertices;
* - execute BeginQuery for PRIMITIVES_GENERATED and
* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
* after draw call;
* - use transform feedback in separate mode.
*
* Separate mode require one buffer per captured variable.
*
* Test pass if results of queries are correct.
*/
class QueryVertexSeparate : public CaptureVertexSeparate
{
public:
QueryVertexSeparate(deqp::Context& context, const char* test_name, const char* test_description);
protected:
glw::GLuint m_query_object;
virtual void createTransformFeedbackBuffer(void);
virtual void draw(glw::GLuint primitive_case);
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
virtual void clean(void);
};
/** QueryGeometrySeparate
*
* Verifies if queries are performed as expected when geometry is captured from
* geometry stage in separate mode.
*
* Test should be run if either EXT_transform_feedback is supported or context
* is at least 3.0 and either ARB_geometry_shader4 is supported or context is
* at least 3.2.
*
* Modify CaptureGeometrySeparate test in the following aspects:
* - buffers used as storage for captured geometry should be too small to fit
* all emitted vertices;
* - execute BeginQuery for PRIMITIVES_GENERATED and
* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN before draw is executed; End queries
* after draw call;
* - use transform feedback in separate mode.
*
* Separate mode require one buffer per captured variable.
*
* Test pass if results of queries are correct.
*/
class QueryGeometrySeparate : public CaptureGeometrySeparate
{
public:
QueryGeometrySeparate(deqp::Context& context, const char* test_name, const char* test_description);
protected:
glw::GLuint m_query_object;
virtual void createTransformFeedbackBuffer(void);
virtual void draw(glw::GLuint primitive_case);
virtual bool checkTransformFeedbackBuffer(BindBufferCase bind_case, glw::GLenum primitive_type);
virtual void clean(void);
};
/** DiscardVertex
*
* Verifies if rasterization is discarded when geometry is captured from vertex
* stage.
*
* Test should be run if EXT_transform_feedback is supported or context is
* at least 3.0.
*
* Modify CaptureVertexInterleaved test in the following aspects:
* - disable rasterization before draw call;
* - it is expected that framebuffer contents will not change, while XFB buffer
* is modified.
*/
class DiscardVertex : public CaptureVertexInterleaved
{
public:
DiscardVertex(deqp::Context& context, const char* test_name, const char* test_description);
protected:
virtual void draw(glw::GLuint primitive_case);
virtual bool checkFramebuffer(glw::GLuint primitive_case);
};
/** DiscardGeometry
*
* Verifies if rasterization is discarded when geometry is captured from
* geometry stage.
*
* Test should be run if EXT_transform_feedback is supported or context is at least 3.0.
* Test should be run if ARB_geometry_shader4 is supported or context is at least 3.2.
*
* Modify CaptureGeometryInterleaved test in the following aspects:
* - disable rasterization before draw call;
* - it is expected that framebuffer contents will not change, while XFB buffer
* is modified.
*/
class DiscardGeometry : public CaptureGeometryInterleaved
{
public:
DiscardGeometry(deqp::Context& context, const char* test_name, const char* test_description);
protected:
virtual void draw(glw::GLuint primitive_case);
virtual bool checkFramebuffer(glw::GLuint primitive_case);
};
/** DrawXFB
*
* Verifies that transform feedback objects can be used to draw.
*
* Test should be executed if ARB_transform_feedback2 is supported or context
* is at least 4.0.
*
* Steps:
* - prepare two programs consisting of vertex shader which will:
* * output position based on gl_VertexID:
* * output color by passing value of uniform;
* First program should use the following positions:
* ID | X | Y
* 0 | -1 | -1
* 1 | -1 | 1
* 2 | 1 | 1
* Second program should use the following positions:
* 0 | -1 | -1
* 1 | 1 | 1
* 2 | 1 | -1
* - prepare three XFB objects and corresponding buffers for captured geometry;
* Each XFB should capture position and color from both programs;
* - activate first program;
* - for each XFB object:
* * set uniform to color corresponding with XFB;
* * activate XFB;
* * execute DrawArrays to draw three points starting at 0;
* * pause XFB;
* - inspect TRANSFORM_FEEDBACK_BUFFER_PAUSED and
* TRANSFORM_FEEDBACK_BUFFER_ACTIVE;
* - activate second program;
* - for each XFB object:
* * set uniform to color corresponding with XFB;
* * resume XFB;
* * execute DrawArrays to draw three points starting at 0;
* * end XFB;
* - inspect TRANSFORM_FEEDBACK_BUFFER_PAUSED and
* TRANSFORM_FEEDBACK_BUFFER_ACTIVE;
* - prepare program consisting of vertex and fragment stage; Vertex shader
* should pass position and color; Fragment stage should pass color;
* - set program;
* - set vertex array to match layout of XFB;
* - for each XFB:
* * prepare and clean framebuffer;
* * execute DrawTransformFeedback to draw triangles;
* * inspect contents of framebuffer;
*
* It is expected that drawn images will be filled with color set via uniform
* variables.
*
* Repeat steps for both interleaved and separate modes.
*/
class DrawXFB : public deqp::TestCase
{
public:
DrawXFB(deqp::Context& context, const char* test_name, const char* test_description);
~DrawXFB(void);
virtual IterateResult iterate(void);
protected:
static const glw::GLchar* s_vertex_shader_xfb;
static const glw::GLchar* s_vertex_shader_draw;
static const glw::GLchar* s_fragment_shader;
static const glw::GLuint s_xfb_varyings_count = 2;
static const glw::GLchar* s_xfb_varyings[s_xfb_varyings_count];
static const glw::GLuint s_vertex_count = 3;
static const glw::GLenum s_capture_modes[];
static const glw::GLuint s_capture_modes_count;
static const glw::GLuint s_capture_size = s_vertex_count * sizeof(glw::GLfloat) * 4 /* number of components */ *
s_xfb_varyings_count * 2 /* number of programs */;
static const glw::GLuint s_view_size = 2;
static const glw::GLuint s_xfb_count = 3;
static const glw::GLfloat s_colours[s_xfb_count][4];
deqp::Context& m_context;
glw::GLuint m_program_id_xfb;
glw::GLuint m_program_id_draw;
glw::GLuint m_xfb_id[s_xfb_count];
glw::GLuint m_bo_id[s_xfb_count];
glw::GLuint m_fbo_id;
glw::GLuint m_rbo_id;
glw::GLuint m_vao_id;
void prepare(glw::GLenum capture_mode);
void bindXFB(glw::GLuint xfb_id);
void bindVAO(glw::GLuint vao_id);
void bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id);
void bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode, glw::GLuint bo_id);
void useProgram(glw::GLuint program_id);
void useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g, glw::GLfloat b, glw::GLfloat a);
void useGeometrySet(glw::GLuint program_id, bool invert_sign);
void drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb);
void drawToFramebuffer(glw::GLuint xfb_id);
bool checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b, glw::GLfloat a);
bool inspectXFBState(bool shall_be_paused, bool shall_be_active);
void clean();
};
/** DrawXFBFeedback
*
* Verifies that data captured with XFB can be used as source for next capture.
*
* Test should be executed if ARB_transform_feedback2 is supported or context
* is at least 4.0.
*
* Steps:
* - prepare program consisting of vertex shader which pass position from input
* attribute to gl_Position multiplying it by 2.0;
* - instruct implementation to capture geometry in interleaved mode;
* - prepare source buffer;
* - prepare buffer to capture geometry;
* - begin transform feedback;
* - draw one vertex using DrawArrays;
* - end transform feedback;
* - swap buffer
* - begin transform feedback;
* - draw using DrawTransformFeedback;
* - end transform feedback;
* - swap buffer
* - begin transform feedback;
* - draw using DrawTransformFeedback;
* - end transform feedback;
* - map last captured buffer, expect position vector multiplied by value 8;
*/
class DrawXFBFeedback : public deqp::TestCase
{
public:
DrawXFBFeedback(deqp::Context& context, const char* test_name, const char* test_description);
~DrawXFBFeedback(void);
virtual IterateResult iterate(void);
protected:
static const glw::GLchar* s_vertex_shader;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* s_xfb_varying;
static const glw::GLchar* s_attrib;
static const glw::GLuint s_draw_vertex_count;
static const glw::GLfloat s_initial_data[];
static const glw::GLuint s_bo_count = 2;
static const glw::GLuint s_bo_size;
deqp::Context& m_context;
glw::GLuint m_program_id;
glw::GLuint m_vao_id[s_bo_count];
glw::GLuint m_xfb_id;
glw::GLuint m_bo_id[s_bo_count];
glw::GLuint m_source_bo_index;
void prepareAndBind();
void draw(bool is_first_draw);
void swapBuffers();
bool check();
void clean();
};
/** DrawXFBStream
*
* Verifies that vertex stream captured with transform feedback can be used to
* draw.
*
* Test should be executed if both ARB_transform_feedback3 and ARB_gpu_shader5
* are supported or context is at least 4.0.
* This test is not supported if MAX_VERTEX_STREAMS is less than 2.
*
* Steps:
* - prepare program consisting of vertex and geometry shaders; Geometry shader
* should output full-screen quad made of two triangles; First triangle should
* be emitted to first vertex stream; Second triangle should be emitted to the
* second vertex stream; Vertex shader can be blank;
* - prepare buffers to capture geometry;
* - instruct implementation to capture geometry in interleaved mode;
* - begin XFB;
* - begin indexed query for PRIMITIVES_GENERATED and
* TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN for both vertex streams;
* - draw single vertex;
* - end queries;
* - end XFB;
* - inspect results of queries;
* - prepare program consisting of vertex and fragment shaders; Vertex stage
* should pass position from input to output; Fragment shader should output
* white color;
* - prepare and clean framebuffer;
* - set vertex array layout to match data captured by XFB;
* - execute DrawTransformFeedbackStream to draw triangle from first stream;
* - execute DrawTransformFeedbackStream to draw triangle from second stream;
* - inspect contents of framebuffer, it is expected to be filled with white
* color.
*/
class DrawXFBStream : public deqp::TestCase
{
public:
DrawXFBStream(deqp::Context& context, const char* test_name, const char* test_description);
~DrawXFBStream(void);
virtual IterateResult iterate(void);
private:
static const glw::GLchar* s_vertex_shader_pass;
static const glw::GLchar* s_vertex_shader_blank;
static const glw::GLchar* s_geometry_shader;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* s_xfb_varyings[];
static const glw::GLuint s_xfb_varyings_count;
static const glw::GLuint s_bo_ids_count = 2;
static const glw::GLuint s_qo_ids_count = 4;
static const glw::GLuint s_bo_size;
static const glw::GLuint s_view_size;
deqp::Context& m_context;
glw::GLuint m_program_id_generate;
glw::GLuint m_program_id_draw;
glw::GLuint m_vao_id;
glw::GLuint m_xfb_id;
glw::GLuint m_bo_id[s_bo_ids_count];
glw::GLuint m_fbo_id;
glw::GLuint m_rbo_id;
glw::GLuint m_qo_id[s_qo_ids_count];
void prepareObjects();
void setupVertexArray(glw::GLuint bo_id);
void useProgram(glw::GLuint program_id);
void drawForXFB();
bool inspectQueries();
void drawForFramebuffer(glw::GLuint stream);
bool check();
void clean();
};
/** CaptureSpecialInterleaved
*
* Verifies that special variable names are respected.
*
* Test should be executed if ARB_transform_feedback3 is supported or context
* is at least 4.0.
*
* Steps:
* - prepare program consisting of vertex shader which outputs four variables;
* - set up XFB to capture the following <varyings>:
* * variable_1,
* * gl_SkipComponents4,
* * variable_2,
* * gl_NextBuffer,
* * variable_3,
* * gl_SkipComponents4,
* * variable_4;
* - begin XFB;
* - draw two vertices;
* - end XFB;
* - verify that captured geometry is correct.
*/
class CaptureSpecialInterleaved : public deqp::TestCase
{
public:
CaptureSpecialInterleaved(deqp::Context& context, const char* test_name, const char* test_description);
~CaptureSpecialInterleaved(void);
virtual IterateResult iterate(void);
private:
static const glw::GLchar* s_vertex_shader;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* s_xfb_varyings[];
static const glw::GLuint s_xfb_varyings_count;
static const glw::GLuint s_bo_ids_count = 2;
static const glw::GLuint s_bo_size;
deqp::Context& m_context;
glw::GLuint m_program_id;
glw::GLuint m_vao_id;
glw::GLuint m_xfb_id;
glw::GLuint m_bo_id[s_bo_ids_count];
void prepareAndBind();
void draw();
bool check();
void clean();
};
/** DrawXFBInstanced
*
* Verifies that transform feedback objects can used with instanced draws.
*
* Test should be executed if context is at least 3.1 and either
* ARB_transform_feedback_instanced is supported or context is at least 4.2.
*
* Steps:
* - prepare program consisting of vertex shader which outputs positions of
* full-screen quad made of triangle strip based on gl_VertexID;
* - instruct implementation to capture geometry in interleaved mode;
* - prepare buffer to capture geometry;
* - begin transform feedback;
* - draw four vertices;
* - end transform feedback;
* - prepare program consisting of vertex and fragment shaders; Vertex stage
* should calculate position as follows:
*
* gl_Position = in_position * uni_matrices[gl_InstanceID];
*
* Fragment shader should output white color;
* - prepare UNIFORM_BUFFER filled with four mat4; Select data so matrices
* transforms quad [-1, -1] : [1, 1] as follows:
* * 0 - [-1, 0] : [0, 1] - left top,
* * 1 - [ 0, 0] : [1, 1] - right top,
* * 2 - [-1, -1] : [0, 0] - left bottom,
* * 3 - [ 0, -1] : [1, 0] - right bottom;
* - prepare and clean framebuffer;
* - set up layout of vertex data in XFB;
* - execute DrawTransformFeedbackInstanced to draw four instances of quad from XFB;
* - it is expected that framebuffer is filled with white color;
*/
class DrawXFBInstanced : public deqp::TestCase
{
public:
DrawXFBInstanced(deqp::Context& context, const char* test_name, const char* test_description);
~DrawXFBInstanced(void);
virtual IterateResult iterate(void);
private:
static const glw::GLchar* s_vertex_shader_generate;
static const glw::GLchar* s_vertex_shader_draw;
static const glw::GLchar* s_fragment_shader;
static const glw::GLchar* s_xfb_varying;
static const glw::GLchar* s_uniform;
static const glw::GLuint s_bo_xfb_size;
static const glw::GLfloat s_bo_uniform_data[];
static const glw::GLuint s_bo_uniform_size;
static const glw::GLuint s_view_size;
deqp::Context& m_context;
glw::GLuint m_program_id_generate;
glw::GLuint m_program_id_draw;
glw::GLuint m_vao_id;
glw::GLuint m_xfb_id;
glw::GLuint m_bo_id_xfb;
glw::GLuint m_bo_id_uniform;
glw::GLuint m_fbo_id;
glw::GLuint m_rbo_id;
void prepareObjects();
void drawForXFB();
void drawInstanced();
bool check();
void clean();
typedef GLW_APICALL glw::GLuint (GLW_APIENTRY *GetUniformBlockIndex_ProcAddress)(glw::GLuint program, const glw::GLchar* uniformBlockName);
typedef GLW_APICALL void (GLW_APIENTRY *UniformBlockBinding_ProcAddress)(glw::GLuint program,
glw::GLuint uniformIndex,
glw::GLuint uniformBlockBinding);
GetUniformBlockIndex_ProcAddress m_glGetUniformBlockIndex;
UniformBlockBinding_ProcAddress m_glUniformBlockBinding;
};
/** DrawXFBStreamInstanced
*
* Verifies that transform feedback objects can used with instanced draws.
*
* Test should be executed if context is at least 3.1 and either
* ARB_gpu_shader5 is supported or context is at least 4.0 and either
* ARB_transform_feedback_instanced is supported or context is at least 4.2.
*
* Steps:
* - prepare program consisting of vertex shader which based on gl_VertexID
* outputs:
* * to stream 0 - color,
* * to stream 1 - positions
* for a full-screen quad made of triangle strip;
* - instruct implementation to capture geometry in interleaved mode;
* - prepare buffers to capture geometry;
* - begin transform feedback;
* - draw four vertices;
* - end transform feedback;
* - prepare program consisting of vertex and fragment shaders; Vertex stage
* should calculate position as follows:
*
* gl_Position = in_position * uni_matrices[gl_InstanceID];
*
* Fragment shader should output white color;
* - prepare UNIFORM_BUFFER filled with four mat4; Select data so matrices
* transforms quad [-1, -1] : [1, 1] as follows:
* * 0 - [-1, 0] : [0, 1] - left top,
* * 1 - [ 0, 0] : [1, 1] - right top,
* * 2 - [-1, -1] : [0, 0] - left bottom,
* * 3 - [ 0, -1] : [1, 0] - right bottom;
* - prepare and clean framebuffer;
* - set up layout of vertex data in XFB;
* - execute DrawTransformFeedbackStreamInstanced to draw four instances of
* quad from XFB, stream 1;
* - it is expected that framebuffer is filled with white color;
*/
class DrawXFBStreamInstanced : public deqp::TestCase
{
public:
DrawXFBStreamInstanced(deqp::Context& context, const char* test_name, const char* test_description);
~DrawXFBStreamInstanced(void);
virtual IterateResult iterate(void);
private:
static const glw::GLchar* s_vertex_shader_blank;
static const glw::GLchar* s_geometry_shader_generate;
static const glw::GLchar* s_vertex_shader_draw;
static const glw::GLchar* s_fragment_shader_blank;
static const glw::GLchar* s_fragment_shader_draw;
static const glw::GLchar* s_xfb_varyings[];
static const glw::GLuint s_xfb_varyings_count;
static const glw::GLchar* s_uniform;
static const glw::GLuint s_bo_xfb_size;
static const glw::GLfloat s_bo_uniform_data[];
static const glw::GLuint s_bo_uniform_size;
static const glw::GLuint s_view_size;
deqp::Context& m_context;
glw::GLuint m_program_id_generate;
glw::GLuint m_program_id_draw;
glw::GLuint m_vao_id;
glw::GLuint m_xfb_id;
glw::GLuint m_bo_id_xfb_position;
glw::GLuint m_bo_id_xfb_color;
glw::GLuint m_bo_id_uniform;
glw::GLuint m_fbo_id;
glw::GLuint m_rbo_id;
void prepareObjects();
void drawForXFB();
void drawStreamInstanced();
bool check();
void clean();
typedef GLW_APICALL glw::GLuint (GLW_APIENTRY *GetUniformBlockIndex_ProcAddress)(glw::GLuint program, const glw::GLchar* uniformBlockName);
typedef GLW_APICALL void (GLW_APIENTRY *UniformBlockBinding_ProcAddress)(glw::GLuint program,
glw::GLuint uniformIndex,
glw::GLuint uniformBlockBinding);
GetUniformBlockIndex_ProcAddress m_glGetUniformBlockIndex;
UniformBlockBinding_ProcAddress m_glUniformBlockBinding;
};
namespace Utilities
{
/** Build a GLSL program
*
* @param [in] gl OpenGL Functions Access.
* @param [in] log Log outut.
* @param [in] geometry_shader_source Pointer to C string of the geometry shader or NULL if not used.
* @param [in] tessellation_control_shader_source Pointer to C string of the tessellation control shader or NULL if not used.
* @param [in] tessellation_evaluation_shader_source Pointer to C string of the tessellation evaluation shader or NULL if not used.
* @param [in] vertex_shader_source Pointer to C string of the vertex shader or NULL if not used.
* @param [in] geometry_shader_source Pointer to C string of the fragment shader or NULL if not used.
* @param [in] transform_feedback_varyings C array of transform feedback varyings names.
* @param [in] transform_feedback_varyings_count Count of transform feedback varyings names.
* @param [in] transform_feedback_varyings_mode Transform feedback capture mode - GL_SEPARATE_ATTRIBS or GL_INTERLEAVED_ATTRIBS.
* @param [in] do_not_detach Do not detach shaders - default is faulse.
* @param [out] linking_status Return pointer to store linking status or NULL if not needed.
*
* @return OpenGL program shader ID or zero if error had occured.
*/
glw::GLuint buildProgram(glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source,
glw::GLchar const* const tessellation_control_shader_source,
glw::GLchar const* const tessellation_evaluation_shader_source,
glw::GLchar const* const vertex_shader_source, glw::GLchar const* const fragment_shader_source,
glw::GLchar const* const* const transform_feedback_varyings,
glw::GLsizei const transform_feedback_varyings_count,
glw::GLenum const transform_feedback_varyings_mode, bool const do_not_detach = false,
glw::GLint* linking_status = DE_NULL);
/** Preprocess source string by replacing key tokens with new values.
*
* @param [in] source Source string.
* @param [in] key Key, substring to be replaced.
* @param [in] value Value, substring to be substituted in place of key.
*
* @return Preprocessed string.
*/
std::string preprocessCode(std::string source, std::string key, std::string value);
/** Change integer number to string
*
* @param [in] i Integer number.
*
* @return String represnting integer number.
*/
std::string itoa(glw::GLint i);
/** Change floating point number to string
*
* @param [in] f Floating point number.
*
* @return String represnting floating point number.
*/
std::string ftoa(glw::GLfloat f);
} /* Utilities namespace */
} /* TransformFeedback namespace */
} /* gl3cts namespace */
#endif // _GL3CTRANSFORMFEEDBACKTESTS_HPP