/*------------------------------------------------------------------------- * 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 "es31cArrayOfArraysTests.hpp" #include "gluContextInfo.hpp" #include "gluDefs.hpp" #include "gluRenderContext.hpp" #include "glwFunctions.hpp" #include "tcuTestLog.hpp" #include #include #include #include using std::string; /* Selects if debug output is enabled */ #define IS_DEBUG 0 #define IS_DEBUG_DUMP_ALL_SHADERS 0 /* Selects if workaround in ExpressionsInvalid2 test is enabled */ #define WRKARD_EXPRESSIONSINVALID2 0 #if IS_DEBUG #include "tcuTestLog.hpp" #endif namespace glcts { namespace ArraysOfArrays { namespace Interface { /* Sets limits on number of dimensions. Value 8 comes from ogirinal "ES" implementation. * Explanation was as follows: * * "The current specifations allow up to 8 array dimensions." */ const size_t ES::MAX_ARRAY_DIMENSIONS = 8; const size_t GL::MAX_ARRAY_DIMENSIONS = 8; /* API specific shader parts */ const char* ES::shader_version_gpu5 = "#version 310 es\n#extension GL_EXT_gpu_shader5 : require\nprecision mediump float;\n\n"; const char* ES::shader_version = "#version 310 es\nprecision mediump float;\n\n"; const char* GL::shader_version_gpu5 = "#version 430 core\n\n"; const char* GL::shader_version = "#version 430 core\n\n"; } /* namespace Interface */ /* Minimal fragment shader source code. * Used when testing the vertex shader. */ const std::string default_fragment_shader_source = "//default fragment shader\n" "out vec4 color;\n" "void main()\n" "{\n" " color = vec4(1.0);\n" "}\n"; /* Minimal vertex shader source code. * Used when testing the fragment shader. */ const std::string default_vertex_shader_source = "//default vertex shader\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(0.0,0.0,0.0,1.0);\n" "}\n"; /* Simple geometry shader source code. * Used when testing the other shaders. */ const std::string default_geometry_shader_source = "//default geometry\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n"; /* Simple tesselation control shader source code. * Used when testing the other shaders. */ const std::string default_tc_shader_source = "//default tcs\n" "\n" "void main()\n" "{\n" " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n" "}\n"; /* Minimal tesselation evaluation shader source code. * Used when testing the other shaders. */ const std::string default_te_shader_source = "//default tes\n" "\n" "void main()\n" "{\n" "}\n"; /* Pass-through shaders source code. Used when testing other stage. */ const std::string pass_fragment_shader_source = "//pass fragment shader\n" "in float fs_result;\n" "out vec4 color;\n" "\n" "void main()\n" "{\n" " color = vec4(fs_result);\n" "}\n"; const std::string pass_geometry_shader_source = "//pass geometry\n" "in float gs_result[];\n" "out float fs_result;\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = gs_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = gs_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = gs_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = gs_result[0];\n" " EmitVertex();\n" "}\n"; const std::string pass_te_shader_source = "//pass tes\n" "in float tcs_result[];\n" "out float fs_result;\n" "\n" "void main()\n" "{\n" " fs_result = tcs_result[0];\n" "}\n"; /* Empty string */ static const std::string empty_string = ""; /* Beginning of a shader source code. */ const std::string shader_start = "void main()\n" "{\n"; /* End of a shader source code. */ const std::string shader_end = "}\n"; /* Emit full screen quad from GS */ const std::string emit_quad = " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n"; /* Set tesselation levels */ const std::string set_tesseation = " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n"; /* Input and output data type modifiers. */ const std::string in_out_type_modifiers[] = { "in", "out", "uniform" }; /* Types and appropriate initialisers, used throughout these tests */ const var_descriptor var_descriptors[] = { { "bool", "", "true", "false", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "int", "", "1", "0", "0", "int", "", "iterator", "1", "N/A", "N/A" }, { "uint", "", "1u", "0u", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "float", "", "1.0", "0.0", "0.0", "float", "", "iterator", "1.0", "N/A", "N/A" }, { "vec2", "", "vec2(1.0)", "vec2(0.0)", "0.0", "float", "[0]", "vec2(iterator)", "vec2(1.0)", "N/A", "N/A" }, { "vec3", "", "vec3(1.0)", "vec3(0.0)", "0.0", "float", "[0]", "vec3(iterator)", "vec3(1.0)", "N/A", "N/A" }, { "vec4", "", "vec4(1.0)", "vec4(0.0)", "0.0", "float", "[0]", "vec4(iterator)", "vec4(1.0)", "N/A", "N/A" }, { "bvec2", "", "bvec2(1)", "bvec2(0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "bvec3", "", "bvec3(1)", "bvec3(0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "bvec4", "", "bvec4(1)", "bvec4(0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "ivec2", "", "ivec2(1)", "ivec2(0)", "0", "int", "[0]", "ivec2(iterator)", "ivec2(1)", "N/A", "N/A" }, { "ivec3", "", "ivec3(1)", "ivec3(0)", "0", "int", "[0]", "ivec3(iterator)", "ivec3(1)", "N/A", "N/A" }, { "ivec4", "", "ivec4(1)", "ivec4(0)", "0", "int", "[0]", "ivec4(iterator)", "ivec4(1)", "N/A", "N/A" }, { "uvec2", "", "uvec2(1u)", "uvec2(0u)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "uvec3", "", "uvec3(1u)", "uvec3(0u)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "uvec4", "", "uvec4(1u)", "uvec4(0u)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat2", "", "mat2(1.0)", "mat2(0.0)", "0.0", "float", "[0][0]", "mat2(iterator)", "mat2(1.0)", "N/A", "N/A" }, { "mat3", "", "mat3(1.0)", "mat3(0.0)", "0.0", "float", "[0][0]", "mat3(iterator)", "mat3(1.0)", "N/A", "N/A" }, { "mat4", "", "mat4(1.0)", "mat4(0.0)", "0.0", "float", "[0][0]", "mat4(iterator)", "mat4(1.0)", "N/A", "N/A" }, { "mat2x2", "", "mat2x2(1.0)", "mat2x2(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat2x3", "", "mat2x3(1.0)", "mat2x3(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat2x4", "", "mat2x4(1.0)", "mat2x4(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat3x2", "", "mat3x2(1.0)", "mat3x2(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat3x3", "", "mat3x3(1.0)", "mat3x3(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat3x4", "", "mat3x4(1.0)", "mat3x4(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat4x2", "", "mat4x2(1.0)", "mat4x2(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat4x3", "", "mat4x3(1.0)", "mat4x3(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "mat4x4", "", "mat4x4(1.0)", "mat4x4(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "imageBuffer", "", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "iimageBuffer", "", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "uimageBuffer", "", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "samplerBuffer", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "isamplerBuffer", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "usamplerBuffer", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "sampler2D", "", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec2(0.0)", "vec4" }, { "sampler3D", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "vec4" }, { "samplerCube", "", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "vec4" }, { "samplerCubeShadow", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec4(0.0)", "float", }, { "sampler2DShadow", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "float" }, { "sampler2DArray", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "vec4" }, { "sampler2DArrayShadow", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec4(0.0)", "float" }, { "isampler2D", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec2(0.0)", "ivec4" }, { "isampler3D", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "ivec4" }, { "isamplerCube", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "ivec4" }, { "isampler2DArray", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "ivec4" }, { "usampler2D", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec2(0.0)", "uvec4" }, { "usampler3D", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "uvec4" }, { "usamplerCube", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "uvec4" }, { "usampler2DArray", "lowp", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "vec3(0.0)", "uvec4" }, }; const var_descriptor var_double_descriptors[] = { { "double", "", "1.0", "0.0", "0.0", "double", "", "iterator", "1.0", "N/A", "N/A" }, { "dmat2", "", "dmat2(1.0)", "dmat2(0.0)", "0.0", "double", "[0][0]", "dmat2(iterator)", "dmat2(1.0)", "N/A", "N/A" }, { "dmat3", "", "dmat3(1.0)", "dmat3(0.0)", "0.0", "double", "[0][0]", "dmat3(iterator)", "dmat3(1.0)", "N/A", "N/A" }, { "dmat4", "", "dmat4(1.0)", "dmat4(0.0)", "0.0", "double", "[0][0]", "dmat4(iterator)", "dmat4(1.0)", "N/A", "N/A" }, { "dmat2x2", "", "dmat2x2(1.0)", "dmat2x2(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat2x3", "", "dmat2x3(1.0)", "dmat2x3(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat2x4", "", "dmat2x4(1.0)", "dmat2x4(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat3x2", "", "dmat3x2(1.0)", "dmat3x2(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat3x3", "", "dmat3x3(1.0)", "dmat3x3(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat3x4", "", "dmat3x4(1.0)", "dmat3x4(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat4x2", "", "dmat4x2(1.0)", "dmat4x2(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat4x3", "", "dmat4x3(1.0)", "dmat4x3(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, { "dmat4x4", "", "dmat4x4(1.0)", "dmat4x4(0.0)", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A" }, }; _supported_variable_types_map supported_variable_types_map; /** List of all supported variable types for es. */ const test_var_type var_types_es[] = { VAR_TYPE_BOOL, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_FLOAT, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_BVEC2, VAR_TYPE_BVEC3, VAR_TYPE_BVEC4, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_UVEC2, VAR_TYPE_UVEC3, VAR_TYPE_UVEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_MAT2X2, VAR_TYPE_MAT2X3, VAR_TYPE_MAT2X4, VAR_TYPE_MAT3X2, VAR_TYPE_MAT3X3, VAR_TYPE_MAT3X4, VAR_TYPE_MAT4X2, VAR_TYPE_MAT4X3, VAR_TYPE_MAT4X4, }; const test_var_type* Interface::ES::var_types = var_types_es; const size_t Interface::ES::n_var_types = sizeof(var_types_es) / sizeof(var_types_es[0]); /** List of all supported variable types for gl. */ static const glcts::test_var_type var_types_gl[] = { VAR_TYPE_BOOL, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_FLOAT, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_BVEC2, VAR_TYPE_BVEC3, VAR_TYPE_BVEC4, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_UVEC2, VAR_TYPE_UVEC3, VAR_TYPE_UVEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_MAT2X2, VAR_TYPE_MAT2X3, VAR_TYPE_MAT2X4, VAR_TYPE_MAT3X2, VAR_TYPE_MAT3X3, VAR_TYPE_MAT3X4, VAR_TYPE_MAT4X2, VAR_TYPE_MAT4X3, VAR_TYPE_MAT4X4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4, VAR_TYPE_DMAT2X2, VAR_TYPE_DMAT2X3, VAR_TYPE_DMAT2X4, VAR_TYPE_DMAT3X2, VAR_TYPE_DMAT3X3, VAR_TYPE_DMAT3X4, VAR_TYPE_DMAT4X2, VAR_TYPE_DMAT4X3, VAR_TYPE_DMAT4X4, }; const test_var_type* Interface::GL::var_types = var_types_gl; const size_t Interface::GL::n_var_types = sizeof(var_types_gl) / sizeof(var_types_gl[0]); /** List of all supported opaque types. */ const glcts::test_var_type opaque_var_types[] = { //Floating Point Sampler Types (opaque) VAR_TYPE_SAMPLER2D, VAR_TYPE_SAMPLER3D, VAR_TYPE_SAMPLERCUBE, VAR_TYPE_SAMPLERCUBESHADOW, VAR_TYPE_SAMPLER2DSHADOW, VAR_TYPE_SAMPLER2DARRAY, VAR_TYPE_SAMPLER2DARRAYSHADOW, //Signed Integer Sampler Types (opaque) VAR_TYPE_ISAMPLER2D, VAR_TYPE_ISAMPLER3D, VAR_TYPE_ISAMPLERCUBE, VAR_TYPE_ISAMPLER2DARRAY, //Unsigned Integer Sampler Types (opaque) VAR_TYPE_USAMPLER2D, VAR_TYPE_USAMPLER3D, VAR_TYPE_USAMPLERCUBE, VAR_TYPE_USAMPLER2DARRAY, }; /** Sets up the type map that will be used to look up the type names, initialisation * values, etc., associated with each of the types used within the array tests * **/ template void initializeMap() { int temp_index = 0; // Set up the map supported_variable_types_map[VAR_TYPE_BOOL] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_INT] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_UINT] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_FLOAT] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_VEC2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_VEC3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_VEC4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_BVEC2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_BVEC3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_BVEC4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_IVEC2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_IVEC3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_IVEC4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_UVEC2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_UVEC3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_UVEC4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT2X2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT2X3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT2X4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT3X2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT3X3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT3X4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT4X2] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT4X3] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_MAT4X4] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_IMAGEBUFFER] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_IIMAGEBUFFER] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_UIMAGEBUFFER] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLERBUFFER] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_ISAMPLERBUFFER] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_USAMPLERBUFFER] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLER2D] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLER3D] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLERCUBE] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLERCUBESHADOW] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLER2DSHADOW] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLER2DARRAY] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_SAMPLER2DARRAYSHADOW] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_ISAMPLER2D] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_ISAMPLER3D] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_ISAMPLERCUBE] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_ISAMPLER2DARRAY] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_USAMPLER2D] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_USAMPLER3D] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_USAMPLERCUBE] = var_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_USAMPLER2DARRAY] = var_descriptors[temp_index++]; if (API::USE_DOUBLE) { temp_index = 0; supported_variable_types_map[VAR_TYPE_DOUBLE] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT2] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT3] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT4] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT2X2] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT2X3] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT2X4] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT3X2] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT3X3] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT3X4] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT4X2] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT4X3] = var_double_descriptors[temp_index++]; supported_variable_types_map[VAR_TYPE_DMAT4X4] = var_double_descriptors[temp_index++]; } } /** Macro appends default ending of main function to source string * * @param SOURCE Tested shader source **/ #define DEFAULT_MAIN_ENDING(TYPE, SOURCE) \ do { \ /* Apply stage specific stuff */ \ switch (TYPE) \ { \ case TestCaseBase::VERTEX_SHADER_TYPE: \ SOURCE += "\n gl_Position = vec4(0.0);\n"; \ break; \ case TestCaseBase::FRAGMENT_SHADER_TYPE: \ break; \ case TestCaseBase::COMPUTE_SHADER_TYPE: \ break; \ case TestCaseBase::GEOMETRY_SHADER_TYPE: \ SOURCE += emit_quad; \ break; \ case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: \ SOURCE += set_tesseation; \ break; \ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: \ break; \ default: \ TCU_FAIL("Unrecognized shader type."); \ break; \ } \ \ /* End main function */ \ SOURCE += shader_end; \ } while (0) /** Macro executes positive test selected on USE_ALL_SHADER_STAGES * * @param TYPE Tested shader stage * @param SOURCE Tested shader source * @param DELETE Selects if program should be deleted afterwards **/ #define EXECUTE_POSITIVE_TEST(TYPE, SOURCE, DELETE, GPU5) \ do { \ const std::string* cs = &empty_string; \ const std::string* vs = &default_vertex_shader_source; \ const std::string* tcs = &default_tc_shader_source; \ const std::string* tes = &default_te_shader_source; \ const std::string* fs = &default_fragment_shader_source; \ \ switch (TYPE) \ { \ case TestCaseBase::COMPUTE_SHADER_TYPE: \ this->execute_positive_test(empty_string, empty_string, empty_string, \ empty_string, empty_string, SOURCE, \ DELETE, GPU5); \ break; \ case TestCaseBase::FRAGMENT_SHADER_TYPE: \ this->execute_positive_test(*vs, SOURCE, DELETE, GPU5); \ break; \ case TestCaseBase::GEOMETRY_SHADER_TYPE: \ this->execute_positive_test(*vs, empty_string, empty_string, SOURCE, *fs, \ *cs, DELETE, GPU5); \ break; \ case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: \ this->execute_positive_test(*vs, SOURCE, *tes, empty_string, *fs, *cs, \ DELETE, GPU5); \ break; \ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: \ this->execute_positive_test(*vs, *tcs, SOURCE, empty_string, *fs, *cs, \ DELETE, GPU5); \ break; \ case TestCaseBase::VERTEX_SHADER_TYPE: \ this->execute_positive_test(SOURCE, *fs, DELETE, GPU5); \ break; \ default: \ TCU_FAIL("Invalid enum"); \ break; \ }; \ } while (0) /** Macro executes either positive or negative test * * @param S Selects negative test when 0, positive test otherwise * @param TYPE Tested shader stage * @param SOURCE Tested shader source **/ #define EXECUTE_SHADER_TEST(S, TYPE, SOURCE) \ do { \ if (S) \ { \ EXECUTE_POSITIVE_TEST(TYPE, SOURCE, true, false); \ } \ else \ { \ this->execute_negative_test(TYPE, SOURCE); \ } \ } while (0) /** Test case constructor. * * @tparam API Tested API descriptor * * @param context EGL context ID. * @param name Name of a test case. * @param description Test case description. **/ template TestCaseBase::TestCaseBase(Context& context, const char* name, const char* description) : tcu::TestCase(context.getTestContext(), name, description) , context_id(context) , program_object_id(0) , compute_shader_object_id(0) , fragment_shader_object_id(0) , geometry_shader_object_id(0) , tess_ctrl_shader_object_id(0) , tess_eval_shader_object_id(0) , vertex_shader_object_id(0) { /* Left blank on purpose */ } /** Clears up the shaders and program that were created during the tests * * @tparam API Tested API descriptor */ template void TestCaseBase::delete_objects(void) { const glw::Functions& gl = context_id.getRenderContext().getFunctions(); /* Release all ES objects that may have been created by iterate() */ if (program_object_id != 0) { gl.deleteProgram(program_object_id); program_object_id = 0; } /* Use default program object to be sure the objects were released. */ gl.useProgram(0); } /** Releases all OpenGL ES objects that were created for test case purposes. * * @tparam API Tested API descriptor */ template void TestCaseBase::deinit(void) { this->delete_objects(); } /** Runs the actual test for each shader type. * * @tparam API Tested API descriptor * * @return QP_TEST_RESULT_FAIL - test has failed; * QP_TEST_RESULT_PASS - test has succeeded; **/ template tcu::TestNode::IterateResult TestCaseBase::iterate(void) { test_shader_compilation(TestCaseBase::VERTEX_SHADER_TYPE); test_shader_compilation(TestCaseBase::FRAGMENT_SHADER_TYPE); if (API::USE_ALL_SHADER_STAGES) { test_shader_compilation(TestCaseBase::COMPUTE_SHADER_TYPE); test_shader_compilation(TestCaseBase::GEOMETRY_SHADER_TYPE); test_shader_compilation(TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE); test_shader_compilation(TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE); } return STOP; } /** Generates a shader object of the specified type, * attaches the specified shader source, * compiles it, and returns the compilation result. * * @tparam API Tested API descriptor * * @param shader_source The source for the shader object. * @param tested_shader_type The type of shader being compiled (vertex or fragment). * * @return Compilation result (GL_TRUE if the shader compilation succeeded, GL_FALSE otherwise). **/ template glw::GLint TestCaseBase::compile_shader_and_get_compilation_result(const std::string& tested_snippet, TestShaderType tested_shader_type, bool require_gpu_shader5) { static const char* preamble_cs = "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n"; static const char* preamble_gs = "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n"; static const char* preamble_tcs = "\n" "layout(vertices = 1) out;\n" "\n"; static const char* preamble_tes = "\n" "layout(isolines, point_mode) in;\n" "\n"; glw::GLint compile_status = GL_TRUE; const glw::Functions& gl = context_id.getRenderContext().getFunctions(); glw::GLint shader_object_id = 0; std::string shader_source; if (true == tested_snippet.empty()) { return compile_status; } if (require_gpu_shader5) { // Add the version number here, rather than in each individual test shader_source = API::shader_version_gpu5; } else { // Add the version number here, rather than in each individual test shader_source = API::shader_version; } /* Apply stage specific stuff */ switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: break; case TestCaseBase::COMPUTE_SHADER_TYPE: shader_source += preamble_cs; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: shader_source += preamble_gs; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: shader_source += preamble_tcs; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: shader_source += preamble_tes; break; default: TCU_FAIL("Unrecognized shader type."); break; } shader_source += tested_snippet; /* Prepare shader object */ switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: { shader_object_id = gl.createShader(GL_VERTEX_SHADER); assert(0 == vertex_shader_object_id); vertex_shader_object_id = shader_object_id; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a vertex shader."); break; } /* case TestCaseBase::VERTEX_SHADER_TYPE: */ case TestCaseBase::FRAGMENT_SHADER_TYPE: { shader_object_id = gl.createShader(GL_FRAGMENT_SHADER); assert(0 == fragment_shader_object_id); fragment_shader_object_id = shader_object_id; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a fragment shader."); break; } /* case TestCaseBase::FRAGMENT_SHADER_TYPE: */ case TestCaseBase::COMPUTE_SHADER_TYPE: { shader_object_id = gl.createShader(GL_COMPUTE_SHADER); assert(0 == compute_shader_object_id); compute_shader_object_id = shader_object_id; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a compute shader."); break; } /* case TestCaseBase::COMPUTE_SHADER_TYPE: */ case TestCaseBase::GEOMETRY_SHADER_TYPE: { shader_object_id = gl.createShader(GL_GEOMETRY_SHADER); assert(0 == geometry_shader_object_id); geometry_shader_object_id = shader_object_id; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a geometry shader."); break; } /* case TestCaseBase::GEOMETRY_SHADER_TYPE: */ case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: { shader_object_id = gl.createShader(GL_TESS_CONTROL_SHADER); assert(0 == tess_ctrl_shader_object_id); tess_ctrl_shader_object_id = shader_object_id; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a tesselation control shader."); break; } /* case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: { shader_object_id = gl.createShader(GL_TESS_EVALUATION_SHADER); assert(0 == tess_eval_shader_object_id); tess_eval_shader_object_id = shader_object_id; GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a tesselation evaluation shader."); break; } /* case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: */ default: { TCU_FAIL("Unrecognized shader type."); break; } /* default: */ } /* switch (tested_shader_type) */ /* Assign source code to the objects */ const char* code_ptr = shader_source.c_str(); #if IS_DEBUG_DUMP_ALL_SHADERS context_id.getTestContext().getLog() << tcu::TestLog::Message << "Compiling: " << tcu::TestLog::EndMessage; context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(code_ptr); #endif /* IS_DEBUG_DUMP_ALL_SHADERS */ gl.shaderSource(shader_object_id, 1 /* count */, &code_ptr, NULL); GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed"); /* Compile the shader */ gl.compileShader(shader_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed"); /* Get the compilation result. */ gl.getShaderiv(shader_object_id, GL_COMPILE_STATUS, &compile_status); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed"); #if IS_DEBUG if (GL_TRUE != compile_status) { glw::GLint length = 0; std::string message; /* Error log length */ gl.getShaderiv(shader_object_id, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); /* Prepare storage */ message.resize(length, 0); /* Get error log */ gl.getShaderInfoLog(shader_object_id, length, 0, &message[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); context_id.getTestContext().getLog() << tcu::TestLog::Message << "Error message: " << &message[0] << tcu::TestLog::EndMessage; #if IS_DEBUG_DUMP_ALL_SHADERS #else /* IS_DEBUG_DUMP_ALL_SHADERS */ context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(code_ptr); #endif /* IS_DEBUG_DUMP_ALL_SHADERS */ } #endif /* IS_DEBUG */ return compile_status; } /** Runs the negative test. * The shader sources are considered as invalid, * and the compilation of a shader object with the specified * shader source is expected to fail. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader object (can be fragment or vertex). * @param shader_source The source for the shader object to be used for this test. * * @return QP_TEST_RESULT_FAIL - test has failed; * QP_TEST_RESULT_PASS - test has succeeded; **/ template tcu::TestNode::IterateResult TestCaseBase::execute_negative_test( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& shader_source) { glw::GLint compile_status = GL_FALSE; const char* error_message = 0; const glw::Functions& gl = context_id.getRenderContext().getFunctions(); bool test_result = true; /* Try to generate and compile the shader object. */ switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: error_message = "The fragment shader was expected to fail to compile, but the compilation process was successful."; break; case TestCaseBase::VERTEX_SHADER_TYPE: error_message = "The vertex shader was expected to fail to compile, but the compilation process was successful."; break; case TestCaseBase::COMPUTE_SHADER_TYPE: error_message = "The compute shader was expected to fail to compile, but the compilation process was successful."; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: error_message = "The geometry shader was expected to fail to compile, but the compilation process was successful."; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: error_message = "The tesselation control shader was expected to fail to compile, but the compilation process " "was successful."; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: error_message = "The tesselation evaluation shader was expected to fail to compile, but the compilation " "process was successful."; break; default: TCU_FAIL("Unrecognized shader type."); test_result = false; break; } /* switch (shader_type) */ compile_status = compile_shader_and_get_compilation_result(shader_source, tested_shader_type); if (compile_status == GL_TRUE) { TCU_FAIL(error_message); test_result = false; } /* Deallocate any resources used. */ this->delete_objects(); if (0 != compute_shader_object_id) { gl.deleteShader(compute_shader_object_id); compute_shader_object_id = 0; } if (0 != fragment_shader_object_id) { gl.deleteShader(fragment_shader_object_id); fragment_shader_object_id = 0; } if (0 != geometry_shader_object_id) { gl.deleteShader(geometry_shader_object_id); geometry_shader_object_id = 0; } if (0 != tess_ctrl_shader_object_id) { gl.deleteShader(tess_ctrl_shader_object_id); tess_ctrl_shader_object_id = 0; } if (0 != tess_eval_shader_object_id) { gl.deleteShader(tess_eval_shader_object_id); tess_eval_shader_object_id = 0; } if (0 != vertex_shader_object_id) { gl.deleteShader(vertex_shader_object_id); vertex_shader_object_id = 0; } /* Return test pass if true. */ if (true == test_result) { m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); } return CONTINUE; } /** Runs the positive test. * The shader sources are considered as valid, * and the compilation and program linking are expected to succeed. * * @tparam API Tested API descriptor * * @param vertex_shader_source The source for the vertex shader to be used for this test. * @param fragment_shader_source The source for the fragment shader to be used for this test. * @param delete_generated_objects If true, the compiled shader objects will be deleted before returning. * * @return QP_TEST_RESULT_FAIL - test has failed; * QP_TEST_RESULT_PASS - test has succeeded; **/ template tcu::TestNode::IterateResult TestCaseBase::execute_positive_test(const std::string& vertex_shader_source, const std::string& fragment_shader_source, bool delete_generated_objects, bool require_gpu_shader5) { glw::GLint compile_status = GL_TRUE; const glw::Functions& gl = context_id.getRenderContext().getFunctions(); glw::GLint link_status = GL_TRUE; bool test_result = true; /* Compile, and check the compilation result for the fragment shader object. */ compile_status = compile_shader_and_get_compilation_result( fragment_shader_source, TestCaseBase::FRAGMENT_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The fragment shader was expected to compile successfully, but failed to compile."); test_result = false; } /* Compile, and check the compilation result for the vertex shader object. */ compile_status = compile_shader_and_get_compilation_result( vertex_shader_source, TestCaseBase::VERTEX_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The vertex shader was expected to compile successfully, but failed to compile."); test_result = false; } if (true == test_result) { /* Create program object. */ assert(0 == program_object_id); program_object_id = gl.createProgram(); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a program object."); /* Configure the program object */ gl.attachShader(program_object_id, fragment_shader_object_id); gl.attachShader(program_object_id, vertex_shader_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed."); gl.deleteShader(fragment_shader_object_id); gl.deleteShader(vertex_shader_object_id); fragment_shader_object_id = 0; vertex_shader_object_id = 0; /* Link the program object */ gl.linkProgram(program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed."); /* Make sure the linking operation succeeded. */ gl.getProgramiv(program_object_id, GL_LINK_STATUS, &link_status); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed."); if (link_status != GL_TRUE) { #if IS_DEBUG glw::GLint length = 0; std::string message; /* Get error log length */ gl.getProgramiv(program_object_id, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); message.resize(length, 0); /* Get error log */ gl.getProgramInfoLog(program_object_id, length, 0, &message[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); context_id.getTestContext().getLog() << tcu::TestLog::Message << "Error message: " << &message[0] << tcu::TestLog::EndMessage; #if IS_DEBUG_DUMP_ALL_SHADERS #else /* IS_DEBUG_DUMP_ALL_SHADERS */ context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(vertex_shader_source); context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(fragment_shader_source); #endif /* IS_DEBUG_DUMP_ALL_SHADERS */ #endif /* IS_DEBUG */ if (delete_generated_objects) { /* Deallocate any resources used. */ this->delete_objects(); } TCU_FAIL("Linking was expected to succeed, but the process was unsuccessful."); test_result = false; } } if (delete_generated_objects) { /* Deallocate any resources used. */ this->delete_objects(); } /* Return test pass if true. */ if (true == test_result) { m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); } return CONTINUE; } /** Check that the shader supports the number of SSBOs used in the test. * The number of active shader storage blocks referenced by the shaders in a program implementation dependent and cannot exceeds * implementation-dependent limits. The limits for vertex, tessellation control, tessellation evaluation and geometry can be obtained * by calling GetIntegerv with pname values of MAX_VERTEX_SHADER_STORAGE_BLOCKS, MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, * MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS and MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, respectively. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader used. * @param num The number of SSBOs used in shader. * * @return STOP - test is not supported by the implementation; * CONTINUE - test is supported by the implementation; **/ template tcu::TestNode::IterateResult TestCaseBase::limit_active_shader_storage_block_number( typename TestCaseBase::TestShaderType tested_shader_type, size_t num) { const glw::Functions& gl = context_id.getRenderContext().getFunctions(); glw::GLint res; switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &res); if (static_cast(res) < num) { tcu::NotSupportedError( "The number of active vertex shader storage blocks exceeds implementation-dependent limits."); return STOP; } break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &res); if (static_cast(res) < num) { tcu::NotSupportedError("The number of active TC shader storage blocks exceeds implementation-dependent limits."); return STOP; } break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &res); if (static_cast(res) < num) { tcu::NotSupportedError("The number of active TE shader storage blocks exceeds implementation-dependent limits."); return STOP; } break; case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &res); if (static_cast(res) < num) { tcu::NotSupportedError("The number of active geometry shader storage blocks exceeds implementation-dependent limits."); return STOP; } break; default: break; } return CONTINUE; } /** Runs the positive test. * The shader sources are considered as valid, * and the compilation and program linking are expected to succeed. * * @tparam API Tested API descriptor * * @param vertex_shader_source The source for the vertex shader to be used for this test. * @param tess_ctrl_shader_source The source for the vertex shader to be used for this test. * @param tess_eval_shader_source The source for the vertex shader to be used for this test. * @param geometry_shader_source The source for the vertex shader to be used for this test. * @param fragment_shader_source The source for the vertex shader to be used for this test. * @param compute_shader_source The source for the fragment shader to be used for this test. * @param delete_generated_objects If true, the compiled shader objects will be deleted before returning. * * @return QP_TEST_RESULT_FAIL - test has failed; * QP_TEST_RESULT_PASS - test has succeeded; **/ template tcu::TestNode::IterateResult TestCaseBase::execute_positive_test( const std::string& vertex_shader_source, const std::string& tess_ctrl_shader_source, const std::string& tess_eval_shader_source, const std::string& geometry_shader_source, const std::string& fragment_shader_source, const std::string& compute_shader_source, bool delete_generated_objects, bool require_gpu_shader5) { glw::GLint compile_status = GL_TRUE; const glw::Functions& gl = context_id.getRenderContext().getFunctions(); glw::GLint link_status = GL_TRUE; bool test_compute = !compute_shader_source.empty(); bool test_result = true; if (false == test_compute) { /* Compile, and check the compilation result for the fragment shader object. */ compile_status = compile_shader_and_get_compilation_result( fragment_shader_source, TestCaseBase::FRAGMENT_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The fragment shader was expected to compile successfully, but failed to compile."); test_result = false; } /* Compile, and check the compilation result for the geometry shader object. */ compile_status = compile_shader_and_get_compilation_result( geometry_shader_source, TestCaseBase::GEOMETRY_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The geometry shader was expected to compile successfully, but failed to compile."); test_result = false; } /* Compile, and check the compilation result for the te shader object. */ compile_status = compile_shader_and_get_compilation_result( tess_eval_shader_source, TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The tesselation evaluation shader was expected to compile successfully, but failed to compile."); test_result = false; } /* Compile, and check the compilation result for the tc shader object. */ compile_status = compile_shader_and_get_compilation_result( tess_ctrl_shader_source, TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The tesselation control shader was expected to compile successfully, but failed to compile."); test_result = false; } /* Compile, and check the compilation result for the vertex shader object. */ compile_status = compile_shader_and_get_compilation_result( vertex_shader_source, TestCaseBase::VERTEX_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The vertex shader was expected to compile successfully, but failed to compile."); test_result = false; } } else { /* Compile, and check the compilation result for the compute shader object. */ compile_status = compile_shader_and_get_compilation_result( compute_shader_source, TestCaseBase::COMPUTE_SHADER_TYPE, require_gpu_shader5); if (compile_status == GL_FALSE) { TCU_FAIL("The compute shader was expected to compile successfully, but failed to compile."); test_result = false; } } if (true == test_result) { /* Create program object. */ program_object_id = gl.createProgram(); GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a program object."); /* Configure the program object */ if (false == test_compute) { gl.attachShader(program_object_id, fragment_shader_object_id); if (geometry_shader_object_id) { gl.attachShader(program_object_id, geometry_shader_object_id); } if (tess_ctrl_shader_object_id) { gl.attachShader(program_object_id, tess_ctrl_shader_object_id); } if (tess_eval_shader_object_id) { gl.attachShader(program_object_id, tess_eval_shader_object_id); } gl.attachShader(program_object_id, vertex_shader_object_id); } else { gl.attachShader(program_object_id, compute_shader_object_id); } GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed."); if (false == test_compute) { gl.deleteShader(fragment_shader_object_id); if (geometry_shader_object_id) { gl.deleteShader(geometry_shader_object_id); } if (tess_ctrl_shader_object_id) { gl.deleteShader(tess_ctrl_shader_object_id); } if (tess_eval_shader_object_id) { gl.deleteShader(tess_eval_shader_object_id); } gl.deleteShader(vertex_shader_object_id); } else { gl.deleteShader(compute_shader_object_id); } fragment_shader_object_id = 0; vertex_shader_object_id = 0; geometry_shader_object_id = 0; tess_ctrl_shader_object_id = 0; tess_eval_shader_object_id = 0; compute_shader_object_id = 0; /* Link the program object */ gl.linkProgram(program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed."); /* Make sure the linking operation succeeded. */ gl.getProgramiv(program_object_id, GL_LINK_STATUS, &link_status); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed."); if (link_status != GL_TRUE) { #if IS_DEBUG glw::GLint length = 0; std::string message; /* Get error log length */ gl.getProgramiv(program_object_id, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); message.resize(length, 0); /* Get error log */ gl.getProgramInfoLog(program_object_id, length, 0, &message[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); context_id.getTestContext().getLog() << tcu::TestLog::Message << "Error message: " << &message[0] << tcu::TestLog::EndMessage; #if IS_DEBUG_DUMP_ALL_SHADERS if (false == test_compute) { context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(vertex_shader_source); context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(tess_ctrl_shader_source); context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(tess_eval_shader_source); context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(geometry_shader_source); context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(fragment_shader_source); } else { context_id.getTestContext().getLog() << tcu::TestLog::KernelSource(compute_shader_source); } #endif /* IS_DEBUG_DUMP_ALL_SHADERS */ #endif /* IS_DEBUG */ if (delete_generated_objects) { /* Deallocate any resources used. */ this->delete_objects(); } TCU_FAIL("Linking was expected to succeed, but the process was unsuccessful."); test_result = false; } } if (delete_generated_objects) { /* Deallocate any resources used. */ this->delete_objects(); } /* Return test pass if true. */ if (true == test_result) { m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); } return CONTINUE; } /** Adds the specified @param sub_script onto the base_string @param number_of_elements times. * E.g. extend_string("a", [2], 3) would give a[2][2][2]. * * @tparam API Tested API descriptor * * @param base_string The base string that is to be added to. * @param sub_string The string to be repeatedly added * @param number_of_elements The number of repetitions. * * @return The extended string. **/ template std::string TestCaseBase::extend_string(std::string base_string, std::string sub_string, size_t number_of_elements) { std::string temp_string = base_string; for (size_t sub_script_index = 0; sub_script_index < number_of_elements; sub_script_index++) { temp_string += sub_string; } return temp_string; } /* Generates the shader source code for the SizedDeclarationsPrimitive * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). * **/ template void SizedDeclarationsPrimitive::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { for (size_t var_type_index = 0; var_type_index < API::n_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { /* Loop round for each var_types ("int", "uint", "float", etc.) * We are testing a[][] to a [][][][][][][][], so start counter at 2. */ for (size_t max_dimension_limit = 2; max_dimension_limit <= API::MAX_ARRAY_DIMENSIONS; max_dimension_limit++) { // Record the base varTypeModifier + varType std::string base_var_type = var_iterator->second.type; std::string base_variable_string = base_var_type; for (size_t base_sub_script_index = 0; base_sub_script_index <= max_dimension_limit; base_sub_script_index++) { std::string shader_source = ""; // Add the shader body start, and the base varTypeModifier + varType + variable name. shader_source += shader_start + " " + base_variable_string + " a"; for (size_t remaining_sub_script_index = base_sub_script_index; remaining_sub_script_index < max_dimension_limit; remaining_sub_script_index++) { /* Add as many array sub_scripts as we can, up to the current dimension limit. */ shader_source += "[2]"; } /* End line */ shader_source += ";\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); /* From now on, we'll have an extra sub_script each time. */ base_variable_string += "[2]"; } /* for (int base_sub_script_index = 0; ...) */ } /* for (int max_dimension_limit = 2; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the SizedDeclarationsStructTypes1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsStructTypes1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_struct("struct light {\n" " float intensity;\n" " int position;\n" "};\n\n"); std::string shader_source; for (size_t max_dimension_index = 1; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { shader_source = example_struct; shader_source += shader_start; shader_source += " light[2]"; for (size_t temp_dimension_index = 0; temp_dimension_index < max_dimension_index; temp_dimension_index++) { shader_source += "[2]"; } shader_source += " x;\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* Generates the shader source code for the SizedDeclarationsStructTypes2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsStructTypes2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string structure_declaration = "struct MyStructure {\n" " float a[2], " "b[2][2], " "c[2][2][2], " "d[2][2][2][2], " "e[2][2][2][2][2], " "f[2][2][2][2][2][2], " "g[2][2][2][2][2][2][2], " "h[2][2][2][2][2][2][2][2];\n" "} myStructureObject;\n\n"; std::string shader_source = structure_declaration; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Generates the shader source code for the SizedDeclarationsStructTypes3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsStructTypes3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_struct("struct light {\n" " float[2] intensity;\n" " int[2] position;\n" "};\n"); std::string shader_source; for (size_t max_dimension_index = 1; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { shader_source = example_struct; shader_source += shader_start; shader_source += this->extend_string(" light my_light_object", "[2]", max_dimension_index); shader_source += ";\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* Generates the shader source code for the SizedDeclarationsStructTypes4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsStructTypes4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_struct("struct light {\n" " float[2] intensity;\n" " int[2] position;\n" "} lightVar[2]"); std::string shader_source; for (size_t max_dimension_index = 1; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { shader_source = example_struct; for (size_t temp_dimension_index = 0; temp_dimension_index < max_dimension_index; temp_dimension_index++) { shader_source += "[2]"; } shader_source += ";\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* Generates the shader source code for the SizedDeclarationsTypenameStyle1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsTypenameStyle1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { for (size_t max_dimension_index = 1; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string shader_source = shader_start; shader_source += this->extend_string(" float", "[2]", max_dimension_index); shader_source += this->extend_string(" x", "[2]", API::MAX_ARRAY_DIMENSIONS - max_dimension_index); shader_source += ";\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* Generates the shader source code for the SizedDeclarationsTypenameStyle2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsTypenameStyle2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_source = shader_start; shader_source += this->extend_string(" float", "[2]", 2); shader_source += this->extend_string(" a", "[2]", 0); shader_source += ", "; shader_source += this->extend_string("b", "[2]", 1); shader_source += ", "; shader_source += this->extend_string("c", "[2]", 2); shader_source += ", "; shader_source += this->extend_string("d", "[2]", 3); shader_source += ", "; shader_source += this->extend_string("e", "[2]", 4); shader_source += ", "; shader_source += this->extend_string("f", "[2]", 5); shader_source += ", "; shader_source += this->extend_string("g", "[2]", 6); shader_source += ";\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Generates the shader source code for the SizedDeclarationsTypenameStyle3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsTypenameStyle3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_source = "struct{\n" + this->extend_string(" float", "[2]", 2); shader_source += this->extend_string(" a", "[2]", 0); shader_source += ","; shader_source += this->extend_string(" b", "[2]", 1); shader_source += ","; shader_source += this->extend_string(" c", "[2]", 2); shader_source += ","; shader_source += this->extend_string(" d", "[2]", 3); shader_source += ","; shader_source += this->extend_string(" e", "[2]", 4); shader_source += ","; shader_source += this->extend_string(" f", "[2]", 5); shader_source += ","; shader_source += this->extend_string(" g", "[2]", 6); shader_source += ";\n} x;\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Generates the shader source code for the SizedDeclarationsTypenameStyle4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsTypenameStyle4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_struct_begin("struct light {\n"); std::string example_struct_end("};\n\n"); for (size_t max_dimension_index = 1; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string shader_source = example_struct_begin; shader_source += this->extend_string(" float", "[2]", max_dimension_index); shader_source += this->extend_string(" x", "[2]", API::MAX_ARRAY_DIMENSIONS - max_dimension_index); shader_source += ";\n"; shader_source += example_struct_end; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* Generates the shader source code for the SizedDeclarationsTypenameStyle5 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsTypenameStyle5::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_struct_begin("struct light {\n"); std::string example_struct_end("};\n\n"); std::string shader_source = example_struct_begin; shader_source += this->extend_string(" float", "[2]", 2); shader_source += this->extend_string(" a", "[2]", 0); shader_source += ", "; shader_source += this->extend_string("b", "[2]", 2); shader_source += ", "; shader_source += this->extend_string("c", "[2]", 3); shader_source += ", "; shader_source += this->extend_string("d", "[2]", 4); shader_source += ", "; shader_source += this->extend_string("e", "[2]", 5); shader_source += ", "; shader_source += this->extend_string("f", "[2]", 6); shader_source += ";\n"; shader_source += example_struct_end; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Generates the shader source code for the SizedDeclarationsFunctionParams * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void SizedDeclarationsFunctionParams::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { size_t dimension_index = 0; std::string example_struct1("\nvoid my_function("); std::string example_struct2(")\n" "{\n" "}\n\n"); std::string base_variable_string; std::string variable_basenames[API::MAX_ARRAY_DIMENSIONS] = { "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8" }; std::string full_variable_names[API::MAX_ARRAY_DIMENSIONS]; for (size_t max_dimension_index = 0; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { full_variable_names[max_dimension_index] = this->extend_string(variable_basenames[max_dimension_index], "[2]", max_dimension_index + 1); } for (size_t max_dimension_index = 0; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { base_variable_string += "float "; base_variable_string += full_variable_names[max_dimension_index]; base_variable_string += ";\n"; } base_variable_string += example_struct1; base_variable_string += this->extend_string("float a", "[2]", 1); base_variable_string += ", "; base_variable_string += this->extend_string("float b", "[2]", 2); base_variable_string += ", "; base_variable_string += this->extend_string("float c", "[2]", 3); base_variable_string += ", "; base_variable_string += this->extend_string("float d", "[2]", 4); base_variable_string += ", "; base_variable_string += this->extend_string("float e", "[2]", 5); base_variable_string += ", "; base_variable_string += this->extend_string("float f", "[2]", 6); base_variable_string += ", "; base_variable_string += this->extend_string("float g", "[2]", 7); base_variable_string += ", "; base_variable_string += this->extend_string("float h", "[2]", 8); base_variable_string += example_struct2; std::string shader_source = base_variable_string; shader_source += shader_start; shader_source += " my_function("; for (dimension_index = 0; dimension_index < API::MAX_ARRAY_DIMENSIONS - 1; dimension_index++) { shader_source += variable_basenames[dimension_index]; shader_source += ", "; } shader_source += variable_basenames[dimension_index]; shader_source += ");\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); /* Only the previous case should succeed, so start from index 1 rather than 0. * The other cases should fail, so only compile them, rather than trying to also link them. * We'll swap items 2/3, then 2/4, then 2/5, then 2/6, ... * Then we'll swap items 3/4, then 3/5, ... * Repeat, starting for 4/5-8, 5/6-8, 6/7-8... * Finally, we'll swap items 7/8 */ for (size_t swap_item = 1; swap_item < API::MAX_ARRAY_DIMENSIONS; swap_item++) { for (size_t max_dimension_index = swap_item + 1; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string temp = variable_basenames[swap_item]; shader_source = base_variable_string; variable_basenames[swap_item] = variable_basenames[max_dimension_index]; variable_basenames[max_dimension_index] = temp; shader_source += shader_start; shader_source += " my_function("; for (dimension_index = 0; dimension_index < API::MAX_ARRAY_DIMENSIONS - 1; dimension_index++) { shader_source += variable_basenames[dimension_index]; shader_source += ", "; } shader_source += variable_basenames[dimension_index]; shader_source += ");\n"; temp = variable_basenames[swap_item]; variable_basenames[swap_item] = variable_basenames[max_dimension_index]; variable_basenames[max_dimension_index] = temp; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int max_dimension_index = swap_item + 1; ...) */ } /* for (int swap_item = 1; ...) */ } /* Generates the shader source code for the sized_declarations_invalid_sizes1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void sized_declarations_invalid_sizes1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string invalid_declarations[] = { "float x[2][2][2][0];\n", "float x[2][2][0][2];\n", "float x[2][0][2][2];\n", "float x[0][2][2][2];\n", "float x[2][2][0][0];\n", "float x[2][0][2][0];\n", "float x[0][2][2][0];\n", "float x[2][0][0][2];\n", "float x[0][2][0][2];\n", "float x[0][0][2][2];\n", "float x[2][0][0][0];\n", "float x[0][2][0][0];\n", "float x[0][0][2][0];\n", "float x[0][0][0][2];\n", "float x[0][0][0][0];\n" }; for (size_t invalid_declarations_index = 0; invalid_declarations_index < DE_LENGTH_OF_ARRAY(invalid_declarations); invalid_declarations_index++) { std::string shader_source; shader_source = shader_start; shader_source += invalid_declarations[invalid_declarations_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_declarations_index = 0; ...) */ } /* Generates the shader source code for the sized_declarations_invalid_sizes2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void sized_declarations_invalid_sizes2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string invalid_declarations[] = { " float x[2][2][2][-1];\n", " float x[2][2][-1][2];\n", " float x[2][-1][2][2];\n", " float x[-1][2][2][2];\n", " float x[2][2][-1][-1];\n", " float x[2][-1][2][-1];\n", " float x[-1][2][2][-1];\n", " float x[2][-1][-1][2];\n", " float x[-1][2][-1][2];\n", " float x[-1][-1][2][2];\n", " float x[2][-1][-1][-1];\n", " float x[-1][2][-1][-1];\n", " float x[-1][-1][2][-1];\n", " float x[-1][-1][-1][2];\n", " float x[-1][-1][-1][-1];\n" }; for (size_t invalid_declarations_index = 0; invalid_declarations_index < DE_LENGTH_OF_ARRAY(invalid_declarations); invalid_declarations_index++) { std::string shader_source; shader_source = shader_start; shader_source += invalid_declarations[invalid_declarations_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_declarations_index = 0; ...) */ } /* Generates the shader source code for the sized_declarations_invalid_sizes3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void sized_declarations_invalid_sizes3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string invalid_declarations[] = { " float x[2][2][2][a];\n", " float x[2][2][a][2];\n", " float x[2][a][2][2];\n", " float x[a][2][2][2];\n", " float x[2][2][a][a];\n", " float x[2][a][2][a];\n", " float x[a][2][2][a];\n", " float x[2][a][a][2];\n", " float x[a][2][a][2];\n", " float x[a][a][2][2];\n", " float x[2][a][a][a];\n", " float x[a][2][a][a];\n", " float x[a][a][2][a];\n", " float x[a][a][a][2];\n", " float x[a][a][a][a];\n" }; std::string non_constant_variable_declaration = " uint a = 2u;\n"; for (size_t invalid_declarations_index = 0; invalid_declarations_index < DE_LENGTH_OF_ARRAY(invalid_declarations); invalid_declarations_index++) { std::string shader_source; shader_source = shader_start; shader_source += non_constant_variable_declaration; shader_source += invalid_declarations[invalid_declarations_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_declarations_index = 0; ...) */ } /* Generates the shader source code for the sized_declarations_invalid_sizes4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void sized_declarations_invalid_sizes4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string input[] = { " float x[2,2][2][2];\n", " float x[2][2,2][2];\n", " float x[2][2][2,2];\n", " float x[2,2,2][2];\n", " float x[2][2,2,2];\n", " float x[2,2,2,2];\n" }; for (size_t string_index = 0; string_index < sizeof(input) / sizeof(input[0]); string_index++) { std::string shader_source; shader_source += shader_start; shader_source += input[string_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int string_index = 0; ...) */ } /* Constructs a suitable constructor for the specified number of dimensions. * * @tparam API Tested API descriptor * * @param var_type The type of the variable * @param dimension_index The current recursion level (counts down) * @param init_string The initialisation string */ template std::string ConstructorsAndUnsizedDeclConstructors1::recursively_initialise(std::string var_type, size_t dimension_index, std::string init_string) { std::string temp_string; if (dimension_index == 0) { temp_string = init_string; } else { std::string prefix = "\n"; for (size_t indent_index = dimension_index; indent_index < (API::MAX_ARRAY_DIMENSIONS + 1); indent_index++) { prefix += " "; } prefix += this->extend_string(var_type, "[]", dimension_index); prefix += "("; for (int sub_script_index = 0; sub_script_index < 2; sub_script_index++) { temp_string += prefix; temp_string += recursively_initialise(var_type, dimension_index - 1, init_string); prefix = ", "; if (sub_script_index == 1) { break; } } temp_string += ")"; } return temp_string; } /* Generates the shader source code for the ConstructorsAndUnsizedDeclConstructors1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclConstructors1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { //vec4 color = vec4(0.0, 1.0, 0.0, 1.0); int num_var_types = API::n_var_types; for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { for (size_t max_dimension_index = 2; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string base_variable_string = this->extend_string(" " + var_iterator->second.type + " a", "[]", max_dimension_index); base_variable_string += " = "; base_variable_string += recursively_initialise(var_iterator->second.type, max_dimension_index, var_iterator->second.initializer_with_ones); base_variable_string += ";\n\n"; std::string shader_source = shader_start + base_variable_string; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string base_structure = "struct my_structure\n"; base_structure += "{\n"; base_structure += " " + var_iterator->second.type + " b;\n"; base_structure += " " + var_iterator->second.type + " c;\n"; base_structure += "};\n\n"; for (size_t max_dimension_index = 1; max_dimension_index < API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string outer_separator = "("; std::string base_variable_string; base_variable_string += this->extend_string(" " + var_iterator->second.type + " a", "[2]", max_dimension_index); base_variable_string += " = "; base_variable_string += recursively_initialise(var_iterator->second.type, max_dimension_index, var_iterator->second.initializer_with_ones); base_variable_string += ";\n\n"; std::string shader_source = base_structure + shader_start + base_variable_string; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 1; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclConstructors2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclConstructors2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string base_variable_string = " float[2][2] x = float[2][2](float[4](1.0, 2.0, 3.0, 4.0));\n"; std::string shader_source = shader_start + base_variable_string; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); base_variable_string = "float[2][2] x = float[2][2](float[1][4](float[4](1.0, 2.0, 3.0, 4.0)));\n\n"; shader_source = base_variable_string + shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* Generates the shader source code for the ConstructorsAndUnsizedDeclUnsizedConstructors * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclUnsizedConstructors::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_variable_declarations = "= float[2][1][2][1](\n" " float[1][2][1](\n" " float[2][1]( \n" " float[1](12.3), float[1](54.2) \n" " )\n" " ),\n" " float[1][2][1](\n" " float[2][1]( \n" " float[1]( 3.2), float[1]( 7.4) \n" " )\n" " )\n" " );\n\n"; std::string input[] = { "float a[2][1][2][]", "float a[2][1][][1]", "float a[2][1][][]", "float a[2][][2][1]", "float a[2][][2][]", "float a[2][][][1]", "float a[2][][][]", "float a[][1][2][1]", "float a[][1][2][]", "float a[][1][][1]", "float a[][1][][]", "float a[][][2][1]", "float a[][][2][]", "float a[][][][1]", "float a[][][][]" }; for (size_t string_index = 0; string_index < sizeof(input) / sizeof(input[0]); string_index++) { std::string shader_source = shader_start + " " + input[string_index] + shader_variable_declarations; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int string_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclConst * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclConst::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_source = "const float[2][2] x = float[2][2](float[2](1.0, 2.0), float[2](3.0, 4.0));\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Generates the shader source code for the ConstructorsAndUnsizedDeclInvalidConstructors1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclInvalidConstructors1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { int num_var_types = sizeof(opaque_var_types) / sizeof(opaque_var_types[0]); for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(opaque_var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string base_variable_string = "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " my_sampler1;\n" + "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " my_sampler2;\n" + "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " my_sampler3;\n" + "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " my_sampler4;\n\n"; std::string shader_source = base_variable_string + shader_start; shader_source += " const " + var_iterator->second.type + "[2][2] x = " + var_iterator->second.type + "[2][2](" + var_iterator->second.type + "[2](my_sampler1, my_sampler2), " + var_iterator->second.type + "[2](my_sampler3, my_sampler4));\n\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclInvalidConstructors2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclInvalidConstructors2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string invalid_initializers[] = { " int x[2][2][0]; \n", " int x[2][0][2]; \n", " int x[0][2][2]; \n", " int x[2][0][0]; \n", " int x[0][2][0]; \n", " int x[0][0][2]; \n", " int x[0][0][0]; \n" }; for (size_t invalid_initializers_index = 0; invalid_initializers_index < sizeof(invalid_initializers) / sizeof(invalid_initializers[0]); invalid_initializers_index++) { std::string shader_source; shader_source = shader_start; shader_source += invalid_initializers[invalid_initializers_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_initializers_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclInvalidConstructors3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclInvalidConstructors3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string invalid_initializers[] = { " int x[2][2][-1]; \n", " int x[2][-1][2]; \n", " int x[-1][2][2]; \n", " int x[2][-1][-1]; \n", " int x[-1][2][-1]; \n", " int x[-1][-1][2]; \n", " int x[-1][-1][-1]; \n" }; for (size_t invalid_initializers_index = 0; invalid_initializers_index < sizeof(invalid_initializers) / sizeof(invalid_initializers[0]); invalid_initializers_index++) { std::string shader_source; shader_source = shader_start; shader_source += invalid_initializers[invalid_initializers_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_initializers_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclInvalidConstructors4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclInvalidConstructors4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string invalid_initializers[] = { " int x[2][2][a]; \n", " int x[2][a][2]; \n", " int x[a][2][2]; \n", " int x[2][a][a]; \n", " int x[a][2][a]; \n", " int x[a][a][2]; \n", " int x[a][a][a]; \n" }; std::string non_constant_variable_init = " uint a = 2u;\n"; for (size_t invalid_initializers_index = 0; invalid_initializers_index < sizeof(invalid_initializers) / sizeof(invalid_initializers[0]); invalid_initializers_index++) { std::string shader_source; shader_source = shader_start; shader_source += non_constant_variable_init; shader_source += invalid_initializers[invalid_initializers_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_initializers_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclConstructorSizing1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclConstructorSizing1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string valid_size_initializers[] = { "[1][1][1][]", "[1][1][][1]", "[1][][1][1]", "[][1][1][1]", "[1][1][][]", "[1][][1][]", "[][1][1][]", "[1][][][1]", "[][1][][1]", "[][][1][1]", "[1][][][]", "[][1][][]", "[][][1][]", "[][][][1]", "[][][][]" }; for (size_t var_type_index = 0; var_type_index < API::n_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { for (size_t valid_size_initializers_index = 0; valid_size_initializers_index < sizeof(valid_size_initializers) / sizeof(valid_size_initializers[0]); valid_size_initializers_index++) { std::string shader_source; std::string variable_constructor = " " + var_iterator->second.type + " x" + valid_size_initializers[valid_size_initializers_index] + " = " + var_iterator->second.type + "[1][1][1][1](" + var_iterator->second.type + "[1][1][1](" + var_iterator->second.type + "[1][1](" + var_iterator->second.type + "[1](" + var_iterator->second.initializer_with_zeroes + "))));\n"; shader_source = shader_start; shader_source += variable_constructor; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int valid_size_initializers_index = 0; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclConstructorSizing2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclConstructorSizing2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_source = shader_start; shader_source += " float[] a =" " float[](1.0, 2.0)," " b[] =" " float[][](" " float[](1.0, 2.0)," " float[](3.0, 4.0)" " )," " c[][] =" " float[][][](" " float[][](" " float[](1.0)," " float[](2.0)" " )" " )," " d[][][] =" " float[][][][](" " float[][][](" " float[][](" " float[](1.0, 2.0)," " float[](3.0, 4.0)," " float[](5.0, 6.0)" " )" " )," " float[][][](" " float[][](" " float[](1.0, 2.0)," " float[](3.0, 4.0)," " float[](5.0, 6.0)" " )" " )" " )," " e[][][][]=" " float[][][][][](" " float[][][][](" " float[][][](" " float[][](" " float[](1.0)," " float[](2.0)" " )," " float[][](" " float[](1.0)," " float[](2.0)" " )," " float[][](" " float[](1.0)," " float[](2.0)" " )" " )," " float[][][](" " float[][](" " float[](1.0)," " float[](2.0)" " )," " float[][](" " float[](1.0)," " float[](2.0)" " )," " float[][](" " float[](1.0)," " float[](2.0)" " )" " )" " )" " )," " f[][][][][]=" " float[][][][][][](" " float[][][][][](" " float[][][][](" " float[][][](" " float[][](" " float[](1.0)" " )" " )" " )" " )" " )," " g[][][][][][]=" " float[][][][][][][](" " float[][][][][][](" " float[][][][][](" " float[][][][](" " float[][][](" " float[][](" " float[](1.0)" " )" " )" " )" " )" " )" " )," " h[][][][][][][]=" " float[][][][][][][][](" " float[][][][][][][](" " float[][][][][][](" " float[][][][][](" " float[][][][](" " float[][][](" " float[][](" " float[](1.0)" " )" " )" " )" " )" " )" " )" " );\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Constructs a suitable constructor for the specified number of dimensions. * * @tparam API Tested API descriptor * * @param var_type The type of the variable * @param dimension_index The current recursion level (counts down) * @param init_string The initialisation string */ template std::string ConstructorsAndUnsizedDeclStructConstructors::recursively_initialise(std::string var_type, size_t dimension_index, std::string init_string) { std::string temp_string; if (dimension_index == 0) { temp_string = var_type + "(" + init_string + ")"; } else { std::string prefix = "\n"; for (size_t indent_index = dimension_index; indent_index < (API::MAX_ARRAY_DIMENSIONS + 1); indent_index++) { prefix += " "; } prefix += this->extend_string(var_type, "[]", dimension_index); prefix += "("; for (int sub_script_index = 0; sub_script_index < 2; sub_script_index++) { temp_string += prefix; temp_string += recursively_initialise(var_type, dimension_index - 1, init_string); prefix = ", "; if (dimension_index == 1) { break; } } temp_string += ")"; } return temp_string; } /* Generates the shader source code for the ConstructorsAndUnsizedDeclStructConstructors * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclStructConstructors::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_structure_definition("struct light {\n" " float intensity;\n" " int position;\n" "};\n"); std::string example_structure_object(" light my_light_variable"); for (size_t max_dimension_index = 2; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string base_variable_string = this->extend_string(example_structure_object, "[]", max_dimension_index); base_variable_string += " = "; base_variable_string += recursively_initialise("light", max_dimension_index, "1.0, 2"); base_variable_string += ";\n\n"; std::string shader_source = example_structure_definition + shader_start + base_variable_string; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 2; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclUnsizedArrays1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclUnsizedArrays1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string base_variable_string; for (size_t max_dimension_index = 2; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { base_variable_string = this->extend_string(" int x", "[]", max_dimension_index); base_variable_string += ";\n\n"; std::string shader_source = shader_start + base_variable_string; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int max_dimension_index = 2; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclUnsizedArrays2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclUnsizedArrays2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string input[] = { " float [] x = float[](1), y;\n\n" }; for (size_t string_index = 0; string_index < sizeof(input) / sizeof(input[0]); string_index++) { std::string shader_source; shader_source += shader_start; shader_source += input[string_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_SHADER_TEST(API::ALLOW_UNSIZED_DECLARATION, tested_shader_type, shader_source); } /* for (int string_index = 0; ...) */ } /* Generates the shader source code for the ConstructorsAndUnsizedDeclUnsizedArrays3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclUnsizedArrays3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string base_variable_string(" float[][] x = mat4(0);\n\n"); std::string shader_source = shader_start + base_variable_string; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* Generates the shader source code for the ConstructorsAndUnsizedDeclUnsizedArrays4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ConstructorsAndUnsizedDeclUnsizedArrays4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string example_struct("struct light {\n" " float[][] intensity;\n" " int position;\n" "} myLight;\n\n"); std::string shader_source = example_struct + shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* Constructs a suitable constructor for the specified number of dimensions. * * @tparam API Tested API descriptor * * @param dimension_index The current recursion level (counts down) * @param init_string The initialisation string */ template std::string ExpressionsAssignment1::recursively_initialise(std::string var_type, size_t dimension_index, std::string init_string) { std::string temp_string; if (dimension_index == 0) { temp_string = init_string; } else { std::string prefix = "\n"; for (size_t indent_index = dimension_index; indent_index < (API::MAX_ARRAY_DIMENSIONS + 1); indent_index++) { prefix += " "; } prefix += this->extend_string(var_type, "[]", dimension_index); prefix += "("; for (int sub_script_index = 0; sub_script_index < 2; sub_script_index++) { temp_string += prefix; temp_string += recursively_initialise(var_type, dimension_index - 1, init_string); prefix = ", "; if (dimension_index == 1) { break; } } temp_string += ")"; } return temp_string; } /* Generates the shader source code for the ExpressionsAssignment1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsAssignment1::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { for (size_t max_dimension_index = 2; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string prefix = "("; std::string base_variable_string; base_variable_string += this->extend_string(" float x", "[2]", max_dimension_index); base_variable_string += " = "; base_variable_string += recursively_initialise("float", max_dimension_index, "4.0, 6.0"); base_variable_string += ";\n"; base_variable_string += this->extend_string(" float y", "[2]", max_dimension_index); base_variable_string += " = "; base_variable_string += recursively_initialise("float", max_dimension_index, "1.0, 2.0"); base_variable_string += ";\n\n"; std::string shader_source = shader_start + base_variable_string; shader_source += " x = y;\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int max_dimension_index = 2; ...) */ } /* Generates the shader source code for the ExpressionsAssignment2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsAssignment2::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_body(" float a[2] = float[](1.0, 2.0);\n" " float b[2][2] = float[][](float[](1.0, 2.0), float[](1.0, 2.0));\n" " float c[2][2][2] = float[][][](" "float[][](float[](1.0, 2.0), float[](1.0, 2.0))," "float[][](float[](1.0, 2.0), float[](1.0, 2.0)));\n" " float d[2][2][2][2] = float[][][][](" "float[][][](" "float[][](float[](1.0, 2.0), float[](1.0, 2.0)), " "float[][](float[](1.0, 2.0), float[](1.0, 2.0)))," "float[][][](" "float[][](float[](1.0, 2.0), float[](1.0, 2.0)), " "float[][](float[](1.0, 2.0), float[](1.0, 2.0))));\n\n"); std::string variable_basenames[] = { "a", "b", "c", "d" }; int number_of_elements = sizeof(variable_basenames) / sizeof(variable_basenames[0]); for (int variable_index = 0; variable_index < number_of_elements; variable_index++) { for (int value_index = variable_index; value_index < number_of_elements; value_index++) { std::string shader_source = shader_start + shader_body; /* Avoid the situation when a variable is assign to itself. */ if (variable_index != value_index) { shader_source += " " + variable_basenames[variable_index] + " = " + variable_basenames[value_index]; shader_source += ";\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if(variable_index != value_index) */ } /* for (int value_index = variable_index; ...) */ } /* for (int variable_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsAssignment3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsAssignment3::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string prefix, base_variable_string; const int test_array_dimensions = 4; prefix = this->extend_string(" float a", "[1]", 4); prefix += " = float[][][][](\n" " float[][][](\n" " float[][](\n" " float[](1.0))));\n"; prefix += " float b"; for (int permutation = 0; permutation < (1 << test_array_dimensions); permutation++) { base_variable_string = prefix; for (int sub_script_index = test_array_dimensions - 1; sub_script_index >= 0; sub_script_index--) { if (permutation & (1 << sub_script_index)) { base_variable_string += "[1]"; } else { base_variable_string += "[2]"; } } base_variable_string += ";\n\n"; if (permutation != (1 << test_array_dimensions) - 1) { std::string shader_source = shader_start + base_variable_string; shader_source += " b = a;\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if (permutation != (1 << test_array_dimensions) - 1) */ } /* for (int permutation = 0; ...) */ } /* Generates the shader source code for the ExpressionsTypeRestrictions1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsTypeRestrictions1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { int num_var_types = sizeof(opaque_var_types) / sizeof(opaque_var_types[0]); for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(opaque_var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source = "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " var1[2][2];\n" "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " var2[2][2];\n\n"; shader_source += shader_start; shader_source += " var1 = var2;\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsTypeRestrictions2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsTypeRestrictions2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { int num_var_types = sizeof(opaque_var_types) / sizeof(opaque_var_types[0]); for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(opaque_var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source = "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " sampler1;\n" "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " sampler2;\n" "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " sampler3;\n" "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " sampler4;\n" "struct light1 {\n" " " + var_iterator->second.type + " var1[2][2];\n" "};\n\n"; shader_source += shader_start; shader_source += (" light1 x = light1(" + var_iterator->second.type + "[][](" + var_iterator->second.type + "[](sampler1, sampler2), " + var_iterator->second.type + "[](sampler3, sampler4)));\n"); shader_source += " light1 y = x;\n\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsIndexingScalar1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingScalar1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { for (size_t var_type_index = 0; var_type_index < API::n_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source = shader_start + " " + var_iterator->second.type + " x[1][2][3][4];\n\n"; shader_source += " for (uint i = 0u; i < 2u; i++) {\n"; shader_source += " for (uint j = 0u; j < 3u; j++) {\n"; shader_source += " for (uint k = 0u; k < 4u; k++) {\n"; shader_source += " x[0][i][j][k] = " + var_iterator->second.initializer_with_ones + ";\n"; shader_source += " }\n"; shader_source += " }\n"; shader_source += " }\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the ExpressionsIndexingScalar2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingScalar2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string base_shader_string, shader_source; // This test tests arrays with 4 dimensions, e.g. x[1][1][1][1] const int test_array_dimensions = 4; base_shader_string = "float a[1][2][3][4];\n"; base_shader_string += "float b = 2.0;\n\n"; base_shader_string += shader_start; // There are 16 permutations, so loop 4x4 times. for (int permutation = 0; permutation < (1 << test_array_dimensions); permutation++) { shader_source = base_shader_string + " a"; // a var called 'a' for (int sub_script_index = test_array_dimensions - 1; sub_script_index >= 0; sub_script_index--) { /* If any bit is set for a particular number then add * a valid array sub_script at that place, otherwise * add an invalid array sub_script. */ if (permutation & (1 << sub_script_index)) { shader_source += "[0]"; } else { shader_source += "[-1]"; } } shader_source += " = b;\n"; if (permutation != (1 << test_array_dimensions) - 1) { /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if (permutation != (1 << test_array_dimensions) - 1) */ } /* for (int permutation = 0; ...) */ } /* Generates the shader source code for the ExpressionsIndexingScalar3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingScalar3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string base_shader_string; std::string shader_source; const int test_array_dimensions = 4; base_shader_string = "float a[1][2][3][4];\n"; base_shader_string += "float b = 2.0;\n\n"; base_shader_string += shader_start; for (int permutation = 0; permutation < (1 << test_array_dimensions); permutation++) { shader_source = base_shader_string + " a"; for (int sub_script_index = test_array_dimensions - 1; sub_script_index >= 0; sub_script_index--) { if (permutation & (1 << sub_script_index)) { shader_source += "[0]"; } else { shader_source += "[4]"; } } shader_source += " = b;\n"; if (permutation != (1 << test_array_dimensions) - 1) { /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if (permutation != (1 << test_array_dimensions) - 1) */ } /* for (int permutation = 0; ...) */ } /* Generates the shader source code for the ExpressionsIndexingScalar4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingScalar4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string base_shader_string; std::string shader_source; const int test_array_dimensions = 4; base_shader_string = "float a[1][2][3][4];\n"; base_shader_string += "float b = 2.0;\n\n"; base_shader_string += shader_start; for (int permutation = 0; permutation < (1 << test_array_dimensions); permutation++) { shader_source = base_shader_string + " a"; for (int sub_script_index = test_array_dimensions - 1; sub_script_index >= 0; sub_script_index--) { if (permutation & (1 << sub_script_index)) { shader_source += "[0]"; } else { shader_source += "[]"; } } shader_source += " = b;\n"; if (permutation != (1 << test_array_dimensions) - 1) { /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* if (permutation != (1 << test_array_dimensions) - 1) */ } /* for (int permutation = 0; ...) */ } /* Generates the shader source code for the ExpressionsIndexingArray1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingArray1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_source; std::string variable_declaration = "float x[1][1][1][1][1][1][1][1];\n\n"; std::string variable_initializations[] = { "x[0] = float[1][1][1][1][1][1][1](" "float[1][1][1][1][1][1](float[1][1][1][1][1](float[1][1][1][1](float[1][1][1](float[1][1](float[1](1.0)))))));" "\n", "x[0][0] = " "float[1][1][1][1][1][1](float[1][1][1][1][1](float[1][1][1][1](float[1][1][1](float[1][1](float[1](1.0))))));" "\n", "x[0][0][0] = " "float[1][1][1][1][1](float[1][1][1][1](float[1][1][1](float[1][1](float[1](1.0)))));\n", "x[0][0][0][0] = float[1][1][1][1](float[1][1][1](float[1][1](float[1](1.0))));\n", "x[0][0][0][0][0] = float[1][1][1](float[1][1](float[1](1.0)));\n", "x[0][0][0][0][0][0] = float[1][1](float[1](1.0));\n", "x[0][0][0][0][0][0][0] = float[1](1.0);\n", "x[0][0][0][0][0][0][0][0] = 1.0;\n" }; for (size_t string_index = 0; string_index < sizeof(variable_initializations) / sizeof(variable_initializations[0]); string_index++) { shader_source = variable_declaration + shader_start; shader_source += " " + variable_initializations[string_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int string_index = 0; ...) */ } /* Constructs a suitable constructor for the specified number of dimensions. * * @tparam API Tested API descriptor * * @param dimension_index The current recursion level (counts down) * @param init_string The initialisation string */ template std::string ExpressionsIndexingArray2::recursively_initialise(std::string var_type, size_t dimension_index, std::string init_string) { std::string temp_string; if (dimension_index == 0) { temp_string = init_string; } else { std::string prefix = "\n"; for (size_t indent_index = dimension_index; indent_index < (API::MAX_ARRAY_DIMENSIONS + 1); indent_index++) { prefix += " "; } prefix += this->extend_string(var_type, "[]", dimension_index); prefix += "("; for (int sub_script_index = 0; sub_script_index < 2; sub_script_index++) { temp_string += prefix; temp_string += recursively_initialise(var_type, dimension_index - 1, init_string); prefix = ", "; if (dimension_index == 1) { break; } } temp_string += ")"; } return temp_string; } /* Generates the shader source code for the ExpressionsIndexingArray2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingArray2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string variable_initialiser = " float[](float[](float(float(float(float(float(float(1.0))))))));\n"; std::string x_variable_initializaton = " float x[2][2][2][2][2][2][2][1] = " + recursively_initialise("float", API::MAX_ARRAY_DIMENSIONS, "1.0") + ";\n"; std::string y_variable_initializaton = " float y[2][2][2][2][2][2][2][1] = " + recursively_initialise("float", API::MAX_ARRAY_DIMENSIONS, "1.0") + ";\n"; std::string shader_code_common_part = shader_start + x_variable_initializaton + y_variable_initializaton; for (size_t max_dimension_index = 1; max_dimension_index <= API::MAX_ARRAY_DIMENSIONS; max_dimension_index++) { std::string iteration_specific_shader_code_part; iteration_specific_shader_code_part += this->extend_string(" x", "[0]", max_dimension_index); iteration_specific_shader_code_part += " = "; iteration_specific_shader_code_part += this->extend_string("y", "[0]", max_dimension_index); iteration_specific_shader_code_part += ";\n"; std::string shader_source = shader_code_common_part + iteration_specific_shader_code_part; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } } /* Generates the shader source code for the ExpressionsIndexingArray3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsIndexingArray3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string input[] = { " x[ivec2(0)] = 1.0;\n\n", " x[ivec3(0)] = 1.0;\n\n", " x[ivec4(0)] = 1.0;\n\n" }; for (size_t string_index = 0; string_index < sizeof(input) / sizeof(input[0]); string_index++) { std::string shader_source = shader_start + this->extend_string(" float x", "[2]", (int)string_index + 2) + ";\n\n" + input[string_index]; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int string_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsDynamicIndexing1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsDynamicIndexing1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { std::string expression_type_declarations = "uniform int a;\n" "const int b = 0;\n" "int c = 0;\n" "float x[2][2];\n"; std::string expressions[] = { "a", "b", "c", "0 + 1" }; std::string shader_source; for (size_t write_index = 0; write_index < sizeof(expressions) / sizeof(expressions[0]); write_index++) { for (size_t read_index = 0; read_index < sizeof(expressions) / sizeof(expressions[0]); read_index++) { shader_source = expression_type_declarations; shader_source += shader_start; shader_source += " x["; shader_source += expressions[write_index]; shader_source += "]["; shader_source += expressions[read_index]; shader_source += "] = 1.0;\n\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* for (int read_index = 0; ...) */ } /* for (int write_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsDynamicIndexing2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsDynamicIndexing2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { int num_var_types = sizeof(opaque_var_types) / sizeof(opaque_var_types[0]); const std::string invalid_size_declarations[] = { "[0][0][0][y]", "[0][0][y][0]", "[0][y][0][0]", "[y][0][0][0]", "[0][0][y][y]", "[0][y][0][y]", "[y][0][0][y]", "[0][y][y][0]", "[y][0][y][0]", "[y][y][0][0]", "[0][y][y][y]", "[y][0][y][y]", "[y][y][0][y]", "[y][y][y][0]", "[y][y][y][y]" }; bool dynamic_indexing_supported = false; if (glu::contextSupports(this->context_id.getRenderContext().getType(), glu::ApiType::es(3, 2)) || glu::contextSupports(this->context_id.getRenderContext().getType(), glu::ApiType::core(4, 0)) || this->context_id.getContextInfo().isExtensionSupported("GL_EXT_gpu_shader5")) { dynamic_indexing_supported = true; } for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(opaque_var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { int num_invalid_size_declarations = sizeof(invalid_size_declarations) / sizeof(invalid_size_declarations[0]); for (int invalid_size_index = 0; invalid_size_index < num_invalid_size_declarations; invalid_size_index++) { std::string shader_source = "int y = 1;\n"; shader_source += "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " x[2][2][2][2];\n\n"; shader_source += "void main()\n"; shader_source += "{\n"; shader_source += (" " + var_iterator->second.type_of_result_of_texture_function + " color = texture(x" + invalid_size_declarations[invalid_size_index] + ", " + var_iterator->second.coord_param_for_texture_function + ");\n"); /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); if (dynamic_indexing_supported) { EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, true); } else { this->execute_negative_test(tested_shader_type, shader_source); } } /* for (int invalid_size_index = 0; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsEquality1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsEquality1::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { int num_var_types = API::n_var_types; for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source = shader_start; shader_source += " "; shader_source += var_iterator->second.type; shader_source += "[][] x = "; shader_source += var_iterator->second.type; shader_source += "[][]("; shader_source += var_iterator->second.type; shader_source += "[]("; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += ","; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += "),"; shader_source += var_iterator->second.type; shader_source += "[]("; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += ","; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += "));\n"; shader_source += " "; shader_source += var_iterator->second.type; shader_source += "[][] y = "; shader_source += var_iterator->second.type; shader_source += "[][]("; shader_source += var_iterator->second.type; shader_source += "[]("; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += ","; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += "),"; shader_source += var_iterator->second.type; shader_source += "[]("; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += ","; shader_source += var_iterator->second.initializer_with_zeroes; shader_source += "));\n\n"; shader_source += " float result = 0.0;\n\n"; shader_source += " if (x == y)\n"; shader_source += " {\n"; shader_source += " result = 1.0;\n"; shader_source += " }\n"; shader_source += " if (y != x)\n"; shader_source += " {\n"; shader_source += " result = 2.0;\n"; shader_source += " }\n"; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the ExpressionsEquality2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsEquality2::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { int num_var_types = API::n_var_types; for (int var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source = "struct light {\n float intensity;\n int position;\n};\n\n"; shader_source += shader_start; shader_source += " light[][] x ="; shader_source += "light"; shader_source += "[][]("; shader_source += "light"; shader_source += "[](light(1.0, 1)),"; shader_source += "light"; shader_source += "[](light(2.0, 2)));\n\n"; shader_source += " light[][] y ="; shader_source += "light"; shader_source += "[][]("; shader_source += "light"; shader_source += "[](light(3.0, 3)),"; shader_source += "light"; shader_source += "[](light(4.0, 4)));\n\n"; shader_source += " float result = 0.0;\n\n"; shader_source += " if (x == y)\n"; shader_source += " {\n"; shader_source += " result = 1.0;\n"; shader_source += " }\n"; shader_source += " if (y != x)\n"; shader_source += " {\n"; shader_source += " result = 2.0;\n"; shader_source += " }\n"; /* Apply stage specific stuff */ switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: shader_source += "\n gl_Position = vec4(0.0,0.0,0.0,1.0);\n"; break; case TestCaseBase::FRAGMENT_SHADER_TYPE: shader_source += "\n gl_FragDepth = result;\n"; break; case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::GEOMETRY_SHADER_TYPE: shader_source += emit_quad; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: shader_source += set_tesseation; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: break; default: TCU_FAIL("Unrecognized shader type."); break; } /* End main function */ shader_source += shader_end; /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the ExpressionsLength1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsLength1::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string array_declaration = " int x[4][3][2][1];\n\n"; std::string case_specific_string[] = { " if (x.length() != 4) {\n" " result = 0.0f;\n }\n", " if (x[0].length() != 3) {\n" " result = 0.0f;\n }\n", " if (x[0][0].length() != 2) {\n" " result = 0.0f;\n }\n", " if (x[0][0][0].length() != 1) {\n" " result = 0.0f;\n }\n" }; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); for (size_t case_specific_string_index = 0; case_specific_string_index < sizeof(case_specific_string) / sizeof(case_specific_string[0]); case_specific_string_index++) { const std::string& test_snippet = case_specific_string[case_specific_string_index]; if (false == test_compute) { execute_draw_test(tested_shader_type, array_declaration, test_snippet); } else { execute_dispatch_test(tested_shader_type, array_declaration, test_snippet); } /* Deallocate any resources used. */ this->delete_objects(); } /* for (int case_specific_string_index = 0; ...) */ } /** Executes test for compute program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template void ExpressionsLength1::execute_dispatch_test(typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { const std::string& compute_shader_source = prepare_compute_shader(tested_shader_type, tested_declaration, tested_snippet); const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); this->execute_positive_test(empty_string, empty_string, empty_string, empty_string, empty_string, compute_shader_source, false, false); /* We are now ready to verify whether the returned size is correct. */ unsigned char buffer[4] = { 0 }; glw::GLuint framebuffer_object_id = 0; glw::GLint location = -1; glw::GLuint texture_object_id = 0; glw::GLuint vao_id = 0; gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); gl.bindImageTexture(0 /* image unit */, texture_object_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY, GL_RGBA8); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() failed."); location = gl.getUniformLocation(this->program_object_id, "uni_image"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed."); if (-1 == location) { TCU_FAIL("Uniform is inactive"); } gl.uniform1i(location, 0 /* image unit */); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() failed."); gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); gl.dispatchCompute(1, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); gl.readBuffer(GL_COLOR_ATTACHMENT0); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed."); gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed."); if (buffer[0] != 255) { TCU_FAIL("Invalid array size was returned."); } /* Delete generated objects. */ gl.deleteTextures(1, &texture_object_id); gl.deleteFramebuffers(1, &framebuffer_object_id); gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); } /** Executes test for draw program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template void ExpressionsLength1::execute_draw_test(typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = empty_string; const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, tested_declaration, tested_snippet); const std::string& geometry_shader_source = this->prepare_geometry_shader(tested_shader_type, tested_declaration, tested_snippet); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, tested_declaration, tested_snippet); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader(tested_shader_type, tested_declaration, tested_snippet); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, tested_declaration, tested_snippet); switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::FRAGMENT_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); break; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, false, false); break; default: TCU_FAIL("Invalid enum"); break; } } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, tested_declaration, tested_snippet); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, tested_declaration, tested_snippet); this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); } /* We are now ready to verify whether the returned size is correct. */ unsigned char buffer[4] = { 0 }; glw::GLuint framebuffer_object_id = 0; glw::GLuint texture_object_id = 0; glw::GLuint vao_id = 0; gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: /* Fall through */ case TestCaseBase::VERTEX_SHADER_TYPE: gl.drawArrays(GL_TRIANGLE_FAN, 0, 4); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); gl.drawArrays(GL_PATCHES, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.drawArrays(GL_POINTS, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; default: TCU_FAIL("Invalid enum"); break; } gl.readBuffer(GL_COLOR_ATTACHMENT0); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed."); gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed."); if (buffer[0] != 255) { TCU_FAIL("Invalid array size was returned."); } /* Delete generated objects. */ gl.deleteTextures(1, &texture_object_id); gl.deleteFramebuffers(1, &framebuffer_object_id); gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template std::string ExpressionsLength1::prepare_compute_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { std::string compute_shader_source; if (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type) { compute_shader_source = "writeonly uniform image2D uni_image;\n" "\n" "void main()\n" "{\n" " float result = 1u;\n" "\n"; compute_shader_source += tested_declaration; compute_shader_source += tested_snippet; compute_shader_source += "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), vec4(result, 0, 0, 0));\n" "}\n" "\n"; } return compute_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template std::string ExpressionsLength1::prepare_fragment_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { std::string fragment_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: fragment_shader_source = "out vec4 colour;\n" "\n" "void main()\n" "{\n"; fragment_shader_source += tested_declaration; fragment_shader_source += " float result = 1.0f;\n"; fragment_shader_source += tested_snippet; fragment_shader_source += " colour = vec4(result);\n" "}\n\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: fragment_shader_source = "in float fs_result;\n\n" "out vec4 colour;\n\n" "void main()\n" "{\n" " colour = vec4(fs_result);\n" "}\n" "\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return fragment_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template std::string ExpressionsLength1::prepare_geometry_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { std::string geometry_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in float tes_result[];\n" "out float fs_result;\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" "}\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "out float fs_result;\n" "\n" "void main()\n" "{\n"; geometry_shader_source += tested_declaration; geometry_shader_source += " float result = 1.0;\n\n"; geometry_shader_source += tested_snippet; geometry_shader_source += "\n gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return geometry_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template std::string ExpressionsLength1::prepare_tess_ctrl_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { std::string tess_ctrl_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_ctrl_shader_source = "layout(vertices = 1) out;\n" "\n" "out float tcs_result[];\n" "\n" "void main()\n" "{\n"; tess_ctrl_shader_source += tested_declaration; tess_ctrl_shader_source += " float result = 1.0;\n\n"; tess_ctrl_shader_source += tested_snippet; tess_ctrl_shader_source += " tcs_result[gl_InvocationID] = result;\n" "\n" " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_ctrl_shader_source = default_tc_shader_source; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_ctrl_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template std::string ExpressionsLength1::prepare_tess_eval_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { std::string tess_eval_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "in float tcs_result[];\n" "out float tes_result;\n" "\n" "void main()\n" "{\n" " tes_result = tcs_result[0];\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "out float tes_result;\n" "\n" "void main()\n" "{\n"; tess_eval_shader_source += tested_declaration; tess_eval_shader_source += " float result = 1.0;\n\n"; tess_eval_shader_source += tested_snippet; tess_eval_shader_source += " tes_result = result;\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_eval_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param tested_declaration Declaration used to prepare shader * @param tested_snippet Snippet used to prepare shader **/ template std::string ExpressionsLength1::prepare_vertex_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& tested_declaration, const std::string& tested_snippet) { std::string vertex_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: vertex_shader_source = "/** GL_TRIANGLE_FAN-type quad vertex data. */\n" "const vec4 vertex_positions[4] = vec4[4](vec4( 1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, 1.0, 0.0, 1.0),\n" " vec4( 1.0, 1.0, 0.0, 1.0) );\n" "\n" "void main()\n" "{\n" " gl_Position = vertex_positions[gl_VertexID];" "}\n\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: vertex_shader_source = default_vertex_shader_source; break; case TestCaseBase::VERTEX_SHADER_TYPE: vertex_shader_source = "out float fs_result;\n" "\n" "/** GL_TRIANGLE_FAN-type quad vertex data. */\n" "const vec4 vertex_positions[4] = vec4[4](vec4( 1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, 1.0, 0.0, 1.0),\n" " vec4( 1.0, 1.0, 0.0, 1.0) );\n" "\n" "void main()\n" "{\n"; vertex_shader_source += tested_declaration; vertex_shader_source += " float result = 1.0;\n\n"; vertex_shader_source += tested_snippet; vertex_shader_source += " gl_Position = vertex_positions[gl_VertexID];\n" " fs_result = result;\n"; vertex_shader_source += shader_end; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return vertex_shader_source; } /* Generates the shader source code for the ExpressionsLength2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsLength2::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string array_declaration = " int x[1][2][3][4];\n\n"; std::string case_specific_string[] = { " if (x.length() != 1) {\n" " result = 0.0f;\n }\n", " if (x[0].length() != 2) {\n" " result = 0.0f;\n }\n", " if (x[0][0].length() != 3) {\n" " result = 0.0f;\n }\n", " if (x[0][0][0].length() != 4) {\n" " result = 0.0f;\n }\n" }; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); for (size_t case_specific_string_index = 0; case_specific_string_index < sizeof(case_specific_string) / sizeof(case_specific_string[0]); case_specific_string_index++) { const std::string& test_snippet = case_specific_string[case_specific_string_index]; if (false == test_compute) { this->execute_draw_test(tested_shader_type, array_declaration, test_snippet); } else { this->execute_dispatch_test(tested_shader_type, array_declaration, test_snippet); } /* Deallocate any resources used. */ this->delete_objects(); } /* for (int case_specific_string_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsLength3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsLength3::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string array_declaration = " int x[1][1][1][1];\n\n"; std::string input[] = { " if (x[].length() != 2) {\n" " result = 0.0f;\n }\n", " if (x[][].length() != 2) {\n" " result = 0.0f;\n }\n", " if (x[][][].length() != 2) {\n" " result = 0.0f;\n }\n" }; for (size_t string_index = 0; string_index < sizeof(input) / sizeof(input[0]); string_index++) { std::string shader_source; const std::string& test_snippet = input[string_index]; switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: shader_source = this->prepare_vertex_shader(tested_shader_type, array_declaration, test_snippet); break; case TestCaseBase::FRAGMENT_SHADER_TYPE: shader_source = this->prepare_fragment_shader(tested_shader_type, array_declaration, test_snippet); break; case TestCaseBase::COMPUTE_SHADER_TYPE: shader_source = this->prepare_compute_shader(tested_shader_type, array_declaration, test_snippet); break; case TestCaseBase::GEOMETRY_SHADER_TYPE: shader_source = this->prepare_geometry_shader(tested_shader_type, array_declaration, test_snippet); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, array_declaration, test_snippet); break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: shader_source = this->prepare_tess_eval_shader(tested_shader_type, array_declaration, test_snippet); break; default: TCU_FAIL("Unrecognized shader type."); break; } /* switch (tested_shader_type) */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int string_index = 0; ...) */ } /* Generates the shader source code for the ExpressionsInvalid1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsInvalid1::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_variable_declarations = " mat2 y = mat2(0.0);\n" " float x[2][2] = float[2][2](float[2](4.0, 5.0), float[2](6.0, 7.0));\n\n"; std::string shader_source = shader_start + shader_variable_declarations; shader_source += " y = x;\n"; DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); this->execute_negative_test(tested_shader_type, shader_source); } /* Generates the shader source code for the ExpressionsInvalid2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void ExpressionsInvalid2::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { std::string shader_variable_declarations[] = { " x", " y" }; std::string variable_relation_opeartors[] = { " float result = 0.0;\n\n if(x < y)\n {\n result = 1.0;\n }\n\n\n", " float result = 0.0;\n\n if(x <= y)\n {\n result = 1.0;\n }\n\n\n", " float result = 0.0;\n\n if(x > y)\n {\n result = 1.0;\n }\n\n\n", " float result = 0.0;\n\n if(x >= y)\n {\n result = 1.0;\n }\n\n\n" }; std::string valid_relation_opeartors = " float result = 0.0;\n\n if(x == y)\n {\n result = 1.0;\n }\n\n\n"; for (size_t var_type_index = 0; var_type_index < API::n_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(API::var_types[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string base_variable_string; for (size_t variable_declaration_index = 0; variable_declaration_index < sizeof(shader_variable_declarations) / sizeof(shader_variable_declarations[0]); variable_declaration_index++) { base_variable_string += var_iterator->second.type; base_variable_string += shader_variable_declarations[variable_declaration_index]; base_variable_string += "[1][1][1][1][1][1][1][1] = "; for (size_t sub_script_index = 0; sub_script_index < API::MAX_ARRAY_DIMENSIONS; sub_script_index++) { base_variable_string += this->extend_string(var_iterator->second.type, "[1]", API::MAX_ARRAY_DIMENSIONS - sub_script_index); base_variable_string += "("; } base_variable_string += var_iterator->second.initializer_with_ones; for (size_t sub_script_index = 0; sub_script_index < API::MAX_ARRAY_DIMENSIONS; sub_script_index++) { base_variable_string += ")"; } base_variable_string += ";\n"; } /* for (int variable_declaration_index = 0; ...) */ /* Run positive case */ { std::string shader_source; shader_source = base_variable_string + "\n"; shader_source += shader_start + valid_relation_opeartors; DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* Run negative cases */ for (size_t string_index = 0; string_index < sizeof(variable_relation_opeartors) / sizeof(variable_relation_opeartors[0]); string_index++) { std::string shader_source; shader_source = base_variable_string + "\n"; shader_source += shader_start + variable_relation_opeartors[string_index]; DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); this->execute_negative_test(tested_shader_type, shader_source); } /* for (int string_index = 0; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the InteractionFunctionCalls1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionFunctionCalls1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string iterator_declaration = " " + var_iterator->second.iterator_type + " iterator = " + var_iterator->second.iterator_initialization + ";\n"; std::string function_definition; std::string function_use; std::string verification; function_definition = "void my_function(out "; function_definition += var_iterator->second.type; function_definition += " output_array[2][2][2][2]) {\n"; function_definition += iterator_declaration; function_definition += iteration_loop_start; function_definition += " output_array[a][b][c][d] = " + var_iterator->second.variable_type_initializer1 + ";\n"; function_definition += " iterator += " + var_iterator->second.iterator_type + "(1);\n"; function_definition += iteration_loop_end; function_definition += "}"; function_use = " " + var_iterator->second.type + " my_array[2][2][2][2];\n"; function_use += " my_function(my_array);"; verification = iterator_declaration; verification += " float result = 1.0;\n"; verification += iteration_loop_start; verification += " if (my_array[a][b][c][d] " + var_iterator->second.specific_element + " != iterator)\n" " {\n" " result = 0.0;\n" " }\n" " iterator += " + var_iterator->second.iterator_type + "(1);\n"; verification += iteration_loop_end; if (false == test_compute) { execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /** Executes test for compute program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template void InteractionFunctionCalls1::execute_dispatch_test( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { const std::string& compute_shader_source = prepare_compute_shader(tested_shader_type, function_definition, function_use, verification); const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); this->execute_positive_test(empty_string, empty_string, empty_string, empty_string, empty_string, compute_shader_source, false, false); /* We are now ready to verify whether the returned size is correct. */ unsigned char buffer[4] = { 0 }; glw::GLuint framebuffer_object_id = 0; glw::GLint location = -1; glw::GLuint texture_object_id = 0; glw::GLuint vao_id = 0; gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); gl.bindImageTexture(0 /* image unit */, texture_object_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY, GL_RGBA8); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() failed."); location = gl.getUniformLocation(this->program_object_id, "uni_image"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed."); if (-1 == location) { TCU_FAIL("Uniform is inactive"); } gl.uniform1i(location, 0 /* image unit */); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() failed."); gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); gl.dispatchCompute(1, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); gl.readBuffer(GL_COLOR_ATTACHMENT0); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed."); gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed."); if (buffer[0] != 255) { TCU_FAIL("Invalid array size was returned."); } /* Delete generated objects. */ gl.deleteTextures(1, &texture_object_id); gl.deleteFramebuffers(1, &framebuffer_object_id); gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); } /** Executes test for draw program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template void InteractionFunctionCalls1::execute_draw_test(typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = empty_string; const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, function_definition, function_use, verification); const std::string& geometry_shader_source = this->prepare_geometry_shader(tested_shader_type, function_definition, function_use, verification); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, function_definition, function_use, verification); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader(tested_shader_type, function_definition, function_use, verification); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, function_definition, function_use, verification); switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::FRAGMENT_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); break; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, false, false); break; default: TCU_FAIL("Invalid enum"); break; } } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, function_definition, function_use, verification); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, function_definition, function_use, verification); this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); } /* We are now ready to verify whether the returned size is correct. */ unsigned char buffer[4] = { 0 }; glw::GLuint framebuffer_object_id = 0; glw::GLuint texture_object_id = 0; glw::GLuint vao_id = 0; gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: /* Fall through */ case TestCaseBase::VERTEX_SHADER_TYPE: gl.drawArrays(GL_TRIANGLE_FAN, 0, 4); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); gl.drawArrays(GL_PATCHES, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.drawArrays(GL_POINTS, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; default: TCU_FAIL("Invalid enum"); break; } gl.readBuffer(GL_COLOR_ATTACHMENT0); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed."); gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed."); if (buffer[0] != 255) { TCU_FAIL("Invalid array size was returned."); } /* Delete generated objects. */ gl.bindTexture(GL_TEXTURE_2D, 0); gl.bindFramebuffer(GL_FRAMEBUFFER, 0); gl.bindVertexArray(0); gl.deleteTextures(1, &texture_object_id); gl.deleteFramebuffers(1, &framebuffer_object_id); gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template std::string InteractionFunctionCalls1::prepare_compute_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string compute_shader_source; if (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type) { compute_shader_source = "writeonly uniform image2D uni_image;\n" "\n"; /* User-defined function definition. */ compute_shader_source += function_definition; compute_shader_source += "\n\n"; /* Main function definition. */ compute_shader_source += shader_start; compute_shader_source += function_use; compute_shader_source += "\n\n"; compute_shader_source += verification; compute_shader_source += "\n\n"; compute_shader_source += "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), vec4(result, 0, 0, 0));\n" "}\n" "\n"; } return compute_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template std::string InteractionFunctionCalls1::prepare_fragment_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string fragment_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: fragment_shader_source = "out vec4 colour;\n\n"; /* User-defined function definition. */ fragment_shader_source += function_definition; fragment_shader_source += "\n\n"; /* Main function definition. */ fragment_shader_source += shader_start; fragment_shader_source += function_use; fragment_shader_source += "\n\n"; fragment_shader_source += verification; fragment_shader_source += "\n\n"; fragment_shader_source += " colour = vec4(result);\n"; fragment_shader_source += shader_end; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: fragment_shader_source = "in float fs_result;\n\n" "out vec4 colour;\n\n" "void main()\n" "{\n" " colour = vec4(fs_result);\n" "}\n" "\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return fragment_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template std::string InteractionFunctionCalls1::prepare_geometry_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string geometry_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in float tes_result[];\n" "out float fs_result;\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" "}\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "out float fs_result;\n" "\n"; /* User-defined function definition. */ geometry_shader_source += function_definition; geometry_shader_source += "\n\n"; /* Main function definition. */ geometry_shader_source += shader_start; geometry_shader_source += function_use; geometry_shader_source += "\n\n"; geometry_shader_source += verification; geometry_shader_source += "\n\n"; geometry_shader_source += "\n gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return geometry_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template std::string InteractionFunctionCalls1::prepare_tess_ctrl_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string tess_ctrl_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_ctrl_shader_source = "layout(vertices = 1) out;\n" "\n" "out float tcs_result[];\n" "\n"; /* User-defined function definition. */ tess_ctrl_shader_source += function_definition; tess_ctrl_shader_source += "\n\n"; /* Main function definition. */ tess_ctrl_shader_source += shader_start; tess_ctrl_shader_source += function_use; tess_ctrl_shader_source += "\n\n"; tess_ctrl_shader_source += verification; tess_ctrl_shader_source += "\n\n"; tess_ctrl_shader_source += " tcs_result[gl_InvocationID] = result;\n" "\n" " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_ctrl_shader_source = default_tc_shader_source; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_ctrl_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template std::string InteractionFunctionCalls1::prepare_tess_eval_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string tess_eval_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "in float tcs_result[];\n" "out float tes_result;\n" "\n" "void main()\n" "{\n" " tes_result = tcs_result[0];\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "out float tes_result;\n" "\n"; /* User-defined function definition. */ tess_eval_shader_source += function_definition; tess_eval_shader_source += "\n\n"; /* Main function definition. */ tess_eval_shader_source += shader_start; tess_eval_shader_source += function_use; tess_eval_shader_source += "\n\n"; tess_eval_shader_source += verification; tess_eval_shader_source += "\n\n"; tess_eval_shader_source += " tes_result = result;\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_eval_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Snippet that makes use of defined function * @param verification Snippet that verifies results **/ template std::string InteractionFunctionCalls1::prepare_vertex_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string vertex_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: vertex_shader_source = "/** GL_TRIANGLE_FAN-type quad vertex data. */\n" "const vec4 vertex_positions[4] = vec4[4](vec4( 1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, 1.0, 0.0, 1.0),\n" " vec4( 1.0, 1.0, 0.0, 1.0) );\n" "\n" "void main()\n" "{\n" " gl_Position = vertex_positions[gl_VertexID];" "}\n\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: vertex_shader_source = default_vertex_shader_source; break; case TestCaseBase::VERTEX_SHADER_TYPE: /* Vertex shader source. */ vertex_shader_source = "out float fs_result;\n\n"; vertex_shader_source += "/** GL_TRIANGLE_FAN-type quad vertex data. */\n" "const vec4 vertex_positions[4] = vec4[4](vec4( 1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, 1.0, 0.0, 1.0),\n" " vec4( 1.0, 1.0, 0.0, 1.0) );\n\n"; /* User-defined function definition. */ vertex_shader_source += function_definition; vertex_shader_source += "\n\n"; /* Main function definition. */ vertex_shader_source += shader_start; vertex_shader_source += function_use; vertex_shader_source += "\n\n"; vertex_shader_source += verification; vertex_shader_source += "\n\n"; vertex_shader_source += " fs_result = result;\n" " gl_Position = vertex_positions[gl_VertexID];\n"; vertex_shader_source += shader_end; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return vertex_shader_source; } /* Generates the shader source code for the InteractionFunctionCalls2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionFunctionCalls2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const std::string multiplier_array = "const int[] multiplier_array = int[]( 1, 2, 3, 4, 5, 6, 7, 8,\n" " 11, 12, 13, 14, 15, 16, 17, 18,\n" " 21, 22, 23, 24, 25, 26, 27, 28,\n" " 31, 32, 33, 34, 35, 36, 37, 38,\n" " 41, 42, 43, 44, 45, 46, 47, 48,\n" " 51, 52, 53, 54, 55, 56, 57, 58,\n" " 61, 62, 63, 64, 65, 66, 67, 68,\n" " 71, 72, 73, 74, 75, 76, 77, 78,\n" " 81, 82, 83, 84, 85, 86, 87, 88);\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string function_definition; std::string function_use; std::string verification; function_definition += multiplier_array; function_definition += "void my_function(inout "; function_definition += var_iterator->second.type; function_definition += " inout_array[2][2][2][2]) {\n" " uint i = 0u;\n"; function_definition += iteration_loop_start; function_definition += " inout_array[a][b][c][d] *= " + var_iterator->second.iterator_type + "(multiplier_array[i % 64u]);\n"; function_definition += " i+= 1u;\n"; function_definition += iteration_loop_end; function_definition += "}"; function_use += " float result = 1.0;\n"; function_use += " uint iterator = 0u;\n"; function_use += " " + var_iterator->second.type + " my_array[2][2][2][2];\n"; function_use += iteration_loop_start; function_use += " my_array[a][b][c][d] = " + var_iterator->second.variable_type_initializer2 + ";\n"; function_use += iteration_loop_end; function_use += " my_function(my_array);"; verification += iteration_loop_start; verification += " if (my_array[a][b][c][d] " + var_iterator->second.specific_element + "!= " + var_iterator->second.iterator_type + "(multiplier_array[iterator % 64u]))\n" " {\n" " result = 0.0;\n" " }\n" " iterator += 1u;\n"; verification += iteration_loop_end; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the InteractionArgumentAliasing1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionArgumentAliasing1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string array_declaration = var_iterator->second.type + " z[2][2][2][2];\n\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "bool gfunc(" + var_iterator->second.type + " x[2][2][2][2], "; function_definition += var_iterator->second.type + " y[2][2][2][2])\n"; function_definition += "{\n"; function_definition += " " + iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += " " + iteration_loop_end; function_definition += "\n"; function_definition += " " + iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += " " + iteration_loop_end; function_definition += " return true;\n"; function_definition += "}"; function_use += " " + array_declaration; function_use += " " + iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += " " + iteration_loop_end; verification += " float result = 0.0;\n"; verification += " if(gfunc(z, z) == true)\n"; verification += " {\n"; verification += " result = 1.0;\n\n"; verification += " }\n"; verification += " else\n"; verification += " {\n"; verification += " result = 0.0;\n\n"; verification += " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionArgumentAliasing2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionArgumentAliasing2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string array_declaration = var_iterator->second.type + " z[2][2][2][2];\n\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "bool gfunc(" + var_iterator->second.type + " x[2][2][2][2], "; function_definition += var_iterator->second.type + " y[2][2][2][2])\n"; function_definition += "{\n"; function_definition += " " + iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += " " + iteration_loop_end; function_definition += "\n"; function_definition += " " + iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += " " + iteration_loop_end; function_definition += " return true;\n"; function_definition += "}"; function_use += " " + array_declaration; function_use += " " + iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += " " + iteration_loop_end; verification += " float result = 0.0;\n"; verification += " if(gfunc(z, z) == true)\n"; verification += " {\n"; verification += " result = 1.0;\n\n"; verification += " }\n"; verification += " else\n"; verification += " {\n"; verification += " result = 0.0;\n\n"; verification += " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionArgumentAliasing3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionArgumentAliasing3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string array_declaration = var_iterator->second.type + " z[2][2][2][2];\n\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "bool gfunc(out " + var_iterator->second.type + " x[2][2][2][2], "; function_definition += var_iterator->second.type + " y[2][2][2][2])\n"; function_definition += "{\n"; function_definition += " " + iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += " " + iteration_loop_end; function_definition += "\n"; function_definition += " " + iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += " " + iteration_loop_end; function_definition += " return true;\n"; function_definition += "}\n\n"; function_use += " " + array_declaration; function_use += " " + iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += " " + iteration_loop_end; verification += " float result = 0.0;\n"; verification += " if(gfunc(z, z) == true)\n"; verification += " {\n"; verification += " result = 1.0;\n\n"; verification += " }\n"; verification += " else\n"; verification += " {\n"; verification += " result = 0.0;\n\n"; verification += " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionArgumentAliasing4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionArgumentAliasing4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string array_declaration = var_iterator->second.type + "[2][2][2][2] z;\n\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "bool gfunc(" + var_iterator->second.type + " x[2][2][2][2], "; function_definition += "out " + var_iterator->second.type + " y[2][2][2][2])\n"; function_definition += "{\n"; function_definition += " " + iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += " " + iteration_loop_end; function_definition += "\n"; function_definition += " " + iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += " " + iteration_loop_end; function_definition += " return true;\n"; function_definition += "}\n\n"; function_use += " " + array_declaration; function_use += " " + iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += " " + iteration_loop_end; verification += " float result = 0.0;\n"; verification += " if(gfunc(z, z) == true)\n"; verification += " {\n"; verification += " result = 1.0;\n\n"; verification += " }\n"; verification += " else\n"; verification += " {\n"; verification += " result = 0.0;\n\n"; verification += " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionArgumentAliasing3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionArgumentAliasing5::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string array_declaration = var_iterator->second.type + "[2][2][2][2] z;\n\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "bool gfunc(inout " + var_iterator->second.type + " x[2][2][2][2], "; function_definition += var_iterator->second.type + " y[2][2][2][2])\n"; function_definition += "{\n"; function_definition += " " + iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += " " + iteration_loop_end; function_definition += "\n"; function_definition += " " + iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += " " + iteration_loop_end; function_definition += " return true;\n"; function_definition += "}\n\n"; function_use += " " + array_declaration; function_use += " " + iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += " " + iteration_loop_end; verification += " float result = 0.0;\n"; verification += " if(gfunc(z, z) == true)\n"; verification += " {\n"; verification += " result = 1.0;\n\n"; verification += " }\n"; verification += " else\n"; verification += " {\n"; verification += " result = 0.0;\n\n"; verification += " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionArgumentAliasing4 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionArgumentAliasing6::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string array_declaration = var_iterator->second.type + "[2][2][2][2] z;\n\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "bool gfunc(" + var_iterator->second.type + " x[2][2][2][2], "; function_definition += "inout " + var_iterator->second.type + " y[2][2][2][2])\n"; function_definition += "{\n"; function_definition += " " + iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += " " + iteration_loop_end; function_definition += "\n"; function_definition += " " + iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += " " + iteration_loop_end; function_definition += " return true;\n"; function_definition += "}\n\n"; function_use += " " + array_declaration; function_use += " " + iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += " " + iteration_loop_end; verification += " float result = 0.0;\n"; verification += " if(gfunc(z, z) == true)\n"; verification += " {\n"; verification += " result = 1.0;\n\n"; verification += " }\n"; verification += " else\n"; verification += " {\n"; verification += " result = 0.0;\n\n"; verification += " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionUniforms1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionUniforms1::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string uniform_definition; std::string uniform_use; uniform_definition += "uniform "; uniform_definition += var_iterator->second.precision; uniform_definition += " "; uniform_definition += var_iterator->second.type; uniform_definition += " my_uniform_1[1][1][1][1];\n\n"; uniform_use = " float result = float(my_uniform_1[0][0][0][0]);\n"; if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = this->prepare_compute_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& geometry_shader_source = this->prepare_geometry_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, uniform_definition, uniform_use); switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::FRAGMENT_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); break; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, false, false); break; default: TCU_FAIL("Invalid enum"); break; } } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, uniform_definition, uniform_use); this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); } glw::GLint uniform_location = -1; /* Make program object active. */ gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); /* Get uniform location. */ uniform_location = gl.getUniformLocation(this->program_object_id, "my_uniform_1[0][0][0][0]"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed."); if (uniform_location == -1) { TCU_FAIL("Uniform is not found or is considered as not active."); } switch (var_type_index) { case 0: //float type of uniform is considered { glw::GLfloat uniform_value = 1.0f; gl.uniform1f(uniform_location, uniform_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1f() failed."); break; } case 1: //int type of uniform is considered { glw::GLint uniform_value = 1; gl.uniform1i(uniform_location, uniform_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() failed."); break; } case 2: //uint type of uniform is considered { glw::GLuint uniform_value = 1; gl.uniform1ui(uniform_location, uniform_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1ui() failed."); break; } case 3: //double type of uniform is considered { glw::GLdouble uniform_value = 1.0; gl.uniform1d(uniform_location, uniform_value); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1d() failed."); break; } default: { TCU_FAIL("Invalid variable-type index."); break; } } /* switch (var_type_index) */ /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param uniform_definition Definition used to prepare shader * @param uniform_use Snippet that use defined uniform **/ template std::string InteractionUniforms1::prepare_compute_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& uniform_definition, const std::string& uniform_use) { std::string compute_shader_source; if (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type) { compute_shader_source = "writeonly uniform image2D uni_image;\n" "\n"; /* User-defined function definition. */ compute_shader_source += uniform_definition; compute_shader_source += "\n\n"; /* Main function definition. */ compute_shader_source += shader_start; compute_shader_source += uniform_use; compute_shader_source += "\n\n"; compute_shader_source += "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), vec4(result, 0, 0, 0));\n" "}\n" "\n"; } return compute_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param uniform_definition Definition used to prepare shader * @param uniform_use Snippet that use defined uniform **/ template std::string InteractionUniforms1::prepare_fragment_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& uniform_definition, const std::string& uniform_use) { std::string fragment_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: fragment_shader_source = "out vec4 colour;\n\n"; /* User-defined function definition. */ fragment_shader_source += uniform_definition; fragment_shader_source += "\n\n"; /* Main function definition. */ fragment_shader_source += shader_start; fragment_shader_source += uniform_use; fragment_shader_source += "\n\n"; fragment_shader_source += " colour = vec4(result);\n"; fragment_shader_source += shader_end; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: fragment_shader_source = "in float fs_result;\n\n" "out vec4 colour;\n\n" "void main()\n" "{\n" " colour = vec4(fs_result);\n" "}\n" "\n"; break; case TestCaseBase::VERTEX_SHADER_TYPE: fragment_shader_source = default_fragment_shader_source; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return fragment_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param uniform_definition Definition used to prepare shader * @param uniform_use Snippet that use defined uniform **/ template std::string InteractionUniforms1::prepare_geometry_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& uniform_definition, const std::string& uniform_use) { std::string geometry_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in float tes_result[];\n" "out float fs_result;\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" "}\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "out float fs_result;\n" "\n"; /* User-defined function definition. */ geometry_shader_source += uniform_definition; geometry_shader_source += "\n\n"; /* Main function definition. */ geometry_shader_source += shader_start; geometry_shader_source += uniform_use; geometry_shader_source += "\n\n"; geometry_shader_source += "\n gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return geometry_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param uniform_definition Definition used to prepare shader * @param uniform_use Snippet that use defined uniform **/ template std::string InteractionUniforms1::prepare_tess_ctrl_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& uniform_definition, const std::string& uniform_use) { std::string tess_ctrl_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_ctrl_shader_source = "layout(vertices = 1) out;\n" "\n" "out float tcs_result[];\n" "\n"; /* User-defined function definition. */ tess_ctrl_shader_source += uniform_definition; tess_ctrl_shader_source += "\n\n"; /* Main function definition. */ tess_ctrl_shader_source += shader_start; tess_ctrl_shader_source += uniform_use; tess_ctrl_shader_source += "\n\n"; tess_ctrl_shader_source += " tcs_result[gl_InvocationID] = result;\n" "\n" " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_ctrl_shader_source = default_tc_shader_source; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_ctrl_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param uniform_definition Definition used to prepare shader * @param uniform_use Snippet that use defined uniform **/ template std::string InteractionUniforms1::prepare_tess_eval_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& uniform_definition, const std::string& uniform_use) { std::string tess_eval_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "in float tcs_result[];\n" "out float tes_result;\n" "\n" "void main()\n" "{\n" " tes_result = tcs_result[0];\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "out float tes_result;\n" "\n"; /* User-defined function definition. */ tess_eval_shader_source += uniform_definition; tess_eval_shader_source += "\n\n"; /* Main function definition. */ tess_eval_shader_source += shader_start; tess_eval_shader_source += uniform_use; tess_eval_shader_source += "\n\n"; tess_eval_shader_source += " tes_result = result;\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_eval_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param uniform_definition Definition used to prepare shader * @param uniform_use Snippet that use defined uniform **/ template std::string InteractionUniforms1::prepare_vertex_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& uniform_definition, const std::string& uniform_use) { std::string vertex_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: vertex_shader_source = default_vertex_shader_source; break; case TestCaseBase::VERTEX_SHADER_TYPE: /* User-defined function definition. */ vertex_shader_source += uniform_definition; /* Main function definition. */ vertex_shader_source += shader_start; vertex_shader_source += uniform_use; vertex_shader_source += " gl_Position = vec4(result);\n"; vertex_shader_source += shader_end; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return vertex_shader_source; } /* Generates the shader source code for the InteractionUniforms2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionUniforms2::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string array_initializers[] = { "int[2][2][2][2](\n" " int[2][2][2](\n" " int[2][2](\n" " int[2]( 1, 2),\n" " int[2]( 3, 4)\n" " ),\n" " int[2][2](\n" " int[2]( 5, 6),\n" " int[2]( 7, 8)\n" " )\n" " ),\n" " int[2][2][2](\n" " int[2][2](\n" " int[2](11, 12),\n" " int[2](13, 14)\n" " ),\n" " int[2][2](\n" " int[2](15, 16),\n" " int[2](17, 18)\n" " )\n" " )\n" ")", "float[2][2][2][2](\n" " float[2][2][2](\n" " float[2][2](\n" " float[2](1.0, 2.0),\n" " float[2](3.0, 4.0)),\n" " float[2][2](\n" " float[2](5.0, 6.0),\n" " float[2](7.0, 8.0))),\n" " float[2][2][2](\n" " float[2][2](\n" " float[2](1.1, 2.1),\n" " float[2](3.1, 4.1)\n" " ),\n" " float[2][2](\n" " float[2](5.1, 6.1),\n" " float[2](7.1, 8.1)\n" " )\n" " )\n" ")", "mat4[2][2][2][2](\n" " mat4[2][2][2](\n" " mat4[2][2](\n" " mat4[2]( mat4(1), mat4(2)),\n" " mat4[2]( mat4(3), mat4(4))\n" " ),\n" " mat4[2][2](\n" " mat4[2](mat4(5), mat4(6)),\n" " mat4[2](mat4(7), mat4(8))\n" " )\n" " ),\n" " mat4[2][2][2](\n" " mat4[2][2](\n" " mat4[2](mat4(9), mat4(10)),\n" " mat4[2](mat4(11), mat4(12))\n" " ),\n" " mat4[2][2](\n" " mat4[2](mat4(13), mat4(14)),\n" " mat4[2](mat4(15), mat4(16))\n" " )\n" " )\n" ")", "double[2][2][2][2](\n" " double[2][2][2](\n" " double[2][2](\n" " double[2](1.0, 2.0),\n" " double[2](3.0, 4.0)),\n" " double[2][2](\n" " double[2](5.0, 6.0),\n" " double[2](7.0, 8.0))),\n" " double[2][2][2](\n" " double[2][2](\n" " double[2](1.1, 2.1),\n" " double[2](3.1, 4.1)\n" " ),\n" " double[2][2](\n" " double[2](5.1, 6.1),\n" " double[2](7.1, 8.1)\n" " )\n" " )\n" ")", "dmat4[2][2][2][2](\n" " dmat4[2][2][2](\n" " dmat4[2][2](\n" " dmat4[2]( dmat4(1), dmat4(2)),\n" " dmat4[2]( dmat4(3), dmat4(4))\n" " ),\n" " dmat4[2][2](\n" " dmat4[2](dmat4(5), dmat4(6)),\n" " dmat4[2](dmat4(7), dmat4(8))\n" " )\n" " ),\n" " dmat4[2][2][2](\n" " dmat4[2][2](\n" " dmat4[2](dmat4(9), dmat4(10)),\n" " dmat4[2](dmat4(11), dmat4(12))\n" " ),\n" " dmat4[2][2](\n" " dmat4[2](dmat4(13), dmat4(14)),\n" " dmat4[2](dmat4(15), dmat4(16))\n" " )\n" " )\n" ")" }; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string base_variable_string; for (int initialiser_selector = 1; initialiser_selector >= 0; initialiser_selector--) { // We normally do all 16 possible permutations of [4][4][4][4] items (15..0). // However, in this case we will skip the case that will work, // so we'll merely process permutations 14..0 for (int permutation_index = 14; permutation_index >= 0; permutation_index--) { base_variable_string = "uniform " + var_iterator->second.precision + " " + var_iterator->second.type + " x"; // for all 4 possible sub_script entries for (int sub_script_entry_index = 3; sub_script_entry_index >= 0; sub_script_entry_index--) { if (permutation_index & (1 << sub_script_entry_index)) { // In this case, we'll use a valid sub_script base_variable_string += "[2]"; } else { // In this case, we'll use an invalid sub_script base_variable_string += "[]"; } } if (initialiser_selector == 0) { // We'll use an initialiser base_variable_string += " = " + array_initializers[var_type_index]; } base_variable_string += ";\n\n"; std::string shader_source = base_variable_string + shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test: * * This will succeed in case of allowed unsized * declarations and when at least one of these is * true: * 1. There is an initialiser. * 2. Only the outermost dimension is unsized, * as in [][2][2][2]. */ EXECUTE_SHADER_TEST(API::ALLOW_UNSIZED_DECLARATION && (initialiser_selector == 0 || permutation_index == 7), tested_shader_type, shader_source); } /* for (int permutation_index = 14; ...) */ } /* for (int initialiser_selector = 1; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the InteractionUniformBuffers1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionUniformBuffers1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source; shader_source += "uniform uBlocka {\n"; shader_source += " " + var_iterator->second.type + " x[1][1][1][1][1][1];\n"; shader_source += "};\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionUniformBuffers2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionUniformBuffers2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } /* Iterate through float / int / uint values. */ for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string uniform_definition; std::string uniform_use; uniform_definition += "layout (std140) uniform uniform_block_name\n" "{\n"; uniform_definition += " "; uniform_definition += var_iterator->second.type; uniform_definition += " my_uniform_1[1][1][1][1];\n" "};\n"; uniform_use = " float result = float(my_uniform_1[0][0][0][0]);\n"; if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = this->prepare_compute_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& geometry_shader_source = this->prepare_geometry_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, uniform_definition, uniform_use); switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::FRAGMENT_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); break; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, false, false); break; default: TCU_FAIL("Invalid enum"); break; } } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, uniform_definition, uniform_use); this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); } glw::GLuint buffer_object_id = 0; glw::GLint my_uniform_block_index = GL_INVALID_INDEX; gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); my_uniform_block_index = gl.getUniformBlockIndex(this->program_object_id, "uniform_block_name"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex() failed."); if ((unsigned)my_uniform_block_index == GL_INVALID_INDEX) { TCU_FAIL("Uniform block not found or is considered as not active."); } gl.genBuffers(1, &buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed."); gl.bindBuffer(GL_UNIFORM_BUFFER, buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed."); switch (var_type_index) { case 0: //float type of uniform is considered { glw::GLfloat buffer_data[] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f }; gl.bufferData(GL_UNIFORM_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* float case */ case 1: //int type of uniform is considered { glw::GLint buffer_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; gl.bufferData(GL_UNIFORM_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* int case */ case 2: //uint type of uniform is considered { glw::GLuint buffer_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; gl.bufferData(GL_UNIFORM_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* uint case */ case 3: //double type of uniform is considered { glw::GLdouble buffer_data[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 }; gl.bufferData(GL_UNIFORM_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* double case */ default: { TCU_FAIL("Invalid variable-type index."); break; } } /* switch (var_type_index) */ gl.uniformBlockBinding(this->program_object_id, my_uniform_block_index, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding() failed."); gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed."); if (TestCaseBase::COMPUTE_SHADER_TYPE != tested_shader_type) { execute_draw_test(tested_shader_type); } else { execute_dispatch_test(); } /* Deallocate any resources used. */ gl.deleteBuffers(1, &buffer_object_id); this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /** Executes test for compute program * * @tparam API Tested API descriptor **/ template void InteractionUniformBuffers2::execute_dispatch_test() { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); gl.dispatchCompute(1, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); } /** Executes test for draw program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested **/ template void InteractionUniformBuffers2::execute_draw_test(typename TestCaseBase::TestShaderType tested_shader_type) { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); glw::GLuint vao_id = 0; gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.drawArrays(GL_POINTS, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); gl.drawArrays(GL_PATCHES, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; default: TCU_FAIL("Invalid enum"); break; } gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() failed."); } /* Generates the shader source code for the InteractionUniformBuffers3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionUniformBuffers3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string invalid_size_declarations[] = { "[2][2][2][]", "[2][2][][2]", "[2][][2][2]", "[][2][2][2]", "[2][2][][]", "[2][][2][]", "[][2][2][]", "[2][][][2]", "[][2][][2]", "[][][2][2]", "[2][][][]", "[][2][][]", "[][][2][]", "[][][][2]", "[][][][]" }; const std::string array_initializers[] = { "float[2][2][2][2](float[2][2][2](float[2][2](float[2](1.0, 2.0)," "float[2](3.0, 4.0))," "float[2][2](float[2](5.0, 6.0)," "float[2](7.0, 8.0)))," "float[2][2][2](float[2][2](float[2](1.1, 2.1)," "float[2](3.1, 4.1))," "float[2][2](float[2](5.1, 6.1)," "float[2](7.1, 8.1))));\n", "int[2][2][2][2](int[2][2][2](int[2][2](int[2]( 1, 2)," "int[2]( 3, 4))," "int[2][2](int[2]( 5, 6)," "int[2]( 7, 8)))," "int[2][2][2](int[2][2](int[2](11, 12)," "int[2](13, 14))," "int[2][2](int[2](15, 16)," "int[2](17, 18))));\n", "uint[2][2][2][2](uint[2][2][2](uint[2][2](uint[2]( 1u, 2u)," "uint[2]( 3u, 4u))," "uint[2][2](uint[2]( 5u, 6u)," "uint[2]( 7u, 8u)))," "uint[2][2][2](uint[2][2](uint[2](11u, 12u)," "uint[2](13u, 14u))," "uint[2][2](uint[2](15u, 16u)," "uint[2](17u, 18u))));\n", "double[2][2][2][2](double[2][2][2](double[2][2](double[2](1.0, 2.0)," "double[2](3.0, 4.0))," "double[2][2](double[2](5.0, 6.0)," "double[2](7.0, 8.0)))," "double[2][2][2](double[2][2](double[2](1.1, 2.1)," "double[2](3.1, 4.1))," "double[2][2](double[2](5.1, 6.1)," "double[2](7.1, 8.1))));\n" }; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } /* Iterate through float/ int/ uint types. * Case: without initializer. */ for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { for (size_t invalid_size_declarations_index = 0; invalid_size_declarations_index < sizeof(invalid_size_declarations) / sizeof(invalid_size_declarations[0]); invalid_size_declarations_index++) { std::string shader_source; shader_source = "layout (std140) uniform MyUniform {\n"; shader_source += " " + var_iterator->second.type + invalid_size_declarations[invalid_size_declarations_index] + " my_variable;\n"; shader_source += "};\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_SHADER_TEST(API::ALLOW_UNSIZED_DECLARATION && invalid_size_declarations_index == 3, tested_shader_type, shader_source); } /* for (int invalid_size_declarations_index = 0; ...) */ } else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ /* Iterate through float/ int/ uint types. * Case: with initializer. */ for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { for (size_t invalid_size_declarations_index = 0; invalid_size_declarations_index < sizeof(invalid_size_declarations) / sizeof(invalid_size_declarations[0]); invalid_size_declarations_index++) { std::string shader_source; shader_source = "layout (std140) uniform MyUniform {\n"; shader_source += " " + var_iterator->second.type + invalid_size_declarations[invalid_size_declarations_index] + " my_variable = " + array_initializers[var_type_index]; shader_source += "};\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_size_declarations_index = 0; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the InteractionStorageBuffers1 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionStorageBuffers1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string shader_source; shader_source += "buffer uBlocka {\n"; shader_source += " " + var_iterator->second.type + " x[1][1][1][1][1][1];\n"; shader_source += "};\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, shader_source, true, false); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } } /* Generates the shader source code for the InteractionUniformBuffers2 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionStorageBuffers2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } /* Iterate through float / int / uint values. */ for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string uniform_definition; std::string uniform_use; uniform_definition += "layout (std140) buffer storage_block_name\n" "{\n"; uniform_definition += " "; uniform_definition += var_iterator->second.type; uniform_definition += " my_storage_1[1][1][1][1];\n" "};\n"; uniform_use = " float result = float(my_storage_1[0][0][0][0]);\n"; if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = this->prepare_compute_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& geometry_shader_source = this->prepare_geometry_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, uniform_definition, uniform_use); switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::FRAGMENT_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); break; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, false, false); break; default: TCU_FAIL("Invalid enum"); break; } } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, uniform_definition, uniform_use); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, uniform_definition, uniform_use); this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); } glw::GLuint buffer_object_id = 0; glw::GLint my_storage_block_index = GL_INVALID_INDEX; gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); my_storage_block_index = gl.getProgramResourceIndex(this->program_object_id, GL_SHADER_STORAGE_BLOCK, "storage_block_name"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() failed."); if ((unsigned)my_storage_block_index == GL_INVALID_INDEX) { TCU_FAIL("Uniform block not found or is considered as not active."); } gl.genBuffers(1, &buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed."); gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed."); switch (var_type_index) { case 0: //float type of uniform is considered { glw::GLfloat buffer_data[] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f }; gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* float case */ case 1: //int type of uniform is considered { glw::GLint buffer_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* int case */ case 2: //uint type of uniform is considered { glw::GLuint buffer_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* uint case */ case 3: //double type of uniform is considered { glw::GLdouble buffer_data[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 }; gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(buffer_data), buffer_data, GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); break; } /* double case */ default: { TCU_FAIL("Invalid variable-type index."); break; } } /* switch (var_type_index) */ gl.shaderStorageBlockBinding(this->program_object_id, my_storage_block_index, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding() failed."); gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed."); if (TestCaseBase::COMPUTE_SHADER_TYPE != tested_shader_type) { execute_draw_test(tested_shader_type); } else { execute_dispatch_test(); } /* Deallocate any resources used. */ gl.deleteBuffers(1, &buffer_object_id); this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /** Executes test for compute program * * @tparam API Tested API descriptor **/ template void InteractionStorageBuffers2::execute_dispatch_test() { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); gl.dispatchCompute(1, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); } /** Executes test for draw program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested **/ template void InteractionStorageBuffers2::execute_draw_test(typename TestCaseBase::TestShaderType tested_shader_type) { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); glw::GLuint vao_id = 0; gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.drawArrays(GL_POINTS, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); gl.drawArrays(GL_PATCHES, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; default: TCU_FAIL("Invalid enum"); break; } gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() failed."); } /* Generates the shader source code for the InteractionUniformBuffers3 * array tests, and attempts to compile each test shader, for both * vertex and fragment shaders. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * (either TestCaseBase::VERTEX_SHADER_TYPE or TestCaseBase::FRAGMENT_SHADER_TYPE). */ template void InteractionStorageBuffers3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_FLOAT, VAR_TYPE_INT, VAR_TYPE_UINT, VAR_TYPE_DOUBLE }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string invalid_size_declarations[] = { "[2][2][2][]", "[2][2][][2]", "[2][][2][2]", "[][2][2][2]", "[2][2][][]", "[2][][2][]", "[][2][2][]", "[2][][][2]", "[][2][][2]", "[][][2][2]", "[2][][][]", "[][2][][]", "[][][2][]", "[][][][2]", "[][][][]" }; const std::string array_initializers[] = { "float[2][2][2][2](float[2][2][2](float[2][2](float[2](1.0, 2.0)," "float[2](3.0, 4.0))," "float[2][2](float[2](5.0, 6.0)," "float[2](7.0, 8.0)))," "float[2][2][2](float[2][2](float[2](1.1, 2.1)," "float[2](3.1, 4.1))," "float[2][2](float[2](5.1, 6.1)," "float[2](7.1, 8.1))));\n", "int[2][2][2][2](int[2][2][2](int[2][2](int[2]( 1, 2)," "int[2]( 3, 4))," "int[2][2](int[2]( 5, 6)," "int[2]( 7, 8)))," "int[2][2][2](int[2][2](int[2](11, 12)," "int[2](13, 14))," "int[2][2](int[2](15, 16)," "int[2](17, 18))));\n", "uint[2][2][2][2](uint[2][2][2](uint[2][2](uint[2]( 1u, 2u)," "uint[2]( 3u, 4u))," "uint[2][2](uint[2]( 5u, 6u)," "uint[2]( 7u, 8u)))," "uint[2][2][2](uint[2][2](uint[2](11u, 12u)," "uint[2](13u, 14u))," "uint[2][2](uint[2](15u, 16u)," "uint[2](17u, 18u))));\n", "double[2][2][2][2](double[2][2][2](double[2][2](double[2](1.0, 2.0)," "double[2](3.0, 4.0))," "double[2][2](double[2](5.0, 6.0)," "double[2](7.0, 8.0)))," "double[2][2][2](double[2][2](double[2](1.1, 2.1)," "double[2](3.1, 4.1))," "double[2][2](double[2](5.1, 6.1)," "double[2](7.1, 8.1))));\n" }; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } /* Iterate through float/ int/ uint types. * Case: without initializer. */ for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { for (size_t invalid_size_declarations_index = 0; invalid_size_declarations_index < sizeof(invalid_size_declarations) / sizeof(invalid_size_declarations[0]); invalid_size_declarations_index++) { std::string shader_source; shader_source = "layout (std140) buffer MyStorage {\n"; shader_source += " " + var_iterator->second.type + invalid_size_declarations[invalid_size_declarations_index] + " my_variable;\n"; shader_source += "};\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ EXECUTE_SHADER_TEST(API::ALLOW_UNSIZED_DECLARATION && invalid_size_declarations_index == 3, tested_shader_type, shader_source); } /* for (int invalid_size_declarations_index = 0; ...) */ } else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ /* Iterate through float/ int/ uint types. * Case: with initializer. */ for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { for (size_t invalid_size_declarations_index = 0; invalid_size_declarations_index < sizeof(invalid_size_declarations) / sizeof(invalid_size_declarations[0]); invalid_size_declarations_index++) { std::string shader_source; shader_source = "layout (std140) buffer MyStorage {\n"; shader_source += " " + var_iterator->second.type + invalid_size_declarations[invalid_size_declarations_index] + " my_variable = " + array_initializers[var_type_index]; shader_source += "};\n\n"; shader_source += shader_start; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, shader_source); /* Execute test */ this->execute_negative_test(tested_shader_type, shader_source); } /* for (int invalid_size_declarations_index = 0; ...) */ } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the InteractionInterfaceArrays1 * array test, and attempts to compile the test shader. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested. */ template void InteractionInterfaceArrays1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { /* Shader source with invalid buffer (buffer cannot be of arrays of arrays type). */ const std::string invalid_buffer_shader_source = "layout(std140) buffer MyBuffer\n" "{\n" " float f;\n" " int i;\n" " uint ui;\n" "} myBuffers[2][2];\n\n" "void main()\n" "{\n"; /* Verify that buffer arrays of arrays type is rejected. */ { std::string source = invalid_buffer_shader_source; DEFAULT_MAIN_ENDING(tested_shader_type, source); EXECUTE_SHADER_TEST(API::ALLOW_A_OF_A_ON_INTERFACE_BLOCKS, tested_shader_type, source); } } /* Generates the shader source code for the InteractionInterfaceArrays2 * array test, and attempts to compile the test shader. * * @tparam API Tested API descriptor * * @param input_shader_type The type of shader that is being tested. */ template void InteractionInterfaceArrays2::test_shader_compilation( typename TestCaseBase::TestShaderType input_shader_type) { /* Shader source with invalid input (input cannot be of arrays of arrays type). */ const std::string input_variable_shader_source[] = { "in float inout_variable", "[2][2];\n" "out float result", ";\n\n" "void main()\n" "{\n" " result", " = inout_variable", "[0][0];\n" }; /* Shader source with invalid output (output cannot be of arrays of arrays type). */ const std::string output_variable_shader_source[] = { "out float inout_variable", "[2][2];\n\n" "void main()\n" "{\n" " inout_variable", "[0][0] = 0.0;\n" " inout_variable", "[0][1] = 1.0;\n" " inout_variable", "[1][0] = 2.0;\n" " inout_variable", "[1][1] = 3.0;\n" }; const typename TestCaseBase::TestShaderType& output_shader_type = this->get_output_shader_type(input_shader_type); std::string input_source; std::string output_source; this->prepare_sources(input_shader_type, output_shader_type, input_variable_shader_source, output_variable_shader_source, input_source, output_source); /* Verify that INPUTs and OUTPUTs arrays of arrays type is rejected. */ if (TestCaseBase::COMPUTE_SHADER_TYPE != input_shader_type) { if (API::ALLOW_A_OF_A_ON_INTERFACE_BLOCKS) { if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = empty_string; const std::string& fragment_shader_source = this->prepare_fragment_shader(input_shader_type, input_source, output_source); const std::string& geometry_shader_source = this->prepare_geometry_shader(input_shader_type, input_source, output_source); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader_source(input_shader_type, input_source, output_source); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader_source(input_shader_type, input_source, output_source); const std::string& vertex_shader_source = this->prepare_vertex_shader(input_shader_type, input_source, output_source); this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, true, false); } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(input_shader_type, input_source, output_source); const std::string& vertex_shader_source = this->prepare_vertex_shader(input_shader_type, input_source, output_source); this->execute_positive_test(vertex_shader_source, fragment_shader_source, true, false); } } else { this->execute_negative_test(input_shader_type, input_source); this->execute_negative_test(output_shader_type, output_source); } } } /** Gets the shader type to test for the outputs * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested **/ template const typename TestCaseBase::TestShaderType InteractionInterfaceArrays2::get_output_shader_type( const typename TestCaseBase::TestShaderType& input_shader_type) { switch (input_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: return TestCaseBase::FRAGMENT_SHADER_TYPE; case TestCaseBase::FRAGMENT_SHADER_TYPE: if (API::USE_ALL_SHADER_STAGES) { return TestCaseBase::GEOMETRY_SHADER_TYPE; } else { return TestCaseBase::VERTEX_SHADER_TYPE; } case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::GEOMETRY_SHADER_TYPE: return TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: return TestCaseBase::VERTEX_SHADER_TYPE; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: return TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE; default: TCU_FAIL("Unrecognized shader type."); break; } return input_shader_type; } /** Prepare fragment shader * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested * @param input_source Shader in case we want to test inputs for this shader * @param output_source Shader in case we want to test outputs for this shader **/ template const std::string InteractionInterfaceArrays2::prepare_fragment_shader( const typename TestCaseBase::TestShaderType& input_shader_type, const std::string& input_source, const std::string& output_source) { switch (input_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: return output_source; case TestCaseBase::FRAGMENT_SHADER_TYPE: return input_source; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: break; default: TCU_FAIL("Unrecognized shader type."); break; } return default_fragment_shader_source; } /** Prepare geometry shader * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested * @param input_source Shader in case we want to test inputs for this shader * @param output_source Shader in case we want to test outputs for this shader **/ template const std::string InteractionInterfaceArrays2::prepare_geometry_shader( const typename TestCaseBase::TestShaderType& input_shader_type, const std::string& input_source, const std::string& output_source) { switch (input_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: if (API::USE_ALL_SHADER_STAGES) { return output_source; } break; case TestCaseBase::GEOMETRY_SHADER_TYPE: return input_source; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: break; default: TCU_FAIL("Unrecognized shader type."); break; } return default_geometry_shader_source; } /** Prepare tessellation control shader * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested * @param input_source Shader in case we want to test inputs for this shader * @param output_source Shader in case we want to test outputs for this shader **/ template const std::string InteractionInterfaceArrays2::prepare_tess_ctrl_shader_source( const typename TestCaseBase::TestShaderType& input_shader_type, const std::string& input_source, const std::string& output_source) { switch (input_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: return input_source; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: return output_source; default: TCU_FAIL("Unrecognized shader type."); break; } return default_tc_shader_source; } /** Prepare tessellation evaluation shader * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested * @param input_source Shader in case we want to test inputs for this shader * @param output_source Shader in case we want to test outputs for this shader **/ template const std::string InteractionInterfaceArrays2::prepare_tess_eval_shader_source( const typename TestCaseBase::TestShaderType& input_shader_type, const std::string& input_source, const std::string& output_source) { switch (input_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: break; case TestCaseBase::GEOMETRY_SHADER_TYPE: return output_source; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: return input_source; default: TCU_FAIL("Unrecognized shader type."); break; } return default_te_shader_source; } /** Prepare vertex shader * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested * @param input_source Shader in case we want to test inputs for this shader * @param output_source Shader in case we want to test outputs for this shader **/ template const std::string InteractionInterfaceArrays2::prepare_vertex_shader( const typename TestCaseBase::TestShaderType& input_shader_type, const std::string& input_source, const std::string& output_source) { switch (input_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: return input_source; case TestCaseBase::FRAGMENT_SHADER_TYPE: if (!API::USE_ALL_SHADER_STAGES) { return output_source; } break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: return output_source; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: break; default: TCU_FAIL("Unrecognized shader type."); break; } return default_vertex_shader_source; } /** Prepare the inputs and outputs shaders * * @tparam API Tested API descriptor * * @param input_shader_type The type of input shader that is being tested * @param output_shader_type The type of output shader that is being tested * @param input_shader_source Snippet used to prepare the input shader * @param output_shader_source Snippet used to prepare the output shader * @param input_source Resulting input shader * @param output_source Resulting output shader **/ template void InteractionInterfaceArrays2::prepare_sources( const typename TestCaseBase::TestShaderType& input_shader_type, const typename TestCaseBase::TestShaderType& output_shader_type, const std::string* input_shader_source, const std::string* output_shader_source, std::string& input_source, std::string& output_source) { if (TestCaseBase::COMPUTE_SHADER_TYPE != input_shader_type) { input_source += input_shader_source[0]; output_source += output_shader_source[0]; if ((TestCaseBase::GEOMETRY_SHADER_TYPE == input_shader_type) || (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == input_shader_type) || (TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE == input_shader_type)) { input_source += "[]"; } if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == output_shader_type) { output_source += "[]"; } input_source += input_shader_source[1]; output_source += output_shader_source[1]; if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == input_shader_type) { input_source += "[]"; } if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == output_shader_type) { output_source += "[gl_InvocationID]"; } input_source += input_shader_source[2]; output_source += output_shader_source[2]; if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == input_shader_type) { input_source += "[gl_InvocationID]"; } if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == output_shader_type) { output_source += "[gl_InvocationID]"; } input_source += input_shader_source[3]; output_source += output_shader_source[3]; if ((TestCaseBase::GEOMETRY_SHADER_TYPE == input_shader_type) || (TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE == input_shader_type)) { input_source += "[0]"; } if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == input_shader_type) { input_source += "[gl_InvocationID]"; } if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == output_shader_type) { output_source += "[gl_InvocationID]"; } input_source += input_shader_source[4]; output_source += output_shader_source[4]; if (TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE == output_shader_type) { output_source += "[gl_InvocationID]"; } output_source += output_shader_source[5]; DEFAULT_MAIN_ENDING(input_shader_type, input_source); DEFAULT_MAIN_ENDING(output_shader_type, output_source); } } /* Generates the shader source code for the InteractionInterfaceArrays3 * array test, and attempts to compile the test shader. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested. */ template void InteractionInterfaceArrays3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { /* Shader source with invalid uniform block (uniform block cannot be of arrays of arrays type). */ const std::string invalid_uniform_block_shader_source = "layout(std140) uniform MyUniformBlock\n" "{\n" " float f;\n" " int i;\n" " uint ui;\n" "} myUniformBlocks[2][2];\n\n" "void main()\n" "{\n"; /* Verify that uniform block arrays of arrays type is rejected. */ { std::string source = invalid_uniform_block_shader_source; DEFAULT_MAIN_ENDING(tested_shader_type, source); EXECUTE_SHADER_TEST(API::ALLOW_A_OF_A_ON_INTERFACE_BLOCKS, tested_shader_type, source); } } /* Generates the shader source code for the InteractionInterfaceArrays4 * array test, and attempts to compile the test shader. * * @tparam API Tested API descriptor * * @param input_shader_type The type of shader that is being tested. */ template void InteractionInterfaceArrays4::test_shader_compilation( typename TestCaseBase::TestShaderType input_shader_type) { /* Shader source with invalid input (input cannot be of arrays of arrays type). */ const std::string input_block_shader_source[] = { "in InOutBlock {\n" " float inout_variable;\n" "} inout_block", "[2][2];\n" "out float result", ";\n\n" "void main()\n" "{\n" " result", " = inout_block", "[0][0].inout_variable;\n" }; /* Shader source with invalid output (output cannot be of arrays of arrays type). */ const std::string output_block_shader_source[] = { "out InOutBlock {\n" " float inout_variable;\n" "} inout_block", "[2][2];\n" "\n" "void main()\n" "{\n" " inout_block", "[0][0].inout_variable = 0.0;\n" " inout_block", "[0][1].inout_variable = 1.0;\n" " inout_block", "[1][0].inout_variable = 2.0;\n" " inout_block", "[1][1].inout_variable = 3.0;\n" }; const typename TestCaseBase::TestShaderType& output_shader_type = this->get_output_shader_type(input_shader_type); std::string input_source; std::string output_source; this->prepare_sources(input_shader_type, output_shader_type, input_block_shader_source, output_block_shader_source, input_source, output_source); /* Verify that INPUTs and OUTPUTs arrays of arrays type is rejected. */ if ((TestCaseBase::VERTEX_SHADER_TYPE != input_shader_type) && (TestCaseBase::COMPUTE_SHADER_TYPE != input_shader_type)) { if (API::ALLOW_A_OF_A_ON_INTERFACE_BLOCKS && API::ALLOW_IN_OUT_INTERFACE_BLOCKS) { if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = empty_string; const std::string& fragment_shader_source = this->prepare_fragment_shader(input_shader_type, input_source, output_source); const std::string& geometry_shader_source = this->prepare_geometry_shader(input_shader_type, input_source, output_source); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader_source(input_shader_type, input_source, output_source); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader_source(input_shader_type, input_source, output_source); const std::string& vertex_shader_source = this->prepare_vertex_shader(input_shader_type, input_source, output_source); this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, true, false); } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(input_shader_type, input_source, output_source); const std::string& vertex_shader_source = this->prepare_vertex_shader(input_shader_type, input_source, output_source); this->execute_positive_test(vertex_shader_source, fragment_shader_source, true, false); } } else { this->execute_negative_test(input_shader_type, input_source); this->execute_negative_test(output_shader_type, output_source); } } } /** Calulate smallest denominator for values over 1 * * @param value Value in question * * @return Smallest denominator **/ size_t findSmallestDenominator(const size_t value) { /* Skip 0 and 1 */ for (size_t i = 2; i < value; ++i) { if (0 == value % i) { return i; } } return value; } /** Check if left is bigger than right * * @tparam T Type of values * @param l Left value * @param r Right value * * @return true if l > r, false otherwise **/ template bool more(const T& l, const T& r) { return l > r; } /** Prepare dimensions of array with given number of entries * * @tparam API Tested API descriptor * * @param n_entries Number of entries * @param dimensions Storage for dimesnions **/ template void prepareDimensions(size_t n_entries, std::vector& dimensions) { if (dimensions.empty()) return; const size_t last = dimensions.size() - 1; /* Calculate */ for (size_t i = 0; i < last; ++i) { const size_t denom = findSmallestDenominator(n_entries); n_entries /= denom; dimensions[i] = denom; } dimensions[last] = n_entries; /* Sort */ std::sort(dimensions.begin(), dimensions.end(), more); } /* Generates the shader source code for the AtomicDeclarationTest * and attempts to compile each shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void AtomicDeclarationTest::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { static const char* indent_step = " "; static const char* uniform_atomic_uint = "layout(binding = 0) uniform atomic_uint"; const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); std::string comment; std::vector dimensions; std::string indent; std::string indexing; std::string invalid_definition = uniform_atomic_uint; std::string invalid_iteration; std::string invalid_shader_source; std::string loop_end; glw::GLint max_atomics = 0; glw::GLenum pname = 0; std::string valid_shader_source; std::string valid_definition = uniform_atomic_uint; std::string valid_iteration; /* Select pname of max for stage */ switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: pname = GL_MAX_COMPUTE_ATOMIC_COUNTERS; break; case TestCaseBase::FRAGMENT_SHADER_TYPE: pname = GL_MAX_FRAGMENT_ATOMIC_COUNTERS; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: pname = GL_MAX_GEOMETRY_ATOMIC_COUNTERS; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: pname = GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: pname = GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS; break; case TestCaseBase::VERTEX_SHADER_TYPE: pname = GL_MAX_VERTEX_ATOMIC_COUNTERS; break; default: TCU_FAIL("Invalid enum"); break; } /* Get maximum */ gl.getIntegerv(pname, &max_atomics); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); if (0 == max_atomics) { /* Not supported - skip */ return; } else { dimensions.resize(API::MAX_ARRAY_DIMENSIONS); prepareDimensions(max_atomics, dimensions); } /* Prepare parts of shader */ for (size_t i = API::MAX_ARRAY_DIMENSIONS; i != 0; --i) { char it[16]; char max[16]; indent += indent_step; loop_end.insert(0, "}\n"); loop_end.insert(0, indent); sprintf(it, "i%u", (unsigned int)(API::MAX_ARRAY_DIMENSIONS - i)); indexing += "["; indexing += it; indexing += "]"; sprintf(max, "%u", (unsigned int)(dimensions[i - 1])); valid_definition += "["; valid_definition += max; valid_definition += "]"; valid_iteration += indent; valid_iteration += "for (uint "; valid_iteration += it; valid_iteration += " = 0; "; valid_iteration += it; valid_iteration += " < "; valid_iteration += max; valid_iteration += "; ++"; valid_iteration += it; valid_iteration += ")\n"; valid_iteration += indent; valid_iteration += "{\n"; if (1 == i) { sprintf(max, "%u", (unsigned int)(dimensions[i - 1] + 1)); } invalid_definition += "["; invalid_definition += max; invalid_definition += "]"; invalid_iteration += indent; invalid_iteration += "for (uint "; invalid_iteration += it; invalid_iteration += " = 0; "; invalid_iteration += it; invalid_iteration += " < "; invalid_iteration += max; invalid_iteration += "; ++"; invalid_iteration += it; invalid_iteration += ")\n"; invalid_iteration += indent; invalid_iteration += "{\n"; } { char max[16]; sprintf(max, "%u", (unsigned int)(max_atomics)); comment += "/* MAX_*_ATOMIC_COUNTERS = "; comment += max; comment += " */\n"; } /* Prepare invalid source */ invalid_shader_source += comment; invalid_shader_source += invalid_definition; invalid_shader_source += " a;\n\nvoid main()\n{\n"; invalid_shader_source += invalid_iteration; invalid_shader_source += indent; invalid_shader_source += indent_step; invalid_shader_source += "atomicCounterIncrement( a"; invalid_shader_source += indexing; invalid_shader_source += " );\n"; invalid_shader_source += loop_end; /* Prepare valid source */ valid_shader_source += comment; valid_shader_source += valid_definition; valid_shader_source += " a;\n\nvoid main()\n{\n"; valid_shader_source += valid_iteration; valid_shader_source += indent; valid_shader_source += indent_step; valid_shader_source += "atomicCounterIncrement( a"; valid_shader_source += indexing; valid_shader_source += " );\n"; valid_shader_source += loop_end; /* End main */ DEFAULT_MAIN_ENDING(tested_shader_type, invalid_shader_source); DEFAULT_MAIN_ENDING(tested_shader_type, valid_shader_source); /* Execute test */ EXECUTE_POSITIVE_TEST(tested_shader_type, valid_shader_source, true, false); /* Expect build failure for invalid shader source */ { bool negative_build_test_result = false; try { EXECUTE_POSITIVE_TEST(tested_shader_type, invalid_shader_source, true, false); } catch (...) { negative_build_test_result = true; } if (false == negative_build_test_result) { TCU_FAIL("It was expected that build process will fail"); } } } /* Generates the shader source code for the AtomicUsageTest * and attempts to compile each shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void AtomicUsageTest::test_shader_compilation(typename TestCaseBase::TestShaderType tested_shader_type) { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); glw::GLint max_atomics = 0; glw::GLint max_bindings = 0; glw::GLint max_size = 0; glw::GLenum pname = 0; /* Select pname of max for stage */ switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: pname = GL_MAX_COMPUTE_ATOMIC_COUNTERS; break; case TestCaseBase::FRAGMENT_SHADER_TYPE: pname = GL_MAX_FRAGMENT_ATOMIC_COUNTERS; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: pname = GL_MAX_GEOMETRY_ATOMIC_COUNTERS; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: pname = GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: pname = GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS; break; case TestCaseBase::VERTEX_SHADER_TYPE: pname = GL_MAX_VERTEX_ATOMIC_COUNTERS; break; default: TCU_FAIL("Invalid enum"); break; } /* Get limits */ gl.getIntegerv(pname, &max_atomics); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &max_bindings); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &max_size); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); if (0 == max_atomics) { /* Not supported - skip */ return; } const glw::GLuint last_binding = (glw::GLuint)max_bindings - 1; const glw::GLuint offset = (glw::GLuint)max_size / 2; glw::GLuint n_entries = std::min((glw::GLuint)(max_size - offset) / (glw::GLuint)sizeof(glw::GLuint), (glw::GLuint)max_atomics); if (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type) { glw::GLint max_uniform_locations = 0; gl.getIntegerv(GL_MAX_UNIFORM_LOCATIONS, &max_uniform_locations); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); max_atomics = std::min(max_atomics, (max_uniform_locations - 1)); n_entries = (glw::GLuint)std::min((glw::GLint)n_entries, (max_uniform_locations - 1)); } execute(tested_shader_type, last_binding, 0 /* offset */, max_atomics); execute(tested_shader_type, last_binding, offset, n_entries); } /* Generates the shader source code for the AtomicUsageTest * and attempts to compile each shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param binding Binding index * @param offset Offset of data * @param n_entries Number of entries in array */ template void AtomicUsageTest::execute(typename TestCaseBase::TestShaderType tested_shader_type, glw::GLuint binding, glw::GLuint offset, glw::GLuint n_entries) { static const char* indent_step = " "; static const char* layout_binding = "layout(binding = "; static const char* layout_offset = ", offset = "; static const char* uniform_atomic_uint = ") uniform atomic_uint"; const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); std::string comment; std::vector dimensions; std::string indent; std::string indexing; std::string loop_end; std::string result; std::string valid_shader_source; std::string valid_definition = layout_binding; std::string valid_iteration; std::string varying_definition; dimensions.resize(API::MAX_ARRAY_DIMENSIONS); prepareDimensions(n_entries, dimensions); /* Prepare parts of shader */ /* Append binding */ { char buffer[16]; sprintf(buffer, "%u", static_cast(binding)); valid_definition += buffer; valid_definition += layout_offset; sprintf(buffer, "%u", static_cast(offset)); valid_definition += buffer; valid_definition += uniform_atomic_uint; } for (size_t i = API::MAX_ARRAY_DIMENSIONS; i != 0; --i) { char it[16]; char max[16]; indent += indent_step; loop_end.insert(0, "}\n"); loop_end.insert(0, indent); sprintf(it, "i%u", (unsigned int)(API::MAX_ARRAY_DIMENSIONS - i)); indexing += "["; indexing += it; indexing += "]"; sprintf(max, "%u", (unsigned int)(dimensions[i - 1])); valid_definition += "["; valid_definition += max; valid_definition += "]"; valid_iteration += indent; valid_iteration += "for (uint "; valid_iteration += it; valid_iteration += " = 0; "; valid_iteration += it; valid_iteration += " < "; valid_iteration += max; valid_iteration += "; ++"; valid_iteration += it; valid_iteration += ")\n"; valid_iteration += indent; valid_iteration += "{\n"; } { char max[16]; sprintf(max, "%u", (unsigned int)(n_entries)); comment += "/* Number of atomic counters = "; comment += max; comment += " */\n"; } /* Select varyings and result */ switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: result = " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), vec4(result, 0, 0, 0));\n"; varying_definition = "writeonly uniform image2D uni_image;\n" "\n"; break; case TestCaseBase::FRAGMENT_SHADER_TYPE: result = " color = vec4(result);\n"; varying_definition = "out vec4 color;\n" "\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: result = " gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n"; varying_definition = "out float fs_result;\n" "\n"; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: result = " tcs_result[gl_InvocationID] = result;\n" "\n" " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n"; varying_definition = "out float tcs_result[];\n" "\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: result = " fs_result = result;\n"; varying_definition = "out float fs_result;\n" "\n"; break; case TestCaseBase::VERTEX_SHADER_TYPE: result = " fs_result = result;\n"; varying_definition = "out float fs_result;\n" "\n"; break; default: TCU_FAIL("Invalid enum"); break; } /* Prepare valid source */ valid_shader_source += varying_definition; valid_shader_source += comment; valid_shader_source += valid_definition; valid_shader_source += " a;\n\nvoid main()\n{\n uint sum = 0u;\n"; valid_shader_source += valid_iteration; valid_shader_source += indent; valid_shader_source += indent_step; valid_shader_source += "sum += atomicCounterIncrement( a"; valid_shader_source += indexing; valid_shader_source += " );\n"; valid_shader_source += loop_end; valid_shader_source += "\n" " float result = 0.0;\n" "\n" " if (16u < sum)\n" " {\n" " result = 1.0;\n" " }\n"; valid_shader_source += result; valid_shader_source += shader_end; /* Build program */ { const std::string* cs = &empty_string; const std::string* vs = &default_vertex_shader_source; const std::string* tcs = &empty_string; const std::string* tes = &empty_string; const std::string* gs = &empty_string; const std::string* fs = &pass_fragment_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: cs = &valid_shader_source; vs = &empty_string; fs = &empty_string; break; case TestCaseBase::FRAGMENT_SHADER_TYPE: fs = &valid_shader_source; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: gs = &valid_shader_source; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tcs = &valid_shader_source; tes = &pass_te_shader_source; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tcs = &default_tc_shader_source; tes = &valid_shader_source; break; case TestCaseBase::VERTEX_SHADER_TYPE: vs = &valid_shader_source; break; default: TCU_FAIL("Invalid enum"); break; } if (API::USE_ALL_SHADER_STAGES) { this->execute_positive_test(*vs, *tcs, *tes, *gs, *fs, *cs, false, false); } else { this->execute_positive_test(*vs, *fs, false, false); } } gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); /* Prepare buffer */ glw::GLuint buffer_object_id = 0; std::vector buffer_data; const size_t start_pos = offset / 4; const size_t last_pos = start_pos + n_entries; const size_t buffer_data_size = last_pos * sizeof(glw::GLuint); gl.genBuffers(1, &buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed."); gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed."); buffer_data.resize(start_pos + n_entries); for (size_t i = 0; i < n_entries; ++i) { buffer_data[start_pos + i] = (glw::GLuint)i; } gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, buffer_data_size, &buffer_data[0], GL_STATIC_DRAW); GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed."); gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, binding, buffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() failed."); /* Run program */ if (TestCaseBase::COMPUTE_SHADER_TYPE != tested_shader_type) { glw::GLuint framebuffer_object_id = 0; glw::GLuint texture_object_id = 0; glw::GLuint vao_id = 0; gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.drawArrays(GL_POINTS, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); gl.drawArrays(GL_PATCHES, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; default: TCU_FAIL("Invalid enum"); break; } gl.memoryBarrier(GL_ALL_BARRIER_BITS); GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier."); gl.bindTexture(GL_TEXTURE_2D, 0); gl.bindFramebuffer(GL_FRAMEBUFFER, 0); gl.bindVertexArray(0); gl.deleteTextures(1, &texture_object_id); gl.deleteFramebuffers(1, &framebuffer_object_id); gl.deleteVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); } else { gl.dispatchCompute(1, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); gl.memoryBarrier(GL_ALL_BARRIER_BITS); GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier."); } /* Verify results */ bool test_result = true; const glw::GLuint* results = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /* offset */, buffer_data_size, GL_MAP_READ_BIT); GLU_EXPECT_NO_ERROR(gl.getError(), "MapBufferRange"); /* Anything before start position should be 0 */ for (size_t i = 0; i < start_pos; ++i) { if (0 != results[i]) { test_result = false; break; } } /* Anything from start_pos should be incremented by 1 */ int diff = 0; for (size_t i = 0; i < n_entries; ++i) { /* Any vertex processing shader could be called an implementation defined * number of times. In here, check the increment is consistent over all results. */ if (tested_shader_type == TestCaseBase::VERTEX_SHADER_TYPE || tested_shader_type == TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE || tested_shader_type == TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE || tested_shader_type == TestCaseBase::GEOMETRY_SHADER_TYPE) { if (i == 0) { diff = static_cast(results[i + start_pos]) - static_cast(i); if (diff <= 0) { test_result = false; break; } } else if ((static_cast(results[i + start_pos]) - static_cast(i)) != diff) { test_result = false; break; } } else { if (i + 1 != results[i + start_pos]) { test_result = false; break; } } } gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER); GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); /* Deallocate any resources used. */ gl.deleteBuffers(1, &buffer_object_id); this->delete_objects(); if (false == test_result) { TCU_FAIL("Invalid results."); } } /* Generates the shader source code for the SubroutineFunctionCalls1 * array tests, attempts to build and execute test program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void SubroutineFunctionCalls1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string iterator_declaration = " " + var_iterator->second.iterator_type + " iterator = " + var_iterator->second.iterator_initialization + ";\n"; std::string function_definition; std::string function_use; std::string verification; function_definition += "// Subroutine types\n" "subroutine void out_routine_type(out "; function_definition += var_iterator->second.type; function_definition += " output_array[2][2][2][2]);\n\n" "// Subroutine definitions\n" "subroutine(out_routine_type) void original_routine(out "; function_definition += var_iterator->second.type; function_definition += " output_array[2][2][2][2]) {\n"; function_definition += iterator_declaration; function_definition += iteration_loop_start; function_definition += " output_array[a][b][c][d] = " + var_iterator->second.variable_type_initializer1 + ";\n"; function_definition += " iterator += " + var_iterator->second.iterator_type + "(1);\n"; function_definition += iteration_loop_end; function_definition += "}\n\n"; function_definition += "subroutine(out_routine_type) void new_routine(out "; function_definition += var_iterator->second.type; function_definition += " output_array[2][2][2][2]) {\n"; function_definition += iterator_declaration; function_definition += iteration_loop_start; function_definition += " output_array[a][b][c][d] = " + var_iterator->second.variable_type_initializer1 + ";\n"; function_definition += " iterator -= " + var_iterator->second.iterator_type + "(1);\n"; function_definition += iteration_loop_end; function_definition += "}\n\n" "// Subroutine uniform\n" "subroutine uniform out_routine_type routine;\n"; function_use = " " + var_iterator->second.type + " my_array[2][2][2][2];\n"; function_use += " routine(my_array);"; verification = iterator_declaration; verification += " float result = 1.0;\n"; verification += iteration_loop_start; verification += " if (my_array[a][b][c][d] " + var_iterator->second.specific_element + " != iterator)\n" " {\n" " result = 0.0;\n" " }\n" " iterator += " + var_iterator->second.iterator_type + "(1);\n"; verification += iteration_loop_end; if (false == test_compute) { execute_draw_test(tested_shader_type, function_definition, function_use, verification, false, true); execute_draw_test(tested_shader_type, function_definition, function_use, verification, true, false); } else { execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, false, true); execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, true, false); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /** Executes test for compute program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification * @param use_original Selects if "original_routine" - true or "new_routine" is choosen * @param expect_invalid_result Does test expects invalid results **/ template void SubroutineFunctionCalls1::execute_dispatch_test(typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification, bool use_original, bool expect_invalid_result) { const std::string& compute_shader_source = prepare_compute_shader(tested_shader_type, function_definition, function_use, verification); const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); this->execute_positive_test(empty_string, empty_string, empty_string, empty_string, empty_string, compute_shader_source, false, false); /* We are now ready to verify whether the returned size is correct. */ unsigned char buffer[4] = { 0 }; glw::GLuint framebuffer_object_id = 0; glw::GLint location = -1; glw::GLuint routine_index = -1; glw::GLuint routine_location = -1; const glw::GLchar* routine_name = "original_routine"; const glw::GLenum shader_type = GL_COMPUTE_SHADER; glw::GLuint texture_object_id = 0; if (false == use_original) { routine_name = "new_routine"; } gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); /* Select subroutine */ routine_index = gl.getSubroutineIndex(this->program_object_id, shader_type, routine_name); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() failed."); routine_location = gl.getSubroutineUniformLocation(this->program_object_id, shader_type, "routine"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() failed."); if (0 != routine_location) { TCU_FAIL("Subroutine location is invalid"); } gl.uniformSubroutinesuiv(shader_type, 1, &routine_index); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() failed."); /* Prepare texture */ gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); gl.bindImageTexture(0 /* image unit */, texture_object_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY, GL_RGBA8); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() failed."); location = gl.getUniformLocation(this->program_object_id, "uni_image"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() failed."); if (-1 == location) { TCU_FAIL("Uniform is inactive"); } gl.uniform1i(location, 0 /* image unit */); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() failed."); /* Execute */ gl.dispatchCompute(1, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); /* Verify */ gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); gl.readBuffer(GL_COLOR_ATTACHMENT0); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed."); gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed."); if ((buffer[0] != 255) != expect_invalid_result) { TCU_FAIL("Invalid result was returned."); } /* Delete generated objects. */ gl.useProgram(0); gl.bindTexture(GL_TEXTURE_2D, 0); gl.bindFramebuffer(GL_FRAMEBUFFER, 0); gl.deleteProgram(this->program_object_id); this->program_object_id = 0; gl.deleteTextures(1, &texture_object_id); gl.deleteFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); } /** Executes test for draw program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification * @param use_original Selects if "original_routine" - true or "new_routine" is choosen * @param expect_invalid_result Does test expects invalid results **/ template void SubroutineFunctionCalls1::execute_draw_test(typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification, bool use_original, bool expect_invalid_result) { const glw::Functions& gl = this->context_id.getRenderContext().getFunctions(); if (API::USE_ALL_SHADER_STAGES) { const std::string& compute_shader_source = empty_string; const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, function_definition, function_use, verification); const std::string& geometry_shader_source = this->prepare_geometry_shader(tested_shader_type, function_definition, function_use, verification); const std::string& tess_ctrl_shader_source = this->prepare_tess_ctrl_shader(tested_shader_type, function_definition, function_use, verification); const std::string& tess_eval_shader_source = this->prepare_tess_eval_shader(tested_shader_type, function_definition, function_use, verification); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, function_definition, function_use, verification); switch (tested_shader_type) { case TestCaseBase::VERTEX_SHADER_TYPE: /* Fall through */ case TestCaseBase::FRAGMENT_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); break; case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: this->execute_positive_test(vertex_shader_source, tess_ctrl_shader_source, tess_eval_shader_source, geometry_shader_source, fragment_shader_source, compute_shader_source, false, false); break; default: TCU_FAIL("Invalid enum"); break; } } else { const std::string& fragment_shader_source = this->prepare_fragment_shader(tested_shader_type, function_definition, function_use, verification); const std::string& vertex_shader_source = this->prepare_vertex_shader(tested_shader_type, function_definition, function_use, verification); this->execute_positive_test(vertex_shader_source, fragment_shader_source, false, false); } /* We are now ready to verify whether the returned size is correct. */ unsigned char buffer[4] = { 0 }; glw::GLuint framebuffer_object_id = 0; glw::GLuint routine_index = -1; glw::GLuint routine_location = -1; const glw::GLchar* routine_name = "original_routine"; glw::GLenum shader_type = 0; glw::GLuint texture_object_id = 0; glw::GLuint vao_id = 0; switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: shader_type = GL_FRAGMENT_SHADER; break; case TestCaseBase::VERTEX_SHADER_TYPE: shader_type = GL_VERTEX_SHADER; break; case TestCaseBase::COMPUTE_SHADER_TYPE: shader_type = GL_COMPUTE_SHADER; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: shader_type = GL_GEOMETRY_SHADER; break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: shader_type = GL_TESS_CONTROL_SHADER; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: shader_type = GL_TESS_EVALUATION_SHADER; break; default: TCU_FAIL("Invalid shader type"); break; } if (false == use_original) { routine_name = "new_routine"; } gl.useProgram(this->program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed."); /* Select subroutine */ routine_index = gl.getSubroutineIndex(this->program_object_id, shader_type, routine_name); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineIndex() failed."); routine_location = gl.getSubroutineUniformLocation(this->program_object_id, shader_type, "routine"); GLU_EXPECT_NO_ERROR(gl.getError(), "glGetSubroutineUniformLocation() failed."); if (0 != routine_location) { TCU_FAIL("Subroutine location is invalid"); } gl.uniformSubroutinesuiv(shader_type, 1, &routine_index); GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformSubroutinesuiv() failed."); /* Prepre texture */ assert(0 == texture_object_id); gl.genTextures(1, &texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() failed."); gl.bindTexture(GL_TEXTURE_2D, texture_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() failed."); gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() failed."); /* Prepare framebuffer */ assert(0 == framebuffer_object_id); gl.genFramebuffers(1, &framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() failed."); gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() failed."); gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_object_id, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() failed."); gl.viewport(0, 0, 1, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() failed."); /* Set VAO */ assert(0 == vao_id); gl.genVertexArrays(1, &vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() failed."); gl.bindVertexArray(vao_id); GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() failed."); switch (tested_shader_type) { case TestCaseBase::FRAGMENT_SHADER_TYPE: /* Fall through */ case TestCaseBase::VERTEX_SHADER_TYPE: gl.drawArrays(GL_TRIANGLE_FAN, 0, 4); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); gl.drawArrays(GL_PATCHES, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; case TestCaseBase::GEOMETRY_SHADER_TYPE: gl.drawArrays(GL_POINTS, 0, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed."); break; default: TCU_FAIL("Invalid enum"); break; } /* Verify */ gl.readBuffer(GL_COLOR_ATTACHMENT0); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer() failed."); gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed."); const bool result = ((buffer[0] != 255) == expect_invalid_result); /* Delete generated objects. */ gl.useProgram(0); gl.bindTexture(GL_TEXTURE_2D, 0); gl.bindFramebuffer(GL_FRAMEBUFFER, 0); gl.bindVertexArray(0); gl.deleteProgram(this->program_object_id); this->program_object_id = 0; gl.deleteTextures(1, &texture_object_id); texture_object_id = 0; gl.deleteFramebuffers(1, &framebuffer_object_id); framebuffer_object_id = 0; gl.deleteVertexArrays(1, &vao_id); vao_id = 0; GLU_EXPECT_NO_ERROR(gl.getError(), "An error ocurred while deleting generated objects."); if (!result) { TCU_FAIL("Invalid result was returned."); } } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification **/ template std::string SubroutineFunctionCalls1::prepare_compute_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string compute_shader_source; if (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type) { compute_shader_source = "writeonly uniform image2D uni_image;\n" "\n"; /* User-defined function definition. */ compute_shader_source += function_definition; compute_shader_source += "\n\n"; /* Main function definition. */ compute_shader_source += shader_start; compute_shader_source += function_use; compute_shader_source += "\n\n"; compute_shader_source += verification; compute_shader_source += "\n\n"; compute_shader_source += "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), vec4(result, 0, 0, 0));\n" "}\n" "\n"; } return compute_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification **/ template std::string SubroutineFunctionCalls1::prepare_fragment_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string fragment_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: fragment_shader_source = "out vec4 colour;\n\n"; /* User-defined function definition. */ fragment_shader_source += function_definition; fragment_shader_source += "\n\n"; /* Main function definition. */ fragment_shader_source += shader_start; fragment_shader_source += function_use; fragment_shader_source += "\n\n"; fragment_shader_source += verification; fragment_shader_source += "\n\n"; fragment_shader_source += " colour = vec4(result);\n"; fragment_shader_source += shader_end; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: /* Fall through */ case TestCaseBase::VERTEX_SHADER_TYPE: fragment_shader_source = "in float fs_result;\n\n" "out vec4 colour;\n\n" "void main()\n" "{\n" " colour = vec4(fs_result);\n" "}\n" "\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return fragment_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification **/ template std::string SubroutineFunctionCalls1::prepare_geometry_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string geometry_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: /* Fall through */ case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: /* Fall through */ case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in float tes_result[];\n" "out float fs_result;\n" "\n" "void main()\n" "{\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = tes_result[0];\n" " EmitVertex();\n" "}\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: geometry_shader_source = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "out float fs_result;\n" "\n"; /* User-defined function definition. */ geometry_shader_source += function_definition; geometry_shader_source += "\n\n"; /* Main function definition. */ geometry_shader_source += shader_start; geometry_shader_source += function_use; geometry_shader_source += "\n\n"; geometry_shader_source += verification; geometry_shader_source += "\n\n"; geometry_shader_source += "\n gl_Position = vec4(-1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " fs_result = result;\n" " EmitVertex();\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return geometry_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification **/ template std::string SubroutineFunctionCalls1::prepare_tess_ctrl_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string tess_ctrl_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_ctrl_shader_source = "layout(vertices = 1) out;\n" "\n" "out float tcs_result[];\n" "\n"; /* User-defined function definition. */ tess_ctrl_shader_source += function_definition; tess_ctrl_shader_source += "\n\n"; /* Main function definition. */ tess_ctrl_shader_source += shader_start; tess_ctrl_shader_source += function_use; tess_ctrl_shader_source += "\n\n"; tess_ctrl_shader_source += verification; tess_ctrl_shader_source += "\n\n"; tess_ctrl_shader_source += " tcs_result[gl_InvocationID] = result;\n" "\n" " gl_TessLevelOuter[0] = 1.0;\n" " gl_TessLevelOuter[1] = 1.0;\n" " gl_TessLevelOuter[2] = 1.0;\n" " gl_TessLevelOuter[3] = 1.0;\n" " gl_TessLevelInner[0] = 1.0;\n" " gl_TessLevelInner[1] = 1.0;\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_ctrl_shader_source = default_tc_shader_source; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_ctrl_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification **/ template std::string SubroutineFunctionCalls1::prepare_tess_eval_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string tess_eval_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: case TestCaseBase::FRAGMENT_SHADER_TYPE: case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::VERTEX_SHADER_TYPE: break; case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "in float tcs_result[];\n" "out float tes_result;\n" "\n" "void main()\n" "{\n" " tes_result = tcs_result[0];\n" "}\n"; break; case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: tess_eval_shader_source = "layout(isolines, point_mode) in;\n" "\n" "out float tes_result;\n" "\n"; /* User-defined function definition. */ tess_eval_shader_source += function_definition; tess_eval_shader_source += "\n\n"; /* Main function definition. */ tess_eval_shader_source += shader_start; tess_eval_shader_source += function_use; tess_eval_shader_source += "\n\n"; tess_eval_shader_source += verification; tess_eval_shader_source += "\n\n"; tess_eval_shader_source += " tes_result = result;\n" "}\n"; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return tess_eval_shader_source; } /** Prepare shader * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested * @param function_definition Definition used to prepare shader * @param function_use Use of definition * @param verification Result verification **/ template std::string SubroutineFunctionCalls1::prepare_vertex_shader( typename TestCaseBase::TestShaderType tested_shader_type, const std::string& function_definition, const std::string& function_use, const std::string& verification) { std::string vertex_shader_source; switch (tested_shader_type) { case TestCaseBase::COMPUTE_SHADER_TYPE: break; case TestCaseBase::FRAGMENT_SHADER_TYPE: vertex_shader_source = "/** GL_TRIANGLE_FAN-type quad vertex data. */\n" "const vec4 vertex_positions[4] = vec4[4](vec4( 1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, 1.0, 0.0, 1.0),\n" " vec4( 1.0, 1.0, 0.0, 1.0) );\n" "\n" "void main()\n" "{\n" " gl_Position = vertex_positions[gl_VertexID];" "}\n\n"; break; case TestCaseBase::GEOMETRY_SHADER_TYPE: case TestCaseBase::TESSELATION_CONTROL_SHADER_TYPE: case TestCaseBase::TESSELATION_EVALUATION_SHADER_TYPE: vertex_shader_source = default_vertex_shader_source; break; case TestCaseBase::VERTEX_SHADER_TYPE: /* Vertex shader source. */ vertex_shader_source = "out float fs_result;\n\n"; vertex_shader_source += "/** GL_TRIANGLE_FAN-type quad vertex data. */\n" "const vec4 vertex_positions[4] = vec4[4](vec4( 1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, -1.0, 0.0, 1.0),\n" " vec4(-1.0, 1.0, 0.0, 1.0),\n" " vec4( 1.0, 1.0, 0.0, 1.0) );\n\n"; /* User-defined function definition. */ vertex_shader_source += function_definition; vertex_shader_source += "\n\n"; /* Main function definition. */ vertex_shader_source += shader_start; vertex_shader_source += function_use; vertex_shader_source += "\n\n"; vertex_shader_source += verification; vertex_shader_source += "\n\n"; vertex_shader_source += " fs_result = result;\n" " gl_Position = vertex_positions[gl_VertexID];\n"; vertex_shader_source += shader_end; break; default: TCU_FAIL("Unrecognized shader object type."); break; } return vertex_shader_source; } /* Generates the shader source code for the InteractionFunctionCalls2 * array tests, and attempts to build and execute test program. * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void SubroutineFunctionCalls2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const std::string multiplier_array = "const int[] multiplier_array = int[]( 1, 2, 3, 4, 5, 6, 7, 8,\n" " 11, 12, 13, 14, 15, 16, 17, 18,\n" " 21, 22, 23, 24, 25, 26, 27, 28,\n" " 31, 32, 33, 34, 35, 36, 37, 38,\n" " 41, 42, 43, 44, 45, 46, 47, 48,\n" " 51, 52, 53, 54, 55, 56, 57, 58,\n" " 61, 62, 63, 64, 65, 66, 67, 68,\n" " 71, 72, 73, 74, 75, 76, 77, 78,\n" " 81, 82, 83, 84, 85, 86, 87, 88);\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string function_definition; std::string function_use; std::string verification; function_definition += multiplier_array; function_definition += "// Subroutine types\n" "subroutine void inout_routine_type(inout "; function_definition += var_iterator->second.type; function_definition += " inout_array[2][2][2][2]);\n\n" "// Subroutine definitions\n" "subroutine(inout_routine_type) void original_routine(inout "; function_definition += var_iterator->second.type; function_definition += " inout_array[2][2][2][2]) {\n" " uint i = 0u;\n"; function_definition += iteration_loop_start; function_definition += " inout_array[a][b][c][d] *= " + var_iterator->second.iterator_type + "(multiplier_array[i % 64u]);\n"; function_definition += " i+= 1u;\n"; function_definition += iteration_loop_end; function_definition += "}\n\n" "subroutine(inout_routine_type) void new_routine(inout "; function_definition += var_iterator->second.type; function_definition += " inout_array[2][2][2][2]) {\n" " uint i = 0u;\n"; function_definition += iteration_loop_start; function_definition += " inout_array[a][b][c][d] /= " + var_iterator->second.iterator_type + "(multiplier_array[i % 64u]);\n"; function_definition += " i+= 1u;\n"; function_definition += iteration_loop_end; function_definition += "}\n\n" "// Subroutine uniform\n" "subroutine uniform inout_routine_type routine;\n"; function_use += " float result = 1.0;\n"; function_use += " uint iterator = 0u;\n"; function_use += " " + var_iterator->second.type + " my_array[2][2][2][2];\n"; function_use += iteration_loop_start; function_use += " my_array[a][b][c][d] = " + var_iterator->second.variable_type_initializer2 + ";\n"; function_use += iteration_loop_end; function_use += " routine(my_array);"; verification += iteration_loop_start; verification += " if (my_array[a][b][c][d] " + var_iterator->second.specific_element + "!= " + var_iterator->second.iterator_type + "(multiplier_array[iterator % 64u]))\n" " {\n" " result = 0.0;\n" " }\n" " iterator += 1u;\n"; verification += iteration_loop_end; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, false, true); this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, true, false); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, false, true); this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, true, false); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the SubroutineArgumentAliasing1 * array tests, attempts to build and execute test program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void SubroutineArgumentAliasing1::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string function_definition; std::string function_use; std::string verification; function_definition += "// Subroutine types\n" "subroutine bool in_routine_type("; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2]);\n\n" "// Subroutine definitions\n" "subroutine(in_routine_type) bool original_routine("; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "subroutine(in_routine_type) bool new_routine("; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "// Subroutine uniform\n" "subroutine uniform in_routine_type routine;\n"; function_use += " " + var_iterator->second.type + " z[2][2][2][2];\n"; function_use += iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += iteration_loop_end; verification = " float result = 0.0;\n" " if(routine(z, z) == true)\n" " {\n" " result = 1.0;\n" " }\n" " else\n" " {\n" " result = 0.5;\n" " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, true, false); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, true, false); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the SubroutineArgumentAliasing1 * array tests, attempts to build and execute test program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void SubroutineArgumentAliasing2::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string function_definition; std::string function_use; std::string verification; function_definition += "// Subroutine types\n" "subroutine bool inout_routine_type(inout "; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], inout "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2]);\n\n" "// Subroutine definitions\n" "subroutine(inout_routine_type) bool original_routine(inout "; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], inout "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "subroutine(inout_routine_type) bool new_routine(inout "; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], inout "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "// Subroutine uniform\n" "subroutine uniform inout_routine_type routine;\n"; function_use += " " + var_iterator->second.type + " z[2][2][2][2];\n"; function_use += iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += iteration_loop_end; verification = " float result = 0.0;\n" " if(routine(z, z) == true)\n" " {\n" " result = 1.0;\n" " }\n" " else\n" " {\n" " result = 0.5;\n" " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, true, false); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, true, false); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the SubroutineArgumentAliasing1 * array tests, attempts to build and execute test program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void SubroutineArgumentAliasing3::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string function_definition; std::string function_use; std::string verification; function_definition += "// Subroutine types\n" "subroutine bool out_routine_type(out "; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2]);\n\n" "// Subroutine definitions\n" "subroutine(out_routine_type) bool original_routine(out "; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "subroutine(out_routine_type) bool new_routine(out "; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " x[a][b][c][d] = " + var_iterator->second.type + "(321);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(y[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "// Subroutine uniform\n" "subroutine uniform out_routine_type routine;\n"; function_use += " " + var_iterator->second.type + " z[2][2][2][2];\n"; function_use += iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += iteration_loop_end; verification = " float result = 0.0;\n" " if(routine(z, z) == true)\n" " {\n" " result = 1.0;\n" " }\n" " else\n" " {\n" " result = 0.5;\n" " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, true, false); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, true, false); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /* Generates the shader source code for the SubroutineArgumentAliasing1 * array tests, attempts to build and execute test program * * @tparam API Tested API descriptor * * @param tested_shader_type The type of shader that is being tested */ template void SubroutineArgumentAliasing4::test_shader_compilation( typename TestCaseBase::TestShaderType tested_shader_type) { static const glcts::test_var_type var_types_set_es[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4 }; static const size_t num_var_types_es = sizeof(var_types_set_es) / sizeof(var_types_set_es[0]); static const glcts::test_var_type var_types_set_gl[] = { VAR_TYPE_INT, VAR_TYPE_FLOAT, VAR_TYPE_IVEC2, VAR_TYPE_IVEC3, VAR_TYPE_IVEC4, VAR_TYPE_VEC2, VAR_TYPE_VEC3, VAR_TYPE_VEC4, VAR_TYPE_MAT2, VAR_TYPE_MAT3, VAR_TYPE_MAT4, VAR_TYPE_DOUBLE, VAR_TYPE_DMAT2, VAR_TYPE_DMAT3, VAR_TYPE_DMAT4 }; static const size_t num_var_types_gl = sizeof(var_types_set_gl) / sizeof(var_types_set_gl[0]); const std::string iteration_loop_end = " }\n" " }\n" " }\n" " }\n"; const std::string iteration_loop_start = " for (uint a = 0u; a < 2u; a++)\n" " {\n" " for (uint b = 0u; b < 2u; b++)\n" " {\n" " for (uint c = 0u; c < 2u; c++)\n" " {\n" " for (uint d = 0u; d < 2u; d++)\n" " {\n"; const glcts::test_var_type* var_types_set = var_types_set_es; size_t num_var_types = num_var_types_es; const bool test_compute = (TestCaseBase::COMPUTE_SHADER_TYPE == tested_shader_type); if (API::USE_DOUBLE) { var_types_set = var_types_set_gl; num_var_types = num_var_types_gl; } for (size_t var_type_index = 0; var_type_index < num_var_types; var_type_index++) { _supported_variable_types_map_const_iterator var_iterator = supported_variable_types_map.find(var_types_set[var_type_index]); if (var_iterator != supported_variable_types_map.end()) { std::string function_definition; std::string function_use; std::string verification; function_definition += "// Subroutine types\n" "subroutine bool out_routine_type("; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], out "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2]);\n\n" "// Subroutine definitions\n" "subroutine(out_routine_type) bool original_routine("; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], out "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(123);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "subroutine(out_routine_type) bool new_routine("; function_definition += var_iterator->second.type; function_definition += " x[2][2][2][2], out "; function_definition += var_iterator->second.type; function_definition += " y[2][2][2][2])\n{\n"; function_definition += iteration_loop_start; function_definition += " y[a][b][c][d] = " + var_iterator->second.type + "(321);\n"; function_definition += iteration_loop_end; function_definition += "\n"; function_definition += iteration_loop_start; function_definition += " if(x[a][b][c][d]"; if (var_iterator->second.type == "mat4") // mat4 comparison { function_definition += "[0][0]"; function_definition += " != float"; } else if (var_iterator->second.type == "dmat4") // dmat4 comparison { function_definition += "[0][0]"; function_definition += " != double"; } else { function_definition += " != "; function_definition += var_iterator->second.type; } function_definition += "(((a*8u)+(b*4u)+(c*2u)+d))) {return false;}\n"; function_definition += iteration_loop_end; function_definition += "\n return true;\n"; function_definition += "}\n\n" "// Subroutine uniform\n" "subroutine uniform out_routine_type routine;\n"; function_use += " " + var_iterator->second.type + " z[2][2][2][2];\n"; function_use += iteration_loop_start; function_use += " z[a][b][c][d] = "; function_use += var_iterator->second.type; function_use += "(((a*8u)+(b*4u)+(c*2u)+d));\n"; function_use += iteration_loop_end; verification = " float result = 0.0;\n" " if(routine(z, z) == true)\n" " {\n" " result = 1.0;\n" " }\n" " else\n" " {\n" " result = 0.5;\n" " }\n"; if (false == test_compute) { this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_draw_test(tested_shader_type, function_definition, function_use, verification, true, false); } else { this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, false, false); this->execute_dispatch_test(tested_shader_type, function_definition, function_use, verification, true, false); } /* Deallocate any resources used. */ this->delete_objects(); } /* if var_type iterator found */ else { TCU_FAIL("Type not found."); } } /* for (int var_type_index = 0; ...) */ } /** Instantiates all tests and adds them as children to the node * * @tparam API Tested API descriptor * * @param context CTS context **/ template void initTests(TestCaseGroup& group, glcts::Context& context) { // Set up the map ArraysOfArrays::initializeMap(); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsPrimitive(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsStructTypes1(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsStructTypes2(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsStructTypes3(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsStructTypes4(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsTypenameStyle1(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsTypenameStyle2(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsTypenameStyle3(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsTypenameStyle4(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsTypenameStyle5(context)); group.addChild(new glcts::ArraysOfArrays::SizedDeclarationsFunctionParams(context)); group.addChild(new glcts::ArraysOfArrays::sized_declarations_invalid_sizes1(context)); group.addChild(new glcts::ArraysOfArrays::sized_declarations_invalid_sizes2(context)); group.addChild(new glcts::ArraysOfArrays::sized_declarations_invalid_sizes3(context)); group.addChild(new glcts::ArraysOfArrays::sized_declarations_invalid_sizes4(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclConstructors1(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclConstructors2(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclUnsizedConstructors(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclConst(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclInvalidConstructors1(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclInvalidConstructors2(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclInvalidConstructors3(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclInvalidConstructors4(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclConstructorSizing1(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclConstructorSizing2(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclStructConstructors(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclUnsizedArrays1(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclUnsizedArrays2(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclUnsizedArrays3(context)); group.addChild(new glcts::ArraysOfArrays::ConstructorsAndUnsizedDeclUnsizedArrays4(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsAssignment1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsAssignment2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsAssignment3(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsTypeRestrictions1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsTypeRestrictions2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingScalar1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingScalar2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingScalar3(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingScalar4(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingArray1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingArray2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsIndexingArray3(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsDynamicIndexing1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsDynamicIndexing2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsEquality1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsEquality2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsLength1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsLength2(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsLength3(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsInvalid1(context)); group.addChild(new glcts::ArraysOfArrays::ExpressionsInvalid2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionFunctionCalls1(context)); group.addChild(new glcts::ArraysOfArrays::InteractionFunctionCalls2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionArgumentAliasing1(context)); group.addChild(new glcts::ArraysOfArrays::InteractionArgumentAliasing2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionArgumentAliasing3(context)); group.addChild(new glcts::ArraysOfArrays::InteractionArgumentAliasing4(context)); group.addChild(new glcts::ArraysOfArrays::InteractionArgumentAliasing5(context)); group.addChild(new glcts::ArraysOfArrays::InteractionArgumentAliasing6(context)); group.addChild(new glcts::ArraysOfArrays::InteractionUniforms1(context)); group.addChild(new glcts::ArraysOfArrays::InteractionUniforms2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionUniformBuffers1(context)); group.addChild(new glcts::ArraysOfArrays::InteractionUniformBuffers2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionUniformBuffers3(context)); group.addChild(new glcts::ArraysOfArrays::InteractionInterfaceArrays1(context)); group.addChild(new glcts::ArraysOfArrays::InteractionInterfaceArrays2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionInterfaceArrays3(context)); group.addChild(new glcts::ArraysOfArrays::InteractionInterfaceArrays4(context)); if (API::USE_STORAGE_BLOCK) { group.addChild(new glcts::ArraysOfArrays::InteractionStorageBuffers1(context)); group.addChild(new glcts::ArraysOfArrays::InteractionStorageBuffers2(context)); group.addChild(new glcts::ArraysOfArrays::InteractionStorageBuffers3(context)); } if (API::USE_ATOMIC) { group.addChild(new glcts::ArraysOfArrays::AtomicDeclarationTest(context)); group.addChild(new glcts::ArraysOfArrays::AtomicUsageTest(context)); } if (API::USE_SUBROUTINE) { group.addChild(new glcts::ArraysOfArrays::SubroutineFunctionCalls1(context)); group.addChild(new glcts::ArraysOfArrays::SubroutineFunctionCalls2(context)); group.addChild(new glcts::ArraysOfArrays::SubroutineArgumentAliasing1(context)); group.addChild(new glcts::ArraysOfArrays::SubroutineArgumentAliasing2(context)); group.addChild(new glcts::ArraysOfArrays::SubroutineArgumentAliasing3(context)); group.addChild(new glcts::ArraysOfArrays::SubroutineArgumentAliasing4(context)); } } } /* namespace ArraysOfArrays */ /** Constructor * * @param context CTS context **/ ArrayOfArraysTestGroup::ArrayOfArraysTestGroup(Context& context) : TestCaseGroup(context, "arrays_of_arrays", "Groups all tests that verify 'arrays of arrays' functionality.") { /* Left blank on purpose */ } /* Instantiates all tests and adds them as children to the node */ void ArrayOfArraysTestGroup::init(void) { ArraysOfArrays::initTests(*this, m_context); } /** Constructor * * @param context CTS context **/ ArrayOfArraysTestGroupGL::ArrayOfArraysTestGroupGL(Context& context) : TestCaseGroup(context, "arrays_of_arrays_gl", "Groups all tests that verify 'arrays of arrays' functionality.") { /* Left blank on purpose */ } /* Instantiates all tests and adds them as children to the node */ void ArrayOfArraysTestGroupGL::init(void) { ArraysOfArrays::initTests(*this, m_context); } } /* namespace glcts */