/*------------------------------------------------------------------------- * OpenGL Conformance Test Suite * ----------------------------- * * Copyright (c) 2014-2016 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ /*! * \file * \brief */ /*-------------------------------------------------------------------*/ /** * \file gl4cShadingLanguage420PackTests.cpp * \brief Implements conformance tests for "Shading Language 420Pack" functionality. */ /*-------------------------------------------------------------------*/ #include "gl4cShadingLanguage420PackTests.hpp" #include "gluContextInfo.hpp" #include "gluDefs.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "tcuTestLog.hpp" #include #include #include #include #include #include #define IS_DEBUG 0 using namespace glw; namespace gl4cts { namespace GLSL420Pack { /** Check binding of uniform * * @param program Program object * @param name Array name * @param expected_binding Expected binding value * * @return true if binding is as expected, false otherwise **/ bool Utils::checkUniformBinding(Utils::program& program, const glw::GLchar* name, glw::GLint expected_binding) { const GLint uniform_location = program.getUniformLocation(name); if (-1 == uniform_location) { TCU_FAIL("Uniform is inactive"); } GLint binding = program.getUniform1i(uniform_location); return (expected_binding == binding); } /** Check binding of uniform array element at * * @param program Program object * @param name Array name * @param index Index * @param expected_binding Expected binding value * * @return true if binding is as expected, false otherwise **/ bool Utils::checkUniformArrayBinding(Utils::program& program, const glw::GLchar* name, glw::GLuint index, glw::GLint expected_binding) { GLchar buffer[64]; sprintf(buffer, "%s[%d]", name, index); const GLint uniform_location = program.getUniformLocation(buffer); if (-1 == uniform_location) { TCU_FAIL("Uniform is inactive"); } GLint binding = program.getUniform1i(uniform_location); return (expected_binding == binding); } /** Check if given qualifier is present in set * * @param qualifier Specific qualifier * @param qualifiers Qualifiers' set * * @return true if qualifier is present, false otherwise **/ bool Utils::doesContainQualifier(Utils::QUALIFIERS qualifier, const Utils::qualifierSet& qualifiers) { for (GLuint i = 0; i < qualifiers.size(); ++i) { if (qualifiers[i] == qualifier) { return true; } } return false; } /** Check if given stage supports specific qualifier * * @param stage Shader stage * @param storage Storage of variable * @param qualifier Qualifier * * @return true if qualifier can be used in given stage, false otherwise **/ bool Utils::doesStageSupportQualifier(Utils::SHADER_STAGES stage, Utils::VARIABLE_STORAGE storage, Utils::QUALIFIERS qualifier) { bool result = true; switch (stage) { case COMPUTE_SHADER: switch (qualifier) { case QUAL_NONE: case QUAL_UNIFORM: case QUAL_LOWP: case QUAL_MEDIUMP: case QUAL_HIGHP: case QUAL_INVARIANT: result = true; break; default: result = false; break; } break; case FRAGMENT_SHADER: if (QUAL_PATCH == qualifier) { result = false; } else if ((OUTPUT == storage) && ((QUAL_SMOOTH == qualifier) || (QUAL_NOPERSPECTIVE == qualifier) || (QUAL_FLAT == qualifier))) { result = false; } break; case VERTEX_SHADER: if (QUAL_PATCH == qualifier) { result = false; } else if ((INPUT == storage) && ((QUAL_SMOOTH == qualifier) || (QUAL_NOPERSPECTIVE == qualifier) || (QUAL_FLAT == qualifier) || (QUAL_INVARIANT == qualifier) || (QUAL_CENTROID == qualifier) || (QUAL_SAMPLE == qualifier))) { result = false; } break; case GEOMETRY_SHADER: if (QUAL_PATCH == qualifier) { result = false; } break; case TESS_CTRL_SHADER: if ((INPUT == storage) && (QUAL_PATCH == qualifier)) { result = false; } break; case TESS_EVAL_SHADER: if ((OUTPUT == storage) && (QUAL_PATCH == qualifier)) { result = false; } break; default: break; } return result; } /** Get string for qualifier * * @param qualifier Qualifier * * @return A string for given qualifier **/ const GLchar* Utils::getQualifierString(Utils::QUALIFIERS qualifier) { const GLchar* result = 0; switch (qualifier) { case QUAL_NONE: result = ""; break; case QUAL_CONST: result = "const"; break; case QUAL_IN: result = "in"; break; case QUAL_OUT: result = "out"; break; case QUAL_INOUT: result = "inout"; break; case QUAL_UNIFORM: result = "uniform"; break; case QUAL_PATCH: result = "patch"; break; case QUAL_CENTROID: result = "centroid"; break; case QUAL_SAMPLE: result = "sample"; break; case QUAL_FLAT: result = "flat"; break; case QUAL_NOPERSPECTIVE: result = "noperspective"; break; case QUAL_SMOOTH: result = "smooth"; break; case QUAL_LOCATION: result = "layout (location = LOC_VALUE)"; break; case QUAL_LOWP: result = "lowp"; break; case QUAL_MEDIUMP: result = "mediump"; break; case QUAL_HIGHP: result = "highp"; break; case QUAL_PRECISE: result = "precise"; break; case QUAL_INVARIANT: result = "invariant"; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Returns a string with set of qualifiers. * * @param qualifiers Set of qualifiers * * @return String **/ std::string Utils::getQualifiersListString(const qualifierSet& qualifiers) { static const GLchar* qualifier_list = "QUALIFIER QUALIFIER_LIST"; const GLuint qualifier_list_length = static_cast(strlen(qualifier_list)); /* Tokens */ static const GLchar* token_qualifier = "QUALIFIER"; static const GLchar* token_qual_list = "QUALIFIER_LIST"; /* Variables */ std::string list = token_qual_list; size_t position = 0; /* Replace tokens */ for (GLuint i = 0; i < qualifiers.size(); ++i) { Utils::replaceToken(token_qual_list, position, qualifier_list, list); position -= qualifier_list_length; const GLchar* qualifier_str = getQualifierString(qualifiers[i]); Utils::replaceToken(token_qualifier, position, qualifier_str, list); } Utils::replaceToken(token_qual_list, position, "", list); return list; } /** Prepare a set of qualifiers for given shader stage and variable storage. * Filters out not supported qualifiers from in_qualifiers * * @param in_qualifiers Origiranl set of qualifiers * @param stage Shader stage * @param storage Variable storage * * @return Set of qualifiers **/ Utils::qualifierSet Utils::prepareQualifiersSet(const qualifierSet& in_qualifiers, SHADER_STAGES stage, VARIABLE_STORAGE storage) { qualifierSet result; for (GLuint i = 0; i < in_qualifiers.size(); ++i) { Utils::QUALIFIERS qualifier = in_qualifiers[i]; if (false == doesStageSupportQualifier(stage, storage, qualifier)) { continue; } /* Replace wrong storage qualifiers */ if ((Utils::INPUT == storage) && ((Utils::QUAL_UNIFORM == qualifier) || (Utils::QUAL_OUT == qualifier))) { qualifier = QUAL_IN; } else if ((Utils::OUTPUT == storage) && ((Utils::QUAL_IN == qualifier) || (Utils::QUAL_UNIFORM == qualifier))) { qualifier = QUAL_OUT; } else if ((Utils::UNIFORM == storage) && ((Utils::QUAL_IN == qualifier) || (Utils::QUAL_OUT == qualifier))) { qualifier = QUAL_UNIFORM; } result.push_back(qualifier); } return result; } /** Get image type for given texture type * * @param type Texture type * * @return String representing sampler type **/ const GLchar* Utils::getImageType(Utils::TEXTURE_TYPES type) { const GLchar* result = 0; switch (type) { case TEX_BUFFER: result = "imageBuffer"; break; case TEX_2D: result = "image2D"; break; case TEX_2D_RECT: result = "image2DRect"; break; case TEX_2D_ARRAY: result = "image2DArray"; break; case TEX_3D: result = "image3D"; break; case TEX_CUBE: result = "imageCube"; break; case TEX_1D: result = "image1D"; break; case TEX_1D_ARRAY: result = "image1DArray"; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Get number of coordinates required to address texture of given type * * @param type Type of texture * * @return Number of coordinates **/ GLuint Utils::getNumberOfCoordinates(Utils::TEXTURE_TYPES type) { GLuint result = 0; switch (type) { case TEX_BUFFER: result = 1; break; case TEX_2D: result = 2; break; case TEX_2D_RECT: result = 2; break; case TEX_2D_ARRAY: result = 3; break; case TEX_3D: result = 3; break; case TEX_CUBE: result = 3; break; case TEX_1D: result = 1; break; case TEX_1D_ARRAY: result = 2; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Get sampler type for given texture type * * @param type Texture type * * @return String representing sampler type **/ const GLchar* Utils::getSamplerType(Utils::TEXTURE_TYPES type) { const GLchar* result = 0; switch (type) { case TEX_BUFFER: result = "samplerBuffer"; break; case TEX_2D: result = "sampler2D"; break; case TEX_2D_RECT: result = "sampler2DRect"; break; case TEX_2D_ARRAY: result = "sampler2DArray"; break; case TEX_3D: result = "sampler3D"; break; case TEX_CUBE: result = "samplerCube"; break; case TEX_1D: result = "sampler1D"; break; case TEX_1D_ARRAY: result = "sampler1DArray"; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Get target for given texture type * * @param type Type of texture * * @return Target **/ GLenum Utils::getTextureTartet(Utils::TEXTURE_TYPES type) { GLenum result = 0; switch (type) { case TEX_BUFFER: result = GL_TEXTURE_BUFFER; break; case TEX_2D: result = GL_TEXTURE_2D; break; case TEX_2D_RECT: result = GL_TEXTURE_RECTANGLE; break; case TEX_2D_ARRAY: result = GL_TEXTURE_2D_ARRAY; break; case TEX_3D: result = GL_TEXTURE_3D; break; case TEX_CUBE: result = GL_TEXTURE_CUBE_MAP; break; case TEX_1D: result = GL_TEXTURE_1D; break; case TEX_1D_ARRAY: result = GL_TEXTURE_1D_ARRAY; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Get name of given texture type * * @param type Texture type * * @return String representing name of texture type **/ const GLchar* Utils::getTextureTypeName(Utils::TEXTURE_TYPES type) { const GLchar* result = 0; switch (type) { case TEX_BUFFER: result = "buffer"; break; case TEX_2D: result = "2D"; break; case TEX_2D_RECT: result = "2D rectangle"; break; case TEX_2D_ARRAY: result = "2D array"; break; case TEX_3D: result = "3D"; break; case TEX_CUBE: result = "cube"; break; case TEX_1D: result = "1D"; break; case TEX_1D_ARRAY: result = "1D array"; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Check if glsl support matrices for specific basic type * * @param type Basic type * * @return true if matrices of are supported, false otherwise **/ bool Utils::doesTypeSupportMatrix(TYPES type) { bool result = false; switch (type) { case FLOAT: case DOUBLE: result = true; break; case INT: case UINT: result = false; break; default: TCU_FAIL("Invliad enum"); } return result; } /** Get string representing name of shader stage * * @param stage Shader stage * * @return String with name of shader stage **/ const glw::GLchar* Utils::getShaderStageName(Utils::SHADER_STAGES stage) { const GLchar* result = 0; switch (stage) { case COMPUTE_SHADER: result = "compute"; break; case VERTEX_SHADER: result = "vertex"; break; case TESS_CTRL_SHADER: result = "tesselation control"; break; case TESS_EVAL_SHADER: result = "tesselation evaluation"; break; case GEOMETRY_SHADER: result = "geomtery"; break; case FRAGMENT_SHADER: result = "fragment"; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Get glsl name of specified type * * @param type Basic type * @param n_columns Number of columns * @param n_rows Number of rows * * @return Name of glsl type **/ const glw::GLchar* Utils::getTypeName(TYPES type, glw::GLuint n_columns, glw::GLuint n_rows) { static const GLchar* float_lut[4][4] = { { "float", "vec2", "vec3", "vec4" }, { 0, "mat2", "mat2x3", "mat2x4" }, { 0, "mat3x2", "mat3", "mat3x4" }, { 0, "mat4x2", "mat4x3", "mat4" }, }; static const GLchar* double_lut[4][4] = { { "double", "dvec2", "dvec3", "dvec4" }, { 0, "dmat2", "dmat2x3", "dmat2x4" }, { 0, "dmat3x2", "dmat3", "dmat3x4" }, { 0, "dmat4x2", "dmat4x3", "dmat4" }, }; static const GLchar* int_lut[4] = { "int", "ivec2", "ivec3", "ivec4" }; static const GLchar* uint_lut[4] = { "uint", "uvec2", "uvec3", "uvec4" }; const GLchar* result = 0; if ((1 > n_columns) || (1 > n_rows) || (4 < n_columns) || (4 < n_rows)) { return 0; } switch (type) { case FLOAT: result = float_lut[n_columns - 1][n_rows - 1]; break; case DOUBLE: result = double_lut[n_columns - 1][n_rows - 1]; break; case INT: result = int_lut[n_rows - 1]; break; case UINT: result = uint_lut[n_rows - 1]; break; default: TCU_FAIL("Invliad enum"); } return result; } /** Get proper glUniformNdv routine for vectors with specified number of rows * * @param gl GL functions * @param n_rows Number of rows * * @return Function address **/ Utils::uniformNdv Utils::getUniformNdv(const glw::Functions& gl, glw::GLuint n_rows) { uniformNdv result = 0; switch (n_rows) { case 1: result = gl.uniform1dv; break; case 2: result = gl.uniform2dv; break; case 3: result = gl.uniform3dv; break; case 4: result = gl.uniform4dv; break; default: TCU_FAIL("Invalid number of rows"); } return result; } /** Get proper glUniformNfv routine for vectors with specified number of rows * * @param gl GL functions * @param n_rows Number of rows * * @return Function address **/ Utils::uniformNfv Utils::getUniformNfv(const glw::Functions& gl, glw::GLuint n_rows) { uniformNfv result = 0; switch (n_rows) { case 1: result = gl.uniform1fv; break; case 2: result = gl.uniform2fv; break; case 3: result = gl.uniform3fv; break; case 4: result = gl.uniform4fv; break; default: TCU_FAIL("Invalid number of rows"); } return result; } /** Get proper glUniformNiv routine for vectors with specified number of rows * * @param gl GL functions * @param n_rows Number of rows * * @return Function address **/ Utils::uniformNiv Utils::getUniformNiv(const glw::Functions& gl, glw::GLuint n_rows) { uniformNiv result = 0; switch (n_rows) { case 1: result = gl.uniform1iv; break; case 2: result = gl.uniform2iv; break; case 3: result = gl.uniform3iv; break; case 4: result = gl.uniform4iv; break; default: TCU_FAIL("Invalid number of rows"); } return result; } /** Get proper glUniformNuiv routine for vectors with specified number of rows * * @param gl GL functions * @param n_rows Number of rows * * @return Function address **/ Utils::uniformNuiv Utils::getUniformNuiv(const glw::Functions& gl, glw::GLuint n_rows) { uniformNuiv result = 0; switch (n_rows) { case 1: result = gl.uniform1uiv; break; case 2: result = gl.uniform2uiv; break; case 3: result = gl.uniform3uiv; break; case 4: result = gl.uniform4uiv; break; default: TCU_FAIL("Invalid number of rows"); } return result; } /** Get proper glUniformMatrixNdv routine for matrix with specified number of columns and rows * * @param gl GL functions * @param n_rows Number of rows * * @return Function address **/ Utils::uniformMatrixNdv Utils::getUniformMatrixNdv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows) { uniformMatrixNdv result = 0; switch (n_columns) { case 2: switch (n_rows) { case 2: result = gl.uniformMatrix2dv; break; case 3: result = gl.uniformMatrix2x3dv; break; case 4: result = gl.uniformMatrix2x4dv; break; default: TCU_FAIL("Invalid number of rows"); } break; case 3: switch (n_rows) { case 2: result = gl.uniformMatrix3x2dv; break; case 3: result = gl.uniformMatrix3dv; break; case 4: result = gl.uniformMatrix3x4dv; break; default: TCU_FAIL("Invalid number of rows"); } break; case 4: switch (n_rows) { case 2: result = gl.uniformMatrix4x2dv; break; case 3: result = gl.uniformMatrix4x3dv; break; case 4: result = gl.uniformMatrix4dv; break; default: TCU_FAIL("Invalid number of rows"); } break; default: TCU_FAIL("Invalid number of columns"); } return result; } /** Get proper glUniformMatrixNfv routine for vectors with specified number of columns and rows * * @param gl GL functions * @param n_rows Number of rows * * @return Function address **/ Utils::uniformMatrixNfv Utils::getUniformMatrixNfv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows) { uniformMatrixNfv result = 0; switch (n_columns) { case 2: switch (n_rows) { case 2: result = gl.uniformMatrix2fv; break; case 3: result = gl.uniformMatrix2x3fv; break; case 4: result = gl.uniformMatrix2x4fv; break; default: TCU_FAIL("Invalid number of rows"); } break; case 3: switch (n_rows) { case 2: result = gl.uniformMatrix3x2fv; break; case 3: result = gl.uniformMatrix3fv; break; case 4: result = gl.uniformMatrix3x4fv; break; default: TCU_FAIL("Invalid number of rows"); } break; case 4: switch (n_rows) { case 2: result = gl.uniformMatrix4x2fv; break; case 3: result = gl.uniformMatrix4x3fv; break; case 4: result = gl.uniformMatrix4fv; break; default: TCU_FAIL("Invalid number of rows"); } break; default: TCU_FAIL("Invalid number of columns"); } return result; } /** Prepare definition of input or output block's variable * * @param qualifiers Set of qualifiers * @param type_name Name of type * @param variable_name Meaningful part of variable name, eg. tex_coord * * @return Definition of variable **/ std::string Utils::getBlockVariableDefinition(const qualifierSet& qualifiers, const glw::GLchar* type_name, const glw::GLchar* variable_name) { /* Templates */ static const GLchar* def_template = "QUALIFIER_LISTTYPE VARIABLE_NAME"; /* Tokens */ static const GLchar* token_type = "TYPE"; static const GLchar* token_variable_name = "VARIABLE_NAME"; static const GLchar* token_qual_list = "QUALIFIER_LIST"; /* Variables */ std::string variable_definition = def_template; size_t position = 0; /* Get qualifiers list */ const std::string& list = getQualifiersListString(qualifiers); /* Replace tokens */ Utils::replaceToken(token_qual_list, position, list.c_str(), variable_definition); Utils::replaceToken(token_type, position, type_name, variable_definition); Utils::replaceToken(token_variable_name, position, variable_name, variable_definition); /* Done */ return variable_definition; } /** Prepare reference to input or output variable * * @param flavour "Flavour" of variable * @param variable_name Meaningful part of variable name, eg. tex_coord * @param block_name Name of block * * @return Reference to variable **/ std::string Utils::getBlockVariableReference(VARIABLE_FLAVOUR flavour, const glw::GLchar* variable_name, const glw::GLchar* block_name) { /* Templates */ static const GLchar* ref_template = "BLOCK_NAME.VARIABLE_NAME"; static const GLchar* array_ref_template = "BLOCK_NAME[0].VARIABLE_NAME"; static const GLchar* tcs_ref_template = "BLOCK_NAME[gl_InvocationID].VARIABLE_NAME"; /* Token */ static const GLchar* token_block_name = "BLOCK_NAME"; static const GLchar* token_variable_name = "VARIABLE_NAME"; /* Variables */ std::string variable_definition; size_t position = 0; /* Select variable reference template */ switch (flavour) { case BASIC: variable_definition = ref_template; break; case ARRAY: variable_definition = array_ref_template; break; case INDEXED_BY_INVOCATION_ID: variable_definition = tcs_ref_template; break; default: variable_definition = ref_template; break; } /* Replace tokens */ replaceAllTokens(token_block_name, block_name, variable_definition); replaceToken(token_variable_name, position, variable_name, variable_definition); /* Done */ return variable_definition; } /** Prepare definition of input or output variable * * @param flavour "Flavour" of variable * @param qualifiers Set of qualifiers * @param type_name Name of type * @param variable_name Meaningful part of variable name, eg. tex_coord * * @return Definition of variable **/ std::string Utils::getVariableDefinition(VARIABLE_FLAVOUR flavour, const qualifierSet& qualifiers, const glw::GLchar* type_name, const glw::GLchar* variable_name) { /* Templates */ static const GLchar* def_template = "QUALIFIER_LISTTYPE VARIABLE_NAME"; static const GLchar* def_array_template = "QUALIFIER_LISTTYPE VARIABLE_NAME[]"; /* Tokens */ static const GLchar* token_type = "TYPE"; static const GLchar* token_variable_name = "VARIABLE_NAME"; static const GLchar* token_qual_list = "QUALIFIER_LIST"; /* Variables */ std::string variable_definition; size_t position = 0; /* Select variable definition template */ switch (flavour) { case BASIC: variable_definition = def_template; break; case ARRAY: case INDEXED_BY_INVOCATION_ID: variable_definition = def_array_template; break; default: TCU_FAIL("Invliad enum"); } /* Get qualifiers list */ const std::string& list = getQualifiersListString(qualifiers); /* Replace tokens */ replaceToken(token_qual_list, position, list.c_str(), variable_definition); replaceToken(token_type, position, type_name, variable_definition); replaceToken(token_variable_name, position, variable_name, variable_definition); /* Done */ return variable_definition; } /** Get "flavour" of variable * * @param stage Shader stage * @param storage Storage of variable * @param qualifiers Set of qualifiers for variable * * @return "Flavour" of variable **/ Utils::VARIABLE_FLAVOUR Utils::getVariableFlavour(SHADER_STAGES stage, VARIABLE_STORAGE storage, const qualifierSet& qualifiers) { VARIABLE_FLAVOUR result; if (UNIFORM == storage) { result = BASIC; } else { switch (stage) { case Utils::GEOMETRY_SHADER: if (Utils::INPUT == storage) { result = ARRAY; } else /* OUTPUT */ { result = BASIC; } break; case Utils::TESS_EVAL_SHADER: if ((false == Utils::doesContainQualifier(Utils::QUAL_PATCH, qualifiers)) && (Utils::INPUT == storage)) { result = ARRAY; } else /* OUTPUT */ { result = BASIC; } break; case Utils::TESS_CTRL_SHADER: if ((true == Utils::doesContainQualifier(Utils::QUAL_PATCH, qualifiers)) && (Utils::OUTPUT == storage)) { result = BASIC; } else { result = INDEXED_BY_INVOCATION_ID; } break; case Utils::VERTEX_SHADER: case Utils::FRAGMENT_SHADER: result = BASIC; break; default: TCU_FAIL("Invliad enum"); } } return result; } /** Prepare name of input or output variable * * @param stage Shader stage * @param storage Storage of variable * @param variable_name Meaningful part of variable name, eg. tex_coord * * @return Name of variable **/ std::string Utils::getVariableName(SHADER_STAGES stage, VARIABLE_STORAGE storage, const glw::GLchar* variable_name) { /* Variable name template */ static const GLchar* variable_name_template = "PRECEEDING_PREFIX_VARIABLE_NAME"; /* Tokens */ static const GLchar* token_preceeding = "PRECEEDING"; static const GLchar* token_prefix = "PREFIX"; static const GLchar* token_variable_name = "VARIABLE_NAME"; static const GLchar* prefixes[Utils::STORAGE_MAX][Utils::SHADER_STAGES_MAX][2] = { /* COMPUTE, VERTEX, TCS, TES, GEOMETRY, FRAGMENT */ { { "", "" }, { "in", "vs" }, { "vs", "tcs" }, { "tcs", "tes" }, { "tes", "gs" }, { "gs", "fs" } }, /* INPUT */ { { "", "" }, { "vs", "tcs" }, { "tcs", "tes" }, { "tes", "gs" }, { "gs", "fs" }, { "fs", "out" } }, /* OUTPUT */ { { "uni", "comp" }, { "uni", "vs" }, { "uni", "tcs" }, { "uni", "tes" }, { "uni", "gs" }, { "uni", "fs" } } /* UNIFORM */ }; /* Variables */ const GLchar* preceeding = prefixes[storage][stage][0]; const GLchar* prefix = prefixes[storage][stage][1]; std::string name = variable_name_template; size_t position = 0; /* Replace tokens */ Utils::replaceToken(token_preceeding, position, preceeding, name); Utils::replaceToken(token_prefix, position, prefix, name); Utils::replaceToken(token_variable_name, position, variable_name, name); /* Done */ return name; } /** Prepare reference to input or output variable * * @param flavour "Flavour" of variable * @param variable_name Meaningful part of variable name, eg. tex_coord * * @return Reference to variable **/ std::string Utils::getVariableReference(VARIABLE_FLAVOUR flavour, const glw::GLchar* variable_name) { /* Templates */ static const GLchar* ref_template = "VARIABLE_NAME"; static const GLchar* array_ref_template = "VARIABLE_NAME[0]"; static const GLchar* tcs_ref_template = "VARIABLE_NAME[gl_InvocationID]"; /* Token */ static const GLchar* token_variable_name = "VARIABLE_NAME"; /* Variables */ std::string variable_definition; size_t position = 0; /* Select variable reference template */ switch (flavour) { case BASIC: variable_definition = ref_template; break; case ARRAY: variable_definition = array_ref_template; break; case INDEXED_BY_INVOCATION_ID: variable_definition = tcs_ref_template; break; default: variable_definition = ref_template; break; } /* Replace token */ Utils::replaceToken(token_variable_name, position, variable_name, variable_definition); /* Done */ return variable_definition; } /** Prepare definition and reference string for block varaible * * @param in_stage Shader stage * @param in_storage Storage of variable * @param in_qualifiers Set of qualifiers * @param in_type_name Type name * @param in_variable_name Meaningful part of variable name, like "color" * @param in_block_name Name of block, like "input" * @param out_definition Definition string * @param out_reference Reference string **/ void Utils::prepareBlockVariableStrings(Utils::SHADER_STAGES in_stage, Utils::VARIABLE_STORAGE in_storage, const Utils::qualifierSet& in_qualifiers, const glw::GLchar* in_type_name, const glw::GLchar* in_variable_name, const glw::GLchar* in_block_name, std::string& out_definition, std::string& out_reference) { VARIABLE_FLAVOUR flavour = getVariableFlavour(in_stage, in_storage, in_qualifiers); const qualifierSet& qualifiers = prepareQualifiersSet(in_qualifiers, in_stage, in_storage); const std::string& name = getVariableName(in_stage, in_storage, in_variable_name); out_definition = getBlockVariableDefinition(qualifiers, in_type_name, name.c_str()); out_reference = getBlockVariableReference(flavour, name.c_str(), in_block_name); } /** Prepare definition and reference string for block varaible * * @param in_stage Shader stage * @param in_storage Storage of variable * @param in_qualifiers Set of qualifiers * @param in_type_name Type name * @param in_variable_name Meaningful part of variable name, like "color" * @param out_definition Definition string * @param out_reference Reference string **/ void Utils::prepareVariableStrings(Utils::SHADER_STAGES in_stage, Utils::VARIABLE_STORAGE in_storage, const Utils::qualifierSet& in_qualifiers, const glw::GLchar* in_type_name, const glw::GLchar* in_variable_name, std::string& out_definition, std::string& out_reference) { VARIABLE_FLAVOUR flavour = getVariableFlavour(in_stage, in_storage, in_qualifiers); const qualifierSet& qualifiers = prepareQualifiersSet(in_qualifiers, in_stage, in_storage); const std::string& name = getVariableName(in_stage, in_storage, in_variable_name); out_definition = getVariableDefinition(flavour, qualifiers, in_type_name, name.c_str()); out_reference = getVariableReference(flavour, name.c_str()); } /** Returns string with UTF8 character for current test case * * @return String with UTF8 character **/ const GLchar* Utils::getUtf8Character(Utils::UTF8_CHARACTERS character) { static const unsigned char two_bytes[] = { 0xd7, 0x84, 0x00 }; static const unsigned char three_bytes[] = { 0xe3, 0x82, 0x81, 0x00 }; static const unsigned char four_bytes[] = { 0xf0, 0x93, 0x83, 0x93, 0x00 }; static const unsigned char five_bytes[] = { 0xfa, 0x82, 0x82, 0x82, 0x82, 0x00 }; static const unsigned char six_bytes[] = { 0xfd, 0x82, 0x82, 0x82, 0x82, 0x82, 0x00 }; static const unsigned char redundant_bytes[] = { 0xf2, 0x80, 0x80, 0x5e, 0x00 }; const GLchar* result = 0; switch (character) { case TWO_BYTES: result = (const GLchar*)two_bytes; break; case THREE_BYTES: result = (const GLchar*)three_bytes; break; case FOUR_BYTES: result = (const GLchar*)four_bytes; break; case FIVE_BYTES: result = (const GLchar*)five_bytes; break; case SIX_BYTES: result = (const GLchar*)six_bytes; break; case REDUNDANT_ASCII: result = (const GLchar*)redundant_bytes; break; case EMPTY: result = ""; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Check if extension is supported * * @param context Test context * @param extension_name Name of extension * * @return true if extension is supported, false otherwise **/ bool Utils::isExtensionSupported(deqp::Context& context, const GLchar* extension_name) { const std::vector& extensions = context.getContextInfo().getExtensions(); if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end()) { return false; } return true; } /** Check if GL context meets version requirements * * @param gl Functions * @param required_major Minimum required MAJOR_VERSION * @param required_minor Minimum required MINOR_VERSION * * @return true if GL context version is at least as requested, false otherwise **/ bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor) { glw::GLint major = 0; glw::GLint minor = 0; gl.getIntegerv(GL_MAJOR_VERSION, &major); gl.getIntegerv(GL_MINOR_VERSION, &minor); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); if (major > required_major) { /* Major is higher than required one */ return true; } else if (major == required_major) { if (minor >= required_minor) { /* Major is equal to required one */ /* Minor is higher than or equal to required one */ return true; } else { /* Major is equal to required one */ /* Minor is lower than required one */ return false; } } else { /* Major is lower than required one */ return false; } } /** Replace first occurance of with in starting at * * @param token Token string * @param search_position Position at which find will start, it is updated to position at which replaced text ends * @param text String that will be used as replacement for * @param string String to work on **/ void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text, std::string& string) { const size_t text_length = strlen(text); const size_t token_length = strlen(token); const size_t token_position = string.find(token, search_position); string.replace(token_position, token_length, text, text_length); search_position = token_position + text_length; } /** Replace all occurances of with in * * @param token Token string * @param text String that will be used as replacement for * @param string String to work on **/ void Utils::replaceAllTokens(const glw::GLchar* token, const glw::GLchar* text, std::string& string) { const size_t text_length = strlen(text); const size_t token_length = strlen(token); size_t search_position = 0; while (1) { const size_t token_position = string.find(token, search_position); if (std::string::npos == token_position) { break; } search_position = token_position + text_length; string.replace(token_position, token_length, text, text_length); } } /** Constructor * * @param context Test context * @param test_name Test name * @param test_description Test description **/ TestBase::TestBase(deqp::Context& context, const glw::GLchar* test_name, const glw::GLchar* test_description) : TestCase(context, test_name, test_description) , m_is_compute_shader_supported(false) , m_is_explicit_uniform_location(false) , m_is_shader_language_420pack(false) { /* Nothing to be done here */ } /** Execute test * * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise **/ tcu::TestNode::IterateResult TestBase::iterate() { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Check extension support and version */ m_is_explicit_uniform_location = Utils::isExtensionSupported(m_context, "GL_ARB_explicit_uniform_location"); m_is_shader_language_420pack = Utils::isExtensionSupported(m_context, "GL_ARB_shading_language_420pack"); m_is_compute_shader_supported = Utils::isGLVersionAtLeast(gl, 4, 3); /* Execute test */ bool test_result = test(); /* Set result */ if (true == test_result) { m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass"); } else { m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail"); } /* Done */ return tcu::TestNode::STOP; } /** Basic implementation of getShaderSourceConfig method. * * @param out_n_parts Number of source parts used by this test case * @param out_use_lengths If source lengths shall be provided to compiler **/ void TestBase::getShaderSourceConfig(glw::GLuint& out_n_parts, bool& out_use_lengths) { out_n_parts = 1; out_use_lengths = false; } /** Basic implementation of prepareNextTestCase method. * * @param test_case_index Index of test case * * @return true if index is -1 or 0, false otherwise **/ bool TestBase::prepareNextTestCase(GLuint test_case_index) { if (((GLuint)-1 == test_case_index) || (0 == test_case_index)) { return true; } else { return false; } } /** Basic implementation of prepareUniforms method * * @param ignored **/ void TestBase::prepareUniforms(Utils::program& /* program */) { /* Nothing to be done */ } /** Basic implementation of testInit method * * @return true if test can be executed, false otherwise **/ bool TestBase::testInit() { return true; } /** Get layout specific for given stage * * @param stage Shader stage * * @return Stage specific part **/ const GLchar* TestBase::getStageSpecificLayout(Utils::SHADER_STAGES stage) const { static const GLchar* stage_layout_geometry = "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n"; static const GLchar* stage_layout_tess_ctrl = "layout(vertices = 1) out;\n"; static const GLchar* stage_layout_tess_eval = "layout(isolines, point_mode) in;\n"; const GLchar* result = ""; switch (stage) { case Utils::GEOMETRY_SHADER: result = stage_layout_geometry; break; case Utils::TESS_CTRL_SHADER: result = stage_layout_tess_ctrl; break; case Utils::TESS_EVAL_SHADER: result = stage_layout_tess_eval; break; case Utils::VERTEX_SHADER: case Utils::FRAGMENT_SHADER: default: break; } return result; } /** Get "version" string * * @param stage Shader stage, compute shader will use 430 * @param use_version_400 Select if 400 or 420 should be used * * @return Version string **/ const GLchar* TestBase::getVersionString(Utils::SHADER_STAGES stage, bool use_version_400) const { static const GLchar* version_400 = "#version 400\n" "#extension GL_ARB_shading_language_420pack : require\n" "#extension GL_ARB_separate_shader_objects : enable"; static const GLchar* version_420 = "#version 420"; static const GLchar* version_430 = "#version 430"; const GLchar* result = ""; if (Utils::COMPUTE_SHADER == stage) { result = version_430; } else if (true == use_version_400) { result = version_400; } else { result = version_420; } return result; } /** Initialize shaderSource instance, reserve storage and prepare shader source * * @param in_stage Shader stage * @param in_use_version_400 If version 400 or 420 should be used * @param out_source Shader source instance **/ void TestBase::initShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { /* Shader source configuration */ glw::GLuint n_parts = 0; bool use_lengths = false; getShaderSourceConfig(n_parts, use_lengths); out_source.m_parts.resize(n_parts); out_source.m_use_lengths = use_lengths; /* Request child class to prepare shader sources */ prepareShaderSource(in_stage, in_use_version_400, out_source); /* Prepare source lengths */ if (true == use_lengths) { for (GLuint i = 0; i < n_parts; ++i) { out_source.m_parts[i].m_length = static_cast(out_source.m_parts[i].m_code.length()); out_source.m_parts[i].m_code.append("This should be ignored by compiler, as source length is provided"); } } else { for (GLuint i = 0; i < n_parts; ++i) { out_source.m_parts[i].m_length = 0; } } } /** Execute test * * @return true if test pass, false otherwise **/ bool TestBase::test() { bool result = true; GLuint test_case_index = 0; /* Prepare test cases */ testInit(); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Tesselation patch set up */ gl.patchParameteri(GL_PATCH_VERTICES, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri"); while (true == prepareNextTestCase(test_case_index)) { bool case_result = true; /* Execute drawing case */ if (false == testDrawArray(false)) { case_result = false; } if (true == m_is_shader_language_420pack) { if (false == testDrawArray(true)) { case_result = false; } } /* Execute compute shader case */ if (true == m_is_compute_shader_supported) { if (false == testCompute()) { case_result = false; } } /* Log failure */ if (false == case_result) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case failed." << tcu::TestLog::EndMessage; result = false; } /* Go to next test case */ test_case_index += 1; } /* Done */ return result; } int TestBase::maxImageUniforms(Utils::SHADER_STAGES stage) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLint max_image_uniforms; switch (stage) { case Utils::COMPUTE_SHADER: gl.getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &max_image_uniforms); break; case Utils::FRAGMENT_SHADER: gl.getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_image_uniforms); break; case Utils::GEOMETRY_SHADER: gl.getIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_image_uniforms); break; case Utils::TESS_CTRL_SHADER: gl.getIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_image_uniforms); break; case Utils::TESS_EVAL_SHADER: gl.getIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_image_uniforms); break; case Utils::VERTEX_SHADER: gl.getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_image_uniforms); break; default: TCU_FAIL("Invalid enum"); } return max_image_uniforms; } /** Constructor * * @param context Test context * @param test_name Name of test * @param test_description Description of test **/ APITestBase::APITestBase(deqp::Context& context, const glw::GLchar* test_name, const glw::GLchar* test_description) : TestBase(context, test_name, test_description) { /* Nothing to be done here */ } /** Execute test with compute shader * * @return true if test pass, false otherwise **/ bool APITestBase::testCompute() { /* GL objects */ Utils::program program(m_context); /* Shaders */ Utils::shaderSource compute_shader; initShaderSource(Utils::COMPUTE_SHADER, false, compute_shader); /* Check if test support compute shaders */ if (true == compute_shader.m_parts[0].m_code.empty()) { return true; } /* Build program */ try { program.build(compute_shader, 0 /* fragment shader */, 0 /* geometry shader */, 0 /* tesselation control shader */, 0 /* tesselation evaluation shader */, 0 /* vertex shader */, 0 /* varying names */, 0 /* n varying names */, false); } catch (Utils::shaderCompilationException& exc) { /* Something wrong with compilation, test case failed */ tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; message << "Shader compilation failed. Error message: " << exc.m_error_message; Utils::program::printShaderSource(exc.m_shader_source, message); message << tcu::TestLog::EndMessage; return false; } catch (Utils::programLinkageException& exc) { /* Something wrong with linking, test case failed */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failed. Error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return false; } /* Set current program */ program.use(); /* Return result of verification */ return checkResults(program); } /** Execute test with VS, TCS, TES, GS and FS * * @param use_version_400 Select if 400 or 420 should be used * * @return true if test pass, false otherwise **/ bool APITestBase::testDrawArray(bool use_version_400) { /* GL objects */ Utils::program program(m_context); /* Shaders */ Utils::shaderSource fragment_data; Utils::shaderSource geometry_data; Utils::shaderSource tess_ctrl_data; Utils::shaderSource tess_eval_data; Utils::shaderSource vertex_data; initShaderSource(Utils::FRAGMENT_SHADER, use_version_400, fragment_data); initShaderSource(Utils::GEOMETRY_SHADER, use_version_400, geometry_data); initShaderSource(Utils::TESS_CTRL_SHADER, use_version_400, tess_ctrl_data); initShaderSource(Utils::TESS_EVAL_SHADER, use_version_400, tess_eval_data); initShaderSource(Utils::VERTEX_SHADER, use_version_400, vertex_data); /* Build program */ try { program.build(0 /* compute shader */, fragment_data, geometry_data, tess_ctrl_data, tess_eval_data, vertex_data, 0 /* varying names */, 0 /* n varying names */, false); } catch (Utils::shaderCompilationException& exc) { /* Something wrong with compilation, test case failed */ tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; message << "Shader compilation failed. Error message: " << exc.m_error_message; Utils::program::printShaderSource(exc.m_shader_source, message); message << tcu::TestLog::EndMessage; return false; } catch (Utils::programLinkageException& exc) { /* Something wrong with linking, test case failed */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failed. Error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return false; } /* Set current program */ program.use(); /* Return result of verification */ return checkResults(program); } /* Constants used by GLSLTestBase */ const glw::GLenum GLSLTestBase::m_color_texture_internal_format = GL_RGBA8; const glw::GLenum GLSLTestBase::m_color_texture_format = GL_RGBA; const glw::GLenum GLSLTestBase::m_color_texture_type = GL_UNSIGNED_BYTE; const glw::GLuint GLSLTestBase::m_color_texture_width = 16; const glw::GLuint GLSLTestBase::m_color_texture_height = 16; /** Constructor * * @param context Test context * @param test_name Test name * @param test_description Test description **/ GLSLTestBase::GLSLTestBase(deqp::Context& context, const glw::GLchar* test_name, const glw::GLchar* test_description) : TestBase(context, test_name, test_description) { /* Nothing to be done here */ } /** Basic implementation of prepareSourceTexture method. * * @param ignored Texture instance * * @return 0 **/ const GLchar* GLSLTestBase::prepareSourceTexture(Utils::texture&) { return 0; } /** Basic implementation of prepareVertexBuffer method. * * @param ignored Program instance * @param ignored Buffer instance * @param vao VertexArray instance * * @return 0 **/ void GLSLTestBase::prepareVertexBuffer(const Utils::program&, Utils::buffer&, Utils::vertexArray& vao) { vao.generate(); vao.bind(); } /** Basic implementation of verifyAdditionalResults * * @return true **/ bool GLSLTestBase::verifyAdditionalResults() const { return true; } /** Basic implementation of releaseResource method * * @param ignored **/ void GLSLTestBase::releaseResource() { /* Nothing to be done */ } /** Bind texture to first image unit and set image uniform to that unit * * @param program Program object * @param texture Texture object * @param uniform_name Name of image uniform **/ void GLSLTestBase::bindTextureToimage(Utils::program& program, Utils::texture& texture, const glw::GLchar* uniform_name) const { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindImageTexture(0 /* unit */, texture.m_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */, GL_WRITE_ONLY, GL_RGBA8); GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); GLint location = program.getUniformLocation(uniform_name); gl.uniform1i(location, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); } /** Bind texture to first texture unit and set sampler uniform to that unit * * @param program Program object * @param texture Texture object * @param uniform_name Name of sampler uniform **/ void GLSLTestBase::bindTextureToSampler(Utils::program& program, Utils::texture& texture, const glw::GLchar* uniform_name) const { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.activeTexture(GL_TEXTURE0); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); texture.bind(); GLint location = program.getUniformLocation(uniform_name); gl.uniform1i(location, 0); GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i"); } /** Check contents of texture. It is expected that it will be filled with green color * * @param color_texture Texture that will be verified * * @return true if texture is all green, false otherwise **/ bool GLSLTestBase::checkResults(Utils::texture& color_texture) const { static const GLuint green_color = 0xff00ff00; const GLuint texture_data_size = m_color_texture_width * m_color_texture_height; std::vector texture_data; texture_data.resize(texture_data_size); color_texture.get(m_color_texture_format, m_color_texture_type, &texture_data[0]); for (GLuint i = 0; i < texture_data_size; ++i) { if (green_color != texture_data[i]) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid texel: " << std::setbase(16) << std::setfill('0') << std::setw(8) << texture_data[i] << " at index: " << i << tcu::TestLog::EndMessage; return false; } } return verifyAdditionalResults(); } /** Prepare framebuffer with texture used as attachment * * @param framebuffer Framebuffer * @param color_texture Textue used as color attachment 0 **/ void GLSLTestBase::prepareFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& color_texture) const { framebuffer.generate(); color_texture.create(m_color_texture_width, m_color_texture_height, m_color_texture_internal_format); framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, color_texture.m_id, m_color_texture_width, m_color_texture_height); framebuffer.clearColor(0.0f, 0.0f, 0.0f, 0.0f); framebuffer.clear(GL_COLOR_BUFFER_BIT); } /** Prepare texture and bind it to image uniform * * @param framebuffer Framebuffer * @param color_texture Textue used as color attachment 0 **/ void GLSLTestBase::prepareImage(Utils::program& program, Utils::texture& color_texture) const { color_texture.create(m_color_texture_width, m_color_texture_height, m_color_texture_internal_format); bindTextureToimage(program, color_texture, "uni_image"); } /** Execute test with compute shader * * @return true if test pass, false otherwise **/ bool GLSLTestBase::testCompute() { /* Test Result */ bool result = true; /* GL objects */ Utils::texture color_tex(m_context); Utils::program program(m_context); Utils::texture source_tex(m_context); /* Shaders */ Utils::shaderSource compute_shader; initShaderSource(Utils::COMPUTE_SHADER, false, compute_shader); /* Check if test support compute shaders */ if (true == compute_shader.m_parts[0].m_code.empty()) { return true; } /* Build program */ try { program.build(compute_shader, 0 /* fragment shader */, 0 /* geometry shader */, 0 /* tesselation control shader */, 0 /* tesselation evaluation shader */, 0 /* vertex shader */, 0 /* varying names */, 0 /* n varying names */, false); } catch (Utils::shaderCompilationException& exc) { /* Something wrong with compilation, test case failed */ tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; message << "Shader compilation failed. Error message: " << exc.m_error_message; Utils::program::printShaderSource(exc.m_shader_source, message); message << tcu::TestLog::EndMessage; return false; } catch (Utils::programLinkageException& exc) { /* Something wrong with linking, test case failed */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failed. Error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return false; } /* Log shaders, for debugging */ #if IS_DEBUG { tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; Utils::program::printShaderSource(compute_shader, message); message << tcu::TestLog::EndMessage; } #endif /* IS_DEBUG */ /* Set current program */ program.use(); /* Prepare image unit */ prepareImage(program, color_tex); /* Test specific preparation of source texture */ const GLchar* sampler_name = prepareSourceTexture(source_tex); if (0 != sampler_name) { bindTextureToSampler(program, source_tex, sampler_name); } /* Set up uniforms */ prepareUniforms(program); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Draw */ gl.dispatchCompute(m_color_texture_width, m_color_texture_height, 1); GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); /* Return result of verification */ result = checkResults(color_tex); /* Release extra resource for the test */ releaseResource(); return result; } /** Execute test with draw array operation * * @param use_version_400 Select if 400 or 420 should be used * * @return true if test pass, false otherwise **/ bool GLSLTestBase::testDrawArray(bool use_version_400) { /* Test Result */ bool result = true; /* GL objects */ Utils::texture color_tex(m_context); Utils::framebuffer framebuffer(m_context); Utils::program program(m_context); Utils::texture source_tex(m_context); Utils::vertexArray vao(m_context); Utils::buffer vertex_buffer(m_context); /* Shaders */ Utils::shaderSource fragment_data; Utils::shaderSource geometry_data; Utils::shaderSource tess_ctrl_data; Utils::shaderSource tess_eval_data; Utils::shaderSource vertex_data; initShaderSource(Utils::FRAGMENT_SHADER, use_version_400, fragment_data); initShaderSource(Utils::GEOMETRY_SHADER, use_version_400, geometry_data); initShaderSource(Utils::TESS_CTRL_SHADER, use_version_400, tess_ctrl_data); initShaderSource(Utils::TESS_EVAL_SHADER, use_version_400, tess_eval_data); initShaderSource(Utils::VERTEX_SHADER, use_version_400, vertex_data); /* Build program */ try { program.build(0 /* compute shader */, fragment_data, geometry_data, tess_ctrl_data, tess_eval_data, vertex_data, 0 /* varying names */, 0 /* n varying names */, false); } catch (Utils::shaderCompilationException& exc) { /* Something wrong with compilation, test case failed */ tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; message << "Shader compilation failed. Error message: " << exc.m_error_message; Utils::program::printShaderSource(exc.m_shader_source, message); message << tcu::TestLog::EndMessage; return false; } catch (Utils::programLinkageException& exc) { /* Something wrong with linking, test case failed */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failed. Error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return false; } /* Log shaders, for debugging */ #if IS_DEBUG { const Utils::shaderSource* data[] = { &vertex_data, &tess_ctrl_data, &tess_eval_data, &geometry_data, &fragment_data }; tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < 5; ++i) { Utils::program::printShaderSource(*data[i], message); } message << tcu::TestLog::EndMessage; } #endif /* IS_DEBUG */ /* Test specific preparation of vertex buffer and vao*/ prepareVertexBuffer(program, vertex_buffer, vao); /* Set current program */ program.use(); /* Prepare framebuffer */ prepareFramebuffer(framebuffer, color_tex); /* Test specific preparation of source texture */ const GLchar* sampler_name = prepareSourceTexture(source_tex); if (0 != sampler_name) { bindTextureToSampler(program, source_tex, sampler_name); } /* Set up uniforms */ prepareUniforms(program); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Draw */ gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */); GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays"); /* Return result of verification */ result = checkResults(color_tex); /* Release extra resource for the test */ releaseResource(); return result; } /** Constructor * * @param context Test context * @param test_name Test name * @param test_description Test description **/ NegativeTestBase::NegativeTestBase(deqp::Context& context, const glw::GLchar* test_name, const glw::GLchar* test_description) : TestBase(context, test_name, test_description) { /* Nothing to be done here */ } /** Execute test with compute shader * * @return true if test pass, false otherwise **/ bool NegativeTestBase::testCompute() { /* GL objects */ Utils::program program(m_context); /* Shaders */ Utils::shaderSource conmpute_data; initShaderSource(Utils::COMPUTE_SHADER, false, conmpute_data); /* Build program */ try { program.build(conmpute_data /* compute shader */, 0 /* fragment shader */, 0 /* geometry shader */, 0 /* tesselation control shader */, 0 /* tesselation evaluation shader */, 0 /* vertex shader */, 0 /* varying names */, 0 /* n varying names */, false); } catch (Utils::shaderCompilationException& exc) { /* Compilation failed, as expected. Verify that reason of failure is as expected */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return true; } catch (Utils::programLinkageException& exc) { /* Something wrong with linking, test case failed */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failed. Error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return true; } /* Build process succeded */ return false; } /** Execute test with draw array operation * * @param use_version_400 Select if 400 or 420 should be used * * @return true if test pass, false otherwise **/ bool NegativeTestBase::testDrawArray(bool use_version_400) { /* GL objects */ Utils::program program(m_context); /* Shaders */ Utils::shaderSource fragment_data; Utils::shaderSource geometry_data; Utils::shaderSource tess_ctrl_data; Utils::shaderSource tess_eval_data; Utils::shaderSource vertex_data; initShaderSource(Utils::FRAGMENT_SHADER, use_version_400, fragment_data); initShaderSource(Utils::GEOMETRY_SHADER, use_version_400, geometry_data); initShaderSource(Utils::TESS_CTRL_SHADER, use_version_400, tess_ctrl_data); initShaderSource(Utils::TESS_EVAL_SHADER, use_version_400, tess_eval_data); initShaderSource(Utils::VERTEX_SHADER, use_version_400, vertex_data); /* Build program */ try { program.build(0 /* compute shader */, fragment_data, geometry_data, tess_ctrl_data, tess_eval_data, vertex_data, 0 /* varying names */, 0 /* n varying names */, false); } catch (Utils::shaderCompilationException& exc) { /* Compilation failed, as expected. Verify that reason of failure is as expected */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return true; } catch (Utils::programLinkageException& exc) { /* Something wrong with linking, test case failed */ m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linking failed. Error message: " << exc.m_error_message << tcu::TestLog::EndMessage; return true; } /* Build process succeded */ return false; } /* Constants used by BindingImageTest */ const GLuint BindingImageTest::m_width = 16; const GLuint BindingImageTest::m_green_color = 0xff00ff00; const GLuint BindingImageTest::m_height = 16; const GLuint BindingImageTest::m_depth = 6; /** Constructor * * @param context Test context **/ BindingImageTest::BindingImageTest(deqp::Context& context, const glw::GLchar* test_name, const glw::GLchar* test_description) : GLSLTestBase(context, test_name, test_description) { /* Nothing to be done */ } /** Prepare buffer, filled with given color * * @param buffer Buffer object * @param color Color **/ void BindingImageTest::prepareBuffer(Utils::buffer& buffer, GLuint color) { std::vector texture_data; texture_data.resize(m_width); buffer.generate(GL_TEXTURE_BUFFER); for (GLuint i = 0; i < texture_data.size(); ++i) { texture_data[i] = color; } buffer.update(m_width * sizeof(GLuint), &texture_data[0], GL_STATIC_DRAW); } /** Prepare texture of given type filled with given color and bind to specified image unit * * @param texture Texture * @param buffer Buffer * @param texture_type Type of texture * @param color Color **/ void BindingImageTest::prepareTexture(Utils::texture& texture, const Utils::buffer& buffer, Utils::TEXTURE_TYPES texture_type, GLuint color, GLuint unit) { std::vector texture_data; texture_data.resize(m_width * m_height * m_depth); GLboolean is_layered = GL_FALSE; for (GLuint i = 0; i < texture_data.size(); ++i) { texture_data[i] = color; } if (Utils::TEX_BUFFER != texture_type) { texture.create(m_width, m_height, m_depth, GL_RGBA8, texture_type); texture.update(m_width, m_height, m_depth, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); } else { buffer.bind(); texture.createBuffer(GL_RGBA8, buffer.m_id); } switch (texture_type) { case Utils::TEX_1D_ARRAY: case Utils::TEX_2D_ARRAY: case Utils::TEX_3D: case Utils::TEX_CUBE: is_layered = GL_TRUE; break; default: break; } const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindImageTexture(unit, texture.m_id, 0 /* level */, is_layered /* layered */, 0 /* layer */, GL_READ_WRITE, GL_RGBA8); GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture"); } /** Verifies that texel at offset 0 is green * * @param buffer Buffer object * * @return true if texel at offset 0 is green, false otherwise **/ bool BindingImageTest::verifyBuffer(const Utils::buffer& buffer) const { GLuint* data = (GLuint*)buffer.map(GL_READ_ONLY); GLuint color = data[0]; buffer.unmap(); return (m_green_color == color); } /** Verifies that texel at offset 0 is green * * @param buffer Buffer object * * @return true if texel at offset 0 is green, false otherwise **/ bool BindingImageTest::verifyTexture(const Utils::texture& texture) const { static const GLuint texture_data_size = m_width * m_height * m_depth; std::vector texture_data; texture_data.resize(texture_data_size); texture.get(GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); GLuint color = texture_data[0]; return (m_green_color == color); } /* Constants used by LineContinuationTest */ const GLuint LineContinuationTest::m_n_repetitions = 20; const GLchar* LineContinuationTest::m_texture_coordinates_name = "texture_coordinates"; /** Constructor * * @param context Test context **/ LineContinuationTest::LineContinuationTest(deqp::Context& context) : GLSLTestBase(context, "line_continuation", "desc") { /* Nothing to be done here */ } /** Overwrite getShaderSourceConfig method * * @param out_n_parts Number of source parts used by this test case * @param out_use_lengths If source lengths shall be provided to compiler **/ void LineContinuationTest::getShaderSourceConfig(GLuint& out_n_parts, bool& out_use_lengths) { out_n_parts = (true == isShaderMultipart()) ? 2 : 1; out_use_lengths = useSourceLengths(); } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool LineContinuationTest::prepareNextTestCase(glw::GLuint test_case_index) { static const testCase test_cases[] = { { ASSIGNMENT_BEFORE_OPERATOR, ONCE, UNIX }, { ASSIGNMENT_BEFORE_OPERATOR, ONCE, DOS }, { ASSIGNMENT_BEFORE_OPERATOR, MULTIPLE_TIMES, UNIX }, { ASSIGNMENT_BEFORE_OPERATOR, MULTIPLE_TIMES, DOS }, { ASSIGNMENT_AFTER_OPERATOR, ONCE, UNIX }, { ASSIGNMENT_AFTER_OPERATOR, ONCE, DOS }, { ASSIGNMENT_AFTER_OPERATOR, MULTIPLE_TIMES, UNIX }, { ASSIGNMENT_AFTER_OPERATOR, MULTIPLE_TIMES, DOS }, { VECTOR_VARIABLE_INITIALIZER, ONCE, UNIX }, { VECTOR_VARIABLE_INITIALIZER, ONCE, DOS }, { VECTOR_VARIABLE_INITIALIZER, MULTIPLE_TIMES, UNIX }, { VECTOR_VARIABLE_INITIALIZER, MULTIPLE_TIMES, DOS }, { TOKEN_INSIDE_FUNCTION_NAME, ONCE, UNIX }, { TOKEN_INSIDE_FUNCTION_NAME, ONCE, DOS }, { TOKEN_INSIDE_FUNCTION_NAME, MULTIPLE_TIMES, UNIX }, { TOKEN_INSIDE_FUNCTION_NAME, MULTIPLE_TIMES, DOS }, { TOKEN_INSIDE_TYPE_NAME, ONCE, UNIX }, { TOKEN_INSIDE_TYPE_NAME, ONCE, DOS }, { TOKEN_INSIDE_TYPE_NAME, MULTIPLE_TIMES, UNIX }, { TOKEN_INSIDE_TYPE_NAME, MULTIPLE_TIMES, DOS }, { TOKEN_INSIDE_VARIABLE_NAME, ONCE, UNIX }, { TOKEN_INSIDE_VARIABLE_NAME, ONCE, DOS }, { TOKEN_INSIDE_VARIABLE_NAME, MULTIPLE_TIMES, UNIX }, { TOKEN_INSIDE_VARIABLE_NAME, MULTIPLE_TIMES, DOS }, { PREPROCESSOR_TOKEN_INSIDE, ONCE, UNIX }, { PREPROCESSOR_TOKEN_INSIDE, ONCE, DOS }, { PREPROCESSOR_TOKEN_INSIDE, MULTIPLE_TIMES, UNIX }, { PREPROCESSOR_TOKEN_INSIDE, MULTIPLE_TIMES, DOS }, { PREPROCESSOR_TOKEN_BETWEEN, ONCE, UNIX }, { PREPROCESSOR_TOKEN_BETWEEN, ONCE, DOS }, { PREPROCESSOR_TOKEN_BETWEEN, MULTIPLE_TIMES, UNIX }, { PREPROCESSOR_TOKEN_BETWEEN, MULTIPLE_TIMES, DOS }, { COMMENT, ONCE, UNIX }, { COMMENT, ONCE, DOS }, { COMMENT, MULTIPLE_TIMES, UNIX }, { COMMENT, MULTIPLE_TIMES, DOS }, { SOURCE_TERMINATION_NULL, ONCE, UNIX }, { SOURCE_TERMINATION_NULL, ONCE, DOS }, { SOURCE_TERMINATION_NULL, MULTIPLE_TIMES, UNIX }, { SOURCE_TERMINATION_NULL, MULTIPLE_TIMES, DOS }, { SOURCE_TERMINATION_NON_NULL, ONCE, UNIX }, { SOURCE_TERMINATION_NON_NULL, ONCE, DOS }, { SOURCE_TERMINATION_NON_NULL, MULTIPLE_TIMES, UNIX }, { SOURCE_TERMINATION_NON_NULL, MULTIPLE_TIMES, DOS }, { PART_TERMINATION_NULL, ONCE, UNIX }, { PART_TERMINATION_NULL, ONCE, DOS }, { PART_TERMINATION_NULL, MULTIPLE_TIMES, UNIX }, { PART_TERMINATION_NULL, MULTIPLE_TIMES, DOS }, { PART_NEXT_TO_TERMINATION_NULL, ONCE, UNIX }, { PART_NEXT_TO_TERMINATION_NULL, ONCE, DOS }, { PART_NEXT_TO_TERMINATION_NULL, MULTIPLE_TIMES, UNIX }, { PART_NEXT_TO_TERMINATION_NULL, MULTIPLE_TIMES, DOS }, { PART_TERMINATION_NON_NULL, ONCE, UNIX }, { PART_TERMINATION_NON_NULL, ONCE, DOS }, { PART_TERMINATION_NON_NULL, MULTIPLE_TIMES, UNIX }, { PART_TERMINATION_NON_NULL, MULTIPLE_TIMES, DOS }, { PART_NEXT_TO_TERMINATION_NON_NULL, ONCE, UNIX }, { PART_NEXT_TO_TERMINATION_NON_NULL, ONCE, DOS }, { PART_NEXT_TO_TERMINATION_NON_NULL, MULTIPLE_TIMES, UNIX }, { PART_NEXT_TO_TERMINATION_NON_NULL, MULTIPLE_TIMES, DOS } }; static const GLuint max_test_cases = sizeof(test_cases) / sizeof(testCase); if ((GLuint)-1 == test_case_index) { m_test_case.m_case = DEBUG_CASE; } else if (max_test_cases <= test_case_index) { return false; } else { m_test_case = test_cases[test_case_index]; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << repetitionsToStr((REPETITIONS)m_test_case.m_repetitions) << " line continuation, with " << lineEndingsToStr((LINE_ENDINGS)m_test_case.m_line_endings) << " line endings, is placed " << casesToStr((CASES)m_test_case.m_case) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void LineContinuationTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { if (Utils::COMPUTE_SHADER == in_stage) { prepareComputShaderSource(out_source); } else { prepareShaderSourceForDraw(in_stage, in_use_version_400, out_source); } } /** Prepare compute shader source * * @param source Result shader source **/ void LineContinuationTest::prepareComputShaderSource(Utils::shaderSource& source) { static const GLchar* shader_template_part_0 = "#version 430\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform sampler2D uni_sampler;\n" "\n" "void funFUNCTION_CASEction(in veTYPE_CASEc4 in_vVARIABLE_CASEalue)\n" "{\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), inVARIABLE_CASE_value);\n" "}\n" "\n" "#define SET_PREPROCESSOR_INSIDE_CASERESULT(XX) " "PREPROCESSOR_BETWEEN_CASEfuncFUNCTION_CASEtion(XPREPROCESSOR_INSIDE_CASEX)\n" "NEXT_TO_TERMINATION_CASE\nTERMINATION_CASE"; static const GLchar* shader_template_part_1 = "void main()\n" "{\n" " ivec2 coordinates ASSIGNMENT_BEFORE_OPERATOR_CASE=ASSIGNMENT_AFTER_OPERATOR_CASE " "ivec2(gl_GlobalInvocationID.xy + ivec2(16, 16));\n" " vec4 sampled_color = texelFetch(uni_sampler, coordinates, 0 /* lod */);\n" " vec4 result = vec4(0, 0VECTOR_VARIABLE_INITIALIZER_CASE, 0, 1);\n" "\n" " if (vec4(0, 0, 1, 1) == sampled_color)\n" " {\n" " result = vecTYPE_CASE4(VECTOR_VARIABLE_INITIALIZER_CASE0, 1, 0, 1);\n" " }\n" " else\n" " {\n" " result = vec4(coordinates.xy, sampled_color.rg);\n" " }\n" "\n" " SET_RESULT(result);" "}\n"; /* Init strings with templates and replace all CASE tokens */ if (true == isShaderMultipart()) { source.m_parts[0].m_code = shader_template_part_0; source.m_parts[1].m_code = shader_template_part_1; replaceAllCaseTokens(source.m_parts[0].m_code); replaceAllCaseTokens(source.m_parts[1].m_code); } else { source.m_parts[0].m_code = shader_template_part_0; source.m_parts[0].m_code.append(shader_template_part_1); replaceAllCaseTokens(source.m_parts[0].m_code); } } /** Prepare source for given shader stage * * @param stage Shader stage, compute shader will use 430 * @param use_version_400 Select if 400 or 420 should be used * @param source Result shader sources **/ void LineContinuationTest::prepareShaderSourceForDraw(Utils::SHADER_STAGES stage, bool use_version_400, Utils::shaderSource& source) { /* Templates */ static const GLchar* shader_template_part_0 = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "STAGE_SPECIFIC\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "IN_COLOR_DEFINITION\n" "IN_TEXTURE_COORDINATES_DEFINITION\n" "OUT_COLOR_DEFINITION\n" "OUT_TEXTURE_COORDINATES_DEFINITION\n" "uniform sampler2D uni_sampler;\n" "\n" "void funFUNCTION_CASEction(in veTYPE_CASEc4 in_vVARIABLE_CASEalue)\n" "{\n" " OUT_COLOR ASSIGNMENT_BEFORE_OPERATOR_CASE=ASSIGNMENT_AFTER_OPERATOR_CASE inVARIABLE_CASE_value;\n" "}\n" "\n" "#define SET_PREPROCESSOR_INSIDE_CASERESULT(XX) " "PREPROCESSOR_BETWEEN_CASEfuncFUNCTION_CASEtion(XPREPROCESSOR_INSIDE_CASEX)\n" "NEXT_TO_TERMINATION_CASE\nTERMINATION_CASE"; static const GLchar* shader_template_part_1 = "void main()\n" "{\n" " vec2 coordinates = TEXTURE_COORDINATES;\n" " vec4 sampled_color = texture(uni_sampler, coordinates);\n" " vec4 result = vec4(0, 0VECTOR_VARIABLE_INITIALIZER_CASE, 0, 1);\n" "\n" " if (PASS_CONDITION)\n" " {\n" " result = vecTYPE_CASE4(VECTOR_VARIABLE_INITIALIZER_CASE0, 1, 0, 1);\n" " }\n" " else\n" " {\n" " result = vec4(coordinates.xy, sampled_color.rg);\n" " }\n" "\n" "STORE_RESULTS" "}\n" "NEXT_TO_TERMINATION_CASE\nTERMINATION_CASE"; static const GLchar* store_results_template = " SET_RESULT(result);\n" " TEXTURE_COORDINATES = coordinates;\n"; static const GLchar* store_results_tcs_template = " SET_RESULT(result);\n" " TEXTURE_COORDINATES = coordinates;\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"; static const GLchar* store_results_fs_template = " SET_RESULT(result);\n"; static const GLchar* store_results_gs_template = " gl_Position = vec4(-1, -1, 0, 1);\n" " SET_RESULT(result);\n" " TEXTURE_COORDINATES = coordinates + vec2(-0.25, -0.25);\n" " EmitVertex();\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " SET_RESULT(result);\n" " TEXTURE_COORDINATES = coordinates + vec2(-0.25, 0.25);\n" " EmitVertex();\n" " gl_Position = vec4(1, -1, 0, 1);\n" " SET_RESULT(result);\n" " TEXTURE_COORDINATES = coordinates + vec2(0.25, -0.25);\n" " EmitVertex();\n" " gl_Position = vec4(1, 1, 0, 1);\n" " SET_RESULT(result);\n" " TEXTURE_COORDINATES = coordinates + vec2(0.25, 0.25);\n" " EmitVertex();\n"; static const GLchar* pass_condition_template = "(EXPECTED_VALUE == sampled_color) &&\n" " (vec4(0, 1, 0, 1) == IN_COLOR) "; static const GLchar* pass_condition_vs_template = "EXPECTED_VALUE == sampled_color"; /* Tokens to be replaced with GLSL stuff */ static const GLchar* token_version = "VERSION"; static const GLchar* token_stage_specific = "STAGE_SPECIFIC"; static const GLchar* token_in_color_definition = "IN_COLOR_DEFINITION"; static const GLchar* token_in_tex_coord_definition = "IN_TEXTURE_COORDINATES_DEFINITION"; static const GLchar* token_out_color_definition = "OUT_COLOR_DEFINITION"; static const GLchar* token_out_tex_coord_definition = "OUT_TEXTURE_COORDINATES_DEFINITION"; static const GLchar* token_expected_value = "EXPECTED_VALUE"; static const GLchar* token_texture_coordinates = "TEXTURE_COORDINATES"; static const GLchar* token_in_color = "IN_COLOR"; static const GLchar* token_out_color = "OUT_COLOR"; static const GLchar* token_store_results = "STORE_RESULTS"; static const GLchar* token_pass_condition = "PASS_CONDITION"; /* Name of variable and empty string*/ static const GLchar* color_name = "color"; static const GLchar* empty = ""; /* GLSL stuff */ const GLchar* version = getVersionString(stage, use_version_400); const GLchar* stage_specific_layout = getStageSpecificLayout(stage); const GLchar* expected_value = getExpectedValueString(); /* Qualifiers */ Utils::qualifierSet in; Utils::qualifierSet out; in.push_back(Utils::QUAL_IN); out.push_back(Utils::QUAL_OUT); /* In/Out variables definitions and references */ std::string in_tex_coord_reference; std::string out_tex_coord_reference; std::string in_color_reference; std::string out_color_reference; std::string in_tex_coord_definition; std::string out_tex_coord_definition; std::string in_color_definition; std::string out_color_definition; Utils::prepareVariableStrings(stage, Utils::INPUT, in, "vec2", m_texture_coordinates_name, in_tex_coord_definition, in_tex_coord_reference); Utils::prepareVariableStrings(stage, Utils::OUTPUT, out, "vec2", m_texture_coordinates_name, out_tex_coord_definition, out_tex_coord_reference); Utils::prepareVariableStrings(stage, Utils::INPUT, in, "vec4", color_name, in_color_definition, in_color_reference); Utils::prepareVariableStrings(stage, Utils::OUTPUT, out, "vec4", color_name, out_color_definition, out_color_reference); in_tex_coord_definition.append(";"); out_tex_coord_definition.append(";"); in_color_definition.append(";"); out_color_definition.append(";"); /* Select pass condition and store results tempaltes */ const GLchar* store_results = store_results_template; const GLchar* pass_condition = pass_condition_template; switch (stage) { case Utils::FRAGMENT_SHADER: store_results = store_results_fs_template; break; case Utils::GEOMETRY_SHADER: store_results = store_results_gs_template; break; case Utils::TESS_CTRL_SHADER: store_results = store_results_tcs_template; break; case Utils::VERTEX_SHADER: pass_condition = pass_condition_vs_template; break; default: break; } const GLuint store_results_length = static_cast(strlen(store_results)); const GLuint pass_condition_length = static_cast(strlen(pass_condition)); /* Init strings with templates and replace all CASE tokens */ if (true == isShaderMultipart()) { source.m_parts[0].m_code = shader_template_part_0; source.m_parts[1].m_code = shader_template_part_1; replaceAllCaseTokens(source.m_parts[0].m_code); replaceAllCaseTokens(source.m_parts[1].m_code); } else { source.m_parts[0].m_code = shader_template_part_0; source.m_parts[0].m_code.append(shader_template_part_1); replaceAllCaseTokens(source.m_parts[0].m_code); } /* Get memory for shader source parts */ const bool is_multipart = isShaderMultipart(); size_t position = 0; std::string& shader_source_part_0 = source.m_parts[0].m_code; std::string& shader_source_part_1 = (true == is_multipart) ? source.m_parts[1].m_code : source.m_parts[0].m_code; /* Replace tokens */ /* Part 0 */ Utils::replaceToken(token_version, position, version, shader_source_part_0); Utils::replaceToken(token_stage_specific, position, stage_specific_layout, shader_source_part_0); if (Utils::VERTEX_SHADER != stage) { Utils::replaceToken(token_in_color_definition, position, in_color_definition.c_str(), shader_source_part_0); } else { Utils::replaceToken(token_in_color_definition, position, empty, shader_source_part_0); } Utils::replaceToken(token_in_tex_coord_definition, position, in_tex_coord_definition.c_str(), shader_source_part_0); Utils::replaceToken(token_out_color_definition, position, out_color_definition.c_str(), shader_source_part_0); if (Utils::FRAGMENT_SHADER == stage) { Utils::replaceToken(token_out_tex_coord_definition, position, empty, shader_source_part_0); } else { Utils::replaceToken(token_out_tex_coord_definition, position, out_tex_coord_definition.c_str(), shader_source_part_0); } Utils::replaceToken(token_out_color, position, out_color_reference.c_str(), shader_source_part_0); /* Part 1 */ if (true == is_multipart) { position = 0; } Utils::replaceToken(token_texture_coordinates, position, in_tex_coord_reference.c_str(), shader_source_part_1); Utils::replaceToken(token_pass_condition, position, pass_condition, shader_source_part_1); position -= pass_condition_length; Utils::replaceToken(token_expected_value, position, expected_value, shader_source_part_1); if (Utils::VERTEX_SHADER != stage) { Utils::replaceToken(token_in_color, position, in_color_reference.c_str(), shader_source_part_1); } Utils::replaceToken(token_store_results, position, store_results, shader_source_part_1); position -= store_results_length; if (Utils::GEOMETRY_SHADER == stage) { for (GLuint i = 0; i < 4; ++i) { Utils::replaceToken(token_texture_coordinates, position, out_tex_coord_reference.c_str(), shader_source_part_1); } } else if (Utils::FRAGMENT_SHADER == stage) { /* Nothing to be done */ } else { Utils::replaceToken(token_texture_coordinates, position, out_tex_coord_reference.c_str(), shader_source_part_1); } } /** Prepare texture * * @param texture Texutre to be created and filled with content * * @return Name of sampler uniform that should be used for the texture **/ const GLchar* LineContinuationTest::prepareSourceTexture(Utils::texture& texture) { std::vector data; static const GLuint width = 64; static const GLuint height = 64; static const GLuint data_size = width * height; static const GLuint blue_color = 0xffff0000; static const GLuint grey_color = 0xaaaaaaaa; data.resize(data_size); for (GLuint i = 0; i < data_size; ++i) { data[i] = grey_color; } for (GLuint y = 16; y < 48; ++y) { const GLuint line_offset = y * 64; for (GLuint x = 16; x < 48; ++x) { const GLuint pixel_offset = x + line_offset; data[pixel_offset] = blue_color; } } texture.create(width, height, GL_RGBA8); texture.update(width, height, 0 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); return "uni_sampler"; } /** Prepare vertex buffer, vec2 tex_coord * * @param program Program object * @param buffer Vertex buffer * @param vao Vertex array object **/ void LineContinuationTest::prepareVertexBuffer(const Utils::program& program, Utils::buffer& buffer, Utils::vertexArray& vao) { std::string tex_coord_name = Utils::getVariableName(Utils::VERTEX_SHADER, Utils::INPUT, m_texture_coordinates_name); GLint tex_coord_loc = program.getAttribLocation(tex_coord_name.c_str()); if (-1 == tex_coord_loc) { TCU_FAIL("Vertex attribute location is invalid"); } vao.generate(); vao.bind(); buffer.generate(GL_ARRAY_BUFFER); GLfloat data[] = { 0.5f, 0.5f, 0.5f, 0.5f }; GLsizeiptr data_size = sizeof(data); buffer.update(data_size, data, GL_STATIC_DRAW); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up vao */ gl.vertexAttribPointer(tex_coord_loc, 2 /* size */, GL_FLOAT /* type */, GL_FALSE /* normalized*/, 0 /* stride */, 0 /* offset */); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer"); /* Enable attribute */ gl.enableVertexAttribArray(tex_coord_loc); GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray"); } /** Get string describing test cases * * @param cases Test case * * @return String describing current test case **/ const GLchar* LineContinuationTest::casesToStr(CASES cases) const { const GLchar* result = 0; switch (cases) { case ASSIGNMENT_BEFORE_OPERATOR: result = "just before assignment operator"; break; case ASSIGNMENT_AFTER_OPERATOR: result = "just after assignment operator"; break; case VECTOR_VARIABLE_INITIALIZER: result = "inside vector variable initializer"; break; case TOKEN_INSIDE_FUNCTION_NAME: result = "inside function name"; break; case TOKEN_INSIDE_TYPE_NAME: result = "inside type name"; break; case TOKEN_INSIDE_VARIABLE_NAME: result = "inside variable name"; break; case PREPROCESSOR_TOKEN_INSIDE: result = "inside preprocessor token"; break; case PREPROCESSOR_TOKEN_BETWEEN: result = "between preprocessor token"; break; case COMMENT: result = "inside comment"; break; case SOURCE_TERMINATION_NULL: result = "just before null terminating source"; break; case SOURCE_TERMINATION_NON_NULL: result = "as last character in source string, without null termination"; break; case PART_TERMINATION_NULL: result = "just before null terminating part of source"; break; case PART_NEXT_TO_TERMINATION_NULL: result = "just before last character in part of source"; break; case PART_TERMINATION_NON_NULL: result = "as last character in part string, without null termination"; break; case PART_NEXT_TO_TERMINATION_NON_NULL: result = "just before last character in part string, without null termination"; break; case DEBUG_CASE: /* intended fall through */ default: result = "nowhere at all. This is debug!"; break; } return result; } /** Get expected value, blue color as vec4 * * @return blue color **/ const GLchar* LineContinuationTest::getExpectedValueString() const { return "vec4(0, 0, 1, 1)"; } /** Get line continuation string, single or multiple \ * * @return String **/ std::string LineContinuationTest::getLineContinuationString() const { static const GLchar line_continuation_ending_dos[] = { '\\', 0x0d, 0x0a, 0x00 }; static const GLchar line_continuation_ending_unix[] = { '\\', 0x0a, 0x00 }; std::string result; const GLchar* selected_string; if (DOS == m_test_case.m_line_endings) { selected_string = line_continuation_ending_dos; } else { selected_string = line_continuation_ending_unix; } GLuint n_repetitions = (ONCE == m_test_case.m_repetitions) ? 1 : m_n_repetitions; for (GLuint i = 0; i < n_repetitions; ++i) { result.append(selected_string); } return result; } /** Decides if shader should consist of multiple parts for the current test case * * @return true if test case requires multiple parts, false otherwise **/ bool LineContinuationTest::isShaderMultipart() const { bool result; switch (m_test_case.m_case) { case ASSIGNMENT_BEFORE_OPERATOR: case ASSIGNMENT_AFTER_OPERATOR: case VECTOR_VARIABLE_INITIALIZER: case TOKEN_INSIDE_FUNCTION_NAME: case TOKEN_INSIDE_TYPE_NAME: case TOKEN_INSIDE_VARIABLE_NAME: case PREPROCESSOR_TOKEN_INSIDE: case PREPROCESSOR_TOKEN_BETWEEN: case COMMENT: case SOURCE_TERMINATION_NULL: case SOURCE_TERMINATION_NON_NULL: default: result = false; break; case PART_TERMINATION_NULL: case PART_NEXT_TO_TERMINATION_NULL: case PART_TERMINATION_NON_NULL: case PART_NEXT_TO_TERMINATION_NON_NULL: result = true; break; } return result; } /** String describing line endings * * @param line_ending Line ending enum * * @return "unix" or "dos" strings **/ const GLchar* LineContinuationTest::lineEndingsToStr(LINE_ENDINGS line_ending) const { const GLchar* result = 0; if (UNIX == line_ending) { result = "unix"; } else { result = "dos"; } return result; } /** String describing number of repetitions * * @param repetitions Repetitions enum * * @return "single" or "multiple" strings **/ const GLchar* LineContinuationTest::repetitionsToStr(REPETITIONS repetitions) const { const GLchar* result = 0; if (ONCE == repetitions) { result = "single"; } else { result = "multiple"; } return result; } /** Replace all CASES tokens * * @param source String with shader template **/ void LineContinuationTest::replaceAllCaseTokens(std::string& source) const { /* Tokens to be replaced with line continuation */ static const GLchar* token_assignment_before_operator_case = "ASSIGNMENT_BEFORE_OPERATOR_CASE"; static const GLchar* token_assignment_after_operator_case = "ASSIGNMENT_AFTER_OPERATOR_CASE"; static const GLchar* token_vector_initializer = "VECTOR_VARIABLE_INITIALIZER_CASE"; static const GLchar* token_function_case = "FUNCTION_CASE"; static const GLchar* token_type_case = "TYPE_CASE"; static const GLchar* token_variable_case = "VARIABLE_CASE"; static const GLchar* token_preprocessor_inside_case = "PREPROCESSOR_INSIDE_CASE"; static const GLchar* token_preprocessor_between_case = "PREPROCESSOR_BETWEEN_CASE"; static const GLchar* token_comment = "COMMENT_CASE"; static const GLchar* token_termination = "TERMINATION_CASE"; static const GLchar* token_next_to_termination = "NEXT_TO_TERMINATION_CASE"; /* Line continuation and empty string*/ static const GLchar* empty = ""; const std::string& line_continuation = getLineContinuationString(); /* These strings will used to replace "CASE" tokens */ const GLchar* assignment_before_operator_case = empty; const GLchar* assignment_after_operator_case = empty; const GLchar* vector_variable_initializer_case = empty; const GLchar* function_case = empty; const GLchar* type_case = empty; const GLchar* variable_case = empty; const GLchar* preprocessor_inside_case = empty; const GLchar* preprocessor_between_case = empty; const GLchar* comment_case = empty; const GLchar* source_termination_case = empty; const GLchar* part_termination_case = empty; const GLchar* next_to_part_termination_case = empty; /* Configuration of test case */ switch (m_test_case.m_case) { case ASSIGNMENT_BEFORE_OPERATOR: assignment_before_operator_case = line_continuation.c_str(); break; case ASSIGNMENT_AFTER_OPERATOR: assignment_after_operator_case = line_continuation.c_str(); break; case VECTOR_VARIABLE_INITIALIZER: vector_variable_initializer_case = line_continuation.c_str(); break; case TOKEN_INSIDE_FUNCTION_NAME: function_case = line_continuation.c_str(); break; case TOKEN_INSIDE_TYPE_NAME: type_case = line_continuation.c_str(); break; case TOKEN_INSIDE_VARIABLE_NAME: variable_case = line_continuation.c_str(); break; case PREPROCESSOR_TOKEN_INSIDE: preprocessor_inside_case = line_continuation.c_str(); break; case PREPROCESSOR_TOKEN_BETWEEN: preprocessor_between_case = line_continuation.c_str(); break; case COMMENT: comment_case = line_continuation.c_str(); break; case SOURCE_TERMINATION_NULL: /* intended fall through */ case SOURCE_TERMINATION_NON_NULL: source_termination_case = line_continuation.c_str(); break; case PART_TERMINATION_NULL: /* intended fall through */ case PART_TERMINATION_NON_NULL: part_termination_case = line_continuation.c_str(); source_termination_case = line_continuation.c_str(); break; case PART_NEXT_TO_TERMINATION_NULL: /* intended fall through */ case PART_NEXT_TO_TERMINATION_NON_NULL: next_to_part_termination_case = line_continuation.c_str(); break; case DEBUG_CASE: /* intended fall through */ default: break; /* no line continuations */ } Utils::replaceAllTokens(token_assignment_after_operator_case, assignment_after_operator_case, source); Utils::replaceAllTokens(token_assignment_before_operator_case, assignment_before_operator_case, source); Utils::replaceAllTokens(token_comment, comment_case, source); Utils::replaceAllTokens(token_function_case, function_case, source); Utils::replaceAllTokens(token_next_to_termination, next_to_part_termination_case, source); Utils::replaceAllTokens(token_termination, part_termination_case, source); Utils::replaceAllTokens(token_preprocessor_between_case, preprocessor_between_case, source); Utils::replaceAllTokens(token_preprocessor_inside_case, preprocessor_inside_case, source); Utils::replaceAllTokens(token_termination, source_termination_case, source); Utils::replaceAllTokens(token_type_case, type_case, source); Utils::replaceAllTokens(token_variable_case, variable_case, source); Utils::replaceAllTokens(token_vector_initializer, vector_variable_initializer_case, source); } /** Decides if the current test case requires source lengths * * @return true if test requires lengths, false otherwise **/ bool LineContinuationTest::useSourceLengths() const { bool result; switch (m_test_case.m_case) { case ASSIGNMENT_BEFORE_OPERATOR: case ASSIGNMENT_AFTER_OPERATOR: case VECTOR_VARIABLE_INITIALIZER: case TOKEN_INSIDE_FUNCTION_NAME: case TOKEN_INSIDE_TYPE_NAME: case TOKEN_INSIDE_VARIABLE_NAME: case PREPROCESSOR_TOKEN_INSIDE: case PREPROCESSOR_TOKEN_BETWEEN: case COMMENT: case SOURCE_TERMINATION_NULL: case PART_TERMINATION_NULL: case PART_NEXT_TO_TERMINATION_NULL: default: result = false; break; case SOURCE_TERMINATION_NON_NULL: case PART_TERMINATION_NON_NULL: case PART_NEXT_TO_TERMINATION_NON_NULL: result = true; break; } return result; } /** Constructor * * @param context Test context **/ LineNumberingTest::LineNumberingTest(deqp::Context& context) : GLSLTestBase(context, "line_numbering", "Verify if line numbering is correct after line continuation") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void LineNumberingTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* test_result_snippet_normal[6] = { /* Utils::COMPUTE_SHADER */ "ivec4(11, 1, 2, 3)", /* Utils::VERTEX_SHADER */ "ivec4(9, 1, 2, 3)", /* Utils::TESS_CTRL_SHADER */ "ivec4(12, 1, 2, 3)", /* Utils::TESS_EVAL_SHADER */ "ivec4(12, 1, 2, 3)", /* Utils::GEOMETRY_SHADER */ "ivec4(13, 1, 2, 3)", /* Utils::FRAGMENT_SHADER */ "ivec4(10, 1, 2, 3)" }; static const GLchar* test_result_snippet_400[6] = { /* Utils::COMPUTE_SHADER */ "ivec4(13, 1, 2, 3)", /* Utils::VERTEX_SHADER */ "ivec4(11, 1, 2, 3)", /* Utils::TESS_CTRL_SHADER */ "ivec4(14, 1, 2, 3)", /* Utils::TESS_EVAL_SHADER */ "ivec4(14, 1, 2, 3)", /* Utils::GEOMETRY_SHADER */ "ivec4(15, 1, 2, 3)", /* Utils::FRAGMENT_SHADER */ "ivec4(12, 1, 2, 3)" }; static const GLchar* line_numbering_snippet = "ivec4 glsl\\\n" "Test\\\n" "Function(in ivec3 arg)\n" "{\n" " return ivec4(__LINE__, arg.xyz);\n" "}\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "GLSL_TEST_FUNCTION" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if (GLSL_TEST_RESULT == glslTestFunction(ivec3(1, 2, 3)))\n" " {\n" " result = vec4(0, 1, 0, 1);\n" " }\n" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "GLSL_TEST_FUNCTION" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((GLSL_TEST_RESULT == glslTestFunction(ivec3(1, 2, 3))) &&\n" " (vec4(0, 1, 0, 1) == gs_fs_result) )\n" " {\n" " result = vec4(0, 1, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "GLSL_TEST_FUNCTION" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((GLSL_TEST_RESULT == glslTestFunction(ivec3(1, 2, 3))) &&\n" " (vec4(0, 1, 0, 1) == tes_gs_result[0]) )\n" " {\n" " result = vec4(0, 1, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "GLSL_TEST_FUNCTION" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((GLSL_TEST_RESULT == glslTestFunction(ivec3(1, 2, 3))) &&\n" " (vec4(0, 1, 0, 1) == vs_tcs_result[gl_InvocationID]) )\n" " {\n" " result = vec4(0, 1, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "GLSL_TEST_FUNCTION" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((GLSL_TEST_RESULT == glslTestFunction(ivec3(1, 2, 3))) &&\n" " (vec4(0, 1, 0, 1) == tcs_tes_result[0]) )\n" " {\n" " result = vec4(0, 1, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "GLSL_TEST_FUNCTION" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if (GLSL_TEST_RESULT == glslTestFunction(ivec3(1, 2, 3)))\n" " {\n" " result = vec4(0, 1, 0, 1);\n" " }\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("GLSL_TEST_FUNCTION", position, line_numbering_snippet, out_source.m_parts[0].m_code); Utils::replaceToken("GLSL_TEST_RESULT", position, in_use_version_400 ? test_result_snippet_400[in_stage] : test_result_snippet_normal[in_stage], out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ UTF8CharactersTest::UTF8CharactersTest(deqp::Context& context) : GLSLTestBase(context, "utf8_characters", "UTF8 character used in comment or preprocessor") { /* Nothing to be done here */ } /** Overwrite getShaderSourceConfig method * * @param out_n_parts Number of source parts used by this test case * @param out_use_lengths If source lengths shall be provided to compiler **/ void UTF8CharactersTest::getShaderSourceConfig(GLuint& out_n_parts, bool& out_use_lengths) { out_n_parts = 1; out_use_lengths = (AS_LAST_CHARACTER_NON_NULL_TERMINATED == m_test_case.m_case) ? true : false; } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool UTF8CharactersTest::prepareNextTestCase(glw::GLuint test_case_index) { static const testCase test_cases[] = { { IN_COMMENT, Utils::TWO_BYTES }, { IN_COMMENT, Utils::THREE_BYTES }, { IN_COMMENT, Utils::FOUR_BYTES }, { IN_COMMENT, Utils::FIVE_BYTES }, { IN_COMMENT, Utils::SIX_BYTES }, { IN_COMMENT, Utils::REDUNDANT_ASCII }, { IN_PREPROCESSOR, Utils::TWO_BYTES }, { IN_PREPROCESSOR, Utils::THREE_BYTES }, { IN_PREPROCESSOR, Utils::FOUR_BYTES }, { IN_PREPROCESSOR, Utils::FIVE_BYTES }, { IN_PREPROCESSOR, Utils::SIX_BYTES }, { IN_PREPROCESSOR, Utils::REDUNDANT_ASCII }, { AS_LAST_CHARACTER_NULL_TERMINATED, Utils::TWO_BYTES }, { AS_LAST_CHARACTER_NULL_TERMINATED, Utils::THREE_BYTES }, { AS_LAST_CHARACTER_NULL_TERMINATED, Utils::FOUR_BYTES }, { AS_LAST_CHARACTER_NULL_TERMINATED, Utils::FIVE_BYTES }, { AS_LAST_CHARACTER_NULL_TERMINATED, Utils::SIX_BYTES }, { AS_LAST_CHARACTER_NULL_TERMINATED, Utils::REDUNDANT_ASCII }, { AS_LAST_CHARACTER_NON_NULL_TERMINATED, Utils::TWO_BYTES }, { AS_LAST_CHARACTER_NON_NULL_TERMINATED, Utils::THREE_BYTES }, { AS_LAST_CHARACTER_NON_NULL_TERMINATED, Utils::FOUR_BYTES }, { AS_LAST_CHARACTER_NON_NULL_TERMINATED, Utils::FIVE_BYTES }, { AS_LAST_CHARACTER_NON_NULL_TERMINATED, Utils::SIX_BYTES }, { AS_LAST_CHARACTER_NON_NULL_TERMINATED, Utils::REDUNDANT_ASCII }, }; static const GLuint max_test_cases = sizeof(test_cases) / sizeof(testCase); if ((GLuint)-1 == test_case_index) { m_test_case.m_case = DEBUG_CASE; m_test_case.m_character = Utils::EMPTY; } else if (max_test_cases <= test_case_index) { return false; } else { m_test_case = test_cases[test_case_index]; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: utf8 character: " << Utils::getUtf8Character(m_test_case.m_character) << " is placed " << casesToStr() << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void UTF8CharactersTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* compute_shader_template = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform sampler2D uni_sampler;\n" "\n" "#if 0\n" " #define SET_REPREPROCESSOR_CASESULT(XX) result = XX\n" "#else\n" " #define SET_RESULT(XX) result = XX\n" "#endif\n" "\n" "void main()\n" "{\n" " ivec2 coordinates = ivec2(gl_GlobalInvocationID.xy + ivec2(16, 16));\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if (vec4(0, 0, 1, 1) == texelFetch(uni_sampler, coordinates, 0 /* lod */))\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "// Lorem ipsum LAST_CHARACTER_CASE"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "in vec4 gs_fs_result;\n" "in vec2 gs_fs_tex_coord;\n" "out vec4 fs_out_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#if 0\n" " #define SET_REPREPROCESSOR_CASESULT(XX) result = XX\n" "#else\n" " #define SET_RESULT(XX) result = XX\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, gs_fs_tex_coord)) &&\n" " (vec4(0, 1, 0, 1) == gs_fs_result) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "// Lorem ipsum LAST_CHARACTER_CASE"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec2 gs_fs_tex_coord;\n" "out vec4 gs_fs_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#if 0\n" " #define SET_REPREPROCESSOR_CASESULT(XX) result = XX\n" "#else\n" " #define SET_RESULT(XX) result = XX\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.5, 0.5))) &&\n" " (vec4(0, 1, 0, 1) == tes_gs_result[0]) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " gs_fs_tex_coord = vec2(0.25, 0.25);\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_tex_coord = vec2(0.25, 0.75);\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_tex_coord = vec2(0.75, 0.25);\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_tex_coord = vec2(0.75, 0.75);\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "// Lorem ipsum LAST_CHARACTER_CASE"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "uniform sampler2D uni_sampler;\n" "\n" "#if 0\n" " #define SET_REPREPROCESSOR_CASESULT(XX) result = XX\n" "#else\n" " #define SET_RESULT(XX) result = XX\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.4, 0.4))) &&\n" " (vec4(0, 1, 0, 1) == vs_tcs_result[gl_InvocationID]) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " tcs_tes_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" "// Lorem ipsum LAST_CHARACTER_CASE"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#if 0\n" " #define SET_REPREPROCESSOR_CASESULT(XX) result = XX\n" "#else\n" " #define SET_RESULT(XX) result = XX\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.6, 0.6))) &&\n" " (vec4(0, 1, 0, 1) == tcs_tes_result[0]) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "// Lorem ipsum LAST_CHARACTER_CASE"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "// Lorem ipsum dolor sit amCOMMENT_CASEet, consectetur adipiscing elit posuere.\n" "\n" "/* Lorem ipsum dolor sit amet, conCOMMENT_CASEsectetur adipiscing elit posuere. */\n" "\n" "out vec4 vs_tcs_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#if 0\n" " #define SET_REPREPROCESSOR_CASESULT(XX) result = XX\n" "#else\n" " #define SET_RESULT(XX) result = XX\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if (vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.5, 0.5)) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " vs_tcs_result = result;\n" "}\n" "// Lorem ipsum LAST_CHARACTER_CASE"; const GLchar* shader_template = 0; const GLchar* comment_case = ""; const GLchar* preprocessor_case = ""; const GLchar* last_character_case = ""; const GLchar* utf8_character = Utils::getUtf8Character(m_test_case.m_character); switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } switch (m_test_case.m_case) { case IN_COMMENT: comment_case = utf8_character; break; case IN_PREPROCESSOR: preprocessor_case = utf8_character; break; case AS_LAST_CHARACTER_NULL_TERMINATED: last_character_case = utf8_character; break; case AS_LAST_CHARACTER_NON_NULL_TERMINATED: last_character_case = utf8_character; break; case DEBUG_CASE: break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceAllTokens("COMMENT_CASE", comment_case, out_source.m_parts[0].m_code); Utils::replaceAllTokens("PREPROCESSOR_CASE", preprocessor_case, out_source.m_parts[0].m_code); Utils::replaceAllTokens("LAST_CHARACTER_CASE", last_character_case, out_source.m_parts[0].m_code); } /** Prepare texture * * @param texture Texutre to be created and filled with content * * @return Name of sampler uniform that should be used for the texture **/ const GLchar* UTF8CharactersTest::prepareSourceTexture(Utils::texture& texture) { std::vector data; static const GLuint width = 64; static const GLuint height = 64; static const GLuint data_size = width * height; static const GLuint blue_color = 0xffff0000; static const GLuint grey_color = 0xaaaaaaaa; data.resize(data_size); for (GLuint i = 0; i < data_size; ++i) { data[i] = grey_color; } for (GLuint y = 16; y < 48; ++y) { const GLuint line_offset = y * 64; for (GLuint x = 16; x < 48; ++x) { const GLuint pixel_offset = x + line_offset; data[pixel_offset] = blue_color; } } texture.create(width, height, GL_RGBA8); texture.update(width, height, 0 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); return "uni_sampler"; } /** Returns description of current test case * * @return String with description **/ const GLchar* UTF8CharactersTest::casesToStr() const { const GLchar* result = 0; switch (m_test_case.m_case) { case IN_COMMENT: result = "in comment"; break; case IN_PREPROCESSOR: result = "in preprocessor"; break; case AS_LAST_CHARACTER_NULL_TERMINATED: result = "just before null"; break; case AS_LAST_CHARACTER_NON_NULL_TERMINATED: result = "as last character"; break; case DEBUG_CASE: result = "nowhere. This is debug!"; break; default: TCU_FAIL("Invalid enum"); } return result; } /** Constructor * * @param context Test context **/ UTF8InSourceTest::UTF8InSourceTest(deqp::Context& context) : NegativeTestBase(context, "utf8_in_source", "UTF8 characters used in shader source") { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool UTF8InSourceTest::prepareNextTestCase(glw::GLuint test_case_index) { static const Utils::UTF8_CHARACTERS test_cases[] = { Utils::TWO_BYTES, Utils::THREE_BYTES, Utils::FOUR_BYTES, Utils::FIVE_BYTES, Utils::SIX_BYTES, Utils::REDUNDANT_ASCII }; static const GLuint max_test_cases = sizeof(test_cases) / sizeof(Utils::UTF8_CHARACTERS); if ((GLuint)-1 == test_case_index) { m_character = Utils::EMPTY; } else if (max_test_cases <= test_case_index) { return false; } else { m_character = test_cases[test_case_index]; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: utf8 character: " << Utils::getUtf8Character(m_character) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void UTF8InSourceTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform sampler2D uni_sampler;\n" "\n" "#define SET_RESULT(XX) resHEREult = XX\n" "\n" "void main()\n" "{\n" " ivec2 coordinates = ivec2(gl_GlobalInvocationID.xy + ivec2(16, 16));\n" " vec4 resHEREult = vec4(1, 0, 0, 1);\n" "\n" " if (vec4(0, 0, 1, 1) == texelFetch(uni_sampler, coordinates, 0 /* lod */))\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), resHEREult);\n" "}\n" ""; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "in vec2 gs_fs_tex_coord;\n" "out vec4 fs_out_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#define SET_RESULT(XX) resHEREult = XX\n" "\n" "void main()\n" "{\n" " vec4 resHEREult = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, gs_fs_tex_coord)) &&\n" " (vec4(0, 1, 0, 1) == gs_fs_result) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " fs_out_result = resHEREult;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gHEREs_result[];\n" "out vec2 gs_fs_tex_coord;\n" "out vec4 gs_fs_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#define SET_RESULT(XX) result = XX\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.5, 0.5))) &&\n" " (vec4(0, 1, 0, 1) == tes_gHEREs_result[0]) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " gs_fs_tex_coord = vec2(0.25, 0.25);\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_tex_coord = vec2(0.25, 0.75);\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_tex_coord = vec2(0.75, 0.25);\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_tex_coord = vec2(0.75, 0.75);\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcHEREs_tes_result[];\n" "uniform sampler2D uni_sampler;\n" "\n" "#define SET_RESULT(XX) resulHEREt = XX\n" "\n" "void main()\n" "{\n" " vec4 resulHEREt = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.4, 0.4))) &&\n" " (vec4(0, 1, 0, 1) == vs_tcs_result[gl_InvocationID]) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " tcHEREs_tes_result[gl_InvocationID] = resulHEREt;\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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 teHEREs_gs_result;\n" "uniform sampler2D uni_sampler;\n" "\n" "#define SET_RESULT(XX) reHEREsult = XX\n" "\n" "void main()\n" "{\n" " vec4 reHEREsult = vec4(1, 0, 0, 1);\n" "\n" " if ((vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.6, 0.6))) &&\n" " (vec4(0, 1, 0, 1) == tcs_tes_result[0]) )\n" " {\n" " SET_RESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " teHEREs_gs_result = reHEREsult;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_HEREresult;\n" "uniform sampler2D uni_sampler;\n" "\n" "#define SET_RHEREESULT(XX) resHEREult = XX\n" "\n" "void main()\n" "{\n" " vec4 resHEREult = vec4(1, 0, 0, 1);\n" "\n" " if (vec4(0, 0, 1, 1) == texture(uni_sampler, vec2(0.5, 0.5)) )\n" " {\n" " SET_RHEREESULT(vec4(0, 1, 0, 1));\n" " }\n" "\n" " vs_tcs_HEREresult = resHEREult;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* utf8_character = Utils::getUtf8Character(m_character); switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceAllTokens("HERE", utf8_character, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ ImplicitConversionsValidTest::ImplicitConversionsValidTest(deqp::Context& context) : GLSLTestBase(context, "implicit_conversions", "Verifies that implicit conversions are allowed") { /* Nothing to be done */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool ImplicitConversionsValidTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { return true; } else if (m_test_cases.size() <= test_case_index) { return false; } const testCase& test_case = m_test_cases[test_case_index]; m_context.getTestContext().getLog() << tcu::TestLog::Message << "T1:" << Utils::getTypeName(test_case.m_types.m_t1, test_case.m_n_cols, test_case.m_n_rows) << " T2:" << Utils::getTypeName(test_case.m_types.m_t2, test_case.m_n_cols, test_case.m_n_rows) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ImplicitConversionsValidTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* function_definition = "T1 function(in T2 left, in T2 right)\n" "{\n" " return left + right;\n" "}\n"; static const GLchar* verification_snippet = " const T2 const_left = T2(VALUE_LIST);\n" " const T2 const_right = T2(VALUE_LIST);\n" "\n" " T1 const_result = function(const_left, const_right);\n" "\n" " T1 literal_result = function(T2(VALUE_LIST), T2(VALUE_LIST));\n" "\n" " T2 var_left = uni_left;\n" " T2 var_right = uni_right;\n" "\n" " T1 var_result = function(var_left, var_right);\n" "\n" " if ((literal_result != const_result) ||\n" " (const_result != var_result) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform T2 uni_left;\n" " uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const testCase& test_case = getCurrentTestCase(); const GLchar* t1 = Utils::getTypeName(test_case.m_types.m_t1, test_case.m_n_cols, test_case.m_n_rows); const GLchar* t2 = Utils::getTypeName(test_case.m_types.m_t2, test_case.m_n_cols, test_case.m_n_rows); const std::string& value_list = getValueList(test_case.m_n_cols, test_case.m_n_rows); const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("FUNCTION_DEFINITION", position, function_definition, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VALUE_LIST", value_list.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("T1", t1, out_source.m_parts[0].m_code); Utils::replaceAllTokens("T2", t2, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void ImplicitConversionsValidTest::prepareUniforms(Utils::program& program) { static const GLdouble double_data[16] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; static const GLfloat float_data[16] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; static const GLint int_data[4] = { 1, 1, 1, 1 }; static const GLuint uint_data[4] = { 1u, 1u, 1u, 1u }; const testCase& test_case = getCurrentTestCase(); switch (test_case.m_types.m_t2) { case Utils::DOUBLE: program.uniform("uni_left", Utils::DOUBLE, test_case.m_n_cols, test_case.m_n_rows, double_data); program.uniform("uni_right", Utils::DOUBLE, test_case.m_n_cols, test_case.m_n_rows, double_data); break; case Utils::FLOAT: program.uniform("uni_left", Utils::FLOAT, test_case.m_n_cols, test_case.m_n_rows, float_data); program.uniform("uni_right", Utils::FLOAT, test_case.m_n_cols, test_case.m_n_rows, float_data); break; case Utils::INT: program.uniform("uni_left", Utils::INT, test_case.m_n_cols, test_case.m_n_rows, int_data); program.uniform("uni_right", Utils::INT, test_case.m_n_cols, test_case.m_n_rows, int_data); break; case Utils::UINT: program.uniform("uni_left", Utils::UINT, test_case.m_n_cols, test_case.m_n_rows, uint_data); program.uniform("uni_right", Utils::UINT, test_case.m_n_cols, test_case.m_n_rows, uint_data); break; default: TCU_FAIL("Invalid enum"); } } /** Prepare test cases * * @return true **/ bool ImplicitConversionsValidTest::testInit() { static const typesPair allowed_conversions[] = { { Utils::UINT, Utils::INT }, { Utils::FLOAT, Utils::INT }, { Utils::DOUBLE, Utils::INT }, { Utils::FLOAT, Utils::UINT }, { Utils::DOUBLE, Utils::UINT }, { Utils::FLOAT, Utils::FLOAT }, }; static GLuint n_allowed_conversions = sizeof(allowed_conversions) / sizeof(typesPair); m_debug_test_case.m_types.m_t1 = Utils::FLOAT; m_debug_test_case.m_types.m_t2 = Utils::FLOAT; m_debug_test_case.m_n_cols = 4; m_debug_test_case.m_n_rows = 4; for (GLuint i = 0; i < n_allowed_conversions; ++i) { const typesPair& types = allowed_conversions[i]; GLuint allowed_columns = 1; if ((true == Utils::doesTypeSupportMatrix(types.m_t1)) && (true == Utils::doesTypeSupportMatrix(types.m_t2))) { allowed_columns = 4; } { testCase test_case = { types, 1, 1 }; m_test_cases.push_back(test_case); } for (GLuint row = 2; row <= 4; ++row) { for (GLuint col = 1; col <= allowed_columns; ++col) { testCase test_case = { types, col, row }; m_test_cases.push_back(test_case); } } } return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const ImplicitConversionsValidTest::testCase& ImplicitConversionsValidTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_debug_test_case; } else { return m_test_cases[m_current_test_case_index]; } } /** Get list of values to for glsl constants * * @param n_columns Number of columns * @param n_rows Number of rows * * @return String with list of values separated with comma **/ std::string ImplicitConversionsValidTest::getValueList(glw::GLuint n_columns, glw::GLuint n_rows) { std::string result; for (GLuint i = 0; i < n_columns * n_rows; ++i) { if (i != n_columns * n_rows - 1) { result.append("1, "); } else { result.append("1"); } } return result; } /** Constructor * * @param context Test context **/ ImplicitConversionsInvalidTest::ImplicitConversionsInvalidTest(deqp::Context& context) : NegativeTestBase(context, "implicit_conversions_invalid", "Verifies that implicit conversions from uint to int are forbidden") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool ImplicitConversionsInvalidTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { return false; } else if (4 <= test_case_index) { return false; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "T1:" << Utils::getTypeName(Utils::UINT, 1, test_case_index + 1) << " T2:" << Utils::getTypeName(Utils::INT, 1, test_case_index + 1) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ImplicitConversionsInvalidTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* function_definition = "T1 function(in T2 left, in T2 right)\n" "{\n" " return left + right;\n" "}\n"; static const GLchar* verification_snippet = " const T2 const_left = T2(VALUE_LIST);\n" " const T2 const_right = T2(VALUE_LIST);\n" "\n" " T1 const_result = function(const_left, const_right);\n" "\n" " T1 literal_result = function(T2(VALUE_LIST), T2(VALUE_LIST));\n" "\n" " T2 var_left = uni_left;\n" " T2 var_right = uni_right;\n" "\n" " T1 var_result = function(var_left, var_right);\n" "\n" " if ((literal_result != const_result) ||\n" " (const_result != var_result) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform T2 uni_left;\n" " uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "uniform T2 uni_left;\n" "uniform T2 uni_right;\n" "\n" "FUNCTION_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; GLuint n_rows = m_current_test_case_index + 1; const GLchar* t1 = Utils::getTypeName(Utils::INT, 1, n_rows); const GLchar* t2 = Utils::getTypeName(Utils::UINT, 1, n_rows); const std::string& value_list = getValueList(n_rows); const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("FUNCTION_DEFINITION", position, function_definition, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VALUE_LIST", value_list.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("T1", t1, out_source.m_parts[0].m_code); Utils::replaceAllTokens("T2", t2, out_source.m_parts[0].m_code); } /** Get list of values to for glsl constants * * @return String with list of values separated with comma **/ std::string ImplicitConversionsInvalidTest::getValueList(glw::GLuint n_rows) { std::string result; for (GLuint i = 0; i < n_rows; ++i) { if (i != n_rows - 1) { result.append("1, "); } else { result.append("1"); } } return result; } /** Constructor * * @param context Test context **/ ConstDynamicValueTest::ConstDynamicValueTest(deqp::Context& context) : GLSLTestBase(context, "const_dynamic_value", "Test if constants can be initialized with dynamic values") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ConstDynamicValueTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* struct_definition = "struct S {\n" " float scalar;\n" " vec4 vector;\n" " mat2 matrix;\n" "};\n"; static const GLchar* verification_snippet = " const float c1 = uni_scalar;\n" " const vec4 c2 = uni_vector;\n" " const mat2 c3 = uni_matrix;\n" " const S c4 = { uni_scalar, uni_vector, uni_matrix };\n" " const vec4 c5[15] = { uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector,\n" " uni_vector };\n" " if ((SCALAR != c1) ||\n" " (VECTOR != c2) ||\n" " (MATRIX != c3) ||\n" " (SCALAR != c4.scalar) ||\n" " (VECTOR != c4.vector) ||\n" " (MATRIX != c4.matrix) ||\n" " (VECTOR != c5[0]) ||\n" " (VECTOR != c5[1]) ||\n" " (VECTOR != c5[2]) ||\n" " (VECTOR != c5[3]) ||\n" " (VECTOR != c5[4]) ||\n" " (VECTOR != c5[5]) ||\n" " (VECTOR != c5[6]) ||\n" " (VECTOR != c5[7]) ||\n" " (VECTOR != c5[8]) ||\n" " (VECTOR != c5[9]) ||\n" " (VECTOR != c5[10]) ||\n" " (VECTOR != c5[11]) ||\n" " (VECTOR != c5[12]) ||\n" " (VECTOR != c5[13]) ||\n" " (VECTOR != c5[14]) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform float uni_scalar;\n" " uniform vec4 uni_vector;\n" " uniform mat2 uni_matrix;\n" "\n" "STRUCTURE_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "uniform float uni_scalar;\n" "uniform vec4 uni_vector;\n" "uniform mat2 uni_matrix;\n" "\n" "STRUCTURE_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "uniform float uni_scalar;\n" "uniform vec4 uni_vector;\n" "uniform mat2 uni_matrix;\n" "\n" "STRUCTURE_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "uniform float uni_scalar;\n" "uniform vec4 uni_vector;\n" "uniform mat2 uni_matrix;\n" "\n" "STRUCTURE_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "uniform float uni_scalar;\n" "uniform vec4 uni_vector;\n" "uniform mat2 uni_matrix;\n" "\n" "STRUCTURE_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "uniform float uni_scalar;\n" "uniform vec4 uni_vector;\n" "uniform mat2 uni_matrix;\n" "\n" "STRUCTURE_DEFINITION" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; static const GLchar* scalar = "0.5"; static const GLchar* vector = "vec4(0.5, 0.125, 0.375, 0)"; static const GLchar* matrix = "mat2(0.5, 0.125, 0.375, 0)"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("STRUCTURE_DEFINITION", position, struct_definition, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("SCALAR", scalar, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VECTOR", vector, out_source.m_parts[0].m_code); Utils::replaceAllTokens("MATRIX", matrix, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void ConstDynamicValueTest::prepareUniforms(Utils::program& program) { static const GLfloat float_data[4] = { 0.5f, 0.125f, 0.375f, 0.0f }; static const GLfloat scalar = 0.5f; program.uniform("uni_scalar", Utils::FLOAT, 1, 1, &scalar); program.uniform("uni_vector", Utils::FLOAT, 1, 4, float_data); program.uniform("uni_matrix", Utils::FLOAT, 2, 2, float_data); } /** Constructor * * @param context Test context **/ ConstAssignmentTest::ConstAssignmentTest(deqp::Context& context) : NegativeTestBase(context, "const_assignment", "Verifies that constants cannot be overwritten") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool ConstAssignmentTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { return true; } else if (2 <= test_case_index) { return false; } return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ConstAssignmentTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " const float c1 = INIT;\n" "\n" " float temp = c1;\n" "\n" " for (uint i = 0; i < 4; ++i)" " {\n" " temp += c1 + uni_value;\n" " c1 -= 0.125;\n" " }\n" "\n" " if (0.0 == temp)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform float uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "uniform float uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "uniform float uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "uniform float uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "uniform float uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "uniform float uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; static const GLchar* dynamic_init = "uni_value"; static const GLchar* const_init = "0.75"; const GLchar* shader_template = 0; const GLchar* l_init = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } if (0 == m_current_test_case_index) { l_init = dynamic_init; } else { l_init = const_init; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("INIT", l_init, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ ConstDynamicValueAsConstExprTest::ConstDynamicValueAsConstExprTest(deqp::Context& context) : NegativeTestBase(context, "const_dynamic_value_as_const_expr", "Verifies that dynamic constants cannot be used as constant foldable expressions") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ConstDynamicValueAsConstExprTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " const uint c1 = INIT;\n" "\n" " float temp[c1];\n" "\n" " for (uint i = 0; i < c1; ++i)" " {\n" " temp[i] += uni_value;\n" " }\n" "\n" " if (0.0 == temp[c1 - 1])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform uint uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "uniform uint uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "uniform uint uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "uniform uint uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "uniform uint uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "uniform uint uni_value;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; static const GLchar* l_init = "uni_value"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("INIT", l_init, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ QualifierOrderTest::QualifierOrderTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_order", "Test verifies that valid permutation of input and output qalifiers are accepted") , m_current_test_case_index(0) { /* Nothing to be done */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool QualifierOrderTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { /* Nothing to be done here */ } else if (m_test_cases.size() <= test_case_index) { return false; } const Utils::qualifierSet& set = getCurrentTestCase(); tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < set.size(); ++i) { message << Utils::getQualifierString(set[i]) << " "; } message << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOrderTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " vec4 diff = INPUT_VARIABLE_NAME - vec4(0, 0, 1, 1);\n" " if (false == all(lessThan(diff, vec4(0.001, 0.001, 0.001, 0.001))))\n" " {\n" " result = INPUT_VARIABLE_NAME;\n" " }\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "layout (location = 0) out vec4 fs_out_result;\n" "\n" "VARIABLE_DECLARATION;\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "VARIABLE_DECLARATION;\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "VARIABLE_DECLARATION;\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_result[gl_InvocationID] = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "VARIABLE_DECLARATION;\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "VARIABLE_DECLARATION;\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } const Utils::qualifierSet& test_case = getCurrentTestCase(); std::string in_test_decl; std::string in_test_ref; std::string out_test_decl; std::string out_test_ref; Utils::prepareVariableStrings(in_stage, Utils::INPUT, test_case, "vec4", "test", in_test_decl, in_test_ref); Utils::prepareVariableStrings(in_stage, Utils::OUTPUT, test_case, "vec4", "test", out_test_decl, out_test_ref); // sample storage qualifier is not a valid qualifier for fragment output if (in_stage == Utils::FRAGMENT_SHADER) { if (out_test_decl.find("sample") != std::string::npos) out_test_decl.erase(out_test_decl.find("sample"), 7); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VARIABLE_DECLARATION", position, in_test_decl.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VARIABLE_DECLARATION", position, out_test_decl.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position -= strlen(verification_snippet); Utils::replaceAllTokens("OUTPUT_VARIABLE_NAME", out_test_ref.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("INPUT_VARIABLE_NAME", in_test_ref.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("LOC_VALUE", "1", out_source.m_parts[0].m_code); } /**Prepare vertex buffer and vertex array object. * * @param program Program instance * @param buffer Buffer instance * @param vao VertexArray instance * * @return 0 **/ void QualifierOrderTest::prepareVertexBuffer(const Utils::program& program, Utils::buffer& buffer, Utils::vertexArray& vao) { std::string test_name = Utils::getVariableName(Utils::VERTEX_SHADER, Utils::INPUT, "test"); GLint test_loc = program.getAttribLocation(test_name.c_str()); if (-1 == test_loc) { TCU_FAIL("Vertex attribute location is invalid"); } vao.generate(); vao.bind(); buffer.generate(GL_ARRAY_BUFFER); GLfloat data[] = { 0.0f, 0.0f, 1.0f, 1.0f }; GLsizeiptr data_size = sizeof(data); buffer.update(data_size, data, GL_STATIC_DRAW); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up vao */ gl.vertexAttribPointer(test_loc, 4 /* size */, GL_FLOAT /* type */, GL_FALSE /* normalized*/, 0 /* stride */, 0 /* offset */); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer"); /* Enable attribute */ gl.enableVertexAttribArray(test_loc); GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray"); } /** Prepare test cases * * @return true **/ bool QualifierOrderTest::testInit() { m_test_cases.resize(5); m_test_cases[0].push_back(Utils::QUAL_HIGHP); m_test_cases[0].push_back(Utils::QUAL_IN); m_test_cases[0].push_back(Utils::QUAL_LOCATION); m_test_cases[0].push_back(Utils::QUAL_SMOOTH); m_test_cases[0].push_back(Utils::QUAL_INVARIANT); m_test_cases[1].push_back(Utils::QUAL_LOWP); m_test_cases[1].push_back(Utils::QUAL_IN); m_test_cases[1].push_back(Utils::QUAL_SAMPLE); m_test_cases[1].push_back(Utils::QUAL_LOCATION); m_test_cases[1].push_back(Utils::QUAL_NOPERSPECTIVE); m_test_cases[1].push_back(Utils::QUAL_INVARIANT); m_test_cases[2].push_back(Utils::QUAL_HIGHP); m_test_cases[2].push_back(Utils::QUAL_IN); m_test_cases[2].push_back(Utils::QUAL_LOCATION); m_test_cases[2].push_back(Utils::QUAL_SMOOTH); m_test_cases[2].push_back(Utils::QUAL_INVARIANT); m_test_cases[2].push_back(Utils::QUAL_LOCATION); m_test_cases[3].push_back(Utils::QUAL_LOWP); m_test_cases[3].push_back(Utils::QUAL_IN); m_test_cases[3].push_back(Utils::QUAL_LOCATION); m_test_cases[3].push_back(Utils::QUAL_SAMPLE); m_test_cases[3].push_back(Utils::QUAL_LOCATION); m_test_cases[3].push_back(Utils::QUAL_NOPERSPECTIVE); m_test_cases[3].push_back(Utils::QUAL_INVARIANT); m_test_cases[4].push_back(Utils::QUAL_HIGHP); m_test_cases[4].push_back(Utils::QUAL_IN); m_test_cases[4].push_back(Utils::QUAL_PATCH); m_test_cases[4].push_back(Utils::QUAL_LOCATION); m_test_cases[4].push_back(Utils::QUAL_INVARIANT); return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const Utils::qualifierSet& QualifierOrderTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_test_cases[0]; } else { return m_test_cases[m_current_test_case_index]; } } /** Constructor * * @param context Test context **/ QualifierOrderBlockTest::QualifierOrderBlockTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_order_block", "Verifies that qualifiers of members of input block can be arranged in any order") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool QualifierOrderBlockTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { /* Nothing to be done here */ } else if (m_test_cases.size() <= test_case_index) { return false; } const Utils::qualifierSet& set = getCurrentTestCase(); tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < set.size(); ++i) { message << Utils::getQualifierString(set[i]) << " "; } message << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOrderBlockTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " vec4 diff = INPUT_VARIABLE_NAME - vec4(0, 0, 1, 1);\n" " if (false == all(lessThan(diff, vec4(0.001, 0.001, 0.001, 0.001))))\n" " {\n" " result = INPUT_VARIABLE_NAME;\n" " }\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "layout (location = 0) out vec4 fs_out_result;\n" "\n" "in GSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block;\n" "out VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "in TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block [];\n" "out GSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "in VSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block [];\n" "out TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block [];\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_result[gl_InvocationID] = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "in TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block [];\n" "out TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "in VARIABLE_DECLARATION;\n" "out VSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } const Utils::qualifierSet& test_case = getCurrentTestCase(); std::string in_test_decl; std::string in_test_ref; std::string out_test_decl; std::string out_test_ref; switch (in_stage) { case Utils::VERTEX_SHADER: Utils::prepareVariableStrings(in_stage, Utils::INPUT, test_case, "vec4", "test", in_test_decl, in_test_ref); break; default: Utils::prepareBlockVariableStrings(in_stage, Utils::INPUT, test_case, "vec4", "test", "input_block", in_test_decl, in_test_ref); break; } switch (in_stage) { case Utils::FRAGMENT_SHADER: Utils::prepareVariableStrings(in_stage, Utils::OUTPUT, test_case, "vec4", "test", out_test_decl, out_test_ref); break; default: Utils::prepareBlockVariableStrings(in_stage, Utils::OUTPUT, test_case, "vec4", "test", "output_block", out_test_decl, out_test_ref); break; } // sample storage qualifier is not a valid qualifier for fragment output if (in_stage == Utils::FRAGMENT_SHADER) { if (out_test_decl.find("sample") != std::string::npos) out_test_decl.erase(out_test_decl.find("sample"), 7); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VARIABLE_DECLARATION", position, in_test_decl.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VARIABLE_DECLARATION", position, out_test_decl.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position -= strlen(verification_snippet); Utils::replaceAllTokens("OUTPUT_VARIABLE_NAME", out_test_ref.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("INPUT_VARIABLE_NAME", in_test_ref.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("LOC_VALUE", "1", out_source.m_parts[0].m_code); } /**Prepare vertex buffer and vertex array object. * * @param program Program instance * @param buffer Buffer instance * @param vao VertexArray instance * * @return 0 **/ void QualifierOrderBlockTest::prepareVertexBuffer(const Utils::program& program, Utils::buffer& buffer, Utils::vertexArray& vao) { std::string test_name = Utils::getVariableName(Utils::VERTEX_SHADER, Utils::INPUT, "test"); GLint test_loc = program.getAttribLocation(test_name.c_str()); if (-1 == test_loc) { TCU_FAIL("Vertex attribute location is invalid"); } vao.generate(); vao.bind(); buffer.generate(GL_ARRAY_BUFFER); GLfloat data[] = { 0.0f, 0.0f, 1.0f, 1.0f }; GLsizeiptr data_size = sizeof(data); buffer.update(data_size, data, GL_STATIC_DRAW); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up vao */ gl.vertexAttribPointer(test_loc, 4 /* size */, GL_FLOAT /* type */, GL_FALSE /* normalized*/, 0 /* stride */, 0 /* offset */); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer"); /* Enable attribute */ gl.enableVertexAttribArray(test_loc); GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray"); } /** Prepare test cases * * @return true **/ bool QualifierOrderBlockTest::testInit() { m_test_cases.resize(4); m_test_cases[0].push_back(Utils::QUAL_HIGHP); m_test_cases[0].push_back(Utils::QUAL_FLAT); m_test_cases[0].push_back(Utils::QUAL_INVARIANT); m_test_cases[1].push_back(Utils::QUAL_LOWP); m_test_cases[1].push_back(Utils::QUAL_SAMPLE); m_test_cases[1].push_back(Utils::QUAL_NOPERSPECTIVE); m_test_cases[1].push_back(Utils::QUAL_INVARIANT); m_test_cases[2].push_back(Utils::QUAL_HIGHP); m_test_cases[2].push_back(Utils::QUAL_SMOOTH); m_test_cases[2].push_back(Utils::QUAL_INVARIANT); m_test_cases[3].push_back(Utils::QUAL_LOWP); m_test_cases[3].push_back(Utils::QUAL_SAMPLE); m_test_cases[3].push_back(Utils::QUAL_NOPERSPECTIVE); m_test_cases[3].push_back(Utils::QUAL_INVARIANT); return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const Utils::qualifierSet& QualifierOrderBlockTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_test_cases[0]; } else { return m_test_cases[m_current_test_case_index]; } } /** Constructor * * @param context Test context **/ QualifierOrderUniformTest::QualifierOrderUniformTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_order_uniform", "Test verifies that all valid permutation of input qalifiers are accepted") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool QualifierOrderUniformTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { /* Nothing to be done here */ } else if (m_test_cases.size() <= test_case_index) { return false; } const Utils::qualifierSet& set = getCurrentTestCase(); tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < set.size(); ++i) { message << Utils::getQualifierString(set[i]) << " "; } message << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOrderUniformTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " vec4 diff = VARIABLE_NAME - vec4(0, 0, 1, 1);\n" " if (false == all(lessThan(diff, vec4(0.001, 0.001, 0.001, 0.001))))\n" " {\n" " result = VARIABLE_NAME;\n" " }\n"; static const GLchar* variable_declaration = " QUALIFIERS VARIABLE_NAME"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_explicit_uniform_location : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_explicit_uniform_location : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_explicit_uniform_location : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_explicit_uniform_location : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_explicit_uniform_location : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "VARIABLE_DECLARATION;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* location_string = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; location_string = "0"; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; location_string = "1"; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; location_string = "4"; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; location_string = "3"; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; location_string = "2"; break; default: TCU_FAIL("Invalid enum"); } const Utils::qualifierSet& test_case = getCurrentTestCase(); std::string uni_declaration; std::string uni_reference; Utils::prepareVariableStrings(in_stage, Utils::UNIFORM, test_case, "vec4", "test", uni_declaration, uni_reference); out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VARIABLE_DECLARATION", position, uni_declaration.c_str(), out_source.m_parts[0].m_code); position -= strlen(variable_declaration); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VARIABLE_NAME", uni_reference.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("LOC_VALUE", location_string, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void QualifierOrderUniformTest::prepareUniforms(Utils::program& program) { static const GLfloat float_data[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; program.uniform("uni_fs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_gs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tcs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tes_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_vs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); } /** Prepare test cases * * @return false if ARB_explicit_uniform_location is not supported, true otherwise **/ bool QualifierOrderUniformTest::testInit() { if (false == m_is_explicit_uniform_location) { return false; } m_test_cases.resize(4); m_test_cases[0].push_back(Utils::QUAL_HIGHP); m_test_cases[0].push_back(Utils::QUAL_UNIFORM); m_test_cases[0].push_back(Utils::QUAL_LOCATION); m_test_cases[1].push_back(Utils::QUAL_LOWP); m_test_cases[1].push_back(Utils::QUAL_UNIFORM); m_test_cases[1].push_back(Utils::QUAL_LOCATION); m_test_cases[2].push_back(Utils::QUAL_HIGHP); m_test_cases[2].push_back(Utils::QUAL_LOCATION); m_test_cases[2].push_back(Utils::QUAL_UNIFORM); m_test_cases[2].push_back(Utils::QUAL_LOCATION); m_test_cases[3].push_back(Utils::QUAL_LOCATION); m_test_cases[3].push_back(Utils::QUAL_LOWP); m_test_cases[3].push_back(Utils::QUAL_UNIFORM); m_test_cases[3].push_back(Utils::QUAL_LOCATION); return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const Utils::qualifierSet& QualifierOrderUniformTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_test_cases[0]; } else { return m_test_cases[m_current_test_case_index]; } } /** Constructor * * @param context Test context **/ QualifierOrderFunctionInoutTest::QualifierOrderFunctionInoutTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_order_function_inout", "Verify order of qualifiers of inout function parameters") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool QualifierOrderFunctionInoutTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { /* Nothing to be done here */ } else if (m_test_cases.size() <= test_case_index) { return false; } const Utils::qualifierSet& set = getCurrentTestCase(); tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < set.size(); ++i) { message << Utils::getQualifierString(set[i]) << " "; } message << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOrderFunctionInoutTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " vec4 temp = VARIABLE_NAME;\n" "\n" " function(temp);\n" "\n" " vec4 diff = temp - vec4(0, 0, 1, 1);\n" " if (false == all(lessThan(diff, vec4(0.001, 0.001, 0.001, 0.001))))\n" " {\n" " result = VARIABLE_NAME;\n" " }\n"; static const GLchar* function_declaration = "void function(QUALIFIERS_LIST vec4 param)\n" "{\n" " param = param.wzyx;\n" "}\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } const std::string& uni_reference = Utils::getVariableName(in_stage, Utils::UNIFORM, "test"); const std::string& qualifier_list = Utils::getQualifiersListString(getCurrentTestCase()); out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("FUNCTION_DECLARATION", position, function_declaration, out_source.m_parts[0].m_code); position -= strlen(function_declaration); Utils::replaceToken("QUALIFIERS_LIST", position, qualifier_list.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VARIABLE_NAME", uni_reference.c_str(), out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void QualifierOrderFunctionInoutTest::prepareUniforms(Utils::program& program) { static const GLfloat float_data[4] = { 1.0f, 1.0f, 0.0f, 0.0f }; program.uniform("uni_fs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_gs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tcs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tes_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_vs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); } /** Prepare test cases * * @return false if ARB_explicit_uniform_location is not supported, true otherwise **/ bool QualifierOrderFunctionInoutTest::testInit() { m_test_cases.resize(6); m_test_cases[0].push_back(Utils::QUAL_HIGHP); m_test_cases[0].push_back(Utils::QUAL_PRECISE); m_test_cases[0].push_back(Utils::QUAL_INOUT); m_test_cases[1].push_back(Utils::QUAL_INOUT); m_test_cases[1].push_back(Utils::QUAL_PRECISE); m_test_cases[1].push_back(Utils::QUAL_HIGHP); m_test_cases[2].push_back(Utils::QUAL_MEDIUMP); m_test_cases[2].push_back(Utils::QUAL_PRECISE); m_test_cases[2].push_back(Utils::QUAL_INOUT); m_test_cases[3].push_back(Utils::QUAL_INOUT); m_test_cases[3].push_back(Utils::QUAL_PRECISE); m_test_cases[3].push_back(Utils::QUAL_MEDIUMP); m_test_cases[4].push_back(Utils::QUAL_LOWP); m_test_cases[4].push_back(Utils::QUAL_PRECISE); m_test_cases[4].push_back(Utils::QUAL_INOUT); m_test_cases[5].push_back(Utils::QUAL_INOUT); m_test_cases[5].push_back(Utils::QUAL_PRECISE); m_test_cases[5].push_back(Utils::QUAL_LOWP); return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const Utils::qualifierSet& QualifierOrderFunctionInoutTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_test_cases[0]; } else { return m_test_cases[m_current_test_case_index]; } } /** Constructor * * @param context Test context **/ QualifierOrderFunctionInputTest::QualifierOrderFunctionInputTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_order_function_input", "Verify order of qualifiers of function input parameters") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool QualifierOrderFunctionInputTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { /* Nothing to be done here */ } else if (m_test_cases.size() <= test_case_index) { return false; } const Utils::qualifierSet& set = getCurrentTestCase(); tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < set.size(); ++i) { message << Utils::getQualifierString(set[i]) << " "; } message << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOrderFunctionInputTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " vec4 temp = function(VARIABLE_NAME);\n" "\n" " vec4 diff = temp - vec4(0, 0, 1, 1);\n" " if (false == all(lessThan(diff, vec4(0.001, 0.001, 0.001, 0.001))))\n" " {\n" " result = VARIABLE_NAME;\n" " }\n"; static const GLchar* function_declaration = "vec4 function(QUALIFIERS_LIST vec4 param)\n" "{\n" " return param.wzyx;\n" "}\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } const std::string& uni_reference = Utils::getVariableName(in_stage, Utils::UNIFORM, "test"); const std::string& qualifier_list = Utils::getQualifiersListString(getCurrentTestCase()); out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("FUNCTION_DECLARATION", position, function_declaration, out_source.m_parts[0].m_code); position -= strlen(function_declaration); Utils::replaceToken("QUALIFIERS_LIST", position, qualifier_list.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VARIABLE_NAME", uni_reference.c_str(), out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void QualifierOrderFunctionInputTest::prepareUniforms(Utils::program& program) { static const GLfloat float_data[4] = { 1.0f, 1.0f, 0.0f, 0.0f }; program.uniform("uni_fs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_gs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tcs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tes_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_vs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); } /** Prepare test cases * * @return false if ARB_explicit_uniform_location is not supported, true otherwise **/ bool QualifierOrderFunctionInputTest::testInit() { m_test_cases.resize(6); m_test_cases[0].push_back(Utils::QUAL_CONST); m_test_cases[0].push_back(Utils::QUAL_HIGHP); m_test_cases[0].push_back(Utils::QUAL_PRECISE); m_test_cases[0].push_back(Utils::QUAL_IN); m_test_cases[1].push_back(Utils::QUAL_IN); m_test_cases[1].push_back(Utils::QUAL_CONST); m_test_cases[1].push_back(Utils::QUAL_PRECISE); m_test_cases[1].push_back(Utils::QUAL_HIGHP); m_test_cases[2].push_back(Utils::QUAL_PRECISE); m_test_cases[2].push_back(Utils::QUAL_MEDIUMP); m_test_cases[2].push_back(Utils::QUAL_CONST); m_test_cases[2].push_back(Utils::QUAL_IN); m_test_cases[3].push_back(Utils::QUAL_IN); m_test_cases[3].push_back(Utils::QUAL_PRECISE); m_test_cases[3].push_back(Utils::QUAL_MEDIUMP); m_test_cases[3].push_back(Utils::QUAL_CONST); m_test_cases[4].push_back(Utils::QUAL_LOWP); m_test_cases[4].push_back(Utils::QUAL_CONST); m_test_cases[4].push_back(Utils::QUAL_IN); m_test_cases[4].push_back(Utils::QUAL_PRECISE); m_test_cases[5].push_back(Utils::QUAL_IN); m_test_cases[5].push_back(Utils::QUAL_PRECISE); m_test_cases[5].push_back(Utils::QUAL_CONST); m_test_cases[5].push_back(Utils::QUAL_LOWP); return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const Utils::qualifierSet& QualifierOrderFunctionInputTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_test_cases[0]; } else { return m_test_cases[m_current_test_case_index]; } } /** Constructor * * @param context Test context **/ QualifierOrderFunctionOutputTest::QualifierOrderFunctionOutputTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_order_function_output", "Verify order of qualifiers of output function parameters") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool QualifierOrderFunctionOutputTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { /* Nothing to be done here */ } else if (m_test_cases.size() <= test_case_index) { return false; } const Utils::qualifierSet& set = getCurrentTestCase(); tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; for (GLuint i = 0; i < set.size(); ++i) { message << Utils::getQualifierString(set[i]) << " "; } message << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOrderFunctionOutputTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " vec4 temp;\n" "\n" " function(temp);\n" "\n" " vec4 diff = temp - vec4(0, 0, 1, 1);\n" " if (false == all(lessThan(diff, vec4(0.001, 0.001, 0.001, 0.001))))\n" " {\n" " result = VARIABLE_NAME;\n" " }\n"; static const GLchar* function_declaration = "void function(QUALIFIERS_LIST vec4 param)\n" "{\n" " param = VARIABLE_NAME.wzyx;\n" "}\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "uniform vec4 VARIABLE_NAME;\n" "\n" "FUNCTION_DECLARATION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } const std::string& uni_reference = Utils::getVariableName(in_stage, Utils::UNIFORM, "test"); const std::string& qualifier_list = Utils::getQualifiersListString(getCurrentTestCase()); out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("FUNCTION_DECLARATION", position, function_declaration, out_source.m_parts[0].m_code); position -= strlen(function_declaration); Utils::replaceToken("QUALIFIERS_LIST", position, qualifier_list.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("VARIABLE_NAME", uni_reference.c_str(), out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void QualifierOrderFunctionOutputTest::prepareUniforms(Utils::program& program) { static const GLfloat float_data[4] = { 1.0f, 1.0f, 0.0f, 0.0f }; program.uniform("uni_fs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_gs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tcs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_tes_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); program.uniform("uni_vs_test", Utils::FLOAT, 1 /* n_cols */, 4 /* n_rows */, float_data); } /** Prepare test cases * * @return false if ARB_explicit_uniform_location is not supported, true otherwise **/ bool QualifierOrderFunctionOutputTest::testInit() { m_test_cases.resize(6); m_test_cases[0].push_back(Utils::QUAL_HIGHP); m_test_cases[0].push_back(Utils::QUAL_PRECISE); m_test_cases[0].push_back(Utils::QUAL_OUT); m_test_cases[1].push_back(Utils::QUAL_OUT); m_test_cases[1].push_back(Utils::QUAL_PRECISE); m_test_cases[1].push_back(Utils::QUAL_HIGHP); m_test_cases[2].push_back(Utils::QUAL_PRECISE); m_test_cases[2].push_back(Utils::QUAL_MEDIUMP); m_test_cases[2].push_back(Utils::QUAL_OUT); m_test_cases[3].push_back(Utils::QUAL_OUT); m_test_cases[3].push_back(Utils::QUAL_PRECISE); m_test_cases[3].push_back(Utils::QUAL_MEDIUMP); m_test_cases[4].push_back(Utils::QUAL_LOWP); m_test_cases[4].push_back(Utils::QUAL_OUT); m_test_cases[4].push_back(Utils::QUAL_PRECISE); m_test_cases[5].push_back(Utils::QUAL_OUT); m_test_cases[5].push_back(Utils::QUAL_PRECISE); m_test_cases[5].push_back(Utils::QUAL_LOWP); return true; } /** Returns reference to current test case * * @return Reference to testCase **/ const Utils::qualifierSet& QualifierOrderFunctionOutputTest::getCurrentTestCase() { if ((glw::GLuint)-1 == m_current_test_case_index) { return m_test_cases[0]; } else { return m_test_cases[m_current_test_case_index]; } } /** Constructor * * @param context Test context **/ QualifierOverrideLayoutTest::QualifierOverrideLayoutTest(deqp::Context& context) : GLSLTestBase(context, "qualifier_override_layout", "Verifies overriding layout qualifiers") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void QualifierOverrideLayoutTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in layout(location = 3) layout(location = 2) vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" " if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 2) layout(max_vertices = 4) out;\n" "\n" "in layout(location = 3) layout(location = 2) vec4 tes_gs_result[];\n" "out layout(location = 3) layout(location = 2) vec4 gs_fs_result;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" " if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 4) layout(vertices = 1) out;\n" "\n" "in layout(location = 3) layout(location = 2) vec4 vs_tcs_result[];\n" "out layout(location = 3) layout(location = 2) vec4 tcs_tes_result[];\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" " if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in layout(location = 3) layout(location = 2) vec4 tcs_tes_result[];\n" "out layout(location = 3) layout(location = 2) vec4 tes_gs_result;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" " if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "in layout(location = 3) layout(location = 2) vec4 in_vs_test;\n" "out layout(location = 3) layout(location = 2) vec4 vs_tcs_result;\n" "\n" "void main()\n" "{\n" " vec4 result = in_vs_test;\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: return; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); } /**Prepare vertex buffer and vertex array object. * * @param program Program instance * @param buffer Buffer instance * @param vao VertexArray instance * * @return 0 **/ void QualifierOverrideLayoutTest::prepareVertexBuffer(const Utils::program& program, Utils::buffer& buffer, Utils::vertexArray& vao) { static const GLint expected_location = 2; std::string test_name = Utils::getVariableName(Utils::VERTEX_SHADER, Utils::INPUT, "test"); GLint test_loc = program.getAttribLocation(test_name.c_str()); if (expected_location != test_loc) { TCU_FAIL("Vertex attribute location is invalid"); } vao.generate(); vao.bind(); buffer.generate(GL_ARRAY_BUFFER); GLfloat data[] = { 0.0f, 1.0f, 0.0f, 1.0f }; GLsizeiptr data_size = sizeof(data); buffer.update(data_size, data, GL_STATIC_DRAW); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up vao */ gl.vertexAttribPointer(test_loc, 4 /* size */, GL_FLOAT /* type */, GL_FALSE /* normalized*/, 0 /* stride */, 0 /* offset */); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer"); /* Enable attribute */ gl.enableVertexAttribArray(test_loc); GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray"); } /** Constructor * * @param context Test context **/ BindingUniformBlocksTest::BindingUniformBlocksTest(deqp::Context& context) : GLSLTestBase(context, "binding_uniform_blocks", "Test verifies uniform block binding") , m_goku_buffer(context) , m_vegeta_buffer(context) , m_children_buffer(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformBlocksTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(std140, binding = 0) uniform GOKU {\n" " vec4 chichi;\n" "} goku;\n"; static const GLchar* uni_vegeta = "layout(std140, binding = 1) uniform VEGETA {\n" " vec3 bulma;\n" "} vegeta;\n"; static const GLchar* uni_children = "layout(std140, binding = 3) uniform CHILDREN {\n" " vec4 gohan;\n" " vec4 trunks;\n" "} children;\n\n"; static const GLchar* verification_snippet = " if ((vec4(1, 0, 0, 0) != goku.chichi) ||\n" " (vec3(0, 1, 0) != vegeta.bulma) ||\n" " (vec4(0, 0, 1, 0) != children.gohan) ||\n" " (vec4(0, 0, 0, 1) != children.trunks) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "UNI_VEGETA\n" "UNI_CHILDREN\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "UNI_VEGETA\n" "UNI_CHILDREN\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_CHILDREN\n" "UNI_GOKU\n" "UNI_VEGETA\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_VEGETA\n" "UNI_CHILDREN\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "UNI_CHILDREN\n" "UNI_VEGETA\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_CHILDREN\n" "UNI_VEGETA\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_VEGETA", uni_vegeta, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_CHILDREN", uni_children, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingUniformBlocksTest::prepareUniforms(Utils::program& program) { (void)program; static const GLfloat goku_data[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; static const GLfloat vegeta_data[3] = { 0.0f, 1.0f, 0.0f }; static const GLfloat children_data[8] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; m_goku_buffer.generate(GL_UNIFORM_BUFFER); m_vegeta_buffer.generate(GL_UNIFORM_BUFFER); m_children_buffer.generate(GL_UNIFORM_BUFFER); m_goku_buffer.update(sizeof(goku_data), (GLvoid*)goku_data, GL_STATIC_DRAW); m_vegeta_buffer.update(sizeof(vegeta_data), (GLvoid*)vegeta_data, GL_STATIC_DRAW); m_children_buffer.update(sizeof(children_data), (GLvoid*)children_data, GL_STATIC_DRAW); m_goku_buffer.bindRange(0 /* index */, 0 /* offset */, sizeof(goku_data)); m_vegeta_buffer.bindRange(1 /* index */, 0 /* offset */, sizeof(vegeta_data)); m_children_buffer.bindRange(3 /* index */, 0 /* offset */, sizeof(children_data)); } /** Overwrite of releaseResource method, release extra uniform buffer * * @param ignored **/ void BindingUniformBlocksTest::releaseResource() { m_goku_buffer.release(); m_vegeta_buffer.release(); m_children_buffer.release(); } /** Constructor * * @param context Test context **/ BindingUniformSingleBlockTest::BindingUniformSingleBlockTest(deqp::Context& context) : GLSLTestBase(context, "binding_uniform_single_block", "Test verifies uniform block binding") , m_goku_buffer(context) , m_test_stage(Utils::SHADER_STAGES_MAX) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingUniformSingleBlockTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: case 0: m_test_stage = Utils::VERTEX_SHADER; break; case 1: m_test_stage = Utils::TESS_CTRL_SHADER; break; case 2: m_test_stage = Utils::TESS_EVAL_SHADER; break; case 3: m_test_stage = Utils::GEOMETRY_SHADER; break; case 4: m_test_stage = Utils::FRAGMENT_SHADER; break; default: return false; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tested stage: " << Utils::getShaderStageName((Utils::SHADER_STAGES)m_test_stage) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformSingleBlockTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku_with_binding = "layout(std140, binding = 0) uniform GOKU {\n" " vec4 gohan;\n" " vec4 goten;\n" "} goku;\n"; static const GLchar* uni_goku_no_binding = "layout(std140) uniform GOKU {\n" " vec4 gohan;\n" " vec4 goten;\n" "} goku;\n"; static const GLchar* verification_snippet = " if ((vec4(1, 0, 0, 0) != goku.gohan) ||\n" " (vec4(0, 1, 0, 0) != goku.goten) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* uniform_definition = uni_goku_no_binding; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; uniform_definition = uni_goku_with_binding; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } if (in_stage == m_test_stage) { uniform_definition = uni_goku_with_binding; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uniform_definition, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingUniformSingleBlockTest::prepareUniforms(Utils::program& program) { (void)program; static const GLfloat goku_data[8] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }; m_goku_buffer.generate(GL_UNIFORM_BUFFER); m_goku_buffer.update(sizeof(goku_data), (GLvoid*)goku_data, GL_STATIC_DRAW); m_goku_buffer.bindRange(0 /* index */, 0 /* offset */, sizeof(goku_data)); } /** Overwrite of releaseResource method, release extra uniform buffer * * @param ignored **/ void BindingUniformSingleBlockTest::releaseResource() { m_goku_buffer.release(); } /** Constructor * * @param context Test context **/ BindingUniformBlockArrayTest::BindingUniformBlockArrayTest(deqp::Context& context) : GLSLTestBase(context, "binding_uniform_block_array", "Test verifies binding of uniform block arrays") , m_goku_00_buffer(context) , m_goku_01_buffer(context) , m_goku_02_buffer(context) , m_goku_03_buffer(context) , m_goku_04_buffer(context) , m_goku_05_buffer(context) , m_goku_06_buffer(context) , m_goku_07_buffer(context) , m_goku_08_buffer(context) , m_goku_09_buffer(context) , m_goku_10_buffer(context) , m_goku_11_buffer(context) , m_goku_12_buffer(context) , m_goku_13_buffer(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformBlockArrayTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(std140, binding = 2) uniform GOKU {\n" " vec4 gohan;\n" " vec4 goten;\n" "} goku[14];\n"; static const GLchar* verification_snippet = " if ((vec4(0, 0, 0, 0) != goku[0].gohan) ||\n" " (vec4(0, 0, 0, 1) != goku[0].goten) ||\n" " (vec4(0, 0, 1, 0) != goku[1].gohan) ||\n" " (vec4(0, 0, 1, 1) != goku[1].goten) ||\n" " (vec4(0, 1, 0, 0) != goku[2].gohan) ||\n" " (vec4(0, 1, 0, 1) != goku[2].goten) ||\n" " (vec4(0, 1, 1, 0) != goku[3].gohan) ||\n" " (vec4(0, 1, 1, 1) != goku[3].goten) ||\n" " (vec4(1, 0, 0, 0) != goku[4].gohan) ||\n" " (vec4(1, 0, 0, 1) != goku[4].goten) ||\n" " (vec4(1, 0, 1, 0) != goku[5].gohan) ||\n" " (vec4(1, 0, 1, 1) != goku[5].goten) ||\n" " (vec4(1, 1, 0, 0) != goku[6].gohan) ||\n" " (vec4(1, 1, 0, 1) != goku[6].goten) ||\n" " (vec4(1, 1, 1, 0) != goku[7].gohan) ||\n" " (vec4(1, 1, 1, 1) != goku[7].goten) ||\n" " (vec4(0, 0, 0, 0) != goku[8].gohan) ||\n" " (vec4(0, 0, 0, 1) != goku[8].goten) ||\n" " (vec4(0, 0, 1, 0) != goku[9].gohan) ||\n" " (vec4(0, 0, 1, 1) != goku[9].goten) ||\n" " (vec4(0, 1, 0, 0) != goku[10].gohan) ||\n" " (vec4(0, 1, 0, 1) != goku[10].goten) ||\n" " (vec4(0, 1, 1, 0) != goku[11].gohan) ||\n" " (vec4(0, 1, 1, 1) != goku[11].goten) ||\n" " (vec4(1, 0, 0, 0) != goku[12].gohan) ||\n" " (vec4(1, 0, 0, 1) != goku[12].goten) ||\n" " (vec4(1, 0, 1, 0) != goku[13].gohan) ||\n" " (vec4(1, 0, 1, 1) != goku[13].goten) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingUniformBlockArrayTest::prepareUniforms(Utils::program& program) { static const GLfloat goku_data[][8] = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, { 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f } }; Utils::buffer* buffers[14] = { &m_goku_00_buffer, &m_goku_01_buffer, &m_goku_02_buffer, &m_goku_03_buffer, &m_goku_04_buffer, &m_goku_05_buffer, &m_goku_06_buffer, &m_goku_07_buffer, &m_goku_08_buffer, &m_goku_09_buffer, &m_goku_10_buffer, &m_goku_11_buffer, &m_goku_12_buffer, &m_goku_13_buffer }; for (GLuint i = 0; i < 14; ++i) { checkBinding(program, i, i + 2); buffers[i]->generate(GL_UNIFORM_BUFFER); buffers[i]->update(sizeof(GLfloat) * 8, (GLvoid*)goku_data[i], GL_STATIC_DRAW); buffers[i]->bindRange(i + 2 /* index */, 0 /* offset */, sizeof(GLfloat) * 8); } } /** Overwrite of releaseResource method, release extra uniform buffer * * @param ignored **/ void BindingUniformBlockArrayTest::releaseResource() { Utils::buffer* buffers[14] = { &m_goku_00_buffer, &m_goku_01_buffer, &m_goku_02_buffer, &m_goku_03_buffer, &m_goku_04_buffer, &m_goku_05_buffer, &m_goku_06_buffer, &m_goku_07_buffer, &m_goku_08_buffer, &m_goku_09_buffer, &m_goku_10_buffer, &m_goku_11_buffer, &m_goku_12_buffer, &m_goku_13_buffer }; for (GLuint i = 0; i < 14; ++i) { buffers[i]->release(); } } /** Verifies that API reports correct uniform binding * * @param program Program * @param index Index of array element * @param expected_binding Expected binding **/ void BindingUniformBlockArrayTest::checkBinding(Utils::program& program, glw::GLuint index, glw::GLint expected_binding) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLchar buffer[64]; sprintf(buffer, "GOKU[%d]", index); const GLuint uniform_index = gl.getUniformBlockIndex(program.m_program_object_id, buffer); GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex"); if (GL_INVALID_INDEX == uniform_index) { TCU_FAIL("Uniform block is inactive"); } GLint binding = -1; gl.getActiveUniformBlockiv(program.m_program_object_id, uniform_index, GL_UNIFORM_BLOCK_BINDING, &binding); GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv"); if (expected_binding != binding) { TCU_FAIL("Wrong binding reported by API"); } } /** Constructor * * @param context Test context **/ BindingUniformDefaultTest::BindingUniformDefaultTest(deqp::Context& context) : APITestBase(context, "binding_uniform_default", "Test verifies default binding of uniform block") { /* Nothing to be done here */ } /** Execute API call and verifies results * * @return true when results are positive, false otherwise **/ bool BindingUniformDefaultTest::checkResults(Utils::program& program) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); const GLuint index = gl.getUniformBlockIndex(program.m_program_object_id, "GOKU"); GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex"); if (GL_INVALID_INDEX == index) { TCU_FAIL("Uniform block is inactive"); return false; } GLint binding = -1; gl.getActiveUniformBlockiv(program.m_program_object_id, index, GL_UNIFORM_BLOCK_BINDING, &binding); GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv"); if (0 != binding) { return false; } return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformDefaultTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(std140) uniform GOKU {\n" " vec4 gohan;\n" " vec4 goten;\n" "} goku;\n"; static const GLchar* verification_snippet = " if ((vec4(0, 0, 0, 0) != goku.gohan) ||\n" " (vec4(0, 0, 0, 1) != goku.goten) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ BindingUniformAPIOverirdeTest::BindingUniformAPIOverirdeTest(deqp::Context& context) : GLSLTestBase(context, "binding_uniform_api_overirde", "Test verifies if binding can be overriden with API") , m_goku_buffer(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformAPIOverirdeTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(std140, binding = 2) uniform GOKU {\n" " vec4 gohan;\n" " vec4 goten;\n" "} goku;\n"; static const GLchar* verification_snippet = " if ((vec4(1, 0, 0, 0) != goku.gohan) ||\n" " (vec4(0, 1, 0, 0) != goku.goten) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingUniformAPIOverirdeTest::prepareUniforms(Utils::program& program) { static const GLfloat goku_data[8] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }; static const GLuint new_binding = 11; const glw::Functions& gl = m_context.getRenderContext().getFunctions(); const GLuint index = gl.getUniformBlockIndex(program.m_program_object_id, "GOKU"); GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex"); if (GL_INVALID_INDEX == index) { TCU_FAIL("Uniform block is inactive"); return; } gl.uniformBlockBinding(program.m_program_object_id, index, new_binding); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding"); GLint binding = -1; gl.getActiveUniformBlockiv(program.m_program_object_id, index, GL_UNIFORM_BLOCK_BINDING, &binding); GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv"); if (new_binding != binding) { TCU_FAIL("GetActiveUniformBlockiv returned wrong binding"); return; } m_goku_buffer.generate(GL_UNIFORM_BUFFER); m_goku_buffer.update(sizeof(GLfloat) * 8, (GLvoid*)goku_data, GL_STATIC_DRAW); m_goku_buffer.bindRange(new_binding /* index */, 0 /* offset */, sizeof(GLfloat) * 8); } /** Overwrite of releaseResource method, release extra uniform buffer * * @param ignored **/ void BindingUniformAPIOverirdeTest::releaseResource() { m_goku_buffer.release(); } /** Constructor * * @param context Test context **/ BindingUniformGlobalBlockTest::BindingUniformGlobalBlockTest(deqp::Context& context) : NegativeTestBase(context, "binding_uniform_global_block", "Test verifies that global uniform cannot be qualified with binding") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformGlobalBlockTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " if (vec4(0, 0, 1, 1) != uni_test)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* uniform_definition = "layout(binding = 0) uniform vec4 uni_test;\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("UNIFORM_DEFINITION", position, uniform_definition, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ BindingUniformInvalidTest::BindingUniformInvalidTest(deqp::Context& context) : NegativeTestBase(context, "binding_uniform_invalid", "Test verifies invalid binding values") , m_case(TEST_CASES_MAX) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingUniformInvalidTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: m_case = TEST_CASES_MAX; break; case NEGATIVE_VALUE: case VARIABLE_NAME: case STD140: case MISSING: m_case = (TESTCASES)test_case_index; break; default: return false; } return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingUniformInvalidTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " if (vec4(0, 0, 1, 1) != goku.gohan)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* uniform_definition = "layout(std140, binding BINDING) uniform GOKU {\n" " vec4 gohan;\n" " vec4 goten;\n" "} goku;\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNIFORM_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("UNIFORM_DEFINITION", position, uniform_definition, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("BINDING", getCaseString(m_case), out_source.m_parts[0].m_code); } const GLchar* BindingUniformInvalidTest::getCaseString(TESTCASES test_case) { (void)test_case; const GLchar* binding = 0; switch (m_case) { case NEGATIVE_VALUE: binding = "= -1"; break; case VARIABLE_NAME: binding = "= goku"; break; case STD140: binding = "= std140"; break; case MISSING: binding = ""; break; case TEST_CASES_MAX: binding = "= 0"; break; default: TCU_FAIL("Invalid enum"); } return binding; } /** Constructor * * @param context Test context **/ BindingSamplersTest::BindingSamplersTest(deqp::Context& context) : GLSLTestBase(context, "binding_samplers", "Test verifies smaplers binding") , m_goku_texture(context) , m_vegeta_texture(context) , m_trunks_texture(context) , m_buffer(context) , m_test_case(Utils::TEXTURE_TYPES_MAX) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingSamplersTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: case 0: m_test_case = Utils::TEX_2D; break; case 1: m_test_case = Utils::TEX_BUFFER; break; case 2: m_test_case = Utils::TEX_2D_RECT; break; case 3: m_test_case = Utils::TEX_2D_ARRAY; break; case 4: m_test_case = Utils::TEX_3D; break; case 5: m_test_case = Utils::TEX_CUBE; break; case 6: m_test_case = Utils::TEX_1D; break; case 7: m_test_case = Utils::TEX_1D_ARRAY; break; default: return false; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tested texture type: " << Utils::getTextureTypeName(m_test_case) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingSamplersTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding = 0) uniform TYPE goku;\n"; static const GLchar* uni_vegeta = "layout(binding = 1) uniform TYPE vegeta;\n"; static const GLchar* uni_trunks = "layout(binding = 3) uniform TYPE trunks;\n\n"; static const GLchar* verification_snippet = " TEX_COORD_TYPE tex_coord = TEX_COORD_TYPE(COORDINATES);\n" " vec4 goku_color = SAMPLING_FUNCTION(goku, tex_coord);\n" " vec4 vegeta_color = SAMPLING_FUNCTION(vegeta, tex_coord);\n" " vec4 trunks_color = SAMPLING_FUNCTION(trunks, tex_coord);\n" "\n" " if ((vec4(1, 0, 0, 0) != goku_color) ||\n" " (vec4(0, 1, 0, 0) != vegeta_color) ||\n" " (vec4(0, 0, 1, 0) != trunks_color) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "UNI_VEGETA\n" "UNI_TRUNKS\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "UNI_VEGETA\n" "UNI_TRUNKS\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_TRUNKS\n" "UNI_GOKU\n" "UNI_VEGETA\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_VEGETA\n" "UNI_TRUNKS\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "UNI_TRUNKS\n" "UNI_VEGETA\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_TRUNKS\n" "UNI_VEGETA\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const Utils::TYPES base_tex_coord_type = (Utils::TEX_BUFFER == m_test_case) ? Utils::INT : Utils::FLOAT; const GLchar* coordinates = 0; GLuint n_coordinates = Utils::getNumberOfCoordinates(m_test_case); const GLchar* shader_template = 0; const GLchar* sampler_type = Utils::getSamplerType(m_test_case); const GLchar* sampling_function = (Utils::TEX_BUFFER == m_test_case) ? "texelFetch" : "texture"; const GLchar* tex_coord_type = Utils::getTypeName(base_tex_coord_type, 1 /* n_columns */, n_coordinates); switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } switch (n_coordinates) { case 1: coordinates = "0"; break; case 2: coordinates = "0, 0"; break; case 3: coordinates = "0, 0, 0"; break; case 4: coordinates = "0, 0, 0, 0"; break; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position -= strlen(verification_snippet); Utils::replaceToken("COORDINATES", position, coordinates, out_source.m_parts[0].m_code); Utils::replaceAllTokens("SAMPLING_FUNCTION", sampling_function, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_VEGETA", uni_vegeta, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_TRUNKS", uni_trunks, out_source.m_parts[0].m_code); Utils::replaceAllTokens("TEX_COORD_TYPE", tex_coord_type, out_source.m_parts[0].m_code); Utils::replaceAllTokens("TYPE", sampler_type, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingSamplersTest::prepareUniforms(Utils::program& program) { (void)program; static const GLuint goku_data = 0x000000ff; static const GLuint vegeta_data = 0x0000ff00; static const GLuint trunks_data = 0x00ff0000; prepareTexture(m_goku_texture, m_test_case, goku_data); prepareTexture(m_vegeta_texture, m_test_case, vegeta_data); prepareTexture(m_trunks_texture, m_test_case, trunks_data); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.activeTexture(GL_TEXTURE0); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); m_goku_texture.bind(); gl.activeTexture(GL_TEXTURE1); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); m_vegeta_texture.bind(); gl.activeTexture(GL_TEXTURE3); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); m_trunks_texture.bind(); } /** Overwrite of releaseResource method, release extra buffer and texture * * @param ignored **/ void BindingSamplersTest::releaseResource() { m_goku_texture.release(); m_vegeta_texture.release(); m_trunks_texture.release(); m_buffer.release(); } /** Prepare texture of given type filled with given color * * @param texture Texture * @param texture_type Type of texture * @param color Color **/ void BindingSamplersTest::prepareTexture(Utils::texture& texture, Utils::TEXTURE_TYPES texture_type, glw::GLuint color) { (void)texture_type; static const GLuint width = 16; static const GLuint height = 16; static const GLuint depth = 1; std::vector texture_data; texture_data.resize(width * height); for (GLuint i = 0; i < texture_data.size(); ++i) { texture_data[i] = color; } if (Utils::TEX_BUFFER != m_test_case) { texture.create(width, height, depth, GL_RGBA8, m_test_case); texture.update(width, height, depth, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); } else { m_buffer.generate(GL_TEXTURE_BUFFER); m_buffer.update(texture_data.size(), &texture_data[0], GL_STATIC_DRAW); texture.createBuffer(GL_RGBA8, m_buffer.m_id); } } /** Constructor * * @param context Test context **/ BindingSamplerSingleTest::BindingSamplerSingleTest(deqp::Context& context) : GLSLTestBase(context, "binding_sampler_single", "Test verifies sampler binding"), m_goku_texture(context) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingSamplerSingleTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: case 0: m_test_stage = Utils::VERTEX_SHADER; break; case 1: m_test_stage = Utils::TESS_CTRL_SHADER; break; case 2: m_test_stage = Utils::TESS_EVAL_SHADER; break; case 3: m_test_stage = Utils::GEOMETRY_SHADER; break; case 4: m_test_stage = Utils::FRAGMENT_SHADER; break; default: return false; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tested stage: " << Utils::getShaderStageName((Utils::SHADER_STAGES)m_test_stage) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingSamplerSingleTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku_with_binding = "layout(binding = 2) uniform sampler2D goku;\n"; static const GLchar* uni_goku_no_binding = "uniform sampler2D goku;\n"; static const GLchar* verification_snippet = " vec4 goku_color = texture(goku, vec2(0,0));\n" "\n" " if (vec4(1, 0, 0, 0) != goku_color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* uniform_definition = uni_goku_no_binding; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; uniform_definition = uni_goku_with_binding; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } if (in_stage == m_test_stage) { uniform_definition = uni_goku_with_binding; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uniform_definition, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingSamplerSingleTest::prepareUniforms(Utils::program& program) { (void)program; static const GLuint goku_data = 0x000000ff; m_goku_texture.create(16, 16, GL_RGBA8); std::vector texture_data; texture_data.resize(16 * 16); for (GLuint i = 0; i < texture_data.size(); ++i) { texture_data[i] = goku_data; } m_goku_texture.update(16, 16, 0 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.activeTexture(GL_TEXTURE2); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); m_goku_texture.bind(); } /** Overwrite of releaseResource method, release extra texture * * @param ignored **/ void BindingSamplerSingleTest::releaseResource() { m_goku_texture.release(); } /** Constructor * * @param context Test context **/ BindingSamplerArrayTest::BindingSamplerArrayTest(deqp::Context& context) : GLSLTestBase(context, "binding_sampler_array", "Test verifies binding of sampler arrays") , m_goku_00_texture(context) , m_goku_01_texture(context) , m_goku_02_texture(context) , m_goku_03_texture(context) , m_goku_04_texture(context) , m_goku_05_texture(context) , m_goku_06_texture(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingSamplerArrayTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding = 1) uniform sampler2D goku[7];\n"; static const GLchar* verification_snippet = " vec4 color[7];\n" "\n" " for (uint i = 0u; i < 7; ++i)\n" " {\n" " color[i] = texture(goku[i], vec2(0, 0));\n" " }\n" "\n" " if ((vec4(0, 0, 0, 0) != color[0]) ||\n" " (vec4(0, 0, 0, 1) != color[1]) ||\n" " (vec4(0, 0, 1, 0) != color[2]) ||\n" " (vec4(0, 0, 1, 1) != color[3]) ||\n" " (vec4(0, 1, 0, 0) != color[4]) ||\n" " (vec4(0, 1, 0, 1) != color[5]) ||\n" " (vec4(0, 1, 1, 0) != color[6]) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingSamplerArrayTest::prepareUniforms(Utils::program& program) { static const GLuint goku_data[7] = { 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, }; static const GLuint binding_offset = 1; Utils::texture* textures[7] = { &m_goku_00_texture, &m_goku_01_texture, &m_goku_02_texture, &m_goku_03_texture, &m_goku_04_texture, &m_goku_05_texture, &m_goku_06_texture, }; std::vector texture_data; texture_data.resize(16 * 16); const glw::Functions& gl = m_context.getRenderContext().getFunctions(); for (GLuint i = 0; i < 7; ++i) { GLint expected_binding = i + binding_offset; checkBinding(program, i, expected_binding); gl.activeTexture(GL_TEXTURE0 + expected_binding); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); textures[i]->create(16, 16, GL_RGBA8); for (GLuint j = 0; j < texture_data.size(); ++j) { texture_data[j] = goku_data[i]; } textures[i]->update(16, 16, 0 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); } } /** Overwrite of releaseResource method, release extra textures * * @param ignored **/ void BindingSamplerArrayTest::releaseResource() { Utils::texture* textures[7] = { &m_goku_00_texture, &m_goku_01_texture, &m_goku_02_texture, &m_goku_03_texture, &m_goku_04_texture, &m_goku_05_texture, &m_goku_06_texture, }; for (GLuint i = 0; i < 7; ++i) { textures[i]->release(); } } /** Verifies that API reports correct uniform binding * * @param program Program * @param index Index of array element * @param expected_binding Expected binding **/ void BindingSamplerArrayTest::checkBinding(Utils::program& program, GLuint index, GLint expected_binding) { if (false == Utils::checkUniformArrayBinding(program, "goku", index, expected_binding)) { TCU_FAIL("Wrong binding reported by API"); } } /** Constructor * * @param context Test context **/ BindingSamplerDefaultTest::BindingSamplerDefaultTest(deqp::Context& context) : APITestBase(context, "binding_sampler_default", "Test verifies default sampler binding") { /* Nothing to be done here */ } /** Execute API call and verifies results * * @return true when results are positive, false otherwise **/ bool BindingSamplerDefaultTest::checkResults(Utils::program& program) { return Utils::checkUniformBinding(program, "goku", 0 /* expected_binding */); } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingSamplerDefaultTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "uniform sampler2D goku;\n"; static const GLchar* verification_snippet = " vec4 color = texture(goku, vec2(0,0));\n" " if (vec4(1, 0, 0, 0) != color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ BindingSamplerAPIOverrideTest::BindingSamplerAPIOverrideTest(deqp::Context& context) : GLSLTestBase(context, "binding_sampler_api_override", "Verifies that API can override sampler binding") , m_goku_texture(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingSamplerAPIOverrideTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding = 2) uniform sampler2D goku;\n"; static const GLchar* verification_snippet = " vec4 color = texture(goku, vec2(0,0));\n" " if (vec4(1, 0, 0, 0) != color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingSamplerAPIOverrideTest::prepareUniforms(Utils::program& program) { static const GLuint goku_data = 0x000000ff; static const GLint new_binding = 11; const glw::Functions& gl = m_context.getRenderContext().getFunctions(); const GLint uniform_location = program.getUniformLocation("goku"); if (-1 == uniform_location) { TCU_FAIL("Uniform is inactive"); } gl.uniform1i(uniform_location, new_binding); GLint binding = -1; gl.getUniformiv(program.m_program_object_id, uniform_location, &binding); GLU_EXPECT_NO_ERROR(gl.getError(), "getUniformiv"); if (new_binding != binding) { TCU_FAIL("Wrong binding value"); return; } m_goku_texture.create(16, 16, GL_RGBA8); std::vector texture_data; texture_data.resize(16 * 16); for (GLuint i = 0; i < texture_data.size(); ++i) { texture_data[i] = goku_data; } m_goku_texture.update(16, 16, 0 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]); gl.activeTexture(GL_TEXTURE11); GLU_EXPECT_NO_ERROR(gl.getError(), "ActiveTexture"); m_goku_texture.bind(); } /** Overwrite of releaseResource method, release extra texture * * @param ignored **/ void BindingSamplerAPIOverrideTest::releaseResource() { m_goku_texture.release(); } /** Constructor * * @param context Test context **/ BindingSamplerInvalidTest::BindingSamplerInvalidTest(deqp::Context& context) : NegativeTestBase(context, "binding_sampler_invalid", "Test verifies invalid binding values") { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingSamplerInvalidTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: m_case = TEST_CASES_MAX; break; case NEGATIVE_VALUE: case VARIABLE_NAME: case STD140: case MISSING: m_case = (TESTCASES)test_case_index; break; default: return false; } return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingSamplerInvalidTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding BINDING) uniform sampler2D goku;\n"; static const GLchar* verification_snippet = " vec4 color = texture(goku, vec2(0,0));\n" " if (vec4(1, 0, 0, 0) != color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); Utils::replaceAllTokens("BINDING", getCaseString(m_case), out_source.m_parts[0].m_code); } const GLchar* BindingSamplerInvalidTest::getCaseString(TESTCASES test_case) { (void)test_case; const GLchar* binding = 0; switch (m_case) { case NEGATIVE_VALUE: binding = "= -1"; break; case VARIABLE_NAME: binding = "= goku"; break; case STD140: binding = "= std140"; break; case MISSING: binding = ""; break; case TEST_CASES_MAX: binding = "= 0"; break; default: TCU_FAIL("Invalid enum"); } return binding; } /* Constants used by BindingImagesTest */ const GLuint BindingImagesTest::m_goku_data = 0x000000ff; const GLuint BindingImagesTest::m_vegeta_data = 0x0000ff00; const GLuint BindingImagesTest::m_trunks_data = 0x00ff0000; /** Constructor * * @param context Test context **/ BindingImagesTest::BindingImagesTest(deqp::Context& context) : BindingImageTest(context, "binding_images", "Test verifies binding of images") , m_goku_texture(context) , m_vegeta_texture(context) , m_trunks_texture(context) , m_goku_buffer(context) , m_vegeta_buffer(context) , m_trunks_buffer(context) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingImagesTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: case 0: m_test_case = Utils::TEX_2D; break; case 1: m_test_case = Utils::TEX_BUFFER; break; case 2: m_test_case = Utils::TEX_2D_RECT; break; case 3: m_test_case = Utils::TEX_2D_ARRAY; break; case 4: m_test_case = Utils::TEX_3D; break; case 5: m_test_case = Utils::TEX_CUBE; break; case 6: m_test_case = Utils::TEX_1D; break; case 7: m_test_case = Utils::TEX_1D_ARRAY; break; default: return false; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tested texture type: " << Utils::getTextureTypeName(m_test_case) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingImagesTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding = 1, rgba8) uniform TYPE goku;\n"; static const GLchar* uni_vegeta = "layout(binding = 2, rgba8) uniform TYPE vegeta;\n"; static const GLchar* uni_trunks = "layout(binding = 4, rgba8) uniform TYPE trunks;\n\n"; static const GLchar* verification_snippet = " TEX_COORD_TYPE tex_coord_read = TEX_COORD_TYPE(COORDINATES);\n" " TEX_COORD_TYPE tex_coord_write = TEX_COORD_TYPE(COORDINATES);\n" " vec4 goku_color = imageLoad(goku, tex_coord_read);\n" " vec4 vegeta_color = imageLoad(vegeta, tex_coord_read);\n" " vec4 trunks_color = imageLoad(trunks, tex_coord_read);\n" "\n" " imageStore(goku, tex_coord_write, vec4(0, 1, 0, 1));\n" " imageStore(vegeta, tex_coord_write, vec4(0, 1, 0, 1));\n" " imageStore(trunks, tex_coord_write, vec4(0, 1, 0, 1));\n" "\n" " if ((vec4(1, 0, 0, 0) != goku_color) ||\n" " (vec4(0, 1, 0, 0) != vegeta_color) ||\n" " (vec4(0, 0, 1, 0) != trunks_color) )\n" " {\n" " result = goku_color;\n" " //result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "UNI_VEGETA\n" "UNI_TRUNKS\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" " if(gl_GlobalInvocationID.xy == vec2(0, 0)) {\n" "VERIFICATION" " }\n" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "UNI_VEGETA\n" "UNI_TRUNKS\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "#if IMAGES\n" "UNI_TRUNKS\n" "UNI_GOKU\n" "UNI_VEGETA\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "#if IMAGES\n" "UNI_VEGETA\n" "UNI_TRUNKS\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "UNI_TRUNKS\n" "UNI_VEGETA\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "#if IMAGES\n" "UNI_TRUNKS\n" "UNI_VEGETA\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION" "#endif\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* coordinates_read = 0; const GLchar* coordinates_write = 0; const GLchar* image_type = Utils::getImageType(m_test_case); GLuint n_coordinates = Utils::getNumberOfCoordinates(m_test_case); const GLchar* shader_template = 0; const GLchar* tex_coord_type = Utils::getTypeName(Utils::INT, 1 /* n_columns */, n_coordinates); switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } switch (n_coordinates) { case 1: coordinates_read = "1"; coordinates_write = "0"; break; case 2: coordinates_read = "1, 0"; coordinates_write = "0, 0"; break; case 3: coordinates_read = "1, 0, 0"; coordinates_write = "0, 0, 0"; break; case 4: coordinates_read = "1, 0, 0, 0"; coordinates_write = "0, 0, 0, 0"; break; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position -= strlen(verification_snippet); Utils::replaceToken("COORDINATES", position, coordinates_read, out_source.m_parts[0].m_code); Utils::replaceToken("COORDINATES", position, coordinates_write, out_source.m_parts[0].m_code); Utils::replaceAllTokens("IMAGES", maxImageUniforms(in_stage) > 0 ? "1" : "0", out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_VEGETA", uni_vegeta, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_TRUNKS", uni_trunks, out_source.m_parts[0].m_code); Utils::replaceAllTokens("TEX_COORD_TYPE", tex_coord_type, out_source.m_parts[0].m_code); Utils::replaceAllTokens("TYPE", image_type, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingImagesTest::prepareUniforms(Utils::program& program) { (void)program; prepareBuffer(m_goku_buffer, m_goku_data); prepareBuffer(m_vegeta_buffer, m_vegeta_data); prepareBuffer(m_trunks_buffer, m_trunks_data); prepareTexture(m_goku_texture, m_goku_buffer, m_test_case, m_goku_data, 1); prepareTexture(m_vegeta_texture, m_vegeta_buffer, m_test_case, m_vegeta_data, 2); prepareTexture(m_trunks_texture, m_trunks_buffer, m_test_case, m_trunks_data, 4); } /** Overwrite of releaseResource method, release extra buffers and textures * * @param ignored **/ void BindingImagesTest::releaseResource() { m_goku_texture.release(); m_vegeta_texture.release(); m_trunks_texture.release(); if (m_test_case != Utils::TEX_BUFFER) { m_goku_buffer.release(); m_vegeta_buffer.release(); m_trunks_buffer.release(); } } /** Verify that all images have green texel at [0,0,0,0] * * @return true texel is green, false otherwise **/ bool BindingImagesTest::verifyAdditionalResults() const { if (Utils::TEX_BUFFER != m_test_case) { return (verifyTexture(m_goku_texture) && verifyTexture(m_vegeta_texture) && verifyTexture(m_trunks_texture)); } else { return (verifyBuffer(m_goku_buffer) && verifyBuffer(m_vegeta_buffer) && verifyBuffer(m_trunks_buffer)); } } /** Constructor * * @param context Test context **/ BindingImageSingleTest::BindingImageSingleTest(deqp::Context& context) : BindingImageTest(context, "binding_image_single", "Test verifies single binding of image used in multiple stages") , m_goku_texture(context) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingImageSingleTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: case 0: m_test_stage = Utils::VERTEX_SHADER; break; case 1: m_test_stage = Utils::TESS_CTRL_SHADER; break; case 2: m_test_stage = Utils::TESS_EVAL_SHADER; break; case 3: m_test_stage = Utils::GEOMETRY_SHADER; break; case 4: m_test_stage = Utils::FRAGMENT_SHADER; break; default: return false; } m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tested stage: " << Utils::getShaderStageName((Utils::SHADER_STAGES)m_test_stage) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingImageSingleTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku_with_binding = "layout(binding = 2, rgba8) uniform image2D goku;\n"; static const GLchar* uni_goku_no_binding = "layout(rgba8) uniform image2D goku;\n"; static const GLchar* verification_snippet = " vec4 goku_color = imageLoad(goku, ivec2(0,1));\n" "\n" " imageStore(goku, ivec2(0,0), vec4(0, 1, 0, 1));\n" "\n" " if (vec4(1, 0, 0, 0) != goku_color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION" "#endif\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* uniform_definition = uni_goku_no_binding; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; uniform_definition = uni_goku_with_binding; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; /* We can't rely on the binding qualifier being present in m_test_stage * if images are unsupported in that stage. */ if (maxImageUniforms(m_test_stage) == 0) uniform_definition = uni_goku_with_binding; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } if (in_stage == m_test_stage) { uniform_definition = uni_goku_with_binding; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("IMAGES", maxImageUniforms(in_stage) > 0 ? "1" : "0", out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uniform_definition, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingImageSingleTest::prepareUniforms(Utils::program& program) { (void)program; static const GLuint goku_data = 0x000000ff; prepareTexture(m_goku_texture, Utils::buffer(m_context), Utils::TEX_2D, goku_data, 2 /* unit */); } /** Overwrite of releaseResource method, release extra texture * * @param ignored **/ void BindingImageSingleTest::releaseResource() { m_goku_texture.release(); } /** Verify that all images have green texel at [0,0,0,0] * * @return true texel is green, false otherwise **/ bool BindingImageSingleTest::verifyAdditionalResults() const { return verifyTexture(m_goku_texture); } /** Constructor * * @param context Test context **/ BindingImageArrayTest::BindingImageArrayTest(deqp::Context& context) : BindingImageTest(context, "binding_image_array", "Test verifies binding of image array") , m_goku_00_texture(context) , m_goku_01_texture(context) , m_goku_02_texture(context) , m_goku_03_texture(context) , m_goku_04_texture(context) , m_goku_05_texture(context) , m_goku_06_texture(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingImageArrayTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding = 1, rgba8) uniform image2D goku[7];\n"; static const GLchar* verification_snippet = " vec4 color[7];\n" "\n" " for (uint i = 0u; i < 7; ++i)\n" " {\n" " color[i] = imageLoad(goku[i], ivec2(0,0));\n" " }\n" "\n" " if ((vec4(0, 0, 0, 0) != color[0]) ||\n" " (vec4(0, 0, 0, 1) != color[1]) ||\n" " (vec4(0, 0, 1, 0) != color[2]) ||\n" " (vec4(0, 0, 1, 1) != color[3]) ||\n" " (vec4(0, 1, 0, 0) != color[4]) ||\n" " (vec4(0, 1, 0, 1) != color[5]) ||\n" " (vec4(0, 1, 1, 0) != color[6]) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION" "#endif\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("IMAGES", maxImageUniforms(in_stage) > 0 ? "1" : "0", out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingImageArrayTest::prepareUniforms(Utils::program& program) { static const GLuint goku_data[7] = { 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, 0x0000ff00, 0xff00ff00, 0x00ffff00, }; Utils::texture* textures[7] = { &m_goku_00_texture, &m_goku_01_texture, &m_goku_02_texture, &m_goku_03_texture, &m_goku_04_texture, &m_goku_05_texture, &m_goku_06_texture, }; for (GLuint i = 0; i < 7; ++i) { GLint expected_binding = i + 1; checkBinding(program, i, expected_binding); prepareTexture(*textures[i], Utils::buffer(m_context), Utils::TEX_2D, goku_data[i], expected_binding); } } /** Overwrite of releaseResource method, release extra textures * * @param ignored **/ void BindingImageArrayTest::releaseResource() { Utils::texture* textures[7] = { &m_goku_00_texture, &m_goku_01_texture, &m_goku_02_texture, &m_goku_03_texture, &m_goku_04_texture, &m_goku_05_texture, &m_goku_06_texture, }; for (GLuint i = 0; i < 7; ++i) { textures[i]->release(); } } /** Verifies that API reports correct uniform binding * * @param program Program * @param index Index of array element * @param expected_binding Expected binding **/ void BindingImageArrayTest::checkBinding(Utils::program& program, GLuint index, GLint expected_binding) { if (false == Utils::checkUniformArrayBinding(program, "goku", index, expected_binding)) { TCU_FAIL("Wrong binding reported by API"); } } /** Constructor * * @param context Test context **/ BindingImageDefaultTest::BindingImageDefaultTest(deqp::Context& context) : APITestBase(context, "binding_image_default", "Test verifies default image binding") { /* Nothing to be done here */ } /** Execute API call and verifies results * * @return true when results are positive, false otherwise **/ bool BindingImageDefaultTest::checkResults(Utils::program& program) { return Utils::checkUniformBinding(program, "goku", 0 /* expected_binding */); } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingImageDefaultTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(rgba8) uniform image2D goku;\n"; static const GLchar* verification_snippet = " vec4 goku_color = imageLoad(goku, ivec2(0,0));\n" "\n" " if (vec4(1, 0, 0, 0) != goku_color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION" "#endif\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("IMAGES", maxImageUniforms(in_stage) > 0 ? "1" : "0", out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ BindingImageAPIOverrideTest::BindingImageAPIOverrideTest(deqp::Context& context) : BindingImageTest(context, "binding_image_api_override", "Verifies that API can override image binding") , m_goku_texture(context) { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingImageAPIOverrideTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding = 3, rgba8) uniform image2D goku;\n"; static const GLchar* verification_snippet = " vec4 goku_color = imageLoad(goku, ivec2(0,0));\n" "\n" " if (vec4(1, 0, 0, 0) != goku_color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION else\n" "#endif\n" " if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "#if IMAGES\n" "UNI_GOKU\n" "#endif\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "#if IMAGES\n" "VERIFICATION" "#endif\n" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("IMAGES", maxImageUniforms(in_stage) > 0 ? "1" : "0", out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method, set up values for unit_left and unit_right * * @param program Current program **/ void BindingImageAPIOverrideTest::prepareUniforms(Utils::program& program) { static const GLuint goku_data = 0x000000ff; static const GLint new_binding = 7; const glw::Functions& gl = m_context.getRenderContext().getFunctions(); const GLint uniform_location = program.getUniformLocation("goku"); if (-1 == uniform_location) { TCU_FAIL("Uniform is inactive"); } gl.uniform1i(uniform_location, new_binding); GLint binding = -1; gl.getUniformiv(program.m_program_object_id, uniform_location, &binding); GLU_EXPECT_NO_ERROR(gl.getError(), "getUniformiv"); if (new_binding != binding) { TCU_FAIL("Wrong binding value"); return; } prepareTexture(m_goku_texture, Utils::buffer(m_context), Utils::TEX_2D, goku_data, new_binding); } /** Overwrite of releaseResource method, release extra texture * * @param ignored **/ void BindingImageAPIOverrideTest::releaseResource() { m_goku_texture.release(); } /** Constructor * * @param context Test context **/ BindingImageInvalidTest::BindingImageInvalidTest(deqp::Context& context) : NegativeTestBase(context, "binding_image_invalid", "Test verifies invalid binding values") { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BindingImageInvalidTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: m_case = TEST_CASES_MAX; break; case NEGATIVE_VALUE: case VARIABLE_NAME: case STD140: case MISSING: m_case = (TESTCASES)test_case_index; break; default: return false; } return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BindingImageInvalidTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uni_goku = "layout(binding BINDING, rgba8) uniform image2D goku;\n"; static const GLchar* verification_snippet = " vec4 goku_color = imageLoad(goku, ivec2(0,0));\n" "\n" " if (vec4(1, 0, 0, 0) != goku_color)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "#extension GL_ARB_shader_image_load_store : enable\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNI_GOKU\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); Utils::replaceAllTokens("UNI_GOKU", uni_goku, out_source.m_parts[0].m_code); Utils::replaceAllTokens("BINDING", getCaseString(m_case), out_source.m_parts[0].m_code); } const GLchar* BindingImageInvalidTest::getCaseString(TESTCASES test_case) { (void)test_case; const GLchar* binding = 0; switch (m_case) { case NEGATIVE_VALUE: binding = "= -1"; break; case VARIABLE_NAME: binding = "= goku"; break; case STD140: binding = "= std140"; break; case MISSING: binding = ""; break; case TEST_CASES_MAX: binding = "= 0"; break; default: TCU_FAIL("Invalid enum"); } return binding; } /* Constants used by InitializerListTest */ const GLfloat InitializerListTest::m_value = 0.0625f; /** Constructor * * @param context Test context **/ InitializerListTest::InitializerListTest(deqp::Context& context) : GLSLTestBase(context, "initializer_list", "Test verifies initializer lists") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool InitializerListTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { m_current_test_case_index = 0; return true; } else if (m_test_cases.size() <= test_case_index) { return false; } logTestCaseName(); return true; } /** Overwritte of prepareUniforms method * * @param program Current program **/ void InitializerListTest::prepareUniforms(Utils::program& program) { static const GLfloat float_data[16] = { m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value, m_value }; program.uniform("uni_matrix", Utils::FLOAT, 4, 4, float_data); } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void InitializerListTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " TYPE_NAME variableARRAY_DEFINITION = INITIALIZATION;\n" "\n" " float sum = SUM;\n" "\n" " if (EXPECTED_VALUE != sum)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform mat4 uni_matrix;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "uniform mat4 uni_matrix;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "uniform mat4 uni_matrix;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "uniform mat4 uni_matrix;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "uniform mat4 uni_matrix;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "uniform mat4 uni_matrix;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const std::string& array_definition = getArrayDefinition(); const std::string& expected_value = getExpectedValue(); const std::string& initialization = getInitialization(); const GLchar* shader_template = 0; const std::string& sum = getSum(); const std::string& type_definition = getTypeDefinition(); const std::string& type_name = getTypeName(); switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("TYPE_DEFINITION", position, type_definition.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position -= strlen(verification_snippet); Utils::replaceToken("TYPE_NAME", position, type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("ARRAY_DEFINITION", position, array_definition.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("INITIALIZATION", position, initialization.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("SUM", position, sum.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("EXPECTED_VALUE", position, expected_value.c_str(), out_source.m_parts[0].m_code); } /** Prepare test cases * * @return true **/ bool InitializerListTest::testInit() { for (GLuint i = 0; i < TESTED_INITIALIZERS_MAX; ++i) { const TESTED_INITIALIZERS l_init = (TESTED_INITIALIZERS)i; testCase test_case = { l_init, 1, 1 }; switch (l_init) { case VECTOR: case ARRAY_VECTOR_CTR: case ARRAY_VECTOR_LIST: case UNSIZED_ARRAY_VECTOR: for (GLuint row = 2; row <= 4; ++row) { test_case.m_n_rows = row; m_test_cases.push_back(test_case); } break; case MATRIX: case MATRIX_ROWS: case ARRAY_MATRIX_CTR: case ARRAY_MATRIX_LIST: case UNSIZED_ARRAY_MATRIX: for (GLuint col = 2; col <= 4; ++col) { for (GLuint row = 2; row <= 4; ++row) { test_case.m_n_cols = col; test_case.m_n_rows = row; m_test_cases.push_back(test_case); } } break; case ARRAY_SCALAR: case UNSIZED_ARRAY_SCALAR: m_test_cases.push_back(test_case); break; case STRUCT: case ARRAY_STRUCT: case NESTED_STRUCT_CTR: case NESTED_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_MIX: case NESTED_ARRAY_STRUCT_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_MIX: case NESTED_STRUCT_STRUCT_ARRAY_LIST: case NESTED_STRUCT_STRUCT_ARRAY_MIX: case UNSIZED_ARRAY_STRUCT: test_case.m_n_rows = 4; m_test_cases.push_back(test_case); break; default: DE_ASSERT(0); break; } } return true; } /** Get string representing "[SIZE]" for current test case * * @return String **/ std::string InitializerListTest::getArrayDefinition() { const testCase& test_case = m_test_cases[m_current_test_case_index]; std::string array_definition; switch (test_case.m_initializer) { case VECTOR: case MATRIX: case MATRIX_ROWS: case STRUCT: case NESTED_STRUCT_CTR: case NESTED_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_MIX: case NESTED_STRUCT_STRUCT_ARRAY_LIST: case NESTED_STRUCT_STRUCT_ARRAY_MIX: array_definition = ""; break; case ARRAY_SCALAR: case ARRAY_VECTOR_CTR: case ARRAY_VECTOR_LIST: case ARRAY_MATRIX_CTR: case ARRAY_MATRIX_LIST: case ARRAY_STRUCT: case NESTED_ARRAY_STRUCT_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_MIX: array_definition = "[4]"; break; case UNSIZED_ARRAY_SCALAR: case UNSIZED_ARRAY_VECTOR: case UNSIZED_ARRAY_MATRIX: case UNSIZED_ARRAY_STRUCT: array_definition = "[]"; break; default: TCU_FAIL("Invalid enum"); } return array_definition; } /** Get string representing expected value of sum for current test case * * @return String **/ std::string InitializerListTest::getExpectedValue() { const testCase& test_case = m_test_cases[m_current_test_case_index]; GLfloat value = 0.0f; switch (test_case.m_initializer) { case VECTOR: case MATRIX: case MATRIX_ROWS: value = (GLfloat)(test_case.m_n_cols * test_case.m_n_rows); break; case ARRAY_VECTOR_CTR: case ARRAY_VECTOR_LIST: case ARRAY_MATRIX_CTR: case ARRAY_MATRIX_LIST: case UNSIZED_ARRAY_VECTOR: case UNSIZED_ARRAY_MATRIX: value = (GLfloat)(test_case.m_n_cols * test_case.m_n_rows) * 4.0f; break; case ARRAY_SCALAR: case UNSIZED_ARRAY_SCALAR: value = 4.0f; break; case STRUCT: value = 8.0f; break; case NESTED_STRUCT_CTR: case NESTED_STRUCT_LIST: value = 12.0f; break; case NESTED_STRUCT_STRUCT_ARRAY_LIST: case NESTED_STRUCT_STRUCT_ARRAY_MIX: value = 16.0f; break; case NESTED_STURCT_ARRAYS_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_MIX: value = 28.0f; break; case ARRAY_STRUCT: case UNSIZED_ARRAY_STRUCT: value = 32.0f; break; case NESTED_ARRAY_STRUCT_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_MIX: value = 48.0f; break; default: TCU_FAIL("Invalid enum"); } value *= m_value; std::string expected_value; expected_value.resize(64, 0); sprintf(&expected_value[0], "%f", value); return expected_value; } /** Get string representing initialization list for current test case * * @return String **/ std::string InitializerListTest::getInitialization() { const testCase& test_case = m_test_cases[m_current_test_case_index]; std::string initialization; switch (test_case.m_initializer) { case VECTOR: initialization.append(getVectorInitializer(0 /*column*/, test_case.m_n_rows)); break; case MATRIX: initialization = "{ "; initialization.append(getVectorArrayList(test_case.m_n_cols, test_case.m_n_rows)); initialization.append(" }"); break; case MATRIX_ROWS: { initialization = "{ "; initialization.append(getVectorArrayCtr(test_case.m_n_cols, test_case.m_n_rows)); initialization.append(" }"); } break; case STRUCT: initialization = "{ "; initialization.append(getVectorInitializer(0 /* column */, test_case.m_n_rows)); initialization.append(", "); initialization.append(getVectorInitializer(2 /* column */, test_case.m_n_rows)); initialization.append(" }"); break; case ARRAY_SCALAR: case UNSIZED_ARRAY_SCALAR: initialization = "{ "; initialization.append(getVectorValues(0 /* column */, 4 /* size */)); initialization.append(" }"); break; case ARRAY_VECTOR_LIST: case UNSIZED_ARRAY_VECTOR: initialization = "{ "; initialization.append(getVectorArrayList(4 /* columns */, test_case.m_n_rows)); initialization.append(" }"); break; case ARRAY_VECTOR_CTR: initialization = "{ "; initialization.append(getVectorArrayCtr(4 /* columns */, test_case.m_n_rows)); initialization.append(" }"); break; case ARRAY_MATRIX_LIST: case UNSIZED_ARRAY_MATRIX: initialization = "{ "; for (GLuint i = 0; i < 4; ++i) { initialization.append("{ "); initialization.append(getVectorArrayList(test_case.m_n_cols, test_case.m_n_rows)); initialization.append(" }"); if (i + 1 < 4) { initialization.append(", "); } } initialization.append(" }"); break; case ARRAY_MATRIX_CTR: { const std::string& type_name = Utils::getTypeName(Utils::FLOAT, test_case.m_n_cols, test_case.m_n_rows); initialization = "{ "; for (GLuint i = 0; i < 4; ++i) { initialization.append(type_name); initialization.append("("); for (GLuint col = 0; col < test_case.m_n_cols; ++col) { initialization.append(getVectorValues(col, test_case.m_n_rows)); if (col + 1 < test_case.m_n_cols) { initialization.append(", "); } } initialization.append(")"); if (i + 1 < 4) { initialization.append(", "); } } initialization.append(" }"); } break; case ARRAY_STRUCT: case UNSIZED_ARRAY_STRUCT: initialization = "{ "; for (GLuint i = 0; i < 4; ++i) { initialization.append("{ "); initialization.append(getVectorInitializer(0 /* column */, test_case.m_n_rows)); initialization.append(", "); initialization.append(getVectorInitializer(2 /* column */, test_case.m_n_rows)); initialization.append(" }"); if (i + 1 < 4) { initialization.append(", "); } } initialization.append(" }"); break; case NESTED_STRUCT_CTR: initialization = "StructureWithStructure(BasicStructure("; initialization.append(getVectorConstructor(0 /* column */, 4)); initialization.append(", "); initialization.append(getVectorConstructor(2 /* column */, 4)); initialization.append("), "); initialization.append(getVectorConstructor(3 /* column */, 4)); initialization.append(")"); break; case NESTED_STRUCT_LIST: initialization = "{ { "; initialization.append(getVectorInitializer(0 /* column */, 4)); initialization.append(", "); initialization.append(getVectorInitializer(2 /* column */, 4)); initialization.append(" }, "); initialization.append(getVectorInitializer(3 /* column */, 4)); initialization.append(" }"); break; case NESTED_STURCT_ARRAYS_STRUCT_LIST: initialization = "{ "; initialization.append(getVectorInitializer(0 /* column */, 4)); initialization.append(", { "); for (GLuint i = 0; i < 3; ++i) { initialization.append("{ "); initialization.append(getVectorInitializer(2 /* column */, 4)); initialization.append(", "); initialization.append(getVectorInitializer(3 /* column */, 4)); initialization.append(" }"); if (i + 1 < 3) { initialization.append(", "); } } initialization.append(" } }"); break; case NESTED_STURCT_ARRAYS_STRUCT_MIX: initialization = "{ "; initialization.append(getVectorConstructor(0 /* column */, 4)); initialization.append(", { "); for (GLuint i = 0; i < 3; ++i) { initialization.append("{ "); initialization.append(getVectorInitializer(2 /* column */, 4)); initialization.append(", "); initialization.append(getVectorConstructor(3 /* column */, 4)); initialization.append(" }"); if (i + 1 < 3) { initialization.append(", "); } } initialization.append(" } }"); break; case NESTED_ARRAY_STRUCT_STRUCT_LIST: initialization = "{ "; for (GLuint i = 0; i < 4; ++i) { initialization.append("{ { "); initialization.append(getVectorInitializer(0 /* column */, 4)); initialization.append(", "); initialization.append(getVectorInitializer(1 /* column */, 4)); initialization.append(" }, "); initialization.append(getVectorInitializer(2 /* column */, 4)); initialization.append(" }"); if (i + 1 < 4) { initialization.append(", "); } } initialization.append(" }"); break; case NESTED_ARRAY_STRUCT_STRUCT_MIX: initialization = "{\n"; for (GLuint i = 0; i < 2; ++i) { initialization.append("StructureWithStructure(\n"); initialization.append("BasicStructure("); initialization.append(getVectorConstructor(0 /* column */, 4)); initialization.append(" , "); initialization.append(getVectorConstructor(1 /* column */, 4)); initialization.append("), "); initialization.append(getVectorConstructor(2 /* column */, 4)); initialization.append(")"); initialization.append(" , "); initialization.append("{ { "); initialization.append(getVectorInitializer(0 /* column */, 4)); initialization.append(", "); initialization.append(getVectorInitializer(1 /* column */, 4)); initialization.append(" }, "); initialization.append(getVectorInitializer(2 /* column */, 4)); initialization.append(" }"); if (i + 1 < 2) { initialization.append(" , "); } } initialization.append(" }"); break; case NESTED_STRUCT_STRUCT_ARRAY_LIST: initialization = "{ "; initialization.append("{ "); initialization.append(getVectorInitializer(0 /* column */, 4)); initialization.append(", "); initialization.append("{ "); initialization.append(getVectorInitializer(1 /* column */, 4)); initialization.append(", "); initialization.append(getVectorInitializer(2 /* column */, 4)); initialization.append(" }"); initialization.append(" }"); initialization.append(", "); initialization.append(getVectorInitializer(3 /* column */, 4)); initialization.append(" }"); break; case NESTED_STRUCT_STRUCT_ARRAY_MIX: initialization = "StructureWithStructureWithArray("; initialization.append("StructureWithArray("); initialization.append(getVectorConstructor(0 /* column */, 4)); initialization.append(" , vec4[2]( "); initialization.append(getVectorConstructor(1 /* column */, 4)); initialization.append(" , "); initialization.append(getVectorConstructor(2 /* column */, 4)); initialization.append(" )"); initialization.append(")"); initialization.append(" , "); initialization.append(getVectorConstructor(3 /* column */, 4)); initialization.append(")"); break; default: TCU_FAIL("Invalid enum"); } return initialization; } /** Logs description of current test case * **/ void InitializerListTest::logTestCaseName() { const testCase& test_case = m_test_cases[m_current_test_case_index]; tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; switch (test_case.m_initializer) { case VECTOR: message << "List. Single vec" << test_case.m_n_rows; break; case MATRIX: message << "List. Single mat" << test_case.m_n_cols << "x" << test_case.m_n_rows; break; case MATRIX_ROWS: message << "Ctr. Single mat" << test_case.m_n_cols << "x" << test_case.m_n_rows; break; case STRUCT: message << "List. Structure"; break; case NESTED_STRUCT_CTR: message << "Ctr. Nested structure"; break; case NESTED_STRUCT_LIST: message << "List. Nested structure"; break; case NESTED_STURCT_ARRAYS_STRUCT_LIST: message << "List. Structure with structure array"; break; case NESTED_STURCT_ARRAYS_STRUCT_MIX: message << "Mix. Structure with structure array"; break; case NESTED_STRUCT_STRUCT_ARRAY_LIST: message << "List. Structure with structure with array"; break; case NESTED_STRUCT_STRUCT_ARRAY_MIX: message << "Mix. Structure with structure with array"; break; case ARRAY_SCALAR: message << "List. Array of scalars"; break; case ARRAY_VECTOR_CTR: message << "Ctr. Array of vec" << test_case.m_n_rows; break; case ARRAY_VECTOR_LIST: message << "List. Array of vec" << test_case.m_n_rows; break; case ARRAY_MATRIX_CTR: message << "Ctr. Array of mat" << test_case.m_n_cols << "x" << test_case.m_n_rows; break; case ARRAY_MATRIX_LIST: message << "List. Array of mat" << test_case.m_n_cols << "x" << test_case.m_n_rows; break; case ARRAY_STRUCT: message << "List. Array of structures"; break; case NESTED_ARRAY_STRUCT_STRUCT_LIST: message << "List. Array of structures with structures"; break; case NESTED_ARRAY_STRUCT_STRUCT_MIX: message << "Mix. Array of structures with structures"; break; case UNSIZED_ARRAY_SCALAR: message << "List. Unsized array of scalars"; break; case UNSIZED_ARRAY_VECTOR: message << "List. Unsized array of vec" << test_case.m_n_rows; break; case UNSIZED_ARRAY_MATRIX: message << "List. Unsized array of mat" << test_case.m_n_cols << "x" << test_case.m_n_rows; break; case UNSIZED_ARRAY_STRUCT: message << "List. Unsized array of structures"; break; default: TCU_FAIL("Invalid enum"); } message << tcu::TestLog::EndMessage; } /** Get string representing sum for current test case * * @return String **/ std::string InitializerListTest::getSum() { static const GLchar* var = "variable"; const testCase& test_case = m_test_cases[m_current_test_case_index]; std::string sum; switch (test_case.m_initializer) { case VECTOR: sum = getVectorSum(var, test_case.m_n_rows); break; case MATRIX: case MATRIX_ROWS: sum = getVectorArraySum("variable[INDEX]", test_case.m_n_cols, test_case.m_n_rows); break; case STRUCT: sum = getVectorSum("variable.member_a", test_case.m_n_rows); sum.append(" + "); sum.append(getVectorSum("variable.member_b", test_case.m_n_rows)); break; case ARRAY_SCALAR: case UNSIZED_ARRAY_SCALAR: sum = "variable[0] + variable[1] + variable[2] + variable[3]"; break; case ARRAY_VECTOR_LIST: case ARRAY_VECTOR_CTR: case UNSIZED_ARRAY_VECTOR: sum = getVectorArraySum("variable[INDEX]", 4 /* columns */, test_case.m_n_rows); break; case ARRAY_MATRIX_LIST: case ARRAY_MATRIX_CTR: case UNSIZED_ARRAY_MATRIX: sum.append(getVectorArraySum("variable[0][INDEX]", test_case.m_n_cols, test_case.m_n_rows)); sum.append(" + "); sum.append(getVectorArraySum("variable[1][INDEX]", test_case.m_n_cols, test_case.m_n_rows)); sum.append(" + "); sum.append(getVectorArraySum("variable[2][INDEX]", test_case.m_n_cols, test_case.m_n_rows)); sum.append(" + "); sum.append(getVectorArraySum("variable[3][INDEX]", test_case.m_n_cols, test_case.m_n_rows)); break; case ARRAY_STRUCT: case UNSIZED_ARRAY_STRUCT: sum.append(getVectorArraySum("variable[INDEX].member_a", 4, test_case.m_n_rows)); sum.append(" + "); sum.append(getVectorArraySum("variable[INDEX].member_b", 4, test_case.m_n_rows)); break; case NESTED_STRUCT_CTR: case NESTED_STRUCT_LIST: sum.append(getVectorSum("variable.member_a.member_a", 4)); sum.append(" + "); sum.append(getVectorSum("variable.member_a.member_b", 4)); sum.append(" + "); sum.append(getVectorSum("variable.member_b", 4)); break; case NESTED_STURCT_ARRAYS_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_MIX: sum.append(getVectorSum("variable.member_a", 4)); sum.append(" + "); sum.append(getVectorArraySum("variable.member_b[INDEX].member_a", 3, 4)); sum.append(" + "); sum.append(getVectorArraySum("variable.member_b[INDEX].member_b", 3, 4)); break; case NESTED_ARRAY_STRUCT_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_MIX: sum.append(getVectorArraySum("variable[INDEX].member_a.member_a", 4, 4)); sum.append(" + "); sum.append(getVectorArraySum("variable[INDEX].member_a.member_b", 4, 4)); sum.append(" + "); sum.append(getVectorArraySum("variable[INDEX].member_b", 4, 4)); break; case NESTED_STRUCT_STRUCT_ARRAY_LIST: case NESTED_STRUCT_STRUCT_ARRAY_MIX: sum.append(getVectorSum("variable.member_a.member_a", 4)); sum.append(" + "); sum.append(getVectorArraySum("variable.member_a.member_b[INDEX]", 2, 4)); sum.append(" + "); sum.append(getVectorSum("variable.member_b", 4)); break; default: TCU_FAIL("Invalid enum"); } return sum; } /** Get string representing types definition for current test case * * @return String **/ std::string InitializerListTest::getTypeDefinition() { const testCase& test_case = m_test_cases[m_current_test_case_index]; static const GLchar* basic_struct = "struct BasicStructure {\n" " vec4 member_a;\n" " vec4 member_b;\n" "};\n"; static const GLchar* struct_with_array = "struct StructureWithArray {\n" " vec4 member_a;\n" " vec4 member_b[2];\n" "};\n"; static const GLchar* struct_with_struct = "struct StructureWithStructure {\n" " BasicStructure member_a;\n" " vec4 member_b;\n" "};\n"; static const GLchar* struct_with_struct_array = "struct StructureWithStructArray {\n" " vec4 member_a;\n" " BasicStructure member_b[3];\n" "};\n"; static const GLchar* struct_with_struct_with_array = "struct StructureWithStructureWithArray {\n" " StructureWithArray member_a;\n" " vec4 member_b;\n" "};\n"; std::string type_definition; switch (test_case.m_initializer) { case VECTOR: case MATRIX: case MATRIX_ROWS: case ARRAY_SCALAR: case ARRAY_VECTOR_CTR: case ARRAY_VECTOR_LIST: case ARRAY_MATRIX_CTR: case ARRAY_MATRIX_LIST: case UNSIZED_ARRAY_SCALAR: case UNSIZED_ARRAY_VECTOR: case UNSIZED_ARRAY_MATRIX: type_definition = ""; break; case STRUCT: case ARRAY_STRUCT: case UNSIZED_ARRAY_STRUCT: type_definition = basic_struct; break; case NESTED_STRUCT_CTR: case NESTED_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_MIX: type_definition = basic_struct; type_definition.append(struct_with_struct); break; case NESTED_STURCT_ARRAYS_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_MIX: type_definition = basic_struct; type_definition.append(struct_with_struct_array); break; case NESTED_STRUCT_STRUCT_ARRAY_LIST: case NESTED_STRUCT_STRUCT_ARRAY_MIX: type_definition = struct_with_array; type_definition.append(struct_with_struct_with_array); break; default: TCU_FAIL("Invalid enum"); } return type_definition; } /** Get string representing name of variable's type for current test case * * @return String **/ std::string InitializerListTest::getTypeName() { const testCase& test_case = m_test_cases[m_current_test_case_index]; static const GLchar* basic_struct = "BasicStructure"; static const GLchar* struct_with_struct = "StructureWithStructure"; static const GLchar* struct_with_struct_array = "StructureWithStructArray"; static const GLchar* struct_with_struct_with_array = "StructureWithStructureWithArray"; std::string type_name; switch (test_case.m_initializer) { case VECTOR: case MATRIX: case MATRIX_ROWS: case ARRAY_VECTOR_CTR: case ARRAY_VECTOR_LIST: case ARRAY_MATRIX_CTR: case ARRAY_MATRIX_LIST: case UNSIZED_ARRAY_VECTOR: case UNSIZED_ARRAY_MATRIX: type_name = Utils::getTypeName(Utils::FLOAT, test_case.m_n_cols, test_case.m_n_rows); break; case STRUCT: case ARRAY_STRUCT: case UNSIZED_ARRAY_STRUCT: type_name = basic_struct; break; case NESTED_STRUCT_CTR: case NESTED_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_LIST: case NESTED_ARRAY_STRUCT_STRUCT_MIX: type_name = struct_with_struct; break; case NESTED_STURCT_ARRAYS_STRUCT_LIST: case NESTED_STURCT_ARRAYS_STRUCT_MIX: type_name = struct_with_struct_array; break; case NESTED_STRUCT_STRUCT_ARRAY_LIST: case NESTED_STRUCT_STRUCT_ARRAY_MIX: type_name = struct_with_struct_with_array; break; case ARRAY_SCALAR: case UNSIZED_ARRAY_SCALAR: type_name = "float"; break; default: TCU_FAIL("Invalid enum"); } return type_name; } /** Get string representing array of vector constructors * * @param columns Number of columns * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorArrayCtr(GLuint columns, GLuint size) { std::string result; for (GLuint col = 0; col < columns; ++col) { result.append(getVectorConstructor(col, size)); if (col + 1 < columns) { result.append(", "); } } return result; } /** Get string representing array of vector initializers * * @param columns Number of columns * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorArrayList(GLuint columns, GLuint size) { std::string result; for (GLuint col = 0; col < columns; ++col) { result.append(getVectorInitializer(col, size)); if (col + 1 < columns) { result.append(", "); } } return result; } /** Get string representing vector constructor * * @param column Index of column of uni_matrix to use as data source * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorConstructor(GLuint column, GLuint size) { const std::string& type_name = Utils::getTypeName(Utils::FLOAT, 1 /*n_cols*/, size); std::string result; result.append(type_name); result.append("("); result.append(getVectorValues(column, size)); result.append(")"); return result; } /** Get string representing vector initializer * * @param column Index of column of uni_matrix to use as data source * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorInitializer(GLuint column, GLuint size) { std::string result; result.append("{"); result.append(getVectorValues(column, size)); result.append("}"); return result; } /** Get string representing sum of vector array. Token INDEX in name will be replaced with element index. * * @param array_name Name of array variable * @param columns Number of columns to sum * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorArraySum(const GLchar* array_name, GLuint columns, GLuint size) { static const GLchar* lut[] = { "0", "1", "2", "3" }; std::string sum; for (GLuint i = 0; i < columns; ++i) { size_t position = 0; std::string name = array_name; Utils::replaceToken("INDEX", position, lut[i], name); sum.append(getVectorSum(name.c_str(), size)); if (i + 1 < columns) { sum.append(" + "); } } return sum; } /** Get string representing sum of vectors' elements * * @param vector_name Name of vector variable * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorSum(const GLchar* vector_name, GLuint size) { static const GLchar* lut[] = { ".x", ".y", ".z", ".w", }; std::string sum; for (GLuint i = 0; i < size; ++i) { sum.append(vector_name); sum.append(lut[i]); if (i + 1 < size) { sum.append(" + "); } } return sum; } /** Get string representing vector values * * @param column Index of column of uni_matrix to use as data source * @param size Size of vector * * @return String **/ std::string InitializerListTest::getVectorValues(GLuint column, GLuint size) { const GLchar* init_template = 0; const GLchar* column_index = 0; switch (size) { case 2: init_template = "uni_matrix[COLUMN].x, uni_matrix[COLUMN].y"; break; case 3: init_template = "uni_matrix[COLUMN].x, uni_matrix[COLUMN].y, uni_matrix[COLUMN].z"; break; case 4: init_template = "uni_matrix[COLUMN].z, uni_matrix[COLUMN].y, uni_matrix[COLUMN].z, uni_matrix[COLUMN].w"; break; } switch (column) { case 0: column_index = "0"; break; case 1: column_index = "1"; break; case 2: column_index = "2"; break; case 3: column_index = "3"; break; } std::string initializer = init_template; Utils::replaceAllTokens("COLUMN", column_index, initializer); return initializer; } /** Constructor * * @param context Test context **/ InitializerListNegativeTest::InitializerListNegativeTest(deqp::Context& context) : NegativeTestBase(context, "initializer_list_negative", "Verifies invalid initializers") , m_current_test_case_index(0) { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool InitializerListNegativeTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { m_current_test_case_index = 0; return true; } else if (m_test_cases.size() <= test_case_index) { return false; } logTestCaseName(); return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void InitializerListNegativeTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " TYPE_NAME variable = INITIALIZATION;\n" "\n" " float sum = SUM;\n" "\n" " if (0 != sum)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "TYPE_DEFINITION\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const std::string& initialization = getInitialization(); const GLchar* shader_template = 0; const std::string& sum = getSum(); const std::string& type_definition = getTypeDefinition(); const std::string& type_name = getTypeName(); switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("TYPE_DEFINITION", position, type_definition.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position -= strlen(verification_snippet); Utils::replaceToken("TYPE_NAME", position, type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("INITIALIZATION", position, initialization.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("SUM", position, sum.c_str(), out_source.m_parts[0].m_code); } /** Prepare test cases * * @return true **/ bool InitializerListNegativeTest::testInit() { for (GLuint i = 0; i < TESTED_ERRORS_MAX; ++i) { const TESTED_ERRORS error = (TESTED_ERRORS)i; m_test_cases.push_back(error); } return true; } /** Get string representing initialization list for current test case * * @return String **/ std::string InitializerListNegativeTest::getInitialization() { const TESTED_ERRORS& error = m_test_cases[m_current_test_case_index]; std::string initialization; switch (error) { case TYPE_UIVEC_BOOL: initialization = "{ true, 0, 1, 2 }"; break; case TYPE_IVEC_BOOL: initialization = "{ true, 0, -1, 2 }"; break; case TYPE_VEC_BOOL: initialization = "{ true, 0.125, 0.25, 0.375 }"; break; case TYPE_MAT_BOOL: initialization = "{ {false, 0, 1, 1}, {0, 1, 0, 1}, {1, 0, 1, 0}, {0, 1, 0, 1} }"; break; case COMPONENTS_VEC_LESS: case COMPONENTS_VEC_MORE: initialization = "{ 0, 0.25, 0.375 }"; break; case COMPONENTS_MAT_LESS_ROWS: initialization = "{ {0, 0, 1, 1}, {0, 0, 1}, {1, 0, 1, 0}, {0, 1, 0, 1} }"; break; case COMPONENTS_MAT_MORE_ROWS: initialization = "{ {0, 0, 1}, {0, 0, 1}, {1, 0, 1, 0}, {1, 0, 1} }"; break; case COMPONENTS_MAT_LESS_COLUMNS: initialization = "{ {0, 0, 1, 1}, {1, 0, 1, 0}, {0, 1, 0, 1} }"; break; case COMPONENTS_MAT_MORE_COLUMNS: initialization = "{ {0, 0, 1}, {0, 0, 1}, {1, 0, 1}, {1, 0, 1} }"; break; case LIST_IN_CONSTRUCTOR: initialization = "Struct( { vec4(0, 1, 0, 1), vec3(0, 1, 0) }, vec4(1, 0, 1, 0) )"; break; case STRUCT_LAYOUT_MEMBER_TYPE: initialization = "{ { {0, 1, 0, 1}, vec4(0, 1, 0, 1) }, vec4(1, 0, 1, 0) }"; break; case STRUCT_LAYOUT_MEMBER_COUNT_MORE: initialization = "{ { {0, 1, 0, 1}, vec3(0, 1, 0) } , vec4(1, 0, 1, 0), vec4(1, 0, 1, 0) }"; break; case STRUCT_LAYOUT_MEMBER_COUNT_LESS: initialization = "{ { {0, 1, 0, 1}, vec3(0, 1, 0) } }"; break; case STRUCT_LAYOUT_MEMBER_ORDER: initialization = "{ vec4(1, 0, 1, 0), { vec3(0, 1, 0) , {0, 1, 0, 1} } }"; break; default: TCU_FAIL("Invalid enum"); } return initialization; } /** Logs description of current test case * **/ void InitializerListNegativeTest::logTestCaseName() { const TESTED_ERRORS& error = m_test_cases[m_current_test_case_index]; tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message; switch (error) { case TYPE_UIVEC_BOOL: message << "Wrong type in uvec initializer list"; break; case TYPE_IVEC_BOOL: message << "Wrong type in ivec initializer list"; break; case TYPE_VEC_BOOL: message << "Wrong type in vec initializer list"; break; case TYPE_MAT_BOOL: message << "Wrong type in mat initializer list"; break; case COMPONENTS_VEC_LESS: message << "Wrong number of componenets in vec initialize list - less"; break; case COMPONENTS_VEC_MORE: message << "Wrong number of componenets in vec initialize list - more"; break; case COMPONENTS_MAT_LESS_ROWS: message << "Wrong number of componenets in mat initialize list - less rows"; break; case COMPONENTS_MAT_LESS_COLUMNS: message << "Wrong number of componenets in mat initialize list - less columns"; break; case COMPONENTS_MAT_MORE_ROWS: message << "Wrong number of componenets in mat initialize list - more rows"; break; case COMPONENTS_MAT_MORE_COLUMNS: message << "Wrong number of componenets in mat initialize list - more columns"; break; case LIST_IN_CONSTRUCTOR: message << "Initializer list in constructor"; break; case STRUCT_LAYOUT_MEMBER_TYPE: message << "Wrong type of structure member"; break; case STRUCT_LAYOUT_MEMBER_COUNT_MORE: message << "Wrong number of structure members - more"; break; case STRUCT_LAYOUT_MEMBER_COUNT_LESS: message << "Wrong number of structure members - less"; break; case STRUCT_LAYOUT_MEMBER_ORDER: message << "Wrong order of structure members"; break; default: TCU_FAIL("Invalid enum"); } message << tcu::TestLog::EndMessage; } /** Get string representing sum for current test case * * @return String **/ std::string InitializerListNegativeTest::getSum() { const TESTED_ERRORS& error = m_test_cases[m_current_test_case_index]; std::string sum; switch (error) { case TYPE_UIVEC_BOOL: case TYPE_IVEC_BOOL: case TYPE_VEC_BOOL: case COMPONENTS_VEC_LESS: sum = "variable.x + variable.y + variable.z + variable.w"; break; case TYPE_MAT_BOOL: case COMPONENTS_MAT_LESS_ROWS: case COMPONENTS_MAT_LESS_COLUMNS: sum = "variable[0].x + variable[0].y + variable[0].z + variable[0].w + " "variable[1].x + variable[1].y + variable[1].z + variable[1].w + " "variable[2].x + variable[2].y + variable[2].z + variable[2].w + " "variable[3].x + variable[3].y + variable[3].z + variable[3].w"; break; case COMPONENTS_VEC_MORE: sum = "variable.x + variable.y + variable.z"; break; case COMPONENTS_MAT_MORE_ROWS: case COMPONENTS_MAT_MORE_COLUMNS: sum = "variable[0].x + variable[0].y + variable[0].z" "variable[1].x + variable[1].y + variable[1].z" "variable[2].x + variable[2].y + variable[2].z"; break; case LIST_IN_CONSTRUCTOR: case STRUCT_LAYOUT_MEMBER_TYPE: case STRUCT_LAYOUT_MEMBER_COUNT_MORE: case STRUCT_LAYOUT_MEMBER_COUNT_LESS: case STRUCT_LAYOUT_MEMBER_ORDER: sum = "variable.member_a.member_a.x + variable.member_a.member_a.y + variable.member_a.member_a.z + " "variable.member_a.member_a.w + " "variable.member_a.member_b.x + variable.member_a.member_b.y + variable.member_a.member_b.z + " "variable.member_b.x + variable.member_b.y + variable.member_b.z + variable.member_b.w"; break; default: TCU_FAIL("Invalid enum"); } return sum; } /** Get string representing types definition for current test case * * @return String **/ std::string InitializerListNegativeTest::getTypeDefinition() { const TESTED_ERRORS& error = m_test_cases[m_current_test_case_index]; static const GLchar* struct_def = "struct BasicStructure {\n" " vec4 member_a;\n" " vec3 member_b;\n" "};\n" "\n" "struct StructureWithStructure {\n" " BasicStructure member_a;\n" " vec4 member_b;\n" "};\n"; std::string type_definition; switch (error) { case TYPE_UIVEC_BOOL: case TYPE_IVEC_BOOL: case TYPE_VEC_BOOL: case TYPE_MAT_BOOL: case COMPONENTS_VEC_LESS: case COMPONENTS_VEC_MORE: case COMPONENTS_MAT_LESS_ROWS: case COMPONENTS_MAT_LESS_COLUMNS: case COMPONENTS_MAT_MORE_ROWS: case COMPONENTS_MAT_MORE_COLUMNS: type_definition = ""; break; case LIST_IN_CONSTRUCTOR: case STRUCT_LAYOUT_MEMBER_TYPE: case STRUCT_LAYOUT_MEMBER_COUNT_MORE: case STRUCT_LAYOUT_MEMBER_COUNT_LESS: case STRUCT_LAYOUT_MEMBER_ORDER: type_definition = struct_def; break; default: TCU_FAIL("Invalid enum"); } return type_definition; } /** Get string representing name of variable's type for current test case * * @return String **/ std::string InitializerListNegativeTest::getTypeName() { const TESTED_ERRORS& error = m_test_cases[m_current_test_case_index]; static const GLchar* struct_with_struct = "StructureWithStructure"; std::string type_name; switch (error) { case TYPE_UIVEC_BOOL: type_name = "uvec4"; break; case TYPE_IVEC_BOOL: type_name = "ivec4"; break; case TYPE_VEC_BOOL: case COMPONENTS_VEC_LESS: type_name = "vec4"; break; case COMPONENTS_VEC_MORE: type_name = "vec2"; break; case TYPE_MAT_BOOL: case COMPONENTS_MAT_LESS_ROWS: case COMPONENTS_MAT_LESS_COLUMNS: type_name = "mat4"; break; case COMPONENTS_MAT_MORE_ROWS: case COMPONENTS_MAT_MORE_COLUMNS: type_name = "mat3"; break; case LIST_IN_CONSTRUCTOR: case STRUCT_LAYOUT_MEMBER_TYPE: case STRUCT_LAYOUT_MEMBER_COUNT_MORE: case STRUCT_LAYOUT_MEMBER_COUNT_LESS: case STRUCT_LAYOUT_MEMBER_ORDER: type_name = struct_with_struct; break; default: TCU_FAIL("Invalid enum"); } return type_name; } /** Constructor * * @param context Test context **/ LengthOfVectorAndMatrixTest::LengthOfVectorAndMatrixTest(deqp::Context& context) : GLSLTestBase(context, "length_of_vector_and_matrix", "Test verifies .length() for vectors and matrices") { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool LengthOfVectorAndMatrixTest::prepareNextTestCase(glw::GLuint test_case_index) { m_current_test_case_index = test_case_index; if ((glw::GLuint)-1 == test_case_index) { m_current_test_case_index = 0; return true; } else if (m_test_cases.size() <= test_case_index) { return false; } const testCase& test_case = m_test_cases[m_current_test_case_index]; m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tested type: " << Utils::getTypeName(test_case.m_type, test_case.m_n_cols, test_case.m_n_rows) << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void LengthOfVectorAndMatrixTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { if (Utils::COMPUTE_SHADER == in_stage) { m_is_compute_program = true; prepareComputeShaderSource(out_source); } else { m_is_compute_program = false; prepareDrawShaderSource(in_stage, in_use_version_400, out_source); } } /** Overwritte of prepareUniforms method * * @param program Current program **/ void LengthOfVectorAndMatrixTest::prepareUniforms(Utils::program& program) { static const GLfloat float_value = 0.125; static const GLint int_value = -1; static const GLuint uint_value = 1; static const GLfloat float_data[16] = { float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value }; static const GLint int_data[4] = { int_value, int_value, int_value, int_value }; static const GLuint uint_data[4] = { uint_value, uint_value, uint_value, uint_value }; if (false == m_is_compute_program) { return; } const testCase& test_case = m_test_cases[m_current_test_case_index]; switch (test_case.m_type) { case Utils::FLOAT: program.uniform("uni_variable", Utils::FLOAT, test_case.m_n_cols, test_case.m_n_rows, float_data); break; case Utils::INT: program.uniform("uni_variable", Utils::INT, 1 /* columns */, test_case.m_n_rows, int_data); break; case Utils::UINT: program.uniform("uni_variable", Utils::UINT, 1 /* columns */, test_case.m_n_rows, uint_data); break; default: TCU_FAIL("Invalid enum"); } } /** Prepare vertex buffer * * @param program Program object * @param buffer Vertex buffer * @param vao Vertex array object * * @return 0 **/ void LengthOfVectorAndMatrixTest::prepareVertexBuffer(const Utils::program& program, Utils::buffer& buffer, Utils::vertexArray& vao) { static const GLfloat float_value = 0.125f; static const GLint int_value = -1; static const GLuint uint_value = 1; static const GLfloat float_data[16] = { float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value, float_value }; static const GLint int_data[4] = { int_value, int_value, int_value, int_value }; static const GLuint uint_data[4] = { uint_value, uint_value, uint_value, uint_value }; const testCase& test_case = m_test_cases[m_current_test_case_index]; std::string variable_name = Utils::getVariableName(Utils::VERTEX_SHADER, Utils::INPUT, "variable"); GLint variable_loc = program.getAttribLocation(variable_name.c_str()); if (-1 == variable_loc) { TCU_FAIL("Vertex attribute location is invalid"); } vao.generate(); vao.bind(); buffer.generate(GL_ARRAY_BUFFER); GLvoid* data_ptr = 0; GLsizeiptr data_size = 0; switch (test_case.m_type) { case Utils::FLOAT: data_ptr = (GLvoid*)float_data; data_size = sizeof(float_data); break; case Utils::INT: data_ptr = (GLvoid*)int_data; data_size = sizeof(int_data); break; case Utils::UINT: data_ptr = (GLvoid*)uint_data; data_size = sizeof(uint_data); break; default: TCU_FAIL("Invalid enum"); } buffer.update(data_size, data_ptr, GL_STATIC_DRAW); /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Set up vao */ switch (test_case.m_type) { case Utils::FLOAT: for (GLuint col = 0; col < test_case.m_n_cols; ++col) { const GLuint index = variable_loc + col; const GLint size = test_case.m_n_rows; const GLvoid* offset = (const GLvoid*)(test_case.m_n_rows * sizeof(GLfloat) * col); gl.vertexAttribPointer(index, size, GL_FLOAT /* type */, GL_FALSE /* normalized*/, 0, offset); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer"); } break; case Utils::INT: gl.vertexAttribIPointer(variable_loc, test_case.m_n_rows /* size */, GL_INT /* type */, 0 /* stride */, 0 /* offset */); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribIPointer"); break; case Utils::UINT: gl.vertexAttribIPointer(variable_loc, test_case.m_n_rows /* size */, GL_UNSIGNED_INT /* type */, 0 /* stride */, 0 /* offset */); GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribIPointer"); break; default: DE_ASSERT(0); break; } /* Enable attribute */ for (GLuint col = 0; col < test_case.m_n_cols; ++col) { gl.enableVertexAttribArray(variable_loc + col); GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray"); } } /** Prepare test cases * * @return true **/ bool LengthOfVectorAndMatrixTest::testInit() { /* Vectors */ for (GLuint row = 2; row <= 4; ++row) { testCase test_case = { Utils::UINT, 1 /* n_cols */, row }; m_test_cases.push_back(test_case); } for (GLuint row = 2; row <= 4; ++row) { testCase test_case = { Utils::INT, 1 /* n_cols */, row }; m_test_cases.push_back(test_case); } for (GLuint row = 2; row <= 4; ++row) { testCase test_case = { Utils::FLOAT, 1 /* n_cols */, row }; m_test_cases.push_back(test_case); } /* Matrices */ for (GLuint col = 2; col <= 4; ++col) { for (GLuint row = 2; row <= 4; ++row) { testCase test_case = { Utils::FLOAT, col, row }; m_test_cases.push_back(test_case); } } return true; } /** Get string representing value that should be placed at token EXPECTED_VALUE * * @param in_stage Shader stage * * @return String with value **/ std::string LengthOfVectorAndMatrixTest::getExpectedValue(Utils::SHADER_STAGES in_stage) { const testCase& test_case = m_test_cases[m_current_test_case_index]; GLuint count = 0; switch (in_stage) { case Utils::FRAGMENT_SHADER: count = 3; break; case Utils::COMPUTE_SHADER: count = 2; break; default: count = 4; } if (1 == test_case.m_n_cols) { count *= test_case.m_n_rows; } else { count *= test_case.m_n_cols; } std::string expected_value; expected_value.resize(64, 0); switch (test_case.m_type) { case Utils::FLOAT: { GLfloat value = 0.125f * (GLfloat)count; sprintf(&expected_value[0], "%f", value); } break; case Utils::INT: { GLint value = -1 * (GLint)count; sprintf(&expected_value[0], "%d", value); } break; case Utils::UINT: { GLuint value = 1 * (GLuint)count; sprintf(&expected_value[0], "%d", value); } break; default: DE_ASSERT(0); break; } return expected_value; } /** Get string reresenting initialization of local variables for current test case * * @return String with initialization **/ std::string LengthOfVectorAndMatrixTest::getInitialization() { const testCase& test_case = m_test_cases[m_current_test_case_index]; std::string initialization; if (1 == test_case.m_n_cols) { initialization = getVectorInitializer(test_case.m_type, test_case.m_n_rows); } else { initialization = getMatrixInitializer(test_case.m_n_cols, test_case.m_n_rows); } return initialization; } /** Get string reresenting initialization of local matrix variables * * @param n_cols Number of columns * @param n_rows Number of rows * * @return String with initialization **/ std::string LengthOfVectorAndMatrixTest::getMatrixInitializer(GLuint n_cols, GLuint n_rows) { std::string result; result.append("{ "); for (GLuint col = 0; col < n_cols; ++col) { result.append(getVectorInitializer(Utils::FLOAT, n_rows)); if (col + 1 < n_cols) { result.append(", "); } } result.append(" }"); return result; } /** Get string reresenting initialization of local vector variables * * @param type Basic type of vector * @param n_rows Number of rows * * @return String with initialization **/ std::string LengthOfVectorAndMatrixTest::getVectorInitializer(Utils::TYPES type, glw::GLuint n_rows) { std::string result; const GLchar* value = 0; switch (type) { case Utils::FLOAT: value = "0.125"; break; case Utils::UINT: value = "1"; break; case Utils::INT: value = "-1"; break; default: TCU_FAIL("Invalid enum"); } result.append("{"); for (GLuint row = 0; row < n_rows; ++row) { result.append(value); if (row + 1 < n_rows) { result.append(", "); } } result.append("}"); return result; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void LengthOfVectorAndMatrixTest::prepareDrawShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " VARIABLE_TYPE variable = INITIALIZATION;\n" " Structure structure = { { 0, 1, 0, 1 } , INITIALIZATION };\n" "\n" " const uint variable_length = variable.length();\n" " const uint structure_member_b_length = structure.member_b.length();\n" " const uint input_member_length = INPUT_VARIABLE_NAME.length();\n" "#ifndef FRAGMENT\n" " const uint output_member_length = OUTPUT_VARIABLE_NAME.length();\n" "#endif // FRAGMENT\n" "\n" " BASE_TYPE array_var[variable.length()];\n" " BASE_TYPE array_str[structure.member_b.length()];\n" " BASE_TYPE array_in [INPUT_VARIABLE_NAME.length()];\n" "#ifndef FRAGMENT\n" " BASE_TYPE array_out[OUTPUT_VARIABLE_NAME.length()];\n" "#endif // FRAGMENT\n" "\n" " BASE_TYPE sum = 0;\n" "\n" " for (uint i = 0; i < variable_length; ++i)\n" " {\n" " array_var[i] = variableARRAY_INDEX.x;\n" " }\n" "\n" " for (uint i = 0; i < structure_member_b_length; ++i)\n" " {\n" " array_str[i] = structure.member_bARRAY_INDEX.y;\n" " }\n" "\n" " for (uint i = 0; i < input_member_length; ++i)\n" " {\n" " array_in[i] = INPUT_VARIABLE_NAMEARRAY_INDEX.x;\n" " }\n" "\n" "#ifndef FRAGMENT\n" " for (uint i = 0; i < output_member_length; ++i)\n" " {\n" " array_out[i] = INPUT_VARIABLE_NAMEARRAY_INDEX.y;\n" " }\n" "#endif // FRAGMENT\n" "\n" " for (uint i = 0; i < array_var.length(); ++i)\n" " {\n" " sum += array_var[i];\n" " }\n" "\n" " for (uint i = 0; i < array_str.length(); ++i)\n" " {\n" " sum += array_str[i];\n" " }\n" "\n" " for (uint i = 0; i < array_in.length(); ++i)\n" " {\n" " sum += array_in[i];\n" " }\n" "\n" "#ifndef FRAGMENT\n" " for (uint i = 0; i < array_out.length(); ++i)\n" " {\n" " sum += array_out[i];\n" " }\n" "#endif // FRAGMENT\n" "\n" " if (EXPECTED_VALUE != sum)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "#define FRAGMENT\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "in GSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block;\n" "\n" "struct Structure {\n" " vec4 member_a;\n" " TYPE_NAME member_b;\n" "};\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "in TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block[];\n" "out GSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block;\n" "\n" "struct Structure {\n" " vec4 member_a;\n" " TYPE_NAME member_b;\n" "};\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "in VSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block[];\n" "out TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block[];\n" "\n" "struct Structure {\n" " vec4 member_a;\n" " TYPE_NAME member_b;\n" "};\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_result[gl_InvocationID] = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "in TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} input_block[];\n" "out TCSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block;\n" "\n" "struct Structure {\n" " vec4 member_a;\n" " TYPE_NAME member_b;\n" "};\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "in VARIABLE_DECLARATION;\n" "out VSOutputBlock {\n" " VARIABLE_DECLARATION;\n" "} output_block;\n" "\n" "struct Structure {\n" " vec4 member_a;\n" " TYPE_NAME member_b;\n" "};\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" " OUTPUT_VARIABLE_NAME = INPUT_VARIABLE_NAME;\n" "}\n" "\n"; const GLchar* array_index = ""; const testCase& test_case = m_test_cases[m_current_test_case_index]; const GLchar* shader_template = 0; const GLchar* input_block_name = "input_block"; const GLchar* output_block_name = "output_block"; const std::string& base_type_name = Utils::getTypeName(test_case.m_type, 1 /* cols */, 1 /* rows */); const std::string& expected_value = getExpectedValue(in_stage); const std::string& initialization = getInitialization(); const std::string& type_name = Utils::getTypeName(test_case.m_type, test_case.m_n_cols, test_case.m_n_rows); std::string input_decl; std::string input_ref; std::string output_decl; std::string output_ref; Utils::qualifierSet in_qualifiers; Utils::qualifierSet out_qualifiers; if ((Utils::UINT == test_case.m_type) || (Utils::INT == test_case.m_type)) { if (Utils::VERTEX_SHADER != in_stage) { in_qualifiers.push_back(Utils::QUAL_FLAT); } out_qualifiers.push_back(Utils::QUAL_FLAT); } switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = 0; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } if (Utils::VERTEX_SHADER != in_stage) { Utils::prepareBlockVariableStrings(in_stage, Utils::INPUT, in_qualifiers, type_name.c_str(), "variable", input_block_name, input_decl, input_ref); } else { Utils::prepareVariableStrings(in_stage, Utils::INPUT, in_qualifiers, type_name.c_str(), "variable", input_decl, input_ref); } if (Utils::FRAGMENT_SHADER != in_stage) { Utils::prepareBlockVariableStrings(in_stage, Utils::OUTPUT, out_qualifiers, type_name.c_str(), "variable", output_block_name, output_decl, output_ref); } else { Utils::prepareVariableStrings(in_stage, Utils::OUTPUT, out_qualifiers, type_name.c_str(), "variable", output_decl, output_ref); } if (1 != test_case.m_n_cols) { array_index = "[i]"; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VARIABLE_DECLARATION", position, input_decl.c_str(), out_source.m_parts[0].m_code); if (Utils::FRAGMENT_SHADER != in_stage) { Utils::replaceToken("VARIABLE_DECLARATION", position, output_decl.c_str(), out_source.m_parts[0].m_code); } Utils::replaceToken("TYPE_NAME", position, type_name.c_str(), out_source.m_parts[0].m_code); size_t temp = position; Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position = temp; Utils::replaceToken("VARIABLE_TYPE", position, type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("INITIALIZATION", position, initialization.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("INITIALIZATION", position, initialization.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("EXPECTED_VALUE", position, expected_value.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("INPUT_VARIABLE_NAME", input_ref.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("OUTPUT_VARIABLE_NAME", output_ref.c_str(), out_source.m_parts[0].m_code); Utils::replaceAllTokens("ARRAY_INDEX", array_index, out_source.m_parts[0].m_code); } /** Prepare source for compute shader stage * * @param out_source Prepared shader source instance **/ void LengthOfVectorAndMatrixTest::prepareComputeShaderSource(Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " VARIABLE_TYPE variable = uni_variable;\n" " Structure structure = { { 0, 1, 0, 1 } , uni_variable };\n" "\n" " const uint variable_length = variable.length();\n" " const uint structure_member_b_length = structure.member_b.length();\n" "\n" " BASE_TYPE array_var[variable.length()];\n" " BASE_TYPE array_str[structure.member_b.length()];\n" "\n" " BASE_TYPE sum = 0;\n" "\n" " for (uint i = 0; i < variable_length; ++i)\n" " {\n" " array_var[i] = variableARRAY_INDEX.x;\n" " }\n" "\n" " for (uint i = 0; i < structure_member_b_length; ++i)\n" " {\n" " array_str[i] = structure.member_bARRAY_INDEX.y;\n" " }\n" "\n" " for (uint i = 0; i < array_var.length(); ++i)\n" " {\n" " sum += array_var[i];\n" " }\n" "\n" " for (uint i = 0; i < array_str.length(); ++i)\n" " {\n" " sum += array_str[i];\n" " }\n" "\n" " if (EXPECTED_VALUE != sum)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform TYPE_NAME uni_variable;\n" "\n" "struct Structure {\n" " vec4 member_a;\n" " TYPE_NAME member_b;\n" "};\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; const testCase& test_case = m_test_cases[m_current_test_case_index]; const GLchar* array_index = ""; const std::string& base_type_name = Utils::getTypeName(test_case.m_type, 1 /* cols */, 1 /* rows */); const std::string& expected_value = getExpectedValue(Utils::COMPUTE_SHADER); const std::string& type_name = Utils::getTypeName(test_case.m_type, test_case.m_n_cols, test_case.m_n_rows); if (1 != test_case.m_n_cols) { array_index = "[i]"; } out_source.m_parts[0].m_code = compute_shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(Utils::COMPUTE_SHADER, false), out_source.m_parts[0].m_code); Utils::replaceToken("TYPE_NAME", position, type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("TYPE_NAME", position, type_name.c_str(), out_source.m_parts[0].m_code); size_t temp = position; Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); position = temp; Utils::replaceToken("VARIABLE_TYPE", position, type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("BASE_TYPE", position, base_type_name.c_str(), out_source.m_parts[0].m_code); Utils::replaceToken("ARRAY_INDEX", position, array_index, out_source.m_parts[0].m_code); Utils::replaceToken("ARRAY_INDEX", position, array_index, out_source.m_parts[0].m_code); Utils::replaceToken("EXPECTED_VALUE", position, expected_value.c_str(), out_source.m_parts[0].m_code); } /** Constructor * * @param context Test context **/ LengthOfComputeResultTest::LengthOfComputeResultTest(deqp::Context& context) : GLSLTestBase(context, "length_of_compute_result", "Test verifies .length() for results of computation") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void LengthOfComputeResultTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uniforms = "uniform mat2x4 goten;\n" "uniform uvec4 indices;\n" "uniform uvec4 expected_lengths;\n" "uniform mat4x3 gohan;\n" "uniform vec3 vegeta;\n" "uniform vec3 trunks;\n" "uniform uint variable;\n" "uniform float expected_sum;\n"; static const GLchar* verification_snippet = " uint lengths[4];\n" " float x[(gohan * goten).length()];\n" " float y[(gohan * goten)[variable - 1].length()];\n" "\n" " lengths[indices.x] = gohan[variable].length();\n" " lengths[indices.y] = (gohan * goten).length();\n" " lengths[indices.z] = (gohan * goten)[variable].length();\n" " lengths[indices.w] = (vegeta * trunks).length();\n" "\n" " float dot_result = dot(vegeta, trunks);\n" " mat2x3 mul_result = gohan * goten;\n" "\n" "#ifdef TESS_CTRL\n" " const uint position_length = gl_out[gl_InvocationID].gl_Position.length();\n" "#endif\n" "#ifndef COMPUTE\n" "#ifndef FRAGMENT\n" "#ifndef TESS_CTRL\n" " const uint position_length = gl_Position.length();\n" "#endif /*TESS_CTRL */\n" "#endif /* FRAGMENT */\n" "#endif /* COMPUTE */\n" "#ifdef FRAGMENT\n" " const uint point_coord_length = gl_PointCoord.length();\n" " const uint sample_position_length = gl_SamplePosition.length();\n" "#endif /* FRAGMENT */\n" " const uint outer_length = outerProduct(vegeta, trunks).length();\n" "\n" " for (uint i = 0; i < x.length(); ++i)\n" " {\n" " x[i] = mul_result[i].x;\n" " }\n" "\n" " for (uint i = 0; i < y.length(); ++i)\n" " {\n" " y[i] = mul_result[0][i];\n" " }\n" "\n" " if ( (expected_lengths.x != lengths[0]) ||\n" " (expected_lengths.y != lengths[1]) ||\n" " (expected_lengths.z != lengths[2]) ||\n" " (expected_lengths.w != lengths[3]) ||\n" "#ifndef COMPUTE\n" "#ifndef FRAGMENT\n" " (4 /* vec4 */ != position_length) ||\n" "#endif /* FRAGMENT */\n" "#endif /* COMPUTE */\n" "#ifdef FRAGMENT\n" " (2 /* vec2 */ != point_coord_length) ||\n" " (2 /* vec2 */ != sample_position_length) ||\n" "#endif /* FRAGMENT */\n" " (0.5 != dot_result) ||\n" " (3 /* mat3 */ != outer_length) ||\n" " (expected_sum != x[variable] + y[variable]) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "#define COMPUTE\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "#define FRAGMENT\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "#define TESS_CTRL\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("UNIFORMS", position, uniforms, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method * * @param program Current program **/ void LengthOfComputeResultTest::prepareUniforms(Utils::program& program) { static const GLfloat gohan_data[12] = { 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f, 0.125f }; static const GLfloat goten_data[8] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; static const GLfloat vegeta_data[3] = { 0.5f, 0.5f, 0.0f }; static const GLfloat trunks_data[3] = { 0.5f, 0.5f, 0.0f }; static const GLuint indices_data[4] = { 2, 1, 0, 3 }; static const GLuint variable_data[1] = { 1 }; static const GLuint expected_lengths_data[4] = { 3, 2, 3, 3 }; static const GLfloat expected_sum_data[1] = { 1.0f }; program.uniform("gohan", Utils::FLOAT, 4 /* n_cols */, 3 /* n_rows */, gohan_data); program.uniform("goten", Utils::FLOAT, 2 /* n_cols */, 4 /* n_rows */, goten_data); program.uniform("vegeta", Utils::FLOAT, 1 /* n_cols */, 3 /* n_rows */, vegeta_data); program.uniform("trunks", Utils::FLOAT, 1 /* n_cols */, 3 /* n_rows */, trunks_data); program.uniform("indices", Utils::UINT, 1 /* n_cols */, 4 /* n_rows */, indices_data); program.uniform("variable", Utils::UINT, 1 /* n_cols */, 1 /* n_rows */, variable_data); program.uniform("expected_lengths", Utils::UINT, 1 /* n_cols */, 4 /* n_rows */, expected_lengths_data); program.uniform("expected_sum", Utils::FLOAT, 1 /* n_cols */, 1 /* n_rows */, expected_sum_data); } /** Constructor * * @param context Test context **/ ScalarSwizzlersTest::ScalarSwizzlersTest(deqp::Context& context) : GLSLTestBase(context, "scalar_swizzlers", "Verifies that swizzlers can be used on scalars") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ScalarSwizzlersTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uniforms = "uniform float variable;\n" "uniform vec3 expected_values;\n"; static const GLchar* literal = "#define LITERAL 0.375\n"; static const GLchar* structure = "struct Structure {\n" " vec2 m_xx;\n" " vec3 m_xxx;\n" " vec4 m_xxxx;\n" " vec2 m_nested_xx;\n" " vec3 m_nested_xxx;\n" " vec4 m_nested_xxxx;\n" "};\n"; static const GLchar* function = "bool check_values(in Structure structure, in float value)\n" "{\n" " const vec2 xx = vec2(value, value);\n" " const vec3 xxx = vec3(value, value, value);\n" " const vec4 xxxx = vec4(value, value, value, value);\n" "\n" " bool result = true;\n" "\n" " if ((xx != structure.m_xx) ||\n" " (xxx != structure.m_xxx) ||\n" " (xxxx != structure.m_xxxx) ||\n" " (xx != structure.m_nested_xx) ||\n" " (xxx != structure.m_nested_xxx) ||\n" " (xxxx != structure.m_nested_xxxx) )\n" " {\n" " result = false;\n" " }\n" "\n" " return result;\n" "}\n"; static const GLchar* verification_snippet = " Structure literal_result;\n" " Structure constant_result;\n" " Structure variable_result;\n" "\n" " literal_result.m_xx = LITERAL.xx ;\n" " literal_result.m_xxx = LITERAL.xxx ;\n" " literal_result.m_xxxx = LITERAL.xxxx;\n" " literal_result.m_nested_xx = LITERAL.x.rr.sss.rr ;\n" " literal_result.m_nested_xxx = LITERAL.s.xx.rrr.xxx ;\n" " literal_result.m_nested_xxxx = LITERAL.r.ss.xxx.ssss;\n" "\n" " const float constant = 0.125;\n" "\n" " constant_result.m_xx = constant.xx ;\n" " constant_result.m_xxx = constant.xxx ;\n" " constant_result.m_xxxx = constant.xxxx;\n" " constant_result.m_nested_xx = constant.x.rr.sss.rr ;\n" " constant_result.m_nested_xxx = constant.s.xx.rrr.xxx ;\n" " constant_result.m_nested_xxxx = constant.r.ss.xxx.ssss;\n" "\n" " variable_result.m_xx = variable.xx ;\n" " variable_result.m_xxx = variable.xxx ;\n" " variable_result.m_xxxx = variable.xxxx;\n" " variable_result.m_nested_xx = variable.x.rr.sss.rr ;\n" " variable_result.m_nested_xxx = variable.s.xx.rrr.xxx ;\n" " variable_result.m_nested_xxxx = variable.r.ss.xxx.ssss;\n" "\n" " if ((false == check_values(literal_result, expected_values.x)) ||\n" " (false == check_values(constant_result, expected_values.y)) ||\n" " (false == check_values(variable_result, expected_values.z)) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "STRUCTURE" "\n" "UNIFORMS" "\n" "FUNCTION" "\n" "LITERAL" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "#define FRAGMENT\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "STRUCTURE" "\n" "UNIFORMS" "\n" "FUNCTION" "\n" "LITERAL" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "STRUCTURE" "\n" "UNIFORMS" "\n" "FUNCTION" "\n" "LITERAL" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "STRUCTURE" "\n" "UNIFORMS" "\n" "FUNCTION" "\n" "LITERAL" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "STRUCTURE" "\n" "UNIFORMS" "\n" "FUNCTION" "\n" "LITERAL" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "STRUCTURE" "\n" "UNIFORMS" "\n" "FUNCTION" "\n" "LITERAL" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("STRUCTURE", position, structure, out_source.m_parts[0].m_code); Utils::replaceToken("UNIFORMS", position, uniforms, out_source.m_parts[0].m_code); Utils::replaceToken("FUNCTION", position, function, out_source.m_parts[0].m_code); Utils::replaceToken("LITERAL", position, literal, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method * * @param program Current program **/ void ScalarSwizzlersTest::prepareUniforms(Utils::program& program) { static const GLfloat variable_data[4] = { 0.75f }; static const GLfloat expected_values_data[3] = { 0.375f, 0.125f, 0.75f }; program.uniform("variable", Utils::FLOAT, 1 /* n_cols */, 1 /* n_rows */, variable_data); program.uniform("expected_values", Utils::FLOAT, 1 /* n_cols */, 3 /* n_rows */, expected_values_data); } /** Constructor * * @param context Test context **/ ScalarSwizzlersInvalidTest::ScalarSwizzlersInvalidTest(deqp::Context& context) : NegativeTestBase(context, "scalar_swizzlers_invalid", "Verifies if invalid use of swizzlers on scalars is reported as error") { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool ScalarSwizzlersInvalidTest::prepareNextTestCase(glw::GLuint test_case_index) { switch (test_case_index) { case (glw::GLuint)-1: case INVALID_Y: case INVALID_B: case INVALID_Q: case INVALID_XY: case INVALID_XRS: case WRONG: case MISSING_PARENTHESIS: m_case = (TESTED_CASES)test_case_index; break; default: return false; } return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void ScalarSwizzlersInvalidTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* uniforms = "uniform float variable;\n"; static const GLchar* verification_invalid_y = "\n" " if (0.125 != variable.y) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* verification_invalid_b = "\n" " if (0.125 != variable.b) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* verification_invalid_q = "\n" " if (0.125 != variable.q) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* verification_invalid_xy = "\n" " if (vec2(0.125, 0.25) != variable.xy) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* verification_invalid_xrs = "\n" " if (vec3(0.125, 0.125, 0.25) != variable.xrs) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* verification_wrong_u = "\n" " if (0.125 != variable.u) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* verification_missing_parenthesis = "\n" " if (variable != 1.x) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "#define FRAGMENT\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "UNIFORMS" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* verification_snippet = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } switch (m_case) { case INVALID_Y: verification_snippet = verification_invalid_y; break; case INVALID_B: verification_snippet = verification_invalid_b; break; case INVALID_Q: verification_snippet = verification_invalid_q; break; case INVALID_XY: verification_snippet = verification_invalid_xy; break; case INVALID_XRS: verification_snippet = verification_invalid_xrs; break; case WRONG: verification_snippet = verification_wrong_u; break; case MISSING_PARENTHESIS: verification_snippet = verification_missing_parenthesis; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("UNIFORMS", position, uniforms, out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); } /* Constants used by BuiltInValuesTest */ const GLint BuiltInValuesTest::m_min_program_texel_offset_limit = -8; const GLint BuiltInValuesTest::m_max_program_texel_offset_limit = 7; /** Constructor * * @param context Test context **/ BuiltInValuesTest::BuiltInValuesTest(deqp::Context& context) : GLSLTestBase(context, "built_in_values", "Test verifies values of gl_Min/Max_ProgramTexelOffset") { /* Nothing to be done here */ } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BuiltInValuesTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* verification_snippet = " if ((expected_values.x != gl_MinProgramTexelOffset) ||\n" " (expected_values.y != gl_MaxProgramTexelOffset) )\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); } /** Overwritte of prepareUniforms method * * @param program Current program **/ void BuiltInValuesTest::prepareUniforms(Utils::program& program) { const GLint expected_values_data[2] = { m_min_program_texel_offset, m_max_program_texel_offset }; program.uniform("expected_values", Utils::INT, 1 /* n_cols */, 2 /* n_rows */, expected_values_data); } /** Prepare test cases * * @return true **/ bool BuiltInValuesTest::testInit() { const Functions& gl = m_context.getRenderContext().getFunctions(); gl.getIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &m_min_program_texel_offset); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); gl.getIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &m_max_program_texel_offset); GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv"); if ((m_min_program_texel_offset_limit > m_min_program_texel_offset) || (m_max_program_texel_offset_limit > m_max_program_texel_offset)) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid GL_PROGRAM_TEXEL_OFFSET values." << " Min: " << m_min_program_texel_offset << " expected at top: " << m_min_program_texel_offset_limit << " Max: " << m_min_program_texel_offset << " expected at least: " << m_max_program_texel_offset_limit << tcu::TestLog::EndMessage; return false; } return true; } /** Constructor * * @param context Test context **/ BuiltInAssignmentTest::BuiltInAssignmentTest(deqp::Context& context) : NegativeTestBase(context, "built_in_assignment", "Test verifies that built in gl_Min/MaxProgramTexelOffset cannot be assigned") { /* Nothing to be done here */ } /** Set up next test case * * @param test_case_index Index of next test case * * @return false if there is no more test cases, true otherwise **/ bool BuiltInAssignmentTest::prepareNextTestCase(glw::GLuint test_case_index) { const GLchar* description = 0; switch (test_case_index) { case (glw::GLuint)-1: case 0: description = "Testing gl_MinProgramTexelOffset"; break; case 1: description = "Testing gl_MaxProgramTexelOffset"; break; default: return false; } m_case = test_case_index; m_context.getTestContext().getLog() << tcu::TestLog::Message << description << tcu::TestLog::EndMessage; return true; } /** Prepare source for given shader stage * * @param in_stage Shader stage, compute shader will use 430 * @param in_use_version_400 Select if 400 or 420 should be used * @param out_source Prepared shader source instance **/ void BuiltInAssignmentTest::prepareShaderSource(Utils::SHADER_STAGES in_stage, bool in_use_version_400, Utils::shaderSource& out_source) { static const GLchar* min_verification_snippet = " gl_MinProgramTexelOffset += gl_MaxProgramTexelOffset\n" "\n" " if (expected_value != gl_MinProgramTexelOffset)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* max_verification_snippet = " gl_MaxProgramTexelOffset += gl_MinProgramTexelOffset\n" "\n" " if (expected_value != gl_MaxProgramTexelOffset)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n"; static const GLchar* compute_shader_template = "VERSION\n" "\n" "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" "\n" "writeonly uniform image2D uni_image;\n" " uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n" "}\n" "\n"; static const GLchar* fragment_shader_template = "VERSION\n" "\n" "in vec4 gs_fs_result;\n" "out vec4 fs_out_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != gs_fs_result)\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " fs_out_result = result;\n" "}\n" "\n"; static const GLchar* geometry_shader_template = "VERSION\n" "\n" "layout(points) in;\n" "layout(triangle_strip, max_vertices = 4) out;\n" "\n" "in vec4 tes_gs_result[];\n" "out vec4 gs_fs_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tes_gs_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(-1, 1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, -1, 0, 1);\n" " EmitVertex();\n" " gs_fs_result = result;\n" " gl_Position = vec4(1, 1, 0, 1);\n" " EmitVertex();\n" "}\n" "\n"; static const GLchar* tess_ctrl_shader_template = "VERSION\n" "\n" "layout(vertices = 1) out;\n" "\n" "in vec4 vs_tcs_result[];\n" "out vec4 tcs_tes_result[];\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != vs_tcs_result[gl_InvocationID])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tcs_tes_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" "\n"; static const GLchar* tess_eval_shader_template = "VERSION\n" "\n" "layout(isolines, point_mode) in;\n" "\n" "in vec4 tcs_tes_result[];\n" "out vec4 tes_gs_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" " else if (vec4(0, 1, 0, 1) != tcs_tes_result[0])\n" " {\n" " result = vec4(1, 0, 0, 1);\n" " }\n" "\n" " tes_gs_result = result;\n" "}\n" "\n"; static const GLchar* vertex_shader_template = "VERSION\n" "\n" "out vec4 vs_tcs_result;\n" "\n" "uniform ivec2 expected_values;\n" "\n" "void main()\n" "{\n" " vec4 result = vec4(0, 1, 0, 1);\n" "\n" "VERIFICATION" "\n" " vs_tcs_result = result;\n" "}\n" "\n"; const GLchar* shader_template = 0; const GLchar* verification_snippet = 0; switch (in_stage) { case Utils::COMPUTE_SHADER: shader_template = compute_shader_template; break; case Utils::FRAGMENT_SHADER: shader_template = fragment_shader_template; break; case Utils::GEOMETRY_SHADER: shader_template = geometry_shader_template; break; case Utils::TESS_CTRL_SHADER: shader_template = tess_ctrl_shader_template; break; case Utils::TESS_EVAL_SHADER: shader_template = tess_eval_shader_template; break; case Utils::VERTEX_SHADER: shader_template = vertex_shader_template; break; default: TCU_FAIL("Invalid enum"); } switch (m_case) { case (glw::GLuint)-1: case 0: verification_snippet = min_verification_snippet; break; case 1: verification_snippet = max_verification_snippet; break; } out_source.m_parts[0].m_code = shader_template; size_t position = 0; Utils::replaceToken("VERSION", position, getVersionString(in_stage, in_use_version_400), out_source.m_parts[0].m_code); Utils::replaceToken("VERIFICATION", position, verification_snippet, out_source.m_parts[0].m_code); } /** Constructor. * * @param context CTS context. **/ Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context), m_target(0) { } /** Destructor * **/ Utils::buffer::~buffer() { release(); } /** Execute BindBuffer * **/ void Utils::buffer::bind() const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindBuffer(m_target, m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer"); } /** Execute BindBufferRange * * @param index parameter * @param offset parameter * @param size parameter **/ void Utils::buffer::bindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindBufferRange(m_target, index, m_id, offset, size); GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange"); } /** Execute GenBuffer * * @param target Target that will be used by this buffer **/ void Utils::buffer::generate(glw::GLenum target) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); m_target = target; gl.genBuffers(1, &m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); } /** Maps buffer content * * @param access Access rights for mapped region * * @return Mapped memory **/ void* Utils::buffer::map(GLenum access) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindBuffer(m_target, m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer"); void* result = gl.mapBuffer(m_target, access); GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer"); return result; } /** Unmaps buffer * **/ void Utils::buffer::unmap() const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindBuffer(m_target, m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer"); gl.unmapBuffer(m_target); GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer"); } /** Execute BufferData * * @param size parameter * @param data parameter * @param usage parameter **/ void Utils::buffer::update(glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindBuffer(m_target, m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer"); gl.bufferData(m_target, size, data, usage); GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData"); } /** Release buffer * **/ void Utils::buffer::release() { if (0 != m_id) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.deleteBuffers(1, &m_id); m_id = 0; } } /** Constructor * * @param context CTS context **/ Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context) { /* Nothing to be done here */ } /** Destructor * **/ Utils::framebuffer::~framebuffer() { if (0 != m_id) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.deleteFramebuffers(1, &m_id); m_id = 0; } } /** Attach texture to specified attachment * * @param attachment Attachment * @param texture_id Texture id * @param width Texture width * @param height Texture height **/ void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width, glw::GLuint height) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); bind(); gl.bindTexture(GL_TEXTURE_2D, texture_id); GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture_id, 0 /* level */); GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D"); gl.viewport(0 /* x */, 0 /* y */, width, height); GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport"); } /** Binds framebuffer to DRAW_FRAMEBUFFER * **/ void Utils::framebuffer::bind() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); } /** Clear framebuffer * * @param mask parameter of glClear. Decides which shall be cleared **/ void Utils::framebuffer::clear(glw::GLenum mask) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.clear(mask); GLU_EXPECT_NO_ERROR(gl.getError(), "Clear"); } /** Specifies clear color * * @param red Red channel * @param green Green channel * @param blue Blue channel * @param alpha Alpha channel **/ void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.clearColor(red, green, blue, alpha); GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor"); } /** Generate framebuffer * **/ void Utils::framebuffer::generate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.genFramebuffers(1, &m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); } Utils::shaderSource::shaderSource() { } Utils::shaderSource::shaderSource(const shaderSource& source) : m_parts(source.m_parts), m_use_lengths(false) { } Utils::shaderSource::shaderSource(const glw::GLchar* source_code) : m_use_lengths(false) { if (0 != source_code) { m_parts.resize(1); m_parts[0].m_code = source_code; } } Utils::shaderCompilationException::shaderCompilationException(const shaderSource& source, const glw::GLchar* message) : m_shader_source(source), m_error_message(message) { /* Nothing to be done */ } const char* Utils::shaderCompilationException::what() const throw() { return "Shader compilation failed"; } Utils::programLinkageException::programLinkageException(const glw::GLchar* message) : m_error_message(message) { /* Nothing to be done */ } const char* Utils::programLinkageException::what() const throw() { return "Program linking failed"; } const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9; /** Constructor. * * @param context CTS context. **/ Utils::program::program(deqp::Context& context) : m_compute_shader_id(0) , m_fragment_shader_id(0) , m_geometry_shader_id(0) , m_program_object_id(0) , m_tesselation_control_shader_id(0) , m_tesselation_evaluation_shader_id(0) , m_vertex_shader_id(0) , m_context(context) { /* Nothing to be done here */ } /** Destructor * **/ Utils::program::~program() { remove(); } /** Build program * * @param compute_shader_code Compute shader source code * @param fragment_shader_code Fragment shader source code * @param geometry_shader_code Geometry shader source code * @param tesselation_control_shader_code Tesselation control shader source code * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code * @param vertex_shader_code Vertex shader source code * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback * @param n_varying_names Number of varyings to be captured with transfrom feedback * @param is_separable Selects if monolithis or separable program should be built. Defaults to false **/ void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code, const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code, const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable) { const shaderSource compute_shader(compute_shader_code); const shaderSource fragment_shader(fragment_shader_code); const shaderSource geometry_shader(geometry_shader_code); const shaderSource tesselation_control_shader(tesselation_control_shader_code); const shaderSource tesselation_evaluation_shader(tesselation_evaluation_shader_code); const shaderSource vertex_shader(vertex_shader_code); build(compute_shader, fragment_shader, geometry_shader, tesselation_control_shader, tesselation_evaluation_shader, vertex_shader, varying_names, n_varying_names, is_separable); } /** Build program * * @param compute_shader_code Compute shader source code * @param fragment_shader_code Fragment shader source code * @param geometry_shader_code Geometry shader source code * @param tesselation_control_shader_code Tesselation control shader source code * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code * @param vertex_shader_code Vertex shader source code * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback * @param n_varying_names Number of varyings to be captured with transfrom feedback * @param is_separable Selects if monolithis or separable program should be built. Defaults to false **/ void Utils::program::build(const shaderSource& compute_shader, const shaderSource& fragment_shader, const shaderSource& geometry_shader, const shaderSource& tesselation_control_shader, const shaderSource& tesselation_evaluation_shader, const shaderSource& vertex_shader, const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable) { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Create shader objects and compile */ if (false == compute_shader.m_parts.empty()) { m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); compile(m_compute_shader_id, compute_shader); } if (false == fragment_shader.m_parts.empty()) { m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); compile(m_fragment_shader_id, fragment_shader); } if (false == geometry_shader.m_parts.empty()) { m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); compile(m_geometry_shader_id, geometry_shader); } if (false == tesselation_control_shader.m_parts.empty()) { m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); compile(m_tesselation_control_shader_id, tesselation_control_shader); } if (false == tesselation_evaluation_shader.m_parts.empty()) { m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader); } if (false == vertex_shader.m_parts.empty()) { m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); compile(m_vertex_shader_id, vertex_shader); } /* Create program object */ m_program_object_id = gl.createProgram(); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); /* Set up captyured varyings' names */ if (0 != n_varying_names) { gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS); GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings"); } /* Set separable parameter */ if (true == is_separable) { gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE); GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri"); } /* Link program */ link(); } void Utils::program::compile(glw::GLuint shader_id, const Utils::shaderSource& source) const { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Compilation status */ glw::GLint status = GL_FALSE; /* Source parts and lengths vectors */ std::vector parts; std::vector lengths_vector; GLint* lengths = 0; /* Prepare storage */ parts.resize(source.m_parts.size()); /* Prepare arrays */ for (GLuint i = 0; i < source.m_parts.size(); ++i) { parts[i] = source.m_parts[i].m_code.c_str(); } if (true == source.m_use_lengths) { lengths_vector.resize(source.m_parts.size()); for (GLuint i = 0; i < source.m_parts.size(); ++i) { lengths_vector[i] = source.m_parts[i].m_length; } lengths = &lengths_vector[0]; } /* Set source code */ gl.shaderSource(shader_id, static_cast(source.m_parts.size()), &parts[0], lengths); GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource"); /* Compile */ gl.compileShader(shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader"); /* Get compilation status */ gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status); GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); /* Log compilation error */ if (GL_TRUE != status) { glw::GLint length = 0; std::vector message; /* Error log length */ gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv"); /* Prepare storage */ message.resize(length); /* Get error log */ gl.getShaderInfoLog(shader_id, length, 0, &message[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog"); throw shaderCompilationException(source, &message[0]); } } /** Create program from provided binary * * @param binary Buffer with binary form of program * @param binary_format Format of data **/ void Utils::program::createFromBinary(const std::vector& binary, GLenum binary_format) { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Create program object */ m_program_object_id = gl.createProgram(); GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram"); gl.programBinary(m_program_object_id, binary_format, &binary[0], static_cast(binary.size())); GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramBinary"); } glw::GLint Utils::program::getAttribLocation(const glw::GLchar* name) const { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLint location = gl.getAttribLocation(m_program_object_id, name); GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation"); return location; } /** Get binary form of program * * @param binary Buffer for binary data * @param binary_format Format of binary data **/ void Utils::program::getBinary(std::vector& binary, GLenum& binary_format) const { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Get binary size */ GLint length = 0; gl.getProgramiv(m_program_object_id, GL_PROGRAM_BINARY_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); /* Allocate storage */ binary.resize(length); /* Get binary */ gl.getProgramBinary(m_program_object_id, static_cast(binary.size()), &length, &binary_format, &binary[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramBinary"); } /** Get subroutine index * * @param subroutine_name Subroutine name * * @return Index of subroutine **/ GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLuint index = -1; index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name); GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex"); if (GL_INVALID_INDEX == index) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name << " is not available" << tcu::TestLog::EndMessage; TCU_FAIL("Subroutine is not available"); } return index; } /** Get subroutine uniform location * * @param uniform_name Subroutine uniform name * * @return Location of subroutine uniform **/ GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLint location = -1; location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name); GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation"); if (-1 == location) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name << " is not available" << tcu::TestLog::EndMessage; TCU_FAIL("Subroutine uniform is not available"); } return location; } /** Get integer uniform at given location * * @param location Uniform location * * @return Value **/ GLint Utils::program::getUniform1i(GLuint location) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLint result; gl.getUniformiv(m_program_object_id, location, &result); GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformiv"); return result; } /** Get uniform location * * @param uniform_name Subroutine uniform name * * @return Location of uniform **/ GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLint location = -1; location = gl.getUniformLocation(m_program_object_id, uniform_name); GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation"); if (-1 == location) { m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name << " is not available" << tcu::TestLog::EndMessage; TCU_FAIL("Uniform is not available"); } return location; } /** Attach shaders and link program * **/ void Utils::program::link() const { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Link status */ glw::GLint status = GL_FALSE; /* Attach shaders */ if (0 != m_compute_shader_id) { gl.attachShader(m_program_object_id, m_compute_shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); } if (0 != m_fragment_shader_id) { gl.attachShader(m_program_object_id, m_fragment_shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); } if (0 != m_geometry_shader_id) { gl.attachShader(m_program_object_id, m_geometry_shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); } if (0 != m_tesselation_control_shader_id) { gl.attachShader(m_program_object_id, m_tesselation_control_shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); } if (0 != m_tesselation_evaluation_shader_id) { gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); } if (0 != m_vertex_shader_id) { gl.attachShader(m_program_object_id, m_vertex_shader_id); GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader"); } /* Link */ gl.linkProgram(m_program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram"); /* Get link status */ gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); /* Log link error */ if (GL_TRUE != status) { glw::GLint length = 0; std::vector message; /* Get error log length */ gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv"); message.resize(length); /* Get error log */ gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]); GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog"); throw programLinkageException(&message[0]); } } /** Delete program object and all attached shaders * **/ void Utils::program::remove() { /* GL entry points */ const glw::Functions& gl = m_context.getRenderContext().getFunctions(); /* Make sure program object is no longer used by GL */ gl.useProgram(0); /* Clean program object */ if (0 != m_program_object_id) { gl.deleteProgram(m_program_object_id); m_program_object_id = 0; } /* Clean shaders */ if (0 != m_compute_shader_id) { gl.deleteShader(m_compute_shader_id); m_compute_shader_id = 0; } if (0 != m_fragment_shader_id) { gl.deleteShader(m_fragment_shader_id); m_fragment_shader_id = 0; } if (0 != m_geometry_shader_id) { gl.deleteShader(m_geometry_shader_id); m_geometry_shader_id = 0; } if (0 != m_tesselation_control_shader_id) { gl.deleteShader(m_tesselation_control_shader_id); m_tesselation_control_shader_id = 0; } if (0 != m_tesselation_evaluation_shader_id) { gl.deleteShader(m_tesselation_evaluation_shader_id); m_tesselation_evaluation_shader_id = 0; } if (0 != m_vertex_shader_id) { gl.deleteShader(m_vertex_shader_id); m_vertex_shader_id = 0; } } void Utils::program::uniform(const glw::GLchar* uniform_name, TYPES type, glw::GLuint n_columns, glw::GLuint n_rows, const void* data) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLuint location = getUniformLocation(uniform_name); if ((glw::GLuint)-1 == location) { TCU_FAIL("Uniform is inactive"); } switch (type) { case DOUBLE: if (1 == n_columns) { getUniformNdv(gl, n_rows)(location, 1 /* count */, (const GLdouble*)data); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNdv"); } else { getUniformMatrixNdv(gl, n_columns, n_rows)(location, 1 /* count */, false, (const GLdouble*)data); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNdv"); } break; case FLOAT: if (1 == n_columns) { getUniformNfv(gl, n_rows)(location, 1 /* count */, (const GLfloat*)data); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNfv"); } else { getUniformMatrixNfv(gl, n_columns, n_rows)(location, 1 /* count */, false, (const GLfloat*)data); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNfv"); } break; case INT: getUniformNiv(gl, n_rows)(location, 1 /* count */, (const GLint*)data); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNiv"); break; case UINT: getUniformNuiv(gl, n_rows)(location, 1 /* count */, (const GLuint*)data); GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNuiv"); break; default: TCU_FAIL("Invalid enum"); } } /** Execute UseProgram * **/ void Utils::program::use() const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.useProgram(m_program_object_id); GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram"); } void Utils::program::printShaderSource(const shaderSource& source, tcu::MessageBuilder& log) { GLuint line_number = 0; log << "Shader source."; for (GLuint i = 0; i < source.m_parts.size(); ++i) { log << "\nLine||Part: " << (i + 1) << "/" << source.m_parts.size(); if (true == source.m_use_lengths) { log << " Length: " << source.m_parts[i].m_length; } log << "\n"; const GLchar* part = source.m_parts[i].m_code.c_str(); while (0 != part) { std::string line; const GLchar* next_line = strchr(part, '\n'); if (0 != next_line) { next_line += 1; line.assign(part, next_line - part); } else { line = part; } if (0 != *part) { log << std::setw(4) << line_number << "||" << line; } part = next_line; line_number += 1; } } } /** Constructor. * * @param context CTS context. **/ Utils::texture::texture(deqp::Context& context) : m_id(0), m_buffer_id(0), m_context(context), m_texture_type(TEX_2D) { /* Nothing to done here */ } /** Destructor * **/ Utils::texture::~texture() { release(); } /** Bind texture to GL_TEXTURE_2D * **/ void Utils::texture::bind() const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLenum target = getTextureTartet(m_texture_type); gl.bindTexture(target, m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture"); } /** Create 2d texture * * @param width Width of texture * @param height Height of texture * @param internal_format Internal format of texture **/ void Utils::texture::create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); release(); m_texture_type = TEX_2D; gl.genTextures(1, &m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); bind(); gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); } /** Create texture of given type * * @param width Width of texture * @param height Height of texture * @param depth Depth of texture * @param internal_format Internal format of texture * @param texture_type Type of texture **/ void Utils::texture::create(GLuint width, GLuint height, GLuint depth, GLenum internal_format, TEXTURE_TYPES texture_type) { static const GLuint levels = 1; const glw::Functions& gl = m_context.getRenderContext().getFunctions(); release(); m_texture_type = texture_type; GLenum target = getTextureTartet(m_texture_type); gl.genTextures(1, &m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); bind(); switch (m_texture_type) { case TEX_1D: gl.texStorage1D(target, levels, internal_format, width); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D"); break; case TEX_2D: case TEX_1D_ARRAY: case TEX_2D_RECT: case TEX_CUBE: gl.texStorage2D(target, levels, internal_format, width, height); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); break; case TEX_3D: case TEX_2D_ARRAY: gl.texStorage3D(target, levels, internal_format, width, height, depth); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D"); break; default: TCU_FAIL("Invliad enum"); } } /** Create buffer texture * * @param internal_format Internal format of texture * @param buffer_id Id of buffer that will be used as data source **/ void Utils::texture::createBuffer(GLenum internal_format, GLuint buffer_id) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); release(); m_texture_type = TEX_BUFFER; m_buffer_id = buffer_id; gl.genTextures(1, &m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures"); bind(); gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id); GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer"); } /** Get contents of texture * * @param format Format of image * @param type Type of image * @param out_data Buffer for image **/ void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLenum target = getTextureTartet(m_texture_type); bind(); gl.memoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT); GLU_EXPECT_NO_ERROR(gl.getError(), "MemoryBarrier"); if (TEX_CUBE != m_texture_type) { gl.getTexImage(target, 0 /* level */, format, type, out_data); GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); } else { GLint width; GLint height; if ((GL_RGBA != format) && (GL_UNSIGNED_BYTE != type)) { TCU_FAIL("Not implemented"); } GLuint texel_size = 4; gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_WIDTH, &width); GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv"); gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_HEIGHT, &height); GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv"); const GLuint image_size = width * height * texel_size; gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, format, type, (GLvoid*)((GLchar*)out_data + (image_size * 0))); gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, format, type, (GLvoid*)((GLchar*)out_data + (image_size * 1))); gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, format, type, (GLvoid*)((GLchar*)out_data + (image_size * 2))); gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, format, type, (GLvoid*)((GLchar*)out_data + (image_size * 3))); gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, format, type, (GLvoid*)((GLchar*)out_data + (image_size * 4))); gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, format, type, (GLvoid*)((GLchar*)out_data + (image_size * 5))); GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage"); } } /** Delete texture * **/ void Utils::texture::release() { if (0 != m_id) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.deleteTextures(1, &m_id); m_id = 0; if ((m_texture_type == TEX_BUFFER) && (0 != m_buffer_id)) { gl.deleteBuffers(1, &m_buffer_id); m_buffer_id = 0; } } } /** Update contents of texture * * @param width Width of texture * @param height Height of texture * @param format Format of data * @param type Type of data * @param data Buffer with image **/ void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format, glw::GLenum type, glw::GLvoid* data) { static const GLuint level = 0; const glw::Functions& gl = m_context.getRenderContext().getFunctions(); GLenum target = getTextureTartet(m_texture_type); bind(); switch (m_texture_type) { case TEX_1D: gl.texSubImage1D(target, level, 0 /* x */, width, format, type, data); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D"); break; case TEX_2D: case TEX_1D_ARRAY: case TEX_2D_RECT: gl.texSubImage2D(target, level, 0 /* x */, 0 /* y */, width, height, format, type, data); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); break; case TEX_CUBE: gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type, data); gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type, data); gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type, data); gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type, data); gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type, data); gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type, data); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D"); break; case TEX_3D: case TEX_2D_ARRAY: gl.texSubImage3D(target, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format, type, data); GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D"); break; default: TCU_FAIL("Invliad enum"); } } /** Constructor. * * @param context CTS context. **/ Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context) { } /** Destructor * **/ Utils::vertexArray::~vertexArray() { if (0 != m_id) { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.deleteVertexArrays(1, &m_id); m_id = 0; } } /** Execute BindVertexArray * **/ void Utils::vertexArray::bind() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.bindVertexArray(m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray"); } /** Execute GenVertexArrays * **/ void Utils::vertexArray::generate() { const glw::Functions& gl = m_context.getRenderContext().getFunctions(); gl.genVertexArrays(1, &m_id); GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays"); } } /* GLSL420Pack namespace */ /** Constructor. * * @param context Rendering context. **/ ShadingLanguage420PackTests::ShadingLanguage420PackTests(deqp::Context& context) : TestCaseGroup(context, "shading_language_420pack", "Verifies \"shading_language_420pack\" functionality") { /* Left blank on purpose */ } /** Initializes a texture_storage_multisample test group. * **/ void ShadingLanguage420PackTests::init(void) { addChild(new GLSL420Pack::BindingSamplerSingleTest(m_context)); addChild(new GLSL420Pack::BindingImageSingleTest(m_context)); addChild(new GLSL420Pack::UTF8CharactersTest(m_context)); addChild(new GLSL420Pack::UTF8InSourceTest(m_context)); addChild(new GLSL420Pack::QualifierOrderTest(m_context)); addChild(new GLSL420Pack::QualifierOrderBlockTest(m_context)); addChild(new GLSL420Pack::LineContinuationTest(m_context)); addChild(new GLSL420Pack::LineNumberingTest(m_context)); addChild(new GLSL420Pack::ImplicitConversionsValidTest(m_context)); addChild(new GLSL420Pack::ImplicitConversionsInvalidTest(m_context)); addChild(new GLSL420Pack::ConstDynamicValueTest(m_context)); addChild(new GLSL420Pack::ConstAssignmentTest(m_context)); addChild(new GLSL420Pack::ConstDynamicValueAsConstExprTest(m_context)); addChild(new GLSL420Pack::QualifierOrderUniformTest(m_context)); addChild(new GLSL420Pack::QualifierOrderFunctionInoutTest(m_context)); addChild(new GLSL420Pack::QualifierOrderFunctionInputTest(m_context)); addChild(new GLSL420Pack::QualifierOrderFunctionOutputTest(m_context)); addChild(new GLSL420Pack::QualifierOverrideLayoutTest(m_context)); addChild(new GLSL420Pack::BindingUniformBlocksTest(m_context)); addChild(new GLSL420Pack::BindingUniformSingleBlockTest(m_context)); addChild(new GLSL420Pack::BindingUniformBlockArrayTest(m_context)); addChild(new GLSL420Pack::BindingUniformDefaultTest(m_context)); addChild(new GLSL420Pack::BindingUniformAPIOverirdeTest(m_context)); addChild(new GLSL420Pack::BindingUniformGlobalBlockTest(m_context)); addChild(new GLSL420Pack::BindingUniformInvalidTest(m_context)); addChild(new GLSL420Pack::BindingSamplersTest(m_context)); addChild(new GLSL420Pack::BindingSamplerArrayTest(m_context)); addChild(new GLSL420Pack::BindingSamplerDefaultTest(m_context)); addChild(new GLSL420Pack::BindingSamplerAPIOverrideTest(m_context)); addChild(new GLSL420Pack::BindingSamplerInvalidTest(m_context)); addChild(new GLSL420Pack::BindingImagesTest(m_context)); addChild(new GLSL420Pack::BindingImageArrayTest(m_context)); addChild(new GLSL420Pack::BindingImageDefaultTest(m_context)); addChild(new GLSL420Pack::BindingImageAPIOverrideTest(m_context)); addChild(new GLSL420Pack::BindingImageInvalidTest(m_context)); addChild(new GLSL420Pack::InitializerListTest(m_context)); addChild(new GLSL420Pack::InitializerListNegativeTest(m_context)); addChild(new GLSL420Pack::LengthOfVectorAndMatrixTest(m_context)); addChild(new GLSL420Pack::LengthOfComputeResultTest(m_context)); addChild(new GLSL420Pack::ScalarSwizzlersTest(m_context)); addChild(new GLSL420Pack::ScalarSwizzlersInvalidTest(m_context)); addChild(new GLSL420Pack::BuiltInValuesTest(m_context)); addChild(new GLSL420Pack::BuiltInAssignmentTest(m_context)); } } /* gl4cts namespace */