| /*------------------------------------------------------------------------- |
| * 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<int32_t> binaryFormats; |
| getSupportedExtensions(GL_NUM_SHADER_BINARY_FORMATS, GL_SHADER_BINARY_FORMATS, binaryFormats); |
| bool 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; |
| |
| // Error handling is different in case of SPIRV. |
| const bool spirvBinary = binaryFormats[0] == GL_SHADER_BINARY_FORMAT_SPIR_V; |
| if (spirvBinary) |
| m_log << TestLog::Section("", "GL_INVALID_VALUE due to invalid data pointer."); |
| else |
| 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); |
| |
| if (spirvBinary) |
| expectError(GL_INVALID_VALUE); |
| else |
| 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; |
| |
| if (glu::isContextTypeES(m_context.getRenderContext().getType())) |
| { |
| 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)); |
| uint32_t buf; |
| uint32_t 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, nullptr, 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)); |
| uint32_t buf; |
| uint32_t 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, nullptr, 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); |
| }); |
| if (glu::isContextTypeES(m_context.getRenderContext().getType())) |
| { |
| 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 unusedShader = glCreateShader(GL_VERTEX_SHADER); |
| GLenum binaryFormat = -1; |
| GLsizei binaryLength = -1; |
| std::vector<uint8_t> 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); |
| |
| if (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(unusedShader, 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(unusedShader); |
| 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)); |
| uint32_t 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, nullptr, 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)); |
| uint32_t 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, nullptr, 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); |
| glEndTransformFeedback(); |
| 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); |
| glLinkProgram(program.getProgram()); |
| expectError(GL_NO_ERROR); |
| glBeginTransformFeedback(GL_TRIANGLES); |
| expectError(GL_INVALID_OPERATION); |
| m_log << tcu::TestLog::EndSection; |
| |
| 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)); |
| uint32_t 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, nullptr, 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)); |
| uint32_t 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, nullptr, 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)); |
| uint32_t 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, nullptr, 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); |
| }); |
| } |
| |
| } // namespace Functional |
| } // namespace gles3 |
| } // namespace deqp |