blob: c5a2c794607c9c0a50fabd4096f0e4215c1d52b8 [file] [log] [blame]
#ifndef _ESEXTCTESSELLATIONSHADERUTILS_HPP
#define _ESEXTCTESSELLATIONSHADERUTILS_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
*/ /*-------------------------------------------------------------------*/
#include "../esextcTestCaseBase.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "glwFunctions.hpp"
#include "tcuDefs.hpp"
#include <cstring>
#include <vector>
namespace glcts
{
/** Stores an ivec4 representation */
typedef struct _ivec4
{
int x;
int y;
int z;
int w;
/** Constructor.
*
* @param in_x Value to use for X component;
* @param in_y Value to use for Y component;
* @param in_z Value to use for Z component;
* @param in_w Value to use for W component.
*/
_ivec4(int in_x, int in_y, int in_z, int in_w)
{
x = in_x;
y = in_y;
z = in_z;
w = in_w;
}
/** Compares all components of _ivec4 instance with
* another instance.
*
* @return true if all components match, false otherwise.
**/
bool operator==(const _ivec4& in) const
{
return (x == in.x) && (y == in.y) && (z == in.z) && (w == in.w);
}
/** Implements inequality operator.
*
* @return true if any of the compared components
* do not match, false otherwise.
**/
bool operator!=(const _ivec4& in) const
{
return !(*this == in);
}
} _ivec4;
/* Stores a vec2 representation */
typedef struct _vec2
{
float x;
float y;
/** Constructor.
*
* @param in_x Value to use for X component;
* @param in_y Value to use for Y component;
*/
_vec2(float in_x, float in_y)
{
x = in_x;
y = in_y;
}
/** Compares all components of _vec2 instance with
* another instance, using == operator.
*
* @return true if all components match, false otherwise.
**/
bool operator==(const _vec2& in) const
{
return (x == in.x) && (y == in.y);
}
/** Implements inequality operator.
*
* @return true if any of the compared components
* do not match, false otherwise.
**/
bool operator!=(const _vec2& in) const
{
return !(*this == in);
}
} _vec2;
/* Stores a vec4 representation */
typedef struct _vec4
{
float x;
float y;
float z;
float w;
/** Constructor.
*
* @param in_x Value to use for X component;
* @param in_y Value to use for Y component;
* @param in_z Value to use for Z component;
* @param in_w Value to use for W component.
*/
_vec4(float in_x, float in_y, float in_z, float in_w)
{
x = in_x;
y = in_y;
z = in_z;
w = in_w;
}
/** Compares all components of _vec4 instance with
* another instance, using == operator.
*
* @return true if all components match, false otherwise.
**/
bool operator==(const _vec4& in) const
{
return (x == in.x) && (y == in.y) && (z == in.z) && (w == in.w);
}
/** Implements inequality operator.
*
* @return true if any of the compared components
* do not match, false otherwise.
**/
bool operator!=(const _vec4& in) const
{
return !(*this == in);
}
} _vec4;
/** Defines a set of tessellation inner+outer levels */
typedef struct _tessellation_levels
{
float inner[2];
float outer[4];
_tessellation_levels()
{
memset(inner, 0, sizeof(inner));
memset(outer, 0, sizeof(outer));
}
} _tessellation_levels;
/* Defines a vector of tessellation levels */
typedef std::vector<_tessellation_levels> _tessellation_levels_set;
typedef _tessellation_levels_set::const_iterator _tessellation_levels_set_const_iterator;
typedef _tessellation_levels_set::iterator _tessellation_levels_set_iterator;
/* Determines condition that returned level sets should meet in order to be returned
* by TessellationShaderUtils::getTessellationLevelSetForPrimitiveMode() .
*/
typedef enum {
/********* General modes: do not use these values in conjugation *********/
/* All combinations of values from the set {-1, 1, GL_MAX_TESS_GEN_LEVEL_EXT / 2,
* GL_MAX_TESS_GEN_LEVEL_EXT} will be used for inner/outer tesselelation
* levels relevant to user-specified primitive mode.
* An important exception is that the negative value will be SKIPPED for
* outer tessellation levels (because otherwise no geometry will be generated
* by the tessellator)
**/
TESSELLATION_LEVEL_SET_FILTER_ALL_COMBINATIONS = 0x1,
/* Only combinations where:
*
* - inner tessellation levels use different values (inner[0] != inner[1])
* - outer tessellation levels use different values (outer[0] != outer[1] !=
* != outer[2] != outer[3]);
*
* are allowed. */
TESSELLATION_LEVEL_SET_FILTER_INNER_AND_OUTER_LEVELS_USE_DIFFERENT_VALUES = 0x2,
/* All inner/outer tessellation level use the same base value */
TESSELLATION_LEVEL_SET_FILTER_ALL_LEVELS_USE_THE_SAME_VALUE = 0x4,
/********* Flags: can be combined with above general mode values *********/
TESSELLATION_LEVEL_SET_FILTER_EXCLUDE_NEGATIVE_BASE_VALUE = 0x8
} _tessellation_level_set_filter;
/* Represents primitive modes supported by GL_EXT_tessellation_shader */
typedef enum {
TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST = 0,
TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES = TESSELLATION_SHADER_PRIMITIVE_MODE_FIRST,
TESSELLATION_SHADER_PRIMITIVE_MODE_TRIANGLES,
TESSELLATION_SHADER_PRIMITIVE_MODE_QUADS,
TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT,
TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN = TESSELLATION_SHADER_PRIMITIVE_MODE_COUNT
} _tessellation_primitive_mode;
/** Represents vertex ordering modes supported by GL_EXT_tessellation_shader */
typedef enum {
TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
TESSELLATION_SHADER_VERTEX_ORDERING_CW,
TESSELLATION_SHADER_VERTEX_ORDERING_DEFAULT,
TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN
} _tessellation_shader_vertex_ordering;
/** Represents vertex spacing modes supported by GL_EXT_tessellation_shader */
typedef enum {
TESSELLATION_SHADER_VERTEX_SPACING_FIRST,
TESSELLATION_SHADER_VERTEX_SPACING_EQUAL = TESSELLATION_SHADER_VERTEX_SPACING_FIRST,
TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD,
TESSELLATION_SHADER_VERTEX_SPACING_DEFAULT,
TESSELLATION_SHADER_VERTEX_SPACING_COUNT,
TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN = TESSELLATION_SHADER_VERTEX_SPACING_COUNT
} _tessellation_shader_vertex_spacing;
/** Defines what tesellation stages should be tested for a given test pass. */
typedef enum {
TESSELLATION_TEST_TYPE_FIRST,
TESSELLATION_TEST_TYPE_TCS_TES = TESSELLATION_TEST_TYPE_FIRST, /* tcs + tes stages defined */
TESSELLATION_TEST_TYPE_TES, /* only tes stage defined */
/* Always last */
TESSELLATION_TEST_TYPE_COUNT,
TESSELLATION_TEST_TYPE_UNKNOWN = TESSELLATION_TEST_TYPE_COUNT
} _tessellation_test_type;
/* Stores various helper functions used across multiple tessellation shader tests */
class TessellationShaderUtils
{
public:
/* Public methods */
TessellationShaderUtils(const glw::Functions& gl, glcts::TestCaseBase* parentTest);
~TessellationShaderUtils();
void compileShaders(glw::GLint n_shaders, const glw::GLuint* shaders, bool should_succeed);
static void convertBarycentricCoordinatesToCartesian(const float* barycentric_coordinates,
float* out_cartesian_coordinates);
static void convertCartesianCoordinatesToBarycentric(const float* cartesian_coordinates,
float* out_barycentric_coordinates);
unsigned int getAmountOfVerticesGeneratedByTessellator(_tessellation_primitive_mode primitive_mode,
const float* inner_tessellation_level,
const float* outer_tessellation_level,
_tessellation_shader_vertex_spacing vertex_spacing,
bool is_point_mode_enabled);
std::vector<char> getDataGeneratedByTessellator(const float* inner, bool point_mode,
_tessellation_primitive_mode primitive_mode,
_tessellation_shader_vertex_ordering vertex_ordering,
_tessellation_shader_vertex_spacing vertex_spacing,
const float* outer);
static std::string getESTokenForPrimitiveMode(_tessellation_primitive_mode primitive_mode);
static std::string getESTokenForVertexOrderingMode(_tessellation_shader_vertex_ordering vertex_ordering);
static std::string getESTokenForVertexSpacingMode(_tessellation_shader_vertex_spacing vertex_spacing);
static std::string getGenericTCCode(unsigned int n_patch_vertices, bool should_use_glInvocationID_indexed_input);
static std::string getGenericTECode(_tessellation_shader_vertex_spacing vertex_spacing,
_tessellation_primitive_mode primitive_mode,
_tessellation_shader_vertex_ordering vertex_ordering, bool point_mode);
static glw::GLint getPatchVerticesForPrimitiveMode(_tessellation_primitive_mode primitive_mode);
static void getTessellationLevelAfterVertexSpacing(_tessellation_shader_vertex_spacing vertex_spacing, float level,
glw::GLint gl_max_tess_gen_level_value, float* out_clamped,
float* out_clamped_and_rounded);
static _tessellation_levels_set getTessellationLevelSetForPrimitiveMode(_tessellation_primitive_mode primitive_mode,
glw::GLint gl_max_tess_gen_level_value,
_tessellation_level_set_filter filter);
static glw::GLenum getTFModeForPrimitiveMode(_tessellation_primitive_mode primitive_mode, bool is_point_mode);
static bool isOuterEdgeVertex(_tessellation_primitive_mode primitive_mode, const float* tessellated_vertex_data);
static bool isTriangleDefined(const float* triangle_vertex_data, const float* vertex_data);
private:
/* Private type definitions */
/** Defines a single counter program */
typedef struct _tessellation_vertex_counter_program
{
/* Properties */
float inner_tess_level[2];
bool is_point_mode_enabled;
glw::GLint n_patch_vertices;
float outer_tess_level[4];
_tessellation_primitive_mode primitive_mode;
_tessellation_shader_vertex_spacing vertex_spacing;
std::vector<char> m_data;
unsigned int n_data_vertices;
glw::GLint po_id;
glw::GLint tc_id;
glw::GLint te_id;
glw::GLint tess_level_inner_uniform_location;
glw::GLint tess_level_outer_uniform_location;
const glw::Functions& m_gl;
_tessellation_vertex_counter_program(const glw::Functions& gl) : m_gl(gl)
{
memset(inner_tess_level, 0, sizeof(inner_tess_level));
memset(outer_tess_level, 0, sizeof(outer_tess_level));
is_point_mode_enabled = false;
n_patch_vertices = 0;
po_id = 0;
primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
tc_id = 0;
te_id = 0;
vertex_spacing = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
n_data_vertices = 0;
tess_level_inner_uniform_location = -1;
tess_level_outer_uniform_location = -1;
}
~_tessellation_vertex_counter_program()
{
if (po_id != 0)
{
m_gl.deleteProgram(po_id);
po_id = 0;
}
if (tc_id != 0)
{
m_gl.deleteShader(tc_id);
tc_id = 0;
}
if (te_id != 0)
{
m_gl.deleteShader(te_id);
te_id = 0;
}
}
} _tessellation_vertex_counter_program;
/* A vector of counter programs */
typedef std::vector<_tessellation_vertex_counter_program> _programs;
typedef _programs::const_iterator _programs_const_iterator;
typedef _programs::iterator _programs_iterator;
/* Private methods */
void captureTessellationData(_tessellation_vertex_counter_program& program);
void deinit();
void init();
void initTessellationVertexCounterProgram(const float* inner_tess_level, const float* outer_tess_level,
glw::GLint n_patch_vertices,
_tessellation_shader_vertex_spacing vertex_spacing,
_tessellation_primitive_mode primitive_mode, bool is_point_mode_enabled,
_tessellation_vertex_counter_program& result_descriptor);
/* Private variables */
const glw::Functions& m_gl;
glw::GLuint m_bo_id;
glw::GLuint m_fs_id;
glw::GLuint m_qo_pg_id;
glw::GLuint m_vs_id;
glcts::TestCaseBase* m_parent_test;
};
} // namespace glcts
#endif // _ESEXTCTESSELLATIONSHADERUTILS_HPP