/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 3.0 Module * ------------------------------------------------- * * Copyright 2014 The Android Open Source Project * * 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 Negative Shader API tests. *//*--------------------------------------------------------------------*/ #include "es3fNegativeShaderApiTests.hpp" #include "es3fApiCase.hpp" #include "gluShaderProgram.hpp" #include "gluContextInfo.hpp" #include "deUniquePtr.hpp" #include "glwDefs.hpp" #include "glwEnums.hpp" using namespace glw; // GL types namespace deqp { namespace gles3 { namespace Functional { using tcu::TestLog; static const char* vertexShaderSource = "#version 300 es\n" "void main (void)\n" "{\n" " gl_Position = vec4(0.0);\n" "}\n\0"; static const char* fragmentShaderSource = "#version 300 es\n" "layout(location = 0) out mediump vec4 fragColor;" "void main (void)\n" "{\n" " fragColor = vec4(0.0);\n" "}\n\0"; static const char* uniformTestVertSource = "#version 300 es\n" "uniform mediump vec4 vec4_v;\n" "uniform mediump mat4 mat4_v;\n" "void main (void)\n" "{\n" " gl_Position = mat4_v * vec4_v;\n" "}\n\0"; static const char* uniformTestFragSource = "#version 300 es\n" "uniform mediump ivec4 ivec4_f;\n" "uniform mediump uvec4 uvec4_f;\n" "uniform sampler2D sampler_f;\n" "layout(location = 0) out mediump vec4 fragColor;" "void main (void)\n" "{\n" " fragColor.xy = (vec4(uvec4_f) + vec4(ivec4_f)).xy;\n" " fragColor.zw = texture(sampler_f, vec2(0.0, 0.0)).zw;\n" "}\n\0"; static const char* uniformBlockVertSource = "#version 300 es\n" "layout(shared) uniform Block { lowp float var; };\n" "void main (void)\n" "{\n" " gl_Position = vec4(var);\n" "}\n\0"; NegativeShaderApiTests::NegativeShaderApiTests (Context& context) : TestCaseGroup(context, "shader", "Negative Shader API Cases") { } NegativeShaderApiTests::~NegativeShaderApiTests (void) { } void NegativeShaderApiTests::init (void) { // Shader control commands ES3F_ADD_API_CASE(create_shader, "Invalid glCreateShader() usage", { m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if shaderType is not an accepted value."); glCreateShader(-1); expectError(GL_INVALID_ENUM); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(shader_source, "Invalid glShaderSource() usage", { // \note Shader compilation must be supported. m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL."); glShaderSource(1, 0, 0, 0); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if count is less than 0."); GLuint shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(shader, -1, 0, 0); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object."); GLuint program = glCreateProgram(); glShaderSource(program, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteProgram(program); glDeleteShader(shader); }); ES3F_ADD_API_CASE(compile_shader, "Invalid glCompileShader() usage", { // \note Shader compilation must be supported. m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL."); glCompileShader(9); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object."); GLuint program = glCreateProgram(); glCompileShader(program); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteProgram(program); }); ES3F_ADD_API_CASE(delete_shader, "Invalid glDeleteShader() usage", { m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if shader is not a value generated by OpenGL."); glDeleteShader(9); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(shader_binary, "Invalid glShaderBinary() usage", { std::vector<deInt32> binaryFormats; getSupportedExtensions(GL_NUM_SHADER_BINARY_FORMATS, GL_SHADER_BINARY_FORMATS, binaryFormats); deBool shaderBinarySupported = !binaryFormats.empty(); if (!shaderBinarySupported) m_log << TestLog::Message << "// Shader binaries not supported." << TestLog::EndMessage; else m_log << TestLog::Message << "// Shader binaries supported" << TestLog::EndMessage; GLuint shaders[2]; shaders[0] = glCreateShader(GL_VERTEX_SHADER); shaders[1] = glCreateShader(GL_VERTEX_SHADER); m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if binaryFormat is not an accepted value."); glShaderBinary(1, &shaders[0], -1, 0, 0); expectError(GL_INVALID_ENUM); m_log << TestLog::EndSection; if (shaderBinarySupported) { m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if the data pointed to by binary does not match the format specified by binaryFormat."); const GLbyte data = 0x005F; glShaderBinary(1, &shaders[0], binaryFormats[0], &data, 1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if more than one of the handles in shaders refers to the same type of shader, or GL_INVALID_VALUE due to invalid data pointer."); glShaderBinary(2, &shaders[0], binaryFormats[0], 0, 0); expectError(GL_INVALID_OPERATION, GL_INVALID_VALUE); m_log << TestLog::EndSection; } glDeleteShader(shaders[0]); glDeleteShader(shaders[1]); }); ES3F_ADD_API_CASE(attach_shader, "Invalid glAttachShader() usage", { GLuint shader1 = glCreateShader(GL_VERTEX_SHADER); GLuint shader2 = glCreateShader(GL_VERTEX_SHADER); GLuint program = glCreateProgram(); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glAttachShader(shader1, shader1); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object."); glAttachShader(program, program); expectError(GL_INVALID_OPERATION); glAttachShader(shader1, program); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if either program or shader is not a value generated by OpenGL."); glAttachShader(program, -1); expectError(GL_INVALID_VALUE); glAttachShader(-1, shader1); expectError(GL_INVALID_VALUE); glAttachShader(-1, -1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is already attached to program."); glAttachShader(program, shader1); expectError(GL_NO_ERROR); glAttachShader(program, shader1); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if a shader of the same type as shader is already attached to program."); glAttachShader(program, shader2); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteProgram(program); glDeleteShader(shader1); glDeleteShader(shader2); }); ES3F_ADD_API_CASE(detach_shader, "Invalid glDetachShader() usage", { GLuint shader = glCreateShader(GL_VERTEX_SHADER); GLuint program = glCreateProgram(); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if either program or shader is not a value generated by OpenGL."); glDetachShader(-1, shader); expectError(GL_INVALID_VALUE); glDetachShader(program, -1); expectError(GL_INVALID_VALUE); glDetachShader(-1, -1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glDetachShader(shader, shader); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not a shader object."); glDetachShader(program, program); expectError(GL_INVALID_OPERATION); glDetachShader(shader, program); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if shader is not attached to program."); glDetachShader(program, shader); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteProgram(program); glDeleteShader(shader); }); ES3F_ADD_API_CASE(link_program, "Invalid glLinkProgram() usage", { GLuint shader = glCreateShader(GL_VERTEX_SHADER); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL."); glLinkProgram(-1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glLinkProgram(shader); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteShader(shader); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is the currently active program object and transform feedback mode is active."); glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; deUint32 tfID; const char* tfVarying = "gl_Position"; glGenTransformFeedbacks (1, &tfID); glGenBuffers (1, &buf); glUseProgram (program.getProgram()); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_NO_ERROR); glLinkProgram (program.getProgram()); expectError (GL_INVALID_OPERATION); glEndTransformFeedback (); glDeleteTransformFeedbacks (1, &tfID); glDeleteBuffers (1, &buf); expectError (GL_NO_ERROR); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(use_program, "Invalid glUseProgram() usage", { GLuint shader = glCreateShader(GL_VERTEX_SHADER); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is neither 0 nor a value generated by OpenGL."); glUseProgram(-1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glUseProgram(shader); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if transform feedback mode is active and not paused."); glu::ShaderProgram program1(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); glu::ShaderProgram program2(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; deUint32 tfID; const char* tfVarying = "gl_Position"; glGenTransformFeedbacks (1, &tfID); glGenBuffers (1, &buf); glUseProgram (program1.getProgram()); glTransformFeedbackVaryings (program1.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program1.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_NO_ERROR); glUseProgram (program2.getProgram()); expectError (GL_INVALID_OPERATION); glPauseTransformFeedback (); glUseProgram (program2.getProgram()); expectError (GL_NO_ERROR); glEndTransformFeedback (); glDeleteTransformFeedbacks (1, &tfID); glDeleteBuffers (1, &buf); expectError (GL_NO_ERROR); m_log << TestLog::EndSection; glUseProgram(0); glDeleteShader(shader); }); ES3F_ADD_API_CASE(delete_program, "Invalid glDeleteProgram() usage", { m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL."); glDeleteProgram(-1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(validate_program, "Invalid glValidateProgram() usage", { GLuint shader = glCreateShader(GL_VERTEX_SHADER); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL."); glValidateProgram(-1); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glValidateProgram(shader); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteShader(shader); }); ES3F_ADD_API_CASE(get_program_binary, "Invalid glGetProgramBinary() usage", { glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); glu::ShaderProgram programInvalid (m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, "")); GLenum binaryFormat = -1; GLsizei binaryLength = -1; GLint binaryPtr = -1; GLint bufSize = -1; GLint linkStatus = -1; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if bufSize is less than the size of GL_PROGRAM_BINARY_LENGTH for program."); glGetProgramiv (program.getProgram(), GL_PROGRAM_BINARY_LENGTH, &bufSize); expectError (GL_NO_ERROR); glGetProgramiv (program.getProgram(), GL_LINK_STATUS, &linkStatus); m_log << TestLog::Message << "// GL_PROGRAM_BINARY_LENGTH = " << bufSize << TestLog::EndMessage; m_log << TestLog::Message << "// GL_LINK_STATUS = " << linkStatus << TestLog::EndMessage; expectError (GL_NO_ERROR); glGetProgramBinary (program.getProgram(), 0, &binaryLength, &binaryFormat, &binaryPtr); expectError (GL_INVALID_OPERATION); if (bufSize > 0) { glGetProgramBinary (program.getProgram(), bufSize-1, &binaryLength, &binaryFormat, &binaryPtr); expectError (GL_INVALID_OPERATION); } m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if GL_LINK_STATUS for the program object is false."); glGetProgramiv (programInvalid.getProgram(), GL_PROGRAM_BINARY_LENGTH, &bufSize); expectError (GL_NO_ERROR); glGetProgramiv (programInvalid.getProgram(), GL_LINK_STATUS, &linkStatus); m_log << TestLog::Message << "// GL_PROGRAM_BINARY_LENGTH = " << bufSize << TestLog::EndMessage; m_log << TestLog::Message << "// GL_LINK_STATUS = " << linkStatus << TestLog::EndMessage; expectError (GL_NO_ERROR); glGetProgramBinary (programInvalid.getProgram(), bufSize, &binaryLength, &binaryFormat, &binaryPtr); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(program_binary, "Invalid glProgramBinary() usage", { glu::ShaderProgram srcProgram (m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); GLuint dstProgram = glCreateProgram(); GLuint dummyShader = glCreateShader(GL_VERTEX_SHADER); GLenum binaryFormat = -1; GLsizei binaryLength = -1; std::vector<deUint8> binaryBuf; GLint bufSize = -1; GLint linkStatus = -1; glGetProgramiv (srcProgram.getProgram(), GL_PROGRAM_BINARY_LENGTH, &bufSize); glGetProgramiv (srcProgram.getProgram(), GL_LINK_STATUS, &linkStatus); m_log << TestLog::Message << "// GL_PROGRAM_BINARY_LENGTH = " << bufSize << TestLog::EndMessage; m_log << TestLog::Message << "// GL_LINK_STATUS = " << linkStatus << TestLog::EndMessage; TCU_CHECK(bufSize > 0); binaryBuf.resize(bufSize); glGetProgramBinary (srcProgram.getProgram(), bufSize, &binaryLength, &binaryFormat, &binaryBuf[0]); expectError (GL_NO_ERROR); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not the name of an existing program object."); glProgramBinary (dummyShader, binaryFormat, &binaryBuf[0], binaryLength); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if binaryFormat is not a value recognized by the implementation."); glProgramBinary (dstProgram, -1, &binaryBuf[0], binaryLength); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteShader(dummyShader); glDeleteProgram(dstProgram); }); ES3F_ADD_API_CASE(program_parameteri, "Invalid glProgramParameteri() usage", { GLuint program = glCreateProgram(); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of an existing program object."); glProgramParameteri (0, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); expectError (GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not GL_PROGRAM_BINARY_RETRIEVABLE_HINT."); glProgramParameteri (program, -1, GL_TRUE); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if value is not GL_FALSE or GL_TRUE."); glProgramParameteri (program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, 2); expectError (GL_INVALID_VALUE); m_log << TestLog::EndSection; glDeleteProgram(program); }); ES3F_ADD_API_CASE(gen_samplers, "Invalid glGenSamplers() usage", { m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative."); GLuint sampler; glGenSamplers (-1, &sampler); expectError (GL_INVALID_VALUE); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(bind_sampler, "Invalid glBindSampler() usage", { int maxTexImageUnits; GLuint sampler; glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTexImageUnits); glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if unit is greater than or equal to the value of GL_MAX_COMBIED_TEXTURE_IMAGE_UNITS."); glBindSampler (maxTexImageUnits, sampler); expectError (GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not zero or a name previously returned from a call to glGenSamplers."); glBindSampler (1, -1); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler has been deleted by a call to glDeleteSamplers."); glDeleteSamplers(1, &sampler); glBindSampler (1, sampler); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(delete_samplers, "Invalid glDeleteSamplers() usage", { m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative."); glDeleteSamplers(-1, 0); expectError (GL_INVALID_VALUE); m_log << TestLog::EndSection; }); ES3F_ADD_API_CASE(get_sampler_parameteriv, "Invalid glGetSamplerParameteriv() usage", { int params = -1; GLuint sampler; glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object returned from a previous call to glGenSamplers."); glGetSamplerParameteriv (-1, GL_TEXTURE_MAG_FILTER, ¶ms); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value."); glGetSamplerParameteriv (sampler, -1, ¶ms); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteSamplers(1, &sampler); }); ES3F_ADD_API_CASE(get_sampler_parameterfv, "Invalid glGetSamplerParameterfv() usage", { float params = 0.0f; GLuint sampler; glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object returned from a previous call to glGenSamplers."); glGetSamplerParameterfv (-1, GL_TEXTURE_MAG_FILTER, ¶ms); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if pname is not an accepted value."); glGetSamplerParameterfv (sampler, -1, ¶ms); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteSamplers(1, &sampler); }); ES3F_ADD_API_CASE(sampler_parameteri, "Invalid glSamplerParameteri() usage", { GLuint sampler; glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers."); glSamplerParameteri (-1, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not."); glSamplerParameteri (sampler, GL_TEXTURE_WRAP_S, -1); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteSamplers(1, &sampler); }); ES3F_ADD_API_CASE(sampler_parameteriv, "Invalid glSamplerParameteriv() usage", { int params = -1; GLuint sampler; glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers."); params = GL_CLAMP_TO_EDGE; glSamplerParameteriv (-1, GL_TEXTURE_WRAP_S, ¶ms); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not."); params = -1; glSamplerParameteriv (sampler, GL_TEXTURE_WRAP_S, ¶ms); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteSamplers(1, &sampler); }); ES3F_ADD_API_CASE(sampler_parameterf, "Invalid glSamplerParameterf() usage", { GLuint sampler; glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers."); glSamplerParameterf (-1, GL_TEXTURE_MIN_LOD, -1000.0f); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not."); glSamplerParameterf (sampler, GL_TEXTURE_WRAP_S, -1.0f); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteSamplers(1, &sampler); }); ES3F_ADD_API_CASE(sampler_parameterfv, "Invalid glSamplerParameterfv() usage", { float params = 0.0f; GLuint sampler; glGenSamplers (1, &sampler); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if sampler is not the name of a sampler object previously returned from a call to glGenSamplers."); params = -1000.0f; glSamplerParameterfv (-1, GL_TEXTURE_WRAP_S, ¶ms); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if params should have a defined constant value (based on the value of pname) and does not."); params = -1.0f; glSamplerParameterfv (sampler, GL_TEXTURE_WRAP_S, ¶ms); expectError (GL_INVALID_ENUM); m_log << TestLog::EndSection; glDeleteSamplers(1, &sampler); }); // Shader data commands ES3F_ADD_API_CASE(get_attrib_location, "Invalid glGetAttribLocation() usage", { GLuint programEmpty = glCreateProgram(); GLuint shader = glCreateShader(GL_VERTEX_SHADER); glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked."); glBindAttribLocation (programEmpty, 0, "test"); glGetAttribLocation (programEmpty, "test"); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a program or shader object."); glUseProgram (program.getProgram()); glBindAttribLocation (program.getProgram(), 0, "test"); expectError (GL_NO_ERROR); glGetAttribLocation (program.getProgram(), "test"); expectError (GL_NO_ERROR); glGetAttribLocation (-2, "test"); expectError (GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glGetAttribLocation (shader, "test"); expectError (GL_INVALID_OPERATION); m_log << TestLog::EndSection; glUseProgram (0); glDeleteShader (shader); glDeleteProgram (programEmpty); }); ES3F_ADD_API_CASE(get_uniform_location, "Invalid glGetUniformLocation() usage", { GLuint programEmpty = glCreateProgram(); GLuint shader = glCreateShader(GL_VERTEX_SHADER); glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program has not been successfully linked."); glGetUniformLocation(programEmpty, "test"); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL."); glUseProgram(program.getProgram()); glGetUniformLocation(-2, "test"); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glGetAttribLocation(shader, "test"); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glUseProgram(0); glDeleteProgram(programEmpty); glDeleteShader(shader); }); ES3F_ADD_API_CASE(bind_attrib_location, "Invalid glBindAttribLocation() usage", { GLuint program = glCreateProgram(); GLuint maxIndex = m_context.getContextInfo().getInt(GL_MAX_VERTEX_ATTRIBS); GLuint shader = glCreateShader(GL_VERTEX_SHADER); m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS."); glBindAttribLocation(program, maxIndex, "test"); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if name starts with the reserved prefix \"gl_\"."); glBindAttribLocation(program, maxIndex-1, "gl_test"); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if program is not a value generated by OpenGL."); glBindAttribLocation(-1, maxIndex-1, "test"); expectError(GL_INVALID_VALUE); m_log << TestLog::EndSection; m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if program is not a program object."); glBindAttribLocation(shader, maxIndex-1, "test"); expectError(GL_INVALID_OPERATION); m_log << TestLog::EndSection; glDeleteProgram(program); glDeleteShader(shader); }); ES3F_ADD_API_CASE(uniform_block_binding, "Invalid glUniformBlockBinding() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformBlockVertSource, uniformTestFragSource)); glUseProgram (program.getProgram()); GLint maxUniformBufferBindings; GLint numActiveUniforms = -1; GLint numActiveBlocks = -1; glGetIntegerv (GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxUniformBufferBindings); glGetProgramiv (program.getProgram(), GL_ACTIVE_UNIFORMS, &numActiveUniforms); glGetProgramiv (program.getProgram(), GL_ACTIVE_UNIFORM_BLOCKS, &numActiveBlocks); m_log << TestLog::Message << "// GL_MAX_UNIFORM_BUFFER_BINDINGS = " << maxUniformBufferBindings << TestLog::EndMessage; m_log << TestLog::Message << "// GL_ACTIVE_UNIFORMS = " << numActiveUniforms << TestLog::EndMessage; m_log << TestLog::Message << "// GL_ACTIVE_UNIFORM_BLOCKS = " << numActiveBlocks << TestLog::EndMessage; expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if uniformBlockIndex is not an active uniform block index of program."); glUniformBlockBinding(program.getProgram(), -1, 0); expectError(GL_INVALID_VALUE); glUniformBlockBinding(program.getProgram(), 5, 0); expectError(GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if uniformBlockBinding is greater than or equal to the value of GL_MAX_UNIFORM_BUFFER_BINDINGS."); glUniformBlockBinding(program.getProgram(), maxUniformBufferBindings, 0); expectError(GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of a program object generated by the GL."); glUniformBlockBinding(-1, 0, 0); expectError(GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; }); // glUniform*f ES3F_ADD_API_CASE(uniformf_invalid_program, "Invalid glUniform{1234}f() usage", { m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniform1f(-1, 0.0f); expectError(GL_INVALID_OPERATION); glUniform2f(-1, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform3f(-1, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform4f(-1, 0.0f, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniformf_incompatible_type, "Invalid glUniform{1234}f() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 GLint uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniform1f(vec4_v, 0.0f); expectError(GL_INVALID_OPERATION); glUniform2f(vec4_v, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform3f(vec4_v, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform4f(vec4_v, 0.0f, 0.0f, 0.0f, 0.0f); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}f is used to load a uniform variable of type int, ivec2, ivec3, ivec4, unsigned int, uvec2, uvec3, uvec4."); glUseProgram(program.getProgram()); glUniform4f(ivec4_f, 0.0f, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform4f(uvec4_f, 0.0f, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv."); glUseProgram(program.getProgram()); glUniform1f(sampler_f, 0.0f); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformf_invalid_location, "Invalid glUniform{1234}f() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniform1f(-2, 0.0f); expectError(GL_INVALID_OPERATION); glUniform2f(-2, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform3f(-2, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUniform4f(-2, 0.0f, 0.0f, 0.0f, 0.0f); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniform1f(-1, 0.0f); expectError(GL_NO_ERROR); glUniform2f(-1, 0.0f, 0.0f); expectError(GL_NO_ERROR); glUniform3f(-1, 0.0f, 0.0f, 0.0f); expectError(GL_NO_ERROR); glUniform4f(-1, 0.0f, 0.0f, 0.0f, 0.0f); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // glUniform*fv ES3F_ADD_API_CASE(uniformfv_invalid_program, "Invalid glUniform{1234}fv() usage", { std::vector<GLfloat> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniform1fv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2fv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3fv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4fv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniformfv_incompatible_type, "Invalid glUniform{1234}fv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 GLint uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLfloat> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniform1fv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2fv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3fv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4fv(vec4_v, 1, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}fv is used to load a uniform variable of type int, ivec2, ivec3, ivec4, unsigned int, uvec2, uvec3, uvec4."); glUseProgram(program.getProgram()); glUniform4fv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4fv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv."); glUseProgram(program.getProgram()); glUniform1fv(sampler_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformfv_invalid_location, "Invalid glUniform{1234}fv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); std::vector<GLfloat> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniform1fv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2fv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3fv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4fv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniform1fv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform2fv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform3fv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform4fv(-1, 1, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformfv_invalid_count, "Invalid glUniform{1234}fv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram (program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 expectError(GL_NO_ERROR); if (vec4_v == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLfloat> data(8); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable."); glUseProgram(program.getProgram()); glUniform1fv(vec4_v, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2fv(vec4_v, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3fv(vec4_v, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4fv(vec4_v, 2, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // glUniform*i ES3F_ADD_API_CASE(uniformi_invalid_program, "Invalid glUniform{1234}i() usage", { m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniform1i(-1, 0); expectError(GL_INVALID_OPERATION); glUniform2i(-1, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3i(-1, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4i(-1, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniformi_incompatible_type, "Invalid glUniform{1234}i() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 GLint uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniform1i(ivec4_f, 0); expectError(GL_INVALID_OPERATION); glUniform2i(ivec4_f, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3i(ivec4_f, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4i(ivec4_f, 0, 0, 0, 0); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type unsigned int, uvec2, uvec3, uvec4, or an array of these."); glUseProgram(program.getProgram()); glUniform1i(uvec4_f, 0); expectError(GL_INVALID_OPERATION); glUniform2i(uvec4_f, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3i(uvec4_f, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4i(uvec4_f, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type float, vec2, vec3, or vec4."); glUseProgram(program.getProgram()); glUniform1i(vec4_v, 0); expectError(GL_INVALID_OPERATION); glUniform2i(vec4_v, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3i(vec4_v, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4i(vec4_v, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformi_invalid_location, "Invalid glUniform{1234}i() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniform1i(-2, 0); expectError(GL_INVALID_OPERATION); glUniform2i(-2, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3i(-2, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4i(-2, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniform1i(-1, 0); expectError(GL_NO_ERROR); glUniform2i(-1, 0, 0); expectError(GL_NO_ERROR); glUniform3i(-1, 0, 0, 0); expectError(GL_NO_ERROR); glUniform4i(-1, 0, 0, 0, 0); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // glUniform*iv ES3F_ADD_API_CASE(uniformiv_invalid_program, "Invalid glUniform{1234}iv() usage", { std::vector<GLint> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniform1iv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2iv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3iv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4iv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniformiv_incompatible_type, "Invalid glUniform{1234}iv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 GLint uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLint> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniform1iv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2iv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3iv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4iv(ivec4_f, 1, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}iv is used to load a uniform variable of type float, vec2, vec3, or vec4."); glUseProgram(program.getProgram()); glUniform1iv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2iv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3iv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4iv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}iv is used to load a uniform variable of type unsigned int, uvec2, uvec3 or uvec4."); glUseProgram(program.getProgram()); glUniform1iv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2iv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3iv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4iv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformiv_invalid_location, "Invalid glUniform{1234}iv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); std::vector<GLint> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniform1iv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2iv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3iv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4iv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniform1iv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform2iv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform3iv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform4iv(-1, 1, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformiv_invalid_count, "Invalid glUniform{1234}iv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram (program.getProgram()); GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 expectError(GL_NO_ERROR); if (ivec4_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLint> data(8); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable."); glUseProgram(program.getProgram()); glUniform1iv(ivec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2iv(ivec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3iv(ivec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4iv(ivec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // glUniform{1234}ui ES3F_ADD_API_CASE(uniformui_invalid_program, "Invalid glUniform{234}ui() usage", { m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniform1ui(-1, 0); expectError(GL_INVALID_OPERATION); glUniform2ui(-1, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3ui(-1, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4ui(-1, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniformui_incompatible_type, "Invalid glUniform{1234}ui() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 GLint uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniform1ui(uvec4_f, 0); expectError(GL_INVALID_OPERATION); glUniform2ui(uvec4_f, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3ui(uvec4_f, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4ui(uvec4_f, 0, 0, 0, 0); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type int, ivec2, ivec3, ivec4, or an array of these."); glUseProgram(program.getProgram()); glUniform1ui(ivec4_f, 0); expectError(GL_INVALID_OPERATION); glUniform2ui(ivec4_f, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3ui(ivec4_f, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4ui(ivec4_f, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}i is used to load a uniform variable of type float, vec2, vec3, or vec4."); glUseProgram(program.getProgram()); glUniform1ui(vec4_v, 0); expectError(GL_INVALID_OPERATION); glUniform2ui(vec4_v, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3ui(vec4_v, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4ui(vec4_v, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv."); glUseProgram(program.getProgram()); glUniform1ui(sampler_f, 0); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformui_invalid_location, "Invalid glUniform{1234}ui() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniform1i(-2, 0); expectError(GL_INVALID_OPERATION); glUniform2i(-2, 0, 0); expectError(GL_INVALID_OPERATION); glUniform3i(-2, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUniform4i(-2, 0, 0, 0, 0); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniform1i(-1, 0); expectError(GL_NO_ERROR); glUniform2i(-1, 0, 0); expectError(GL_NO_ERROR); glUniform3i(-1, 0, 0, 0); expectError(GL_NO_ERROR); glUniform4i(-1, 0, 0, 0, 0); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // glUniform{1234}uiv ES3F_ADD_API_CASE(uniformuiv_invalid_program, "Invalid glUniform{234}uiv() usage", { std::vector<GLuint> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniform1uiv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2uiv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3uiv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4uiv(-1, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniformuiv_incompatible_type, "Invalid glUniform{1234}uiv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); GLint vec4_v = glGetUniformLocation(program.getProgram(), "vec4_v"); // vec4 GLint ivec4_f = glGetUniformLocation(program.getProgram(), "ivec4_f"); // ivec4 GLint uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (vec4_v == -1 || ivec4_f == -1 || uvec4_f == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLuint> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniform1uiv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2uiv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3uiv(uvec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4uiv(uvec4_f, 1, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}uiv is used to load a uniform variable of type float, vec2, vec3, or vec4."); glUseProgram(program.getProgram()); glUniform1uiv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2uiv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3uiv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4uiv(vec4_v, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if glUniform{1234}uiv is used to load a uniform variable of type int, ivec2, ivec3 or ivec4."); glUseProgram(program.getProgram()); glUniform1uiv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2uiv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3uiv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4uiv(ivec4_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv."); glUseProgram(program.getProgram()); glUniform1uiv(sampler_f, 1, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformuiv_invalid_location, "Invalid glUniform{1234}uiv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); std::vector<GLuint> data(4); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniform1uiv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2uiv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3uiv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4uiv(-2, 1, &data[0]); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniform1uiv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform2uiv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform3uiv(-1, 1, &data[0]); expectError(GL_NO_ERROR); glUniform4uiv(-1, 1, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniformuiv_invalid_count, "Invalid glUniform{1234}uiv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram (program.getProgram()); int uvec4_f = glGetUniformLocation(program.getProgram(), "uvec4_f"); // uvec4 expectError(GL_NO_ERROR); if (uvec4_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLuint> data(8); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable."); glUseProgram(program.getProgram()); glUniform1uiv(uvec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform2uiv(uvec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform3uiv(uvec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); glUniform4uiv(uvec4_f, 2, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // glUniformMatrix*fv ES3F_ADD_API_CASE(uniform_matrixfv_invalid_program, "Invalid glUniformMatrix{234}fv() usage", { std::vector<GLfloat> data(16); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if there is no current program object."); glUseProgram(0); glUniformMatrix2fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x3fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x2fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x4fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x2fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x4fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x3fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(uniform_matrixfv_incompatible_type, "Invalid glUniformMatrix{234}fv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram (program.getProgram()); GLint mat4_v = glGetUniformLocation(program.getProgram(), "mat4_v"); // mat4 GLint sampler_f = glGetUniformLocation(program.getProgram(), "sampler_f"); // sampler2D expectError(GL_NO_ERROR); if (mat4_v == -1 || sampler_f == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLfloat> data(16); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the size of the uniform variable declared in the shader does not match the size indicated by the glUniform command."); glUseProgram(program.getProgram()); glUniformMatrix2fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix2x3fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x2fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x4fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x2fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x4fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x3fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if a sampler is loaded using a command other than glUniform1i and glUniform1iv."); glUseProgram(program.getProgram()); glUniformMatrix2fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x3fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x2fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x4fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x2fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x4fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x3fv(sampler_f, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniform_matrixfv_invalid_location, "Invalid glUniformMatrix{234}fv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram(program.getProgram()); expectError(GL_NO_ERROR); std::vector<GLfloat> data(16); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if location is an invalid uniform location for the current program object and location is not equal to -1."); glUseProgram(program.getProgram()); glUniformMatrix2fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x3fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x2fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x4fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x2fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x4fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x3fv(-2, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUseProgram(program.getProgram()); glUniformMatrix2fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix3fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix4fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix2x3fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix3x2fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix2x4fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix4x2fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix3x4fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); glUniformMatrix4x3fv(-1, 1, GL_FALSE, &data[0]); expectError(GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); ES3F_ADD_API_CASE(uniform_matrixfv_invalid_count, "Invalid glUniformMatrix{234}fv() usage", { glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(uniformTestVertSource, uniformTestFragSource)); glUseProgram (program.getProgram()); GLint mat4_v = glGetUniformLocation(program.getProgram(), "mat4_v"); // mat4 expectError(GL_NO_ERROR); if (mat4_v == -1) { m_log << TestLog::Message << "// ERROR: Failed to retrieve uniform location" << TestLog::EndMessage; m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to retrieve uniform location"); } std::vector<GLfloat> data(32); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if count is greater than 1 and the indicated uniform variable is not an array variable."); glUseProgram(program.getProgram()); glUniformMatrix2fv(mat4_v, 2, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3fv(mat4_v, 2, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4fv(mat4_v, 2, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x3fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x2fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix2x4fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x2fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix3x4fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); glUniformMatrix4x3fv(mat4_v, 1, GL_FALSE, &data[0]); expectError(GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glUseProgram(0); }); // Transform feedback ES3F_ADD_API_CASE(gen_transform_feedbacks, "Invalid glGenTransformFeedbacks() usage", { m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative."); GLuint id; glGenTransformFeedbacks(-1, &id); expectError(GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; }); ES3F_ADD_API_CASE(bind_transform_feedback, "Invalid glBindTransformFeedback() usage", { GLuint tfID[2]; glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; const char* tfVarying = "gl_Position"; glGenBuffers (1, &buf); glGenTransformFeedbacks (2, tfID); m_log << tcu::TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_TRANSFORM_FEEDBACK."); glBindTransformFeedback(-1, tfID[0]); expectError(GL_INVALID_ENUM); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the transform feedback operation is active on the currently bound transform feedback object, and is not paused."); glUseProgram (program.getProgram()); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID[0]); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_NO_ERROR); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID[1]); expectError (GL_INVALID_OPERATION); glEndTransformFeedback (); expectError (GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glUseProgram (0); glDeleteBuffers (1, &buf); glDeleteTransformFeedbacks (2, tfID); expectError (GL_NO_ERROR); }); ES3F_ADD_API_CASE(delete_transform_feedbacks, "Invalid glDeleteTransformFeedbacks() usage", { GLuint id; glGenTransformFeedbacks(1, &id); m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative."); glDeleteTransformFeedbacks(-1, &id); expectError(GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; glDeleteTransformFeedbacks(1, &id); }); ES3F_ADD_API_CASE(begin_transform_feedback, "Invalid glBeginTransformFeedback() usage", { GLuint tfID[2]; glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; const char* tfVarying = "gl_Position"; glGenBuffers (1, &buf); glGenTransformFeedbacks (2, tfID); glUseProgram (program.getProgram()); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID[0]); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_ENUM is generated if primitiveMode is not one of GL_POINTS, GL_LINES, or GL_TRIANGLES."); glBeginTransformFeedback (-1); expectError (GL_INVALID_ENUM); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if transform feedback is already active."); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_NO_ERROR); glBeginTransformFeedback (GL_POINTS); expectError (GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if any binding point used in transform feedback mode does not have a buffer object bound."); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_INVALID_OPERATION); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if no binding points would be used because no program object is active."); glUseProgram (0); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_INVALID_OPERATION); glUseProgram (program.getProgram()); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if no binding points would be used because the active program object has specified no varying variables to record."); glTransformFeedbackVaryings (program.getProgram(), 0, 0, GL_INTERLEAVED_ATTRIBS); glBeginTransformFeedback (GL_TRIANGLES); expectError (GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glEndTransformFeedback (); glDeleteBuffers (1, &buf); glDeleteTransformFeedbacks (2, tfID); expectError (GL_NO_ERROR); }); ES3F_ADD_API_CASE(pause_transform_feedback, "Invalid glPauseTransformFeedback() usage", { GLuint tfID[2]; glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; const char* tfVarying = "gl_Position"; glGenBuffers (1, &buf); glGenTransformFeedbacks (2, tfID); glUseProgram (program.getProgram()); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID[0]); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the currently bound transform feedback object is not active or is paused."); glPauseTransformFeedback (); expectError (GL_INVALID_OPERATION); glBeginTransformFeedback (GL_TRIANGLES); glPauseTransformFeedback (); expectError (GL_NO_ERROR); glPauseTransformFeedback (); expectError (GL_INVALID_OPERATION); m_log << tcu::TestLog::EndSection; glEndTransformFeedback (); glDeleteBuffers (1, &buf); glDeleteTransformFeedbacks (2, tfID); expectError (GL_NO_ERROR); }); ES3F_ADD_API_CASE(resume_transform_feedback, "Invalid glResumeTransformFeedback() usage", { GLuint tfID[2]; glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; const char* tfVarying = "gl_Position"; glGenBuffers (1, &buf); glGenTransformFeedbacks (2, tfID); glUseProgram (program.getProgram()); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID[0]); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if the currently bound transform feedback object is not active or is not paused."); glResumeTransformFeedback (); expectError (GL_INVALID_OPERATION); glBeginTransformFeedback (GL_TRIANGLES); glResumeTransformFeedback (); expectError (GL_INVALID_OPERATION); glPauseTransformFeedback (); glResumeTransformFeedback (); expectError (GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glEndTransformFeedback (); glDeleteBuffers (1, &buf); glDeleteTransformFeedbacks (2, tfID); expectError (GL_NO_ERROR); }); ES3F_ADD_API_CASE(end_transform_feedback, "Invalid glEndTransformFeedback() usage", { GLuint tfID; glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); deUint32 buf; const char* tfVarying = "gl_Position"; glGenBuffers (1, &buf); glGenTransformFeedbacks (1, &tfID); glUseProgram (program.getProgram()); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); glLinkProgram (program.getProgram()); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID); glBindBuffer (GL_TRANSFORM_FEEDBACK_BUFFER, buf); glBufferData (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW); glBindBufferBase (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION is generated if transform feedback is not active."); glEndTransformFeedback (); expectError (GL_INVALID_OPERATION); glBeginTransformFeedback (GL_TRIANGLES); glEndTransformFeedback (); expectError (GL_NO_ERROR); m_log << tcu::TestLog::EndSection; glDeleteBuffers (1, &buf); glDeleteTransformFeedbacks (1, &tfID); expectError (GL_NO_ERROR); }); ES3F_ADD_API_CASE(get_transform_feedback_varying, "Invalid glGetTransformFeedbackVarying() usage", { GLuint tfID; glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); glu::ShaderProgram programInvalid (m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, "")); const char* tfVarying = "gl_Position"; int maxTransformFeedbackVaryings = 0; GLsizei length; GLsizei size; GLenum type; char name[32]; glGenTransformFeedbacks (1, &tfID); glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); expectError (GL_NO_ERROR); glLinkProgram (program.getProgram()); expectError (GL_NO_ERROR); glBindTransformFeedback (GL_TRANSFORM_FEEDBACK, tfID); expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of a program object."); glGetTransformFeedbackVarying (-1, 0, 32, &length, &size, &type, &name[0]); expectError (GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if index is greater or equal to the value of GL_TRANSFORM_FEEDBACK_VARYINGS."); glGetProgramiv (program.getProgram(), GL_TRANSFORM_FEEDBACK_VARYINGS, &maxTransformFeedbackVaryings); glGetTransformFeedbackVarying (program.getProgram(), maxTransformFeedbackVaryings, 32, &length, &size, &type, &name[0]); expectError (GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_OPERATION or GL_INVALID_VALUE is generated program has not been linked."); glGetTransformFeedbackVarying (programInvalid.getProgram(), 0, 32, &length, &size, &type, &name[0]); expectError (GL_INVALID_OPERATION, GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; glDeleteTransformFeedbacks (1, &tfID); expectError (GL_NO_ERROR); }); ES3F_ADD_API_CASE(transform_feedback_varyings, "Invalid glTransformFeedbackVaryings() usage", { GLuint tfID; glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource)); const char* tfVarying = "gl_Position"; GLint maxTransformFeedbackSeparateAttribs = 0; glGenTransformFeedbacks (1, &tfID); expectError (GL_NO_ERROR); m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if program is not the name of a program object."); glTransformFeedbackVaryings (0, 1, &tfVarying, GL_INTERLEAVED_ATTRIBS); expectError (GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; m_log << tcu::TestLog::Section("", "GL_INVALID_VALUE is generated if bufferMode is GL_SEPARATE_ATTRIBS and count is greater than GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."); glGetIntegerv (GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxTransformFeedbackSeparateAttribs); glTransformFeedbackVaryings (program.getProgram(), maxTransformFeedbackSeparateAttribs+1, &tfVarying, GL_SEPARATE_ATTRIBS); expectError (GL_INVALID_VALUE); m_log << tcu::TestLog::EndSection; glDeleteTransformFeedbacks (1, &tfID); expectError (GL_NO_ERROR); }); } } // Functional } // gles3 } // deqp