#ifndef _ESEXTCTESSELLATIONSHADERTESSELLATION_HPP #define _ESEXTCTESSELLATIONSHADERTESSELLATION_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 "esextcTessellationShaderUtils.hpp" #include "gluShaderUtil.hpp" #include "tcuDefs.hpp" namespace glcts { /** A DEQP CTS test group that collects all tests that verify tessellation * functionality for multiple primitive modes at once, as opposed to some * other tests that are mode-specific. */ class TessellationShaderTessellationTests : public glcts::TestCaseGroupBase { public: /* Public methods */ TessellationShaderTessellationTests(glcts::Context& context, const ExtParameters& extParams); virtual ~TessellationShaderTessellationTests(void) { } void init(void); private: /* Private methods */ TessellationShaderTessellationTests(const TessellationShaderTessellationTests& other); TessellationShaderTessellationTests& operator=(const TessellationShaderTessellationTests& other); }; /** Implementation of Test Case 24 * * Make sure that patches, for which relevant outer tessellation levels have * been defined to zero or less, are discarded by the tessellation * primitive generator. Confirm that such patches never reach tessellation * evaluation shader program. * Cover all three tessellation primitive generator modes (triangles, quads, * isolines). * Note that an assumption was made here that TE's primitive id counter * works on output patches that are generated afresh from data fed by TC, * meaning XFBed TE-stage gl_PrimitiveID should be a sequential set, and * XFBed TC-stage gl_PrimitiveID should be missing every 4th and 6th patch * vertices. * This is backed by http://www.khronos.org/bugzilla/show_bug.cgi?id=754 * * Technical details: * * 0. If (gl_PrimitiveID % 4) == 0, TC should set all relevant outer * tessellation levels to 0. * 1. If (gl_PrimitiveID % 4) == 2, TC should set all relevant outer * tessellation level to -1. * 2. If (gl_PrimitiveID % 4) == 1 OR (gl_PrimitiveID % 4) == 3, TC should * set all relevant outer tessellation levels to 1. * 3. Inner tessellation level should always be set to 1. * 4. TC should also set a per-vertex output variable to gl_PrimitiveID * value. * 5. TC should also pass gl_PrimitiveID to TE. * 6. TE should store both pieces of data using Transform Feedback for each * patch vertex processed. Test passes if the data retrieved is valid. * * **/ class TessellationShaderTessellationInputPatchDiscard : public TestCaseBase { public: /* Public methods */ TessellationShaderTessellationInputPatchDiscard(Context& context, const ExtParameters& extParams); virtual ~TessellationShaderTessellationInputPatchDiscard(void) { } virtual void deinit(void); void initTest(void); virtual IterateResult iterate(void); private: /* Private type definitions */ /** Defines a single test pass */ typedef struct _run { glw::GLuint po_id; _tessellation_primitive_mode primitive_mode; glw::GLuint tc_id; glw::GLuint te_id; _run() { po_id = 0; primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN; tc_id = 0; te_id = 0; } } _run; /** Defines a vector of test passes */ typedef std::vector<_run> _runs; typedef _runs::const_iterator _runs_const_iterator; /* Private methods */ std::string getTCCode(); std::string getTECode(_tessellation_primitive_mode primitive_mode); void deinitRun(_run& test); void initRun(_run& test, _tessellation_primitive_mode primitive_mode); /* Private variables */ glw::GLuint m_bo_id; glw::GLuint m_fs_id; glw::GLuint m_vs_id; glw::GLuint m_vao_id; _runs m_runs; TessellationShaderUtils* m_utils_ptr; }; /** Implementation for Test Case 18 * * Make sure that tessellation control shader is fed with correct gl_InvocationID * values. * Make sure that tessellation control and tessellation evaluation shaders are * fed with correct gl_PatchVerticesIn values. * Make sure that tessellation control and tessellation evaluation shaders are * fed with correct gl_PrimitiveID values. Make sure restarting a primitive * topology does not restart primitive counter. * * Technical details: * * 0. The test to be executed for all three geometry types supported by * the tessellator. The draw calls used should draw at least a few * instances of a set of patches generating a few primitives for each type * considered. Vertex arrayed and indiced draw calls should be tested. * A few vertices-per-patch configurations should be considered. * * 1. Tessellation control shader to pass gl_InvocationID to tessellation * evaluation shader for XFB, for later inspection. The values captured * should run from 0 to the last invocation number for particular draw * call. Whole range should be covered by exactly one appearance of each index. * * 2. Tessellation control shader should pass gl_PatchVerticesIn value to * tessellation evaluation shader. The value passed from TC, as well as * gl_PatchVerticesIn value exposed to TE should be captured for later * inspection. * * 3. Step 2 should be repeated for gl_PrimitiveID. The test should confirm * that using a primitive restart index does not reset the counter, when * indiced draw calls are tested. **/ class TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID : public TestCaseBase { public: /* Public methods */ TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(Context& context, const ExtParameters& extParams); virtual ~TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(void) { } virtual void deinit(void); void initTest(void); virtual IterateResult iterate(void); private: /* Private type definitions */ /** Defines a single test run */ typedef struct _run { glw::GLuint bo_indices_id; unsigned int drawcall_count_multiplier; bool drawcall_is_indiced; glw::GLuint drawcall_n_instances; glw::GLuint n_instances; glw::GLint n_patch_vertices; unsigned int n_restart_indices; unsigned int n_result_vertices; glw::GLuint po_id; _tessellation_primitive_mode primitive_mode; glw::GLuint tc_id; glw::GLuint te_id; _run() { bo_indices_id = 0; drawcall_count_multiplier = 0; drawcall_is_indiced = false; drawcall_n_instances = 0; n_result_vertices = 0; n_instances = 0; n_patch_vertices = 0; n_restart_indices = 0; po_id = 0; primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN; tc_id = 0; te_id = 0; } } _run; /** Defines a vector of test runs */ typedef std::vector<_run> _runs; typedef _runs::const_iterator _runs_const_iterator; /* Private methods */ std::string getTCCode(glw::GLuint n_patch_vertices); std::string getTECode(_tessellation_primitive_mode primitive_mode); void deinitRun(_run& run); void initRun(_run& run, _tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, bool is_indiced, glw::GLint n_instances, unsigned int drawcall_count_multiplier); /* Private variables */ glw::GLuint m_bo_id; glw::GLuint m_fs_id; glw::GLuint m_vs_id; glw::GLuint m_vao_id; _runs m_runs; TessellationShaderUtils* m_utils_ptr; }; /** Implementation of Test Case 51 * * Make sure that coordinates of all triangles generated by fixed-function * tessellation primitive generator meet the barycentric coordinate requirement * u + v + w = 1 * * Consider a few inner/outer tessellation level combinations * for triangle and quad inputs of a tessellation evaluation shader. * * Epsilon: 1e-5. This is dictated by the language in ES 3.0 specification, * which seems to be the best pick, given that the tessellator is * a fixed-function unit. * * Make sure that gl_TessCoord is not an array. * Make sure that gl_TessCoord is not accessible for any of the vertices in * gl_in[]. * Make sure that (u, v, w) coordinates are in range [0, 1] for all * tessellation primitive modes. * Make sure that the w coordinate is always zero for "quads" and "isolines" * tessellation primitive modes. * * This test should be executed in two invocations, depending on the test type: * * * Without a tessellation control shader, where the patch tessellation levels * are configured by using glPatchParameterfv() function (*); * * With a tessellation control shader used to configure the levels; * * (*) Only applies to Desktop * **/ class TessellationShaderTessellationgl_TessCoord : public TestCaseBase { static std::string getTypeName(_tessellation_test_type test_type); public: /* Public methods */ TessellationShaderTessellationgl_TessCoord(Context& context, const ExtParameters& extParams, _tessellation_test_type test_type); virtual ~TessellationShaderTessellationgl_TessCoord(void) { } virtual void deinit(void); void initTest(void); virtual IterateResult iterate(void); private: /* Private type definitions */ /** Defines a single test pass */ typedef struct _test_descriptor { glw::GLint n_patch_vertices; glw::GLuint po_id; _tessellation_primitive_mode primitive_mode; glw::GLuint tc_id; glw::GLuint te_id; glw::GLfloat tess_level_inner[2]; glw::GLfloat tess_level_outer[4]; _tessellation_test_type type; _tessellation_shader_vertex_spacing vertex_spacing; glw::GLint inner_tess_level_uniform_location; glw::GLint outer_tess_level_uniform_location; _test_descriptor() { memset(tess_level_inner, 0, sizeof(tess_level_inner)); memset(tess_level_outer, 0, sizeof(tess_level_outer)); n_patch_vertices = 0; po_id = 0; primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN; tc_id = 0; te_id = 0; type = TESSELLATION_TEST_TYPE_UNKNOWN; vertex_spacing = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN; inner_tess_level_uniform_location = -1; outer_tess_level_uniform_location = -1; } } _test_descriptor; /** Defines a vector of test passes */ typedef std::vector<_test_descriptor> _tests; typedef _tests::const_iterator _tests_const_iterator; /* Private methods */ std::string getTCCode(glw::GLint n_patch_vertices); std::string getTECode(_tessellation_shader_vertex_spacing vertex_spacing, _tessellation_primitive_mode primitive_mode); void deinitTestDescriptor(_test_descriptor& test); void initTestDescriptor(_test_descriptor& test, _tessellation_shader_vertex_spacing vertex_spacing, _tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, const float* inner_tess_levels, const float* outer_tess_levels, _tessellation_test_type test_type); /* Private variables */ _tessellation_test_type m_test_type; glw::GLuint m_bo_id; glw::GLuint m_broken_ts_id; glw::GLuint m_fs_id; glw::GLuint m_vs_id; glw::GLuint m_vao_id; _tests m_tests; TessellationShaderUtils* m_utils_ptr; }; /* This test class implements the following test cases: * * 20. Make sure it is possible to use up to GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT/4 * vec4 input variables in a tessellation control shader. * Make sure it is possible to use up to GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT/4 * vec4 input variables in a tessellation evaluation shader. * This test should issue at least one draw call and verify the results to * make sure the implementation actually supports the maximums it reports. * * 21. Make sure it is possible to use up to GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT/4 * vec4 per-vertex output variables in a tessellation control shader. * Make sure it is possible to use up to GL_MAX_TESS_PATCH_COMPONENTS_EXT/4 * vec4 per-patch output variables in a tessellation control shader. * Make sure it is possible to use up to GL_MAX_TESS_PATCH_COMPONENTS_EXT/4 * vec4 per-patch input variables in a tessellation evaluation shader. * Make sure it is possible to use up to GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT/4 * vec4 per-vertex output variables in a tessellation evaluation shader. * * NOTE: The test should separately check if a maximum number of per-vertex and * per-patch output variables used in a tessellation control shader works * correctly. This is due to a risk that, had both types been used at once, * the maximum amount of output components supported for tessellation * control shader GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT may * have been exceeded for implementations, for which the property is * not equal to: * * (per-vertex output component count multiplied by output patch size + * + per-patch output component count). * * This test should issue at least one draw call and verify the results to * make sure the implementation actually supports the maximums it reports. * * Category: Functional Test. * Priority: Must-Have * * The test is implemented by checking two different cases: * 1) In first case, it makes sure it is possible to use up to: * - GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT / 4 vec4 per-vertex variables in tessellation control shader, * - GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT / 4 vec4 per-vertex variables in tessellation control shader, * - GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT / 4 vec4 per-vertex variables in tessellation evaluation shader, * - GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT / 4 vec4 per-vertex variables in tessellation evaluation shader. * * 2) In second case, it makes sure it is possible to use up to: * - GL_MAX_TESS_PATCH_COMPONENTS_EXT/4 vec4 per-patch variables in tessellation control shader, * - GL_MAX_TESS_PATCH_COMPONENTS_EXT/4 vec4 per-patch variables in tessellation evaluation shader. */ class TessellationShaderTessellationMaxInOut : public TestCaseBase { public: /* Public methods */ TessellationShaderTessellationMaxInOut(Context& context, const ExtParameters& extParams); virtual ~TessellationShaderTessellationMaxInOut() { } virtual void deinit(void); virtual IterateResult iterate(void); private: /* private methods */ void initBufferObjects(void); void initProgramObjects(void); void initReferenceValues(void); void initTest(void); void retrieveGLConstantValues(void); bool compareValues(char const* description, glw::GLfloat* reference_values, int n_reference_values); /* private variables */ glw::GLuint m_po_id_1; /* program object name for case 1 */ glw::GLuint m_po_id_2; /* program object name for case 2 */ glw::GLuint m_fs_id; /* fragment shader object name */ glw::GLuint m_tcs_id_1; /* tessellation control shader object name for case 1 */ glw::GLuint m_tcs_id_2; /* tessellation control shader object name for case 2 */ glw::GLuint m_tes_id_1; /* tessellation evaluation shader object name for case 1 */ glw::GLuint m_tes_id_2; /* tessellation evaluation shader object name for case 2 */ glw::GLuint m_vs_id_1; /* vertex shader object name for case 1 */ glw::GLuint m_vs_id_2; /* vertex shader object name for case 2 */ glw::GLuint m_tf_bo_id_1; /* buffer object name */ glw::GLuint m_tf_bo_id_2; /* buffer object name */ glw::GLuint m_patch_data_bo_id; /* buffer object name for patch submission */ glw::GLuint m_vao_id; /* vertex array object */ glw::GLint m_gl_max_tess_control_input_components_value; /* value of MAX_TESS_CONTROL_INPUT_COMPONENTS */ glw::GLint m_gl_max_tess_control_output_components_value; /* value of MAX_TESS_CONTROL_OUTPUT_COMPONENTS */ glw::GLint m_gl_max_tess_evaluation_input_components_value; /* value of MAX_TESS_EVALUATION_INPUT_COMPONENTS */ glw::GLint m_gl_max_tess_evaluation_output_components_value; /* value of MAX_TESS_EVALUATION_OUTPUT_COMPONENTS */ glw::GLint m_gl_max_transform_feedback_interleaved_components_value; /* value of MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS */ glw::GLint m_gl_max_tess_patch_components_value; /* value of MAX_TESS_PATCH_COMPONENTS */ glw::GLint m_gl_max_vertex_output_components_value; /* value of MAX_VERTEX_OUTPUT_COMPONENTS */ glw::GLfloat m_ref_patch_attributes[4]; /* reference values for max per-patch attributes case 2 */ glw::GLfloat* m_ref_vertex_attributes; /* reference values for max per-vertex attributes case 1 */ static const char* m_fs_code; /* fragment shader code */ static const char* m_vs_code; /* vertex shader code */ static const char* m_tcs_code_1; /* tessellation control shader code for per vertex components check */ static const char* m_tcs_code_2; /* tessellation control shader code per patch components check */ static const char* m_tes_code_1; /* tessellation evaluation shader code per vertex components check */ static const char* m_tes_code_2; /* tessellation evaluation shader code per patch components check */ char** m_tf_varyings_names; /* transform feedback varyings names array */ }; } // namespace glcts #endif // _ESEXTCTESSELLATIONSHADERTESSELLATION_HPP