| /*------------------------------------------------------------------------- |
| * 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 gl4GPUShaderFP64Tests.cpp |
| * \brief Implements conformance tests for "GPU Shader FP64" functionality. |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "gl4cGPUShaderFP64Tests.hpp" |
| #include "gluContextInfo.hpp" |
| #include "glwFunctions.hpp" |
| #include "tcuMatrix.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include <iomanip> |
| |
| #include "deMath.h" |
| #include "deUniquePtr.hpp" |
| #include "tcuMatrixUtil.hpp" |
| #include "tcuVectorUtil.hpp" |
| |
| #include <cstdlib> |
| #include <cstring> |
| #include <limits> |
| #include <memory> |
| |
| namespace gl4cts |
| { |
| |
| const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9; |
| |
| /** Constructor |
| * |
| * @param context Test context |
| **/ |
| Utils::programInfo::programInfo(deqp::Context& context) |
| : m_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) |
| { |
| /* Nothing to be done here */ |
| } |
| |
| /** Destructor |
| * |
| **/ |
| Utils::programInfo::~programInfo() |
| { |
| /* 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; |
| } |
| } |
| |
| /** 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 |
| **/ |
| void Utils::programInfo::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) |
| { |
| /* GL entry points */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Create shader objects and compile */ |
| if (0 != compute_shader_code) |
| { |
| m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); |
| |
| compile(m_compute_shader_id, compute_shader_code); |
| } |
| |
| if (0 != fragment_shader_code) |
| { |
| m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); |
| |
| compile(m_fragment_shader_id, fragment_shader_code); |
| } |
| |
| if (0 != geometry_shader_code) |
| { |
| m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); |
| |
| compile(m_geometry_shader_id, geometry_shader_code); |
| } |
| |
| if (0 != tesselation_control_shader_code) |
| { |
| 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_code); |
| } |
| |
| if (0 != tesselation_evaluation_shader_code) |
| { |
| 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_code); |
| } |
| |
| if (0 != vertex_shader_code) |
| { |
| m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader"); |
| |
| compile(m_vertex_shader_id, vertex_shader_code); |
| } |
| |
| /* 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"); |
| } |
| |
| /* Link program */ |
| link(); |
| } |
| |
| /** Compile shader |
| * |
| * @param shader_id Shader object id |
| * @param shader_code Shader source code |
| **/ |
| void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const |
| { |
| /* GL entry points */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Compilation status */ |
| glw::GLint status = GL_FALSE; |
| |
| /* Set source code */ |
| gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0); |
| 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<glw::GLchar> 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"); |
| |
| /* Log */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n" |
| << &message[0] << "\nShader source\n" |
| << shader_code << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Failed to compile shader"); |
| } |
| } |
| |
| /** Attach shaders and link program |
| * |
| **/ |
| void Utils::programInfo::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<glw::GLchar> 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"); |
| |
| /* Log */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n" |
| << &message[0] << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Failed to link program"); |
| } |
| } |
| |
| /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision |
| * matrix types. |
| * |
| * @param type Variable type to return base type for. |
| * |
| * @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized. |
| **/ |
| Utils::_variable_type Utils::getBaseVariableType(_variable_type type) |
| { |
| _variable_type result = VARIABLE_TYPE_UNKNOWN; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| { |
| result = VARIABLE_TYPE_BOOL; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DOUBLE: |
| case VARIABLE_TYPE_DMAT2: |
| case VARIABLE_TYPE_DMAT2X3: |
| case VARIABLE_TYPE_DMAT2X4: |
| case VARIABLE_TYPE_DMAT3: |
| case VARIABLE_TYPE_DMAT3X2: |
| case VARIABLE_TYPE_DMAT3X4: |
| case VARIABLE_TYPE_DMAT4: |
| case VARIABLE_TYPE_DMAT4X2: |
| case VARIABLE_TYPE_DMAT4X3: |
| case VARIABLE_TYPE_DVEC2: |
| case VARIABLE_TYPE_DVEC3: |
| case VARIABLE_TYPE_DVEC4: |
| { |
| result = VARIABLE_TYPE_DOUBLE; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_INT: |
| case VARIABLE_TYPE_IVEC2: |
| case VARIABLE_TYPE_IVEC3: |
| case VARIABLE_TYPE_IVEC4: |
| { |
| result = VARIABLE_TYPE_INT; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_UINT: |
| case VARIABLE_TYPE_UVEC2: |
| case VARIABLE_TYPE_UVEC3: |
| case VARIABLE_TYPE_UVEC4: |
| { |
| result = VARIABLE_TYPE_UINT; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_FLOAT: |
| case VARIABLE_TYPE_MAT2: |
| case VARIABLE_TYPE_MAT2X3: |
| case VARIABLE_TYPE_MAT2X4: |
| case VARIABLE_TYPE_MAT3: |
| case VARIABLE_TYPE_MAT3X2: |
| case VARIABLE_TYPE_MAT3X4: |
| case VARIABLE_TYPE_MAT4: |
| case VARIABLE_TYPE_MAT4X2: |
| case VARIABLE_TYPE_MAT4X3: |
| case VARIABLE_TYPE_VEC2: |
| case VARIABLE_TYPE_VEC3: |
| case VARIABLE_TYPE_VEC4: |
| { |
| result = VARIABLE_TYPE_FLOAT; |
| |
| break; |
| } |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type"); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Returns size (in bytes) of a single component of a base variable type. |
| * |
| * @param type Base variable type to use for the query. |
| * |
| * @return Requested value or 0 if @param type was not recognized. |
| **/ |
| unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type) |
| { |
| unsigned int result = 0; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| result = sizeof(bool); |
| break; |
| case VARIABLE_TYPE_DOUBLE: |
| result = sizeof(double); |
| break; |
| case VARIABLE_TYPE_FLOAT: |
| result = sizeof(float); |
| break; |
| case VARIABLE_TYPE_INT: |
| result = sizeof(int); |
| break; |
| case VARIABLE_TYPE_UINT: |
| result = sizeof(unsigned int); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type"); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Returns component, corresponding to user-specified index |
| * (eg. index:0 corresponds to 'x', index:1 corresponds to 'y', |
| * and so on. |
| * |
| * @param index Component index. |
| * |
| * @return As per description. |
| **/ |
| unsigned char Utils::getComponentAtIndex(unsigned int index) |
| { |
| unsigned char result = '?'; |
| |
| switch (index) |
| { |
| case 0: |
| result = 'x'; |
| break; |
| case 1: |
| result = 'y'; |
| break; |
| case 2: |
| result = 'z'; |
| break; |
| case 3: |
| result = 'w'; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized component index"); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** Get _variable_type representing double-precision type with given dimmensions |
| * |
| * @param n_columns Number of columns |
| * @param n_row Number of rows |
| * |
| * @return Corresponding _variable_type |
| **/ |
| Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows) |
| { |
| Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN; |
| |
| static const _variable_type types[4][4] = { |
| { VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4 }, |
| { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4 }, |
| { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4 }, |
| { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4 } |
| }; |
| |
| type = types[n_columns - 1][n_rows - 1]; |
| |
| return type; |
| } |
| |
| /** Returns a single-precision equivalent of a double-precision floating-point variable |
| * type. |
| * |
| * @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types |
| * are accepted. |
| * |
| * @return Requested GLSL type. |
| **/ |
| std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type) |
| { |
| std::string result = "[?]"; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_DOUBLE: |
| result = "float"; |
| break; |
| case VARIABLE_TYPE_DMAT2: |
| result = "mat2"; |
| break; |
| case VARIABLE_TYPE_DMAT2X3: |
| result = "mat2x3"; |
| break; |
| case VARIABLE_TYPE_DMAT2X4: |
| result = "mat2x4"; |
| break; |
| case VARIABLE_TYPE_DMAT3: |
| result = "mat3"; |
| break; |
| case VARIABLE_TYPE_DMAT3X2: |
| result = "mat3x2"; |
| break; |
| case VARIABLE_TYPE_DMAT3X4: |
| result = "mat3x4"; |
| break; |
| case VARIABLE_TYPE_DMAT4: |
| result = "mat4"; |
| break; |
| case VARIABLE_TYPE_DMAT4X2: |
| result = "mat4x2"; |
| break; |
| case VARIABLE_TYPE_DMAT4X3: |
| result = "mat4x3"; |
| break; |
| case VARIABLE_TYPE_DVEC2: |
| result = "vec2"; |
| break; |
| case VARIABLE_TYPE_DVEC3: |
| result = "vec3"; |
| break; |
| case VARIABLE_TYPE_DVEC4: |
| result = "vec4"; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type"); |
| } |
| }; /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Returns GL data type enum corresponding to user-provided base variable type. |
| * |
| * @param type Base variable type to return corresponding GLenum value for. |
| * |
| * @return Corresponding GLenum value or GL_NONE if the input value was not |
| * recognized. |
| **/ |
| glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type) |
| { |
| glw::GLenum result = GL_NONE; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| result = GL_BOOL; |
| break; |
| case VARIABLE_TYPE_DOUBLE: |
| result = GL_DOUBLE; |
| break; |
| case VARIABLE_TYPE_FLOAT: |
| result = GL_FLOAT; |
| break; |
| case VARIABLE_TYPE_INT: |
| result = GL_INT; |
| break; |
| case VARIABLE_TYPE_UINT: |
| result = GL_UNSIGNED_INT; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type"); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** Return GLenum representing given <type> |
| * |
| * @param type Type of variable |
| * |
| * @return GL enumeration |
| **/ |
| glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type) |
| { |
| glw::GLenum result = GL_NONE; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| result = GL_BOOL; |
| break; |
| case VARIABLE_TYPE_DOUBLE: |
| result = GL_DOUBLE; |
| break; |
| case VARIABLE_TYPE_DMAT2: |
| result = GL_DOUBLE_MAT2; |
| break; |
| case VARIABLE_TYPE_DMAT2X3: |
| result = GL_DOUBLE_MAT2x3; |
| break; |
| case VARIABLE_TYPE_DMAT2X4: |
| result = GL_DOUBLE_MAT2x4; |
| break; |
| case VARIABLE_TYPE_DMAT3: |
| result = GL_DOUBLE_MAT3; |
| break; |
| case VARIABLE_TYPE_DMAT3X2: |
| result = GL_DOUBLE_MAT3x2; |
| break; |
| case VARIABLE_TYPE_DMAT3X4: |
| result = GL_DOUBLE_MAT3x4; |
| break; |
| case VARIABLE_TYPE_DMAT4: |
| result = GL_DOUBLE_MAT4; |
| break; |
| case VARIABLE_TYPE_DMAT4X2: |
| result = GL_DOUBLE_MAT4x2; |
| break; |
| case VARIABLE_TYPE_DMAT4X3: |
| result = GL_DOUBLE_MAT4x3; |
| break; |
| case VARIABLE_TYPE_DVEC2: |
| result = GL_DOUBLE_VEC2; |
| break; |
| case VARIABLE_TYPE_DVEC3: |
| result = GL_DOUBLE_VEC3; |
| break; |
| case VARIABLE_TYPE_DVEC4: |
| result = GL_DOUBLE_VEC4; |
| break; |
| case VARIABLE_TYPE_FLOAT: |
| result = GL_FLOAT; |
| break; |
| case VARIABLE_TYPE_INT: |
| result = GL_INT; |
| break; |
| case VARIABLE_TYPE_IVEC2: |
| result = GL_INT_VEC2; |
| break; |
| case VARIABLE_TYPE_IVEC3: |
| result = GL_INT_VEC3; |
| break; |
| case VARIABLE_TYPE_IVEC4: |
| result = GL_INT_VEC4; |
| break; |
| case VARIABLE_TYPE_MAT2: |
| result = GL_FLOAT_MAT2; |
| break; |
| case VARIABLE_TYPE_MAT2X3: |
| result = GL_FLOAT_MAT2x3; |
| break; |
| case VARIABLE_TYPE_MAT2X4: |
| result = GL_FLOAT_MAT2x4; |
| break; |
| case VARIABLE_TYPE_MAT3: |
| result = GL_FLOAT_MAT3; |
| break; |
| case VARIABLE_TYPE_MAT3X2: |
| result = GL_FLOAT_MAT3x2; |
| break; |
| case VARIABLE_TYPE_MAT3X4: |
| result = GL_FLOAT_MAT3x4; |
| break; |
| case VARIABLE_TYPE_MAT4: |
| result = GL_FLOAT_MAT4; |
| break; |
| case VARIABLE_TYPE_MAT4X2: |
| result = GL_FLOAT_MAT4x2; |
| break; |
| case VARIABLE_TYPE_MAT4X3: |
| result = GL_FLOAT_MAT4x3; |
| break; |
| case VARIABLE_TYPE_UINT: |
| result = GL_UNSIGNED_INT; |
| break; |
| case VARIABLE_TYPE_UVEC2: |
| result = GL_UNSIGNED_INT_VEC2; |
| break; |
| case VARIABLE_TYPE_UVEC3: |
| result = GL_UNSIGNED_INT_VEC3; |
| break; |
| case VARIABLE_TYPE_UVEC4: |
| result = GL_UNSIGNED_INT_VEC4; |
| break; |
| case VARIABLE_TYPE_VEC2: |
| result = GL_FLOAT_VEC2; |
| break; |
| case VARIABLE_TYPE_VEC3: |
| result = GL_FLOAT_VEC3; |
| break; |
| case VARIABLE_TYPE_VEC4: |
| result = GL_FLOAT_VEC4; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type"); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** Get _variable_type representing integer type with given dimmensions |
| * |
| * @param n_columns Number of columns |
| * @param n_row Number of rows |
| * |
| * @return Corresponding _variable_type |
| **/ |
| Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows) |
| { |
| Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN; |
| |
| static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3, |
| VARIABLE_TYPE_IVEC4 }; |
| |
| if (1 != n_columns) |
| { |
| TCU_FAIL("Not implemented"); |
| } |
| else |
| { |
| type = types[n_rows - 1]; |
| } |
| |
| return type; |
| } |
| |
| /** Returns te number of components that variables defined with user-specified type |
| * support. For matrix types, total amount of values accessible for the type will be |
| * returned. |
| * |
| * @param type Variable type to return the described vale for. |
| * |
| * @return As per description or 0 if @param type was not recognized. |
| */ |
| unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type) |
| { |
| unsigned int result = 0; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| case VARIABLE_TYPE_DOUBLE: |
| case VARIABLE_TYPE_FLOAT: |
| case VARIABLE_TYPE_INT: |
| case VARIABLE_TYPE_UINT: |
| { |
| result = 1; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DVEC2: |
| case VARIABLE_TYPE_IVEC2: |
| case VARIABLE_TYPE_UVEC2: |
| case VARIABLE_TYPE_VEC2: |
| { |
| result = 2; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DVEC3: |
| case VARIABLE_TYPE_IVEC3: |
| case VARIABLE_TYPE_UVEC3: |
| case VARIABLE_TYPE_VEC3: |
| { |
| result = 3; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DVEC4: |
| case VARIABLE_TYPE_IVEC4: |
| case VARIABLE_TYPE_UVEC4: |
| case VARIABLE_TYPE_VEC4: |
| { |
| result = 4; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT2: |
| case VARIABLE_TYPE_MAT2: |
| { |
| result = 2 * 2; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT2X3: |
| case VARIABLE_TYPE_DMAT3X2: |
| case VARIABLE_TYPE_MAT2X3: |
| case VARIABLE_TYPE_MAT3X2: |
| { |
| result = 2 * 3; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT2X4: |
| case VARIABLE_TYPE_DMAT4X2: |
| case VARIABLE_TYPE_MAT2X4: |
| case VARIABLE_TYPE_MAT4X2: |
| { |
| result = 2 * 4; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT3: |
| case VARIABLE_TYPE_MAT3: |
| { |
| result = 3 * 3; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT3X4: |
| case VARIABLE_TYPE_DMAT4X3: |
| case VARIABLE_TYPE_MAT3X4: |
| case VARIABLE_TYPE_MAT4X3: |
| { |
| result = 3 * 4; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT4: |
| case VARIABLE_TYPE_MAT4: |
| { |
| result = 4 * 4; |
| |
| break; |
| } |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized type"); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Returns number of columns user-specified matrix variable type describes. |
| * |
| * @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT* |
| * values are valid. |
| * |
| * @return As per description. |
| **/ |
| unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type) |
| { |
| unsigned int result = 0; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| case VARIABLE_TYPE_DOUBLE: |
| case VARIABLE_TYPE_FLOAT: |
| case VARIABLE_TYPE_INT: |
| case VARIABLE_TYPE_UINT: |
| case VARIABLE_TYPE_DVEC2: |
| case VARIABLE_TYPE_IVEC2: |
| case VARIABLE_TYPE_UVEC2: |
| case VARIABLE_TYPE_VEC2: |
| case VARIABLE_TYPE_DVEC3: |
| case VARIABLE_TYPE_IVEC3: |
| case VARIABLE_TYPE_UVEC3: |
| case VARIABLE_TYPE_VEC3: |
| case VARIABLE_TYPE_DVEC4: |
| case VARIABLE_TYPE_IVEC4: |
| case VARIABLE_TYPE_UVEC4: |
| case VARIABLE_TYPE_VEC4: |
| { |
| result = 1; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT2: |
| case VARIABLE_TYPE_DMAT2X3: |
| case VARIABLE_TYPE_DMAT2X4: |
| case VARIABLE_TYPE_MAT2: |
| case VARIABLE_TYPE_MAT2X3: |
| case VARIABLE_TYPE_MAT2X4: |
| { |
| result = 2; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT3: |
| case VARIABLE_TYPE_DMAT3X2: |
| case VARIABLE_TYPE_DMAT3X4: |
| case VARIABLE_TYPE_MAT3: |
| case VARIABLE_TYPE_MAT3X2: |
| case VARIABLE_TYPE_MAT3X4: |
| { |
| result = 3; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DMAT4: |
| case VARIABLE_TYPE_DMAT4X2: |
| case VARIABLE_TYPE_DMAT4X3: |
| case VARIABLE_TYPE_MAT4: |
| case VARIABLE_TYPE_MAT4X2: |
| case VARIABLE_TYPE_MAT4X3: |
| { |
| result = 4; |
| |
| break; |
| } |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized type"); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Returns maximum number of uniform locations taken by user-specified double-precision |
| * variable type. |
| * |
| * @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid. |
| * |
| * @return As per description. |
| **/ |
| unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type) |
| { |
| unsigned int result = 0; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_DOUBLE: |
| result = 1; |
| break; |
| case VARIABLE_TYPE_DVEC2: |
| result = 1; |
| break; |
| case VARIABLE_TYPE_DVEC3: |
| result = 2; |
| break; |
| case VARIABLE_TYPE_DVEC4: |
| result = 2; |
| break; |
| case VARIABLE_TYPE_DMAT2: |
| result = 2; |
| break; |
| case VARIABLE_TYPE_DMAT2X3: |
| result = 6; |
| break; |
| case VARIABLE_TYPE_DMAT2X4: |
| result = 8; |
| break; |
| case VARIABLE_TYPE_DMAT3: |
| result = 6; |
| break; |
| case VARIABLE_TYPE_DMAT3X2: |
| result = 4; |
| break; |
| case VARIABLE_TYPE_DMAT3X4: |
| result = 8; |
| break; |
| case VARIABLE_TYPE_DMAT4: |
| result = 8; |
| break; |
| case VARIABLE_TYPE_DMAT4X2: |
| result = 4; |
| break; |
| case VARIABLE_TYPE_DMAT4X3: |
| result = 6; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized type"); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Get number of rows for given variable type |
| * |
| * @param type Type of variable |
| * |
| * @return Number of rows |
| **/ |
| unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type) |
| { |
| unsigned int result = 0; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| case VARIABLE_TYPE_DOUBLE: |
| case VARIABLE_TYPE_FLOAT: |
| case VARIABLE_TYPE_INT: |
| case VARIABLE_TYPE_UINT: |
| { |
| result = 1; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DVEC2: |
| case VARIABLE_TYPE_IVEC2: |
| case VARIABLE_TYPE_UVEC2: |
| case VARIABLE_TYPE_VEC2: |
| case VARIABLE_TYPE_DMAT2: |
| case VARIABLE_TYPE_DMAT3X2: |
| case VARIABLE_TYPE_DMAT4X2: |
| case VARIABLE_TYPE_MAT2: |
| case VARIABLE_TYPE_MAT3X2: |
| case VARIABLE_TYPE_MAT4X2: |
| { |
| result = 2; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DVEC3: |
| case VARIABLE_TYPE_IVEC3: |
| case VARIABLE_TYPE_UVEC3: |
| case VARIABLE_TYPE_VEC3: |
| case VARIABLE_TYPE_DMAT2X3: |
| case VARIABLE_TYPE_DMAT3: |
| case VARIABLE_TYPE_DMAT4X3: |
| case VARIABLE_TYPE_MAT2X3: |
| case VARIABLE_TYPE_MAT3: |
| case VARIABLE_TYPE_MAT4X3: |
| { |
| result = 3; |
| |
| break; |
| } |
| |
| case VARIABLE_TYPE_DVEC4: |
| case VARIABLE_TYPE_IVEC4: |
| case VARIABLE_TYPE_UVEC4: |
| case VARIABLE_TYPE_VEC4: |
| case VARIABLE_TYPE_DMAT2X4: |
| case VARIABLE_TYPE_DMAT3X4: |
| case VARIABLE_TYPE_DMAT4: |
| case VARIABLE_TYPE_MAT2X4: |
| case VARIABLE_TYPE_MAT3X4: |
| case VARIABLE_TYPE_MAT4: |
| { |
| result = 4; |
| |
| break; |
| } |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized type"); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Returns variable type of a matrix constructed by multiplying two matrices. |
| * |
| * @param type_matrix_a L-side matrix type. |
| * @param type_matrix_b R-side matrix type. |
| * |
| * @return As per description. |
| **/ |
| Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a, |
| _variable_type type_matrix_b) |
| { |
| const unsigned int n_a_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_a); |
| const unsigned int n_a_components = Utils::getNumberOfComponentsForVariableType(type_matrix_a); |
| const unsigned int n_a_rows = n_a_components / n_a_columns; |
| const unsigned int n_b_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_b); |
| const unsigned int n_result_columns = n_b_columns; |
| const unsigned int n_result_rows = n_a_rows; |
| Utils::_variable_type result; |
| |
| switch (n_result_columns) |
| { |
| case 2: |
| { |
| switch (n_result_rows) |
| { |
| case 2: |
| result = VARIABLE_TYPE_DMAT2; |
| break; |
| case 3: |
| result = VARIABLE_TYPE_DMAT2X3; |
| break; |
| case 4: |
| result = VARIABLE_TYPE_DMAT2X4; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized amount of rows in result variable"); |
| } |
| } /* switch (n_result_rows) */ |
| |
| break; |
| } /* case 2: */ |
| |
| case 3: |
| { |
| switch (n_result_rows) |
| { |
| case 2: |
| result = VARIABLE_TYPE_DMAT3X2; |
| break; |
| case 3: |
| result = VARIABLE_TYPE_DMAT3; |
| break; |
| case 4: |
| result = VARIABLE_TYPE_DMAT3X4; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized amount of rows in result variable"); |
| } |
| } /* switch (n_result_rows) */ |
| |
| break; |
| } /* case 3: */ |
| |
| case 4: |
| { |
| switch (n_result_rows) |
| { |
| case 2: |
| result = VARIABLE_TYPE_DMAT4X2; |
| break; |
| case 3: |
| result = VARIABLE_TYPE_DMAT4X3; |
| break; |
| case 4: |
| result = VARIABLE_TYPE_DMAT4; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized amount of rows in result variable"); |
| } |
| } /* switch (n_result_rows) */ |
| |
| break; |
| } /* case 4: */ |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized amount of columns in result variable"); |
| } |
| } /* switch (n_result_columns) */ |
| |
| /* Done */ |
| return result; |
| } |
| |
| /** Returns a string holding the value represented by user-provided variable, for which |
| * the data are represented in @param type variable type. |
| * |
| * @return As per description. |
| **/ |
| std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr) |
| { |
| std::stringstream result_sstream; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| result_sstream << *((bool*)data_ptr); |
| break; |
| case VARIABLE_TYPE_DOUBLE: |
| result_sstream << *((double*)data_ptr); |
| break; |
| case VARIABLE_TYPE_FLOAT: |
| result_sstream << *((float*)data_ptr); |
| break; |
| case VARIABLE_TYPE_INT: |
| result_sstream << *((int*)data_ptr); |
| break; |
| case VARIABLE_TYPE_UINT: |
| result_sstream << *((unsigned int*)data_ptr); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type requested"); |
| } |
| } /* switch (type) */ |
| |
| return result_sstream.str(); |
| } |
| |
| /** Returns variable type of a transposed matrix of user-specified variable type. |
| * |
| * @param type Variable type of the matrix to be transposed. |
| * |
| * @return Transposed matrix variable type. |
| **/ |
| Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type) |
| { |
| Utils::_variable_type result; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_DMAT2: |
| result = VARIABLE_TYPE_DMAT2; |
| break; |
| case VARIABLE_TYPE_DMAT2X3: |
| result = VARIABLE_TYPE_DMAT3X2; |
| break; |
| case VARIABLE_TYPE_DMAT2X4: |
| result = VARIABLE_TYPE_DMAT4X2; |
| break; |
| case VARIABLE_TYPE_DMAT3: |
| result = VARIABLE_TYPE_DMAT3; |
| break; |
| case VARIABLE_TYPE_DMAT3X2: |
| result = VARIABLE_TYPE_DMAT2X3; |
| break; |
| case VARIABLE_TYPE_DMAT3X4: |
| result = VARIABLE_TYPE_DMAT4X3; |
| break; |
| case VARIABLE_TYPE_DMAT4: |
| result = VARIABLE_TYPE_DMAT4; |
| break; |
| case VARIABLE_TYPE_DMAT4X2: |
| result = VARIABLE_TYPE_DMAT2X4; |
| break; |
| case VARIABLE_TYPE_DMAT4X3: |
| result = VARIABLE_TYPE_DMAT3X4; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized double-precision matrix variable type."); |
| } |
| } /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Get _variable_type representing unsigned integer type with given dimmensions |
| * |
| * @param n_columns Number of columns |
| * @param n_row Number of rows |
| * |
| * @return Corresponding _variable_type |
| **/ |
| Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows) |
| { |
| Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN; |
| |
| static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3, |
| VARIABLE_TYPE_UVEC4 }; |
| |
| if (1 != n_columns) |
| { |
| TCU_FAIL("Not implemented"); |
| } |
| else |
| { |
| type = types[n_rows - 1]; |
| } |
| |
| return type; |
| } |
| |
| /** Returns a literal corresponding to a GLSL keyword describing user-specified |
| * variable type. |
| * |
| * @param type Variable type to use for the query. |
| * |
| * @return Requested GLSL keyword or [?] if @param type was not recognized. |
| **/ |
| std::string Utils::getVariableTypeString(_variable_type type) |
| { |
| std::string result = "[?]"; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| result = "bool"; |
| break; |
| case VARIABLE_TYPE_BVEC2: |
| result = "bvec2"; |
| break; |
| case VARIABLE_TYPE_BVEC3: |
| result = "bvec3"; |
| break; |
| case VARIABLE_TYPE_BVEC4: |
| result = "bvec4"; |
| break; |
| case VARIABLE_TYPE_DOUBLE: |
| result = "double"; |
| break; |
| case VARIABLE_TYPE_DMAT2: |
| result = "dmat2"; |
| break; |
| case VARIABLE_TYPE_DMAT2X3: |
| result = "dmat2x3"; |
| break; |
| case VARIABLE_TYPE_DMAT2X4: |
| result = "dmat2x4"; |
| break; |
| case VARIABLE_TYPE_DMAT3: |
| result = "dmat3"; |
| break; |
| case VARIABLE_TYPE_DMAT3X2: |
| result = "dmat3x2"; |
| break; |
| case VARIABLE_TYPE_DMAT3X4: |
| result = "dmat3x4"; |
| break; |
| case VARIABLE_TYPE_DMAT4: |
| result = "dmat4"; |
| break; |
| case VARIABLE_TYPE_DMAT4X2: |
| result = "dmat4x2"; |
| break; |
| case VARIABLE_TYPE_DMAT4X3: |
| result = "dmat4x3"; |
| break; |
| case VARIABLE_TYPE_DVEC2: |
| result = "dvec2"; |
| break; |
| case VARIABLE_TYPE_DVEC3: |
| result = "dvec3"; |
| break; |
| case VARIABLE_TYPE_DVEC4: |
| result = "dvec4"; |
| break; |
| case VARIABLE_TYPE_FLOAT: |
| result = "float"; |
| break; |
| case VARIABLE_TYPE_INT: |
| result = "int"; |
| break; |
| case VARIABLE_TYPE_IVEC2: |
| result = "ivec2"; |
| break; |
| case VARIABLE_TYPE_IVEC3: |
| result = "ivec3"; |
| break; |
| case VARIABLE_TYPE_IVEC4: |
| result = "ivec4"; |
| break; |
| case VARIABLE_TYPE_MAT2: |
| result = "mat2"; |
| break; |
| case VARIABLE_TYPE_MAT2X3: |
| result = "mat2x3"; |
| break; |
| case VARIABLE_TYPE_MAT2X4: |
| result = "mat2x4"; |
| break; |
| case VARIABLE_TYPE_MAT3: |
| result = "mat3"; |
| break; |
| case VARIABLE_TYPE_MAT3X2: |
| result = "mat3x2"; |
| break; |
| case VARIABLE_TYPE_MAT3X4: |
| result = "mat3x4"; |
| break; |
| case VARIABLE_TYPE_MAT4: |
| result = "mat4"; |
| break; |
| case VARIABLE_TYPE_MAT4X2: |
| result = "mat4x2"; |
| break; |
| case VARIABLE_TYPE_MAT4X3: |
| result = "mat4x3"; |
| break; |
| case VARIABLE_TYPE_UINT: |
| result = "uint"; |
| break; |
| case VARIABLE_TYPE_UVEC2: |
| result = "uvec2"; |
| break; |
| case VARIABLE_TYPE_UVEC3: |
| result = "uvec3"; |
| break; |
| case VARIABLE_TYPE_UVEC4: |
| result = "uvec4"; |
| break; |
| case VARIABLE_TYPE_VEC2: |
| result = "vec2"; |
| break; |
| case VARIABLE_TYPE_VEC3: |
| result = "vec3"; |
| break; |
| case VARIABLE_TYPE_VEC4: |
| result = "vec4"; |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized variable type"); |
| } |
| }; /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** 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; |
| } |
| } |
| |
| /** Tells whether user-specified variable type corresponds to a matrix type. |
| * |
| * @param type Variable type to use for the query. |
| * |
| * @return true if the variable type describes a matrix, false otherwise. |
| **/ |
| bool Utils::isMatrixVariableType(_variable_type type) |
| { |
| return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 || |
| type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 || |
| type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 || |
| type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 || |
| type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 || |
| type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3); |
| } |
| |
| /** Tells whether user-specified variable type is scalar. |
| * |
| * @return true if @param type is a scalar variable type, false otherwise. |
| **/ |
| bool Utils::isScalarVariableType(_variable_type type) |
| { |
| bool result = false; |
| |
| switch (type) |
| { |
| case VARIABLE_TYPE_BOOL: |
| result = true; |
| break; |
| case VARIABLE_TYPE_DOUBLE: |
| result = true; |
| break; |
| case VARIABLE_TYPE_FLOAT: |
| result = true; |
| break; |
| case VARIABLE_TYPE_INT: |
| result = true; |
| break; |
| case VARIABLE_TYPE_UINT: |
| result = true; |
| break; |
| default: |
| break; |
| }; /* switch (type) */ |
| |
| return result; |
| } |
| |
| /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion> |
| * |
| * @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 <token> |
| * @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; |
| } |
| |
| /** Constructor. |
| * |
| * @param context Rendering context. |
| * |
| **/ |
| GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context) |
| : TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision " |
| "float uniform support & glUniform*() / glUniformMatrix*() API " |
| " are reported correctly.") |
| , m_has_test_passed(true) |
| , m_po_bool_arr_uniform_location(0) |
| , m_po_bool_uniform_location(0) |
| , m_po_bvec2_arr_uniform_location(0) |
| , m_po_bvec2_uniform_location(0) |
| , m_po_bvec3_arr_uniform_location(0) |
| , m_po_bvec3_uniform_location(0) |
| , m_po_bvec4_arr_uniform_location(0) |
| , m_po_bvec4_uniform_location(0) |
| , m_po_dmat2_arr_uniform_location(0) |
| , m_po_dmat2_uniform_location(0) |
| , m_po_dmat2x3_arr_uniform_location(0) |
| , m_po_dmat2x3_uniform_location(0) |
| , m_po_dmat2x4_arr_uniform_location(0) |
| , m_po_dmat2x4_uniform_location(0) |
| , m_po_dmat3_arr_uniform_location(0) |
| , m_po_dmat3_uniform_location(0) |
| , m_po_dmat3x2_arr_uniform_location(0) |
| , m_po_dmat3x2_uniform_location(0) |
| , m_po_dmat3x4_arr_uniform_location(0) |
| , m_po_dmat3x4_uniform_location(0) |
| , m_po_dmat4_arr_uniform_location(0) |
| , m_po_dmat4_uniform_location(0) |
| , m_po_dmat4x2_arr_uniform_location(0) |
| , m_po_dmat4x2_uniform_location(0) |
| , m_po_dmat4x3_arr_uniform_location(0) |
| , m_po_dmat4x3_uniform_location(0) |
| , m_po_double_arr_uniform_location(0) |
| , m_po_double_uniform_location(0) |
| , m_po_dvec2_arr_uniform_location(0) |
| , m_po_dvec2_uniform_location(0) |
| , m_po_dvec3_arr_uniform_location(0) |
| , m_po_dvec3_uniform_location(0) |
| , m_po_dvec4_arr_uniform_location(0) |
| , m_po_dvec4_uniform_location(0) |
| , m_po_float_arr_uniform_location(0) |
| , m_po_float_uniform_location(0) |
| , m_po_int_arr_uniform_location(0) |
| , m_po_int_uniform_location(0) |
| , m_po_ivec2_arr_uniform_location(0) |
| , m_po_ivec2_uniform_location(0) |
| , m_po_ivec3_arr_uniform_location(0) |
| , m_po_ivec3_uniform_location(0) |
| , m_po_ivec4_arr_uniform_location(0) |
| , m_po_ivec4_uniform_location(0) |
| , m_po_sampler_uniform_location(0) |
| , m_po_uint_arr_uniform_location(0) |
| , m_po_uint_uniform_location(0) |
| , m_po_uvec2_arr_uniform_location(0) |
| , m_po_uvec2_uniform_location(0) |
| , m_po_uvec3_arr_uniform_location(0) |
| , m_po_uvec3_uniform_location(0) |
| , m_po_uvec4_arr_uniform_location(0) |
| , m_po_uvec4_uniform_location(0) |
| , m_po_vec2_arr_uniform_location(0) |
| , m_po_vec2_uniform_location(0) |
| , m_po_vec3_arr_uniform_location(0) |
| , m_po_vec3_uniform_location(0) |
| , m_po_vec4_arr_uniform_location(0) |
| , m_po_vec4_uniform_location(0) |
| , m_po_id(0) |
| , m_vs_id(0) |
| { |
| /* Left blank intentionally */ |
| } |
| |
| /** Deinitializes all GL objects that may have been created during |
| * test execution. |
| **/ |
| void GPUShaderFP64Test1::deinit() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| if (m_po_id != 0) |
| { |
| gl.deleteProgram(m_po_id); |
| |
| m_po_id = 0; |
| } |
| |
| if (m_vs_id != 0) |
| { |
| gl.deleteShader(m_vs_id); |
| |
| m_vs_id = 0; |
| } |
| } |
| |
| /** Returns a string describing GL API function represented by user-provided enum. |
| * |
| * @param func Uniform function to return the string for. |
| * |
| * @return As per description. [?] will be returned if the function was not recognized. |
| **/ |
| const char* GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func) |
| { |
| const char* result = "[?]"; |
| |
| switch (func) |
| { |
| case UNIFORM_FUNCTION_1D: |
| result = "glUniform1d"; |
| break; |
| case UNIFORM_FUNCTION_1DV: |
| result = "glUniform1dv"; |
| break; |
| case UNIFORM_FUNCTION_2D: |
| result = "glUniform2d"; |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| result = "glUniform2dv"; |
| break; |
| case UNIFORM_FUNCTION_3D: |
| result = "glUniform3d"; |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| result = "glUniform3dv"; |
| break; |
| case UNIFORM_FUNCTION_4D: |
| result = "glUniform4d"; |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| result = "glUniform4dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| result = "glUniformMatrix2dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| result = "glUniformMatrix2x3dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| result = "glUniformMatrix2x4dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| result = "glUniformMatrix3dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| result = "glUniformMatrix3x2dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| result = "glUniformMatrix3x4dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| result = "glUniformMatrix4dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| result = "glUniformMatrix4x2dv"; |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| result = "glUniformMatrix4x3dv"; |
| break; |
| default: |
| break; |
| } |
| |
| return result; |
| } |
| |
| /** Returns name of an uniform bound to user-provided location. |
| * |
| * @param location Location of the uniform to return the name for. |
| * |
| * @return As per description. [?] will be returned if the location was not |
| * recognized. |
| **/ |
| const char* GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location) |
| { |
| const char* result = "[?]"; |
| |
| if (location == m_po_bool_arr_uniform_location) |
| result = "uniform_bool_arr"; |
| else if (location == m_po_bool_uniform_location) |
| result = "uniform_bool"; |
| else if (location == m_po_bvec2_arr_uniform_location) |
| result = "uniform_bvec2_arr"; |
| else if (location == m_po_bvec2_uniform_location) |
| result = "uniform_bvec2"; |
| else if (location == m_po_bvec3_arr_uniform_location) |
| result = "uniform_bvec3_arr"; |
| else if (location == m_po_bvec3_uniform_location) |
| result = "uniform_bvec3"; |
| else if (location == m_po_bvec4_arr_uniform_location) |
| result = "uniform_bvec4_arr"; |
| else if (location == m_po_bvec4_uniform_location) |
| result = "uniform_bvec4"; |
| else if (location == m_po_dmat2_arr_uniform_location) |
| result = "uniform_dmat2_arr"; |
| else if (location == m_po_dmat2_uniform_location) |
| result = "uniform_dmat2"; |
| else if (location == m_po_dmat2x3_arr_uniform_location) |
| result = "uniform_dmat2x3_arr"; |
| else if (location == m_po_dmat2x3_uniform_location) |
| result = "uniform_dmat2x3"; |
| else if (location == m_po_dmat2x4_arr_uniform_location) |
| result = "uniform_dmat2x4_arr"; |
| else if (location == m_po_dmat2x4_uniform_location) |
| result = "uniform_dmat2x4"; |
| else if (location == m_po_dmat3_arr_uniform_location) |
| result = "uniform_dmat3_arr"; |
| else if (location == m_po_dmat3_uniform_location) |
| result = "uniform_dmat3"; |
| else if (location == m_po_dmat3x2_arr_uniform_location) |
| result = "uniform_dmat3x2_arr"; |
| else if (location == m_po_dmat3x2_uniform_location) |
| result = "uniform_dmat3x2"; |
| else if (location == m_po_dmat3x4_arr_uniform_location) |
| result = "uniform_dmat3x4_arr"; |
| else if (location == m_po_dmat3x4_uniform_location) |
| result = "uniform_dmat3x4"; |
| else if (location == m_po_dmat4_arr_uniform_location) |
| result = "uniform_dmat4_arr"; |
| else if (location == m_po_dmat4_uniform_location) |
| result = "uniform_dmat4"; |
| else if (location == m_po_dmat4x2_arr_uniform_location) |
| result = "uniform_dmat4x2_arr"; |
| else if (location == m_po_dmat4x2_uniform_location) |
| result = "uniform_dmat4x2"; |
| else if (location == m_po_dmat4x3_arr_uniform_location) |
| result = "uniform_dmat4x3_arr"; |
| else if (location == m_po_dmat4x3_uniform_location) |
| result = "uniform_dmat4x3"; |
| else if (location == m_po_double_arr_uniform_location) |
| result = "uniform_double_arr"; |
| else if (location == m_po_double_uniform_location) |
| result = "uniform_double"; |
| else if (location == m_po_dvec2_arr_uniform_location) |
| result = "uniform_dvec2_arr"; |
| else if (location == m_po_dvec2_uniform_location) |
| result = "uniform_dvec2"; |
| else if (location == m_po_dvec3_arr_uniform_location) |
| result = "uniform_dvec3_arr"; |
| else if (location == m_po_dvec3_uniform_location) |
| result = "uniform_dvec3"; |
| else if (location == m_po_dvec4_arr_uniform_location) |
| result = "uniform_dvec4_arr"; |
| else if (location == m_po_dvec4_uniform_location) |
| result = "uniform_dvec4"; |
| else if (location == m_po_float_arr_uniform_location) |
| result = "uniform_float_arr"; |
| else if (location == m_po_float_uniform_location) |
| result = "uniform_float"; |
| else if (location == m_po_int_arr_uniform_location) |
| result = "uniform_int_arr"; |
| else if (location == m_po_int_uniform_location) |
| result = "uniform_int"; |
| else if (location == m_po_ivec2_arr_uniform_location) |
| result = "uniform_ivec2_arr"; |
| else if (location == m_po_ivec2_uniform_location) |
| result = "uniform_ivec2"; |
| else if (location == m_po_ivec3_arr_uniform_location) |
| result = "uniform_ivec3_arr"; |
| else if (location == m_po_ivec3_uniform_location) |
| result = "uniform_ivec3"; |
| else if (location == m_po_ivec4_arr_uniform_location) |
| result = "uniform_ivec4_arr"; |
| else if (location == m_po_ivec4_uniform_location) |
| result = "uniform_ivec4"; |
| else if (location == m_po_uint_arr_uniform_location) |
| result = "uniform_uint_arr"; |
| else if (location == m_po_uint_uniform_location) |
| result = "uniform_uint"; |
| else if (location == m_po_uvec2_arr_uniform_location) |
| result = "uniform_uvec2_arr"; |
| else if (location == m_po_uvec2_uniform_location) |
| result = "uniform_uvec2"; |
| else if (location == m_po_uvec3_arr_uniform_location) |
| result = "uniform_uvec3_arr"; |
| else if (location == m_po_uvec3_uniform_location) |
| result = "uniform_uvec3"; |
| else if (location == m_po_uvec4_arr_uniform_location) |
| result = "uniform_uvec4_arr"; |
| else if (location == m_po_uvec4_uniform_location) |
| result = "uniform_uvec4"; |
| else if (location == m_po_vec2_arr_uniform_location) |
| result = "uniform_vec2_arr"; |
| else if (location == m_po_vec2_uniform_location) |
| result = "uniform_vec2"; |
| else if (location == m_po_vec3_arr_uniform_location) |
| result = "uniform_vec3_arr"; |
| else if (location == m_po_vec3_uniform_location) |
| result = "uniform_vec3"; |
| else if (location == m_po_vec4_arr_uniform_location) |
| result = "uniform_vec4_arr"; |
| else if (location == m_po_vec4_uniform_location) |
| result = "uniform_vec4"; |
| |
| return result; |
| } |
| |
| /** Initializes all GL objects required to run the test. Also extracts locations of all |
| * uniforms used by the test. |
| * |
| * This function can throw a TestError exception if the implementation misbehaves. |
| */ |
| void GPUShaderFP64Test1::initTest() |
| { |
| glw::GLint compile_status = GL_FALSE; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| glw::GLint link_status = GL_FALSE; |
| |
| /* Set up a program object using all new double-precision types */ |
| const char* vs_body = |
| "#version 400\n" |
| "\n" |
| "uniform bool uniform_bool;\n" |
| "uniform bvec2 uniform_bvec2;\n" |
| "uniform bvec3 uniform_bvec3;\n" |
| "uniform bvec4 uniform_bvec4;\n" |
| "uniform dmat2 uniform_dmat2;\n" |
| "uniform dmat2x3 uniform_dmat2x3;\n" |
| "uniform dmat2x4 uniform_dmat2x4;\n" |
| "uniform dmat3 uniform_dmat3;\n" |
| "uniform dmat3x2 uniform_dmat3x2;\n" |
| "uniform dmat3x4 uniform_dmat3x4;\n" |
| "uniform dmat4 uniform_dmat4;\n" |
| "uniform dmat4x2 uniform_dmat4x2;\n" |
| "uniform dmat4x3 uniform_dmat4x3;\n" |
| "uniform double uniform_double;\n" |
| "uniform dvec2 uniform_dvec2;\n" |
| "uniform dvec3 uniform_dvec3;\n" |
| "uniform dvec4 uniform_dvec4;\n" |
| "uniform float uniform_float;\n" |
| "uniform int uniform_int;\n" |
| "uniform ivec2 uniform_ivec2;\n" |
| "uniform ivec3 uniform_ivec3;\n" |
| "uniform ivec4 uniform_ivec4;\n" |
| "uniform sampler2D uniform_sampler;\n" |
| "uniform uint uniform_uint;\n" |
| "uniform uvec2 uniform_uvec2;\n" |
| "uniform uvec3 uniform_uvec3;\n" |
| "uniform uvec4 uniform_uvec4;\n" |
| "uniform vec2 uniform_vec2;\n" |
| "uniform vec3 uniform_vec3;\n" |
| "uniform vec4 uniform_vec4;\n" |
| "uniform bool uniform_bool_arr [2];\n" |
| "uniform bvec2 uniform_bvec2_arr [2];\n" |
| "uniform bvec3 uniform_bvec3_arr [2];\n" |
| "uniform bvec4 uniform_bvec4_arr [2];\n" |
| "uniform dmat2 uniform_dmat2_arr [2];\n" |
| "uniform dmat2x3 uniform_dmat2x3_arr[2];\n" |
| "uniform dmat2x4 uniform_dmat2x4_arr[2];\n" |
| "uniform dmat3 uniform_dmat3_arr [2];\n" |
| "uniform dmat3x2 uniform_dmat3x2_arr[2];\n" |
| "uniform dmat3x4 uniform_dmat3x4_arr[2];\n" |
| "uniform dmat4 uniform_dmat4_arr [2];\n" |
| "uniform dmat4x2 uniform_dmat4x2_arr[2];\n" |
| "uniform dmat4x3 uniform_dmat4x3_arr[2];\n" |
| "uniform double uniform_double_arr [2];\n" |
| "uniform dvec2 uniform_dvec2_arr [2];\n" |
| "uniform dvec3 uniform_dvec3_arr [2];\n" |
| "uniform dvec4 uniform_dvec4_arr [2];\n" |
| "uniform float uniform_float_arr [2];\n" |
| "uniform int uniform_int_arr [2];\n" |
| "uniform ivec2 uniform_ivec2_arr [2];\n" |
| "uniform ivec3 uniform_ivec3_arr [2];\n" |
| "uniform ivec4 uniform_ivec4_arr [2];\n" |
| "uniform uint uniform_uint_arr [2];\n" |
| "uniform uvec2 uniform_uvec2_arr [2];\n" |
| "uniform uvec3 uniform_uvec3_arr [2];\n" |
| "uniform uvec4 uniform_uvec4_arr [2];\n" |
| "uniform vec2 uniform_vec2_arr [2];\n" |
| "uniform vec3 uniform_vec3_arr [2];\n" |
| "uniform vec4 uniform_vec4_arr [2];\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n" |
| "\n" |
| " if (uniform_bool && uniform_bvec2.y && uniform_bvec3.z && uniform_bvec4.w &&\n" |
| " uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n" |
| " {\n" |
| " double sum = uniform_dmat2 [0].x + uniform_dmat2x3 [0].x + uniform_dmat2x4 [0].x +\n" |
| " uniform_dmat3 [0].x + uniform_dmat3x2 [0].x + uniform_dmat3x4 [0].x +\n" |
| " uniform_dmat4 [0].x + uniform_dmat4x2 [0].x + uniform_dmat4x3 [0].x +\n" |
| " uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n" |
| " uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n" |
| " uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n" |
| " uniform_double + uniform_double_arr [0] +\n" |
| " uniform_dvec2.x + uniform_dvec3.x + uniform_dvec4.x +\n" |
| " uniform_dvec2_arr[0].x + uniform_dvec3_arr[0].x + uniform_dvec4_arr[0].x;\n" |
| " int sum2 = uniform_int + uniform_ivec2.x + uniform_ivec3.x +\n" |
| " uniform_ivec4.x + uniform_ivec2_arr[0].x + uniform_ivec3_arr[0].x +\n" |
| " uniform_ivec4_arr[0].x + uniform_int_arr[0];\n" |
| " uint sum3 = uniform_uint + uniform_uvec2.x + uniform_uvec3.x +\n" |
| " uniform_uvec4.x + uniform_uint_arr[0] + uniform_uvec2_arr[0].x +\n" |
| " uniform_uvec3_arr[0].x + uniform_uvec4_arr[0].x;\n" |
| " float sum4 = uniform_float + uniform_float_arr[0] + \n" |
| " uniform_vec2.x + uniform_vec2_arr[0].x + \n" |
| " uniform_vec3.x + uniform_vec3_arr[0].x + \n" |
| " uniform_vec4.x + uniform_vec4_arr[0].x;\n" |
| "\n" |
| " if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n" |
| " {\n" |
| " gl_Position = vec4(1);\n" |
| " }\n" |
| " }\n" |
| "}\n"; |
| |
| m_po_id = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed."); |
| |
| m_vs_id = gl.createShader(GL_VERTEX_SHADER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed."); |
| |
| gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed."); |
| |
| gl.compileShader(m_vs_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed."); |
| |
| gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed."); |
| |
| if (compile_status != GL_TRUE) |
| { |
| TCU_FAIL("Shader compilation failed."); |
| } |
| |
| gl.attachShader(m_po_id, m_vs_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed."); |
| |
| gl.linkProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed."); |
| |
| gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed."); |
| |
| if (link_status != GL_TRUE) |
| { |
| TCU_FAIL("Program linking failed."); |
| } |
| |
| m_po_bool_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]"); |
| m_po_bool_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bool"); |
| m_po_bvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]"); |
| m_po_bvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec2"); |
| m_po_bvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]"); |
| m_po_bvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec3"); |
| m_po_bvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]"); |
| m_po_bvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec4"); |
| m_po_dmat2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]"); |
| m_po_dmat2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2"); |
| m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]"); |
| m_po_dmat2x3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3"); |
| m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]"); |
| m_po_dmat2x4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4"); |
| m_po_dmat3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]"); |
| m_po_dmat3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3"); |
| m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]"); |
| m_po_dmat3x2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2"); |
| m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]"); |
| m_po_dmat3x4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4"); |
| m_po_dmat4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]"); |
| m_po_dmat4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4"); |
| m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]"); |
| m_po_dmat4x2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2"); |
| m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]"); |
| m_po_dmat4x3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3"); |
| m_po_double_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]"); |
| m_po_double_uniform_location = gl.getUniformLocation(m_po_id, "uniform_double"); |
| m_po_dvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]"); |
| m_po_dvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec2"); |
| m_po_dvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]"); |
| m_po_dvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec3"); |
| m_po_dvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]"); |
| m_po_dvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec4"); |
| m_po_float_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]"); |
| m_po_float_uniform_location = gl.getUniformLocation(m_po_id, "uniform_float"); |
| m_po_int_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]"); |
| m_po_int_uniform_location = gl.getUniformLocation(m_po_id, "uniform_int"); |
| m_po_ivec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]"); |
| m_po_ivec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec2"); |
| m_po_ivec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]"); |
| m_po_ivec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec3"); |
| m_po_ivec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]"); |
| m_po_ivec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec4"); |
| m_po_sampler_uniform_location = gl.getUniformLocation(m_po_id, "uniform_sampler"); |
| m_po_uint_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]"); |
| m_po_uint_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uint"); |
| m_po_uvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]"); |
| m_po_uvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec2"); |
| m_po_uvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]"); |
| m_po_uvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec3"); |
| m_po_uvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]"); |
| m_po_uvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec4"); |
| m_po_vec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]"); |
| m_po_vec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec2"); |
| m_po_vec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]"); |
| m_po_vec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec3"); |
| m_po_vec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]"); |
| m_po_vec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec4"); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed."); |
| |
| if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 || |
| m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 || |
| m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 || |
| m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 || |
| m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 || |
| m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 || |
| m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 || |
| m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 || |
| m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 || |
| m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 || |
| m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 || |
| m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 || |
| m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 || |
| m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 || |
| m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 || |
| m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 || |
| m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 || |
| m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 || |
| m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 || |
| m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 || |
| m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 || |
| m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 || |
| m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 || |
| m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 || |
| m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 || |
| m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 || |
| m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 || |
| m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 || |
| m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1) |
| { |
| TCU_FAIL("At last one of the required uniforms is considered inactive."); |
| } |
| } |
| |
| /** Tells wheter uniform at user-specified location represents a double-precision |
| * matrix uniform. |
| * |
| * @param uniform_location Location of the uniform to use for the query. |
| * |
| * @return Requested information. |
| **/ |
| bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location) |
| { |
| return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location || |
| uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location || |
| uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location || |
| uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location || |
| uniform_location == m_po_dmat4x3_uniform_location); |
| } |
| |
| /** Tells whether user-specified uniform function corresponds to one of the |
| * functions in glUniformMatrix*() class. |
| * |
| * @param func Uniform function enum to use for the query. |
| * |
| * @return true if the specified enum represents one of the glUniformMatrix*() functions, |
| * false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func) |
| { |
| return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV || |
| func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV || |
| func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV || |
| func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV || |
| func == UNIFORM_FUNCTION_MATRIX4X3DV); |
| } |
| |
| /** Executes test iteration. |
| * |
| * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed. |
| */ |
| tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate() |
| { |
| /* Do not execute the test if GL_ARB_texture_view is not supported */ |
| if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64")) |
| { |
| throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported."); |
| } |
| |
| /* Initialize all ES objects required to run all the checks */ |
| initTest(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated by glUniform*() and |
| * glUniformMatrix*() functions if there is no current program object. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated by glUniform*() if |
| * the size of the uniform variable declared in the shader does not |
| * match the size indicated by the command. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and |
| * glUniformMatrix*() are used to load a uniform variable of type |
| * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4, |
| * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array |
| * of these. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and |
| * glUniformMatrix*() are used to load incompatible double-typed |
| * uniforms, as presented below: |
| * |
| * I. double-typed uniform configured by glUniform2d(); |
| * II. double-typed uniform configured by glUniform3d(); |
| * III. double-typed uniform configured by glUniform4d(); |
| * IV. double-typed uniform configured by glUniformMatrix*(); |
| * V. dvec2-typed uniform configured by glUniform1d(); |
| * VI. dvec2-typed uniform configured by glUniform3d(); |
| * VII. dvec2-typed uniform configured by glUniform4d(); |
| * VIII. dvec2-typed uniform configured by glUniformMatrix*(); |
| * |
| * (etc.) |
| * |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated if <location> of |
| * glUniform*() and glUniformMatrix*() is an invalid uniform |
| * location for the current program object and location is not |
| * equal to -1. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation(); |
| |
| /* Make sure GL_INVALID_VALUE is generated if <count> of |
| * glUniform*() (*dv() functions only) and glUniformMatrix*() is |
| * negative. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated if <count> of |
| * glUniform*() (*dv() functions only) and glUniformMatrix*() is |
| * greater than 1 and the indicated uniform variable is not an |
| * array variable. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated if a sampler is |
| * loaded by glUniform*() and glUniformMatrix*(). |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers(); |
| |
| /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and |
| * glUniformMatrix*() is used to load values for uniforms of |
| * boolean types. |
| */ |
| m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans(); |
| |
| if (m_has_test_passed) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| |
| return STOP; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or |
| * glUniformMatrix*dv() functions is used to load a boolean uniform. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans() |
| { |
| const double double_data[] = { |
| 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 |
| }; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| glw::GLint uniform_locations[] = { m_po_bool_arr_uniform_location, m_po_bool_uniform_location, |
| m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location, |
| m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location, |
| m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location }; |
| const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]); |
| |
| for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT; |
| ++n_uniform_function) |
| { |
| const _uniform_function uniform_function = (_uniform_function)n_uniform_function; |
| |
| for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location) |
| { |
| const glw::GLint uniform_location = uniform_locations[n_uniform_location]; |
| |
| switch (uniform_function) |
| { |
| case UNIFORM_FUNCTION_1D: |
| gl.uniform1d(uniform_location, 0.0); |
| break; |
| case UNIFORM_FUNCTION_2D: |
| gl.uniform2d(uniform_location, 0.0, 1.0); |
| break; |
| case UNIFORM_FUNCTION_3D: |
| gl.uniform3d(uniform_location, 0.0, 1.0, 2.0); |
| break; |
| case UNIFORM_FUNCTION_4D: |
| gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0); |
| break; |
| |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(uniform_location, 1 /* count */, double_data); |
| break; |
| |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized uniform function"); |
| } |
| } |
| |
| /* Make sure GL_INVALID_OPERATION was generated by the call */ |
| const glw::GLenum error_code = gl.getError(); |
| |
| if (error_code != GL_INVALID_OPERATION) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) |
| << "() did not generate an error" |
| " when applied against a boolean uniform." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all bool uniforms) */ |
| } /* for (all uniform functions) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or |
| * glUniformMatrix*dv() functions is used to load a sampler2D uniform. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers() |
| { |
| const double double_data[] = { |
| 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 |
| }; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT; |
| ++n_uniform_function) |
| { |
| _uniform_function uniform_function = (_uniform_function)n_uniform_function; |
| |
| switch (uniform_function) |
| { |
| case UNIFORM_FUNCTION_1D: |
| gl.uniform1d(m_po_sampler_uniform_location, 0.0); |
| break; |
| case UNIFORM_FUNCTION_2D: |
| gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0); |
| break; |
| case UNIFORM_FUNCTION_3D: |
| gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0); |
| break; |
| case UNIFORM_FUNCTION_4D: |
| gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0); |
| break; |
| |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data); |
| break; |
| |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized uniform function"); |
| } |
| } |
| |
| /* Make sure GL_INVALID_OPERATION was generated by the call */ |
| const glw::GLenum error_code = gl.getError(); |
| |
| if (error_code != GL_INVALID_OPERATION) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) |
| << "() did not generate an error" |
| " when applied against a sampler uniform." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all uniform functions) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or |
| * glUniformMatrix*dv() functions is used to load a compatible uniform using an |
| * invalid <count> argument. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount() |
| { |
| const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, |
| 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV, |
| UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV, |
| UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV, |
| UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV, |
| UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV, |
| UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV, |
| UNIFORM_FUNCTION_MATRIX4X3DV }; |
| const glw::GLint uniforms[] = { |
| m_po_bool_uniform_location, m_po_bvec2_uniform_location, m_po_bvec3_uniform_location, |
| m_po_bvec4_uniform_location, m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location, |
| m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location, m_po_dmat3x2_uniform_location, |
| m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location, |
| m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location, |
| m_po_dvec3_uniform_location, m_po_dvec4_uniform_location, m_po_float_uniform_location, |
| m_po_int_uniform_location, m_po_ivec2_uniform_location, m_po_ivec3_uniform_location, |
| m_po_ivec4_uniform_location, m_po_uint_uniform_location, m_po_uvec2_uniform_location, |
| m_po_uvec3_uniform_location, m_po_uvec4_uniform_location, m_po_vec2_uniform_location, |
| m_po_vec3_uniform_location, m_po_vec4_uniform_location |
| }; |
| |
| const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]); |
| const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]); |
| |
| for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function) |
| { |
| _uniform_function uniform_function = uniform_functions[n_uniform_function]; |
| |
| for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform) |
| { |
| glw::GLint uniform_location = uniforms[n_uniform]; |
| |
| /* Make sure we only use glUniformMatrix*() functions with matrix uniforms, |
| * and glUniform*() functions with vector uniforms. |
| */ |
| bool is_matrix_uniform = isMatrixUniform(uniform_location); |
| |
| if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) || |
| ((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function)))) |
| { |
| continue; |
| } |
| |
| /* Issue the call with an invalid <count> argument */ |
| switch (uniform_function) |
| { |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(uniform_location, 2, double_values); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(uniform_location, 2, double_values); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(uniform_location, 2, double_values); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(uniform_location, 2, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized uniform function"); |
| } |
| } /* switch (uniform_function) */ |
| |
| /* Make sure GL_INVALID_VALUE was generated */ |
| glw::GLenum error_code = gl.getError(); |
| |
| if (error_code != GL_INVALID_OPERATION) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) |
| << "() " |
| "was called with an invalid count argument but did not generate a " |
| "GL_INVALID_OPERATION error" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all non-arrayed uniforms) */ |
| } /* for (all uniform functions) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or |
| * glUniformMatrix*dv() functions is used to load an uniform at an invalid location. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation() |
| { |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| /* Find the largest valid uniform location */ |
| const glw::GLint uniform_locations[] = { |
| m_po_bool_arr_uniform_location, m_po_bool_uniform_location, m_po_bvec2_arr_uniform_location, |
| m_po_bvec2_uniform_location, m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location, |
| m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location, m_po_dmat2_arr_uniform_location, |
| m_po_dmat2_uniform_location, m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location, |
| m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location, m_po_dmat3_arr_uniform_location, |
| m_po_dmat3_uniform_location, m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location, |
| m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location, m_po_dmat4_arr_uniform_location, |
| m_po_dmat4_uniform_location, m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location, |
| m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location, m_po_double_arr_uniform_location, |
| m_po_double_uniform_location, m_po_dvec2_arr_uniform_location, m_po_dvec2_uniform_location, |
| m_po_dvec3_arr_uniform_location, m_po_dvec3_uniform_location, m_po_dvec4_arr_uniform_location, |
| m_po_dvec4_uniform_location, m_po_float_arr_uniform_location, m_po_float_uniform_location, |
| m_po_int_arr_uniform_location, m_po_int_uniform_location, m_po_ivec2_arr_uniform_location, |
| m_po_ivec2_uniform_location, m_po_ivec3_arr_uniform_location, m_po_ivec3_uniform_location, |
| m_po_ivec4_arr_uniform_location, m_po_ivec4_uniform_location, m_po_uint_arr_uniform_location, |
| m_po_uint_uniform_location, m_po_uvec2_arr_uniform_location, m_po_uvec2_uniform_location, |
| m_po_uvec3_arr_uniform_location, m_po_uvec3_uniform_location, m_po_uvec4_arr_uniform_location, |
| m_po_uvec4_uniform_location, m_po_vec2_arr_uniform_location, m_po_vec2_uniform_location, |
| m_po_vec3_arr_uniform_location, m_po_vec3_uniform_location, m_po_vec4_arr_uniform_location, |
| m_po_vec4_uniform_location |
| }; |
| const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]); |
| glw::GLint valid_uniform_location = -1; |
| |
| for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location) |
| { |
| glw::GLint uniform_location = uniform_locations[n_uniform_location]; |
| |
| if (uniform_location > valid_uniform_location) |
| { |
| valid_uniform_location = uniform_location; |
| } |
| } /* for (all uniform locations) */ |
| |
| /* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated |
| * for invalid uniform location that is != -1 |
| */ |
| const double double_data[] = { |
| 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 |
| }; |
| const glw::GLint invalid_uniform_location = valid_uniform_location + 1; |
| |
| for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT; |
| ++n_uniform_function) |
| { |
| _uniform_function uniform_function = (_uniform_function)n_uniform_function; |
| |
| switch (uniform_function) |
| { |
| case UNIFORM_FUNCTION_1D: |
| gl.uniform1d(invalid_uniform_location, 0.0); |
| break; |
| case UNIFORM_FUNCTION_2D: |
| gl.uniform2d(invalid_uniform_location, 0.0, 1.0); |
| break; |
| case UNIFORM_FUNCTION_3D: |
| gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0); |
| break; |
| case UNIFORM_FUNCTION_4D: |
| gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0); |
| break; |
| |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data); |
| break; |
| |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized uniform function"); |
| } |
| } |
| |
| const glw::GLenum error_code = gl.getError(); |
| |
| if (error_code != GL_INVALID_OPERATION) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) |
| << "() did not generate an error" |
| " when passed an invalid uniform location different from -1." |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all uniform functions) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or |
| * glUniformMatrix*dv() functions is used to load a compatible uniform using an |
| * invalid <count> argument of -1. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount() |
| { |
| const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, |
| 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV, |
| UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV, |
| UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV, |
| UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV, |
| UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV, |
| UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV, |
| UNIFORM_FUNCTION_MATRIX4X3DV }; |
| const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]); |
| |
| for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function) |
| { |
| _uniform_function uniform_function = uniform_functions[n_uniform_function]; |
| |
| switch (uniform_function) |
| { |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized uniform function"); |
| } |
| } /* switch (uniform_function) */ |
| |
| /* Make sure GL_INVALID_VALUE was generated */ |
| glw::GLenum error_code = gl.getError(); |
| |
| if (error_code != GL_INVALID_VALUE) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function) |
| << "() " |
| "was called with a negative count argument but did not generate a " |
| "GL_INVALID_VALUE error" |
| << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all uniform functions) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or |
| * glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the |
| * function (as per spec). |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions() |
| { |
| const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; |
| glw::GLenum error_code = GL_NO_ERROR; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location, |
| m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location, |
| m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location, |
| m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location, |
| m_po_dmat4x3_uniform_location, m_po_double_uniform_location, |
| m_po_dvec2_uniform_location, m_po_dvec3_uniform_location, |
| m_po_dvec4_uniform_location }; |
| const unsigned int n_double_uniform_locations = |
| sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]); |
| |
| gl.useProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); |
| |
| for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location) |
| { |
| glw::GLint uniform_location = double_uniform_locations[n_uniform_location]; |
| |
| for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); |
| function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++) |
| { |
| _uniform_function e_function = static_cast<_uniform_function>(function); |
| /* Exclude valid combinations */ |
| if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) || |
| ((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) || |
| ((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) || |
| ((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) || |
| ((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) || |
| ((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) || |
| ((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) || |
| ((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) || |
| ((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) || |
| ((uniform_location == m_po_double_uniform_location) && |
| ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) || |
| ((uniform_location == m_po_dvec2_uniform_location) && |
| ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) || |
| ((uniform_location == m_po_dvec3_uniform_location) && |
| ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) || |
| ((uniform_location == m_po_dvec4_uniform_location) && |
| ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV)))) |
| { |
| continue; |
| } |
| |
| switch (e_function) |
| { |
| case UNIFORM_FUNCTION_1D: |
| { |
| gl.uniform1d(uniform_location, double_data[0]); |
| |
| break; |
| } |
| |
| case UNIFORM_FUNCTION_2D: |
| { |
| gl.uniform2d(uniform_location, double_data[0], double_data[1]); |
| |
| break; |
| } |
| |
| case UNIFORM_FUNCTION_3D: |
| { |
| gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]); |
| |
| break; |
| } |
| |
| case UNIFORM_FUNCTION_4D: |
| { |
| gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]); |
| |
| break; |
| } |
| |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(uniform_location, 1 /* count */, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2DV: |
| gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X3DV: |
| gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX2X4DV: |
| gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3DV: |
| gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X2DV: |
| gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX3X4DV: |
| gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4DV: |
| gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X2DV: |
| gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| case UNIFORM_FUNCTION_MATRIX4X3DV: |
| gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data); |
| break; |
| |
| default: |
| { |
| TCU_FAIL("Unrecognized function"); |
| } |
| } /* switch (function) */ |
| |
| /* Make sure GL_INVALID_OPERATION error was generated */ |
| error_code = gl.getError(); |
| |
| if (error_code != GL_INVALID_OPERATION) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code |
| << "] was generated when a mismatched " |
| "double-precision uniform function " |
| << getUniformFunctionString(e_function) << "() was used to configure uniform " |
| << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all uniform functions) */ |
| } /* for (all uniform locations) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or |
| * glUniform*dv() functions is used to load an uniform, size of which is incompatible |
| * with the function. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions() |
| { |
| const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; |
| glw::GLenum error_code = GL_NO_ERROR; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| const int data[] = { |
| /* API function */ /* Uniform location */ /* Count (dv functions only) */ |
| (int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV, |
| m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0, |
| (int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D, |
| m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2, |
| (int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV, |
| m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0, |
| (int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D, |
| m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2, |
| (int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV, |
| m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0, |
| (int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D, |
| m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2, |
| (int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV, |
| m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0, |
| (int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, |
| m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2, |
| }; |
| const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */; |
| |
| gl.useProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); |
| |
| for (unsigned int n_check = 0; n_check < n_checks; ++n_check) |
| { |
| _uniform_function function = (_uniform_function)data[n_check * 3 + 0]; |
| int uniform_location = data[n_check * 3 + 1]; |
| int uniform_count = data[n_check * 3 + 2]; |
| |
| switch (function) |
| { |
| case UNIFORM_FUNCTION_1D: |
| gl.uniform1d(uniform_location, 0.0); |
| break; |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(uniform_location, uniform_count, double_data); |
| break; |
| case UNIFORM_FUNCTION_2D: |
| gl.uniform2d(uniform_location, 0.0, 1.0); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(uniform_location, uniform_count, double_data); |
| break; |
| case UNIFORM_FUNCTION_3D: |
| gl.uniform3d(uniform_location, 0.0, 1.0, 2.0); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(uniform_location, uniform_count, double_data); |
| break; |
| case UNIFORM_FUNCTION_4D: |
| gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(uniform_location, uniform_count, double_data); |
| break; |
| |
| default: |
| { |
| DE_ASSERT(false); |
| } |
| } /* switch (function) */ |
| |
| error_code = gl.getError(); |
| if (error_code != GL_INVALID_OPERATION) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function) |
| << "() function did not generate GL_INVALID_OPERATION error when called for" |
| " a uniform of incompatible size. (check index: " |
| << n_check << ")" << tcu::TestLog::EndMessage; |
| |
| result = false; |
| } |
| } /* for (all checks) */ |
| |
| return result; |
| } |
| |
| /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or |
| * glUniform*dv() functions is used to load an uniform, type of which is incompatible |
| * with the function. |
| * |
| * @return true if the implementation was found to behave as expected, false otherwise. |
| **/ |
| bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions() |
| { |
| const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; |
| glw::GLenum error_code = GL_NO_ERROR; |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| bool result = true; |
| |
| const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location, m_po_bvec2_uniform_location, |
| m_po_bvec3_uniform_location, m_po_bvec4_uniform_location, |
| m_po_float_uniform_location, m_po_int_uniform_location, |
| m_po_ivec2_uniform_location, m_po_ivec3_uniform_location, |
| m_po_ivec4_uniform_location, m_po_uint_uniform_location, |
| m_po_uvec2_uniform_location, m_po_uvec3_uniform_location, |
| m_po_uvec4_uniform_location, m_po_vec2_uniform_location, |
| m_po_vec3_uniform_location, m_po_vec4_uniform_location }; |
| const unsigned int n_nondouble_uniform_locations = |
| sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]); |
| |
| gl.useProgram(m_po_id); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed."); |
| |
| for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location) |
| { |
| glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location]; |
| |
| for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); |
| function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function) |
| { |
| switch (static_cast<_uniform_function>(function)) |
| { |
| case UNIFORM_FUNCTION_1D: |
| gl.uniform1d(uniform_location, 0.0); |
| break; |
| case UNIFORM_FUNCTION_1DV: |
| gl.uniform1dv(uniform_location, 1, double_data); |
| break; |
| case UNIFORM_FUNCTION_2D: |
| gl.uniform2d(uniform_location, 0.0, 1.0); |
| break; |
| case UNIFORM_FUNCTION_2DV: |
| gl.uniform2dv(uniform_location, 1, double_data); |
| break; |
| case UNIFORM_FUNCTION_3D: |
| gl.uniform3d(uniform_location, 0.0, 1.0, 2.0); |
| break; |
| case UNIFORM_FUNCTION_3DV: |
| gl.uniform3dv(uniform_location, 1, double_data); |
| break; |
| case UNIFORM_FUNCTION_4D: |
| gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0); |
| break; |
| case UNIFORM_FUNCTION_4DV: |
| gl.uniform4dv(uniform_location, 1, double_data); |
| break; |
| |
|