blob: 648aea0753d6a34221176b2c5740544c94b478ca [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2014-2016 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/ /*!
* \file
* \brief
*/ /*-------------------------------------------------------------------*/
#include "gl4cProgramInterfaceQueryTests.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include <cstdarg>
#include <map>
#include <set>
namespace gl4cts
{
using namespace glw;
namespace
{
class PIQBase : public deqp::SubcaseBase
{
public:
virtual std::string PassCriteria()
{
return "All called functions return expected values.";
}
virtual std::string Purpose()
{
return "Verify that the set of tested functions glGetProgram* return\n"
"expected results when used to get data from program\n"
"made of " +
ShadersDesc() + "." + PurposeExt();
}
virtual std::string Method()
{
return "Create a program using " + ShadersDesc() +
"\n"
"then use set of tested functions to get an information about it and\n"
"verify that information with the expected data" +
Expectations();
}
virtual long Cleanup()
{
glUseProgram(0);
return NO_ERROR;
}
virtual long Setup()
{
return NO_ERROR;
}
virtual ~PIQBase()
{
}
protected:
void LinkProgram(GLuint program)
{
glLinkProgram(program);
GLsizei length;
GLchar log[1024];
glGetProgramInfoLog(program, sizeof(log), &length, log);
if (length > 1)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
<< log << tcu::TestLog::EndMessage;
}
}
GLuint CreateProgram(const char* src_vs, const char* src_fs, bool link)
{
const GLuint p = glCreateProgram();
if (src_vs)
{
GLuint sh = glCreateShader(GL_VERTEX_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_vs, NULL);
glCompileShader(sh);
}
if (src_fs)
{
GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_fs, NULL);
glCompileShader(sh);
}
if (link)
{
LinkProgram(p);
}
return p;
}
GLuint CreateProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
const char* src_fs, bool link)
{
const GLuint p = glCreateProgram();
if (src_vs)
{
GLuint sh = glCreateShader(GL_VERTEX_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_vs, NULL);
glCompileShader(sh);
}
if (src_tcs)
{
GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_tcs, NULL);
glCompileShader(sh);
}
if (src_tes)
{
GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_tes, NULL);
glCompileShader(sh);
}
if (src_gs)
{
GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_gs, NULL);
glCompileShader(sh);
}
if (src_fs)
{
GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
glShaderSource(sh, 1, &src_fs, NULL);
glCompileShader(sh);
}
if (link)
{
LinkProgram(p);
}
return p;
}
virtual std::string ShadersDesc()
{
return "";
}
virtual std::string Expectations()
{
return ".";
}
virtual std::string PurposeExt()
{
return "";
}
virtual inline void ExpectError(GLenum expected, long& error)
{
if (error != NO_ERROR)
return;
GLenum tmp = glGetError();
if (tmp == expected)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Found expected error" << tcu::TestLog::EndMessage;
error = NO_ERROR; // Error is expected
}
else
{
error = ERROR;
m_context.getTestContext().getLog() << tcu::TestLog::Message << expected
<< " error was expected, found: " << tmp << tcu::TestLog::EndMessage;
}
}
virtual inline void VerifyGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, int expected,
long& error)
{
GLint res;
glGetProgramInterfaceiv(program, programInterface, pname, &res);
if (res != expected)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
<< expected << tcu::TestLog::EndMessage;
error = ERROR;
}
}
virtual inline void VerifyGetProgramResourceIndex(GLuint program, GLenum programInterface, const std::string& name,
GLuint expected, long& error)
{
GLuint res = glGetProgramResourceIndex(program, programInterface, name.c_str());
if (res != expected)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
<< expected << tcu::TestLog::EndMessage;
error = ERROR;
}
}
virtual inline void VerifyGetProgramResourceIndex(GLuint program, GLenum programInterface,
std::map<std::string, GLuint>& indices, const std::string& name,
long& error)
{
GLuint res = glGetProgramResourceIndex(program, programInterface, name.c_str());
if (res == GL_INVALID_INDEX)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res
<< ", expected number other than -1" << tcu::TestLog::EndMessage;
error = ERROR;
return;
}
std::map<std::string, GLuint>::iterator it = indices.begin();
while (it != indices.end())
{
if (it->second == res)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ERROR: Duplicated value found: " << res << tcu::TestLog::EndMessage;
error = ERROR;
return;
}
++it;
}
indices[name] = res;
}
virtual inline void VerifyGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index,
const std::string& expected, long& error)
{
GLchar name[1024] = { '\0' };
GLsizei len;
glGetProgramResourceName(program, programInterface, index, 1024, &len, name);
if (len <= 0 || len > 1023 || name[len - 1] == '\0')
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "ERROR: Length in glGetProgramResourceName should not count null terminator!"
<< tcu::TestLog::EndMessage;
error = ERROR;
}
else if (name != expected || name[len] != '\0')
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << name << ", expected "
<< expected << tcu::TestLog::EndMessage;
error = ERROR;
}
}
virtual inline void VerifyGetProgramResourceLocation(GLuint program, GLenum programInterface,
const std::string& name, GLint expected, long& error)
{
GLint res = glGetProgramResourceLocation(program, programInterface, name.c_str());
if (res != expected)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
<< expected << tcu::TestLog::EndMessage;
error = ERROR;
}
}
virtual inline void VerifyGetProgramResourceLocation(GLuint program, GLenum programInterface,
std::map<std::string, GLint>& locations,
const std::string& name, long& error)
{
GLint res = glGetProgramResourceLocation(program, programInterface, name.c_str());
if (res < 0)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res
<< ", expected not less than 0" << tcu::TestLog::EndMessage;
error = ERROR;
return;
}
std::map<std::string, GLint>::iterator it = locations.begin();
while (it != locations.end())
{
if (it->second == res)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ERROR: Duplicated value found: " << res << tcu::TestLog::EndMessage;
error = ERROR;
return;
}
++it;
}
locations[name] = res;
}
virtual inline void VerifyGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index,
GLsizei propCount, const GLenum props[], GLsizei expectedLength,
const GLint expected[], long& error)
{
const GLsizei bufSize = 1000;
GLsizei length;
GLint params[bufSize];
glGetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, &length, params);
if (length != expectedLength || length <= 0)
{
error = ERROR;
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ERROR: Got length " << length << ", expected " << expectedLength
<< "\nCALL: glGetProgramResourceiv, with " << programInterface << ", " << index
<< tcu::TestLog::EndMessage;
return;
}
for (int i = 0; i < length; ++i)
{
if (params[i] != expected[i])
{
error = ERROR;
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "ERROR: Got " << params[i] << ", expected " << expected[i]
<< " at: " << i << "\nCALL: glGetProgramResourceiv, with " << programInterface << ", " << index
<< tcu::TestLog::EndMessage;
}
}
}
virtual inline void VerifyGetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
const std::string& name, GLint expected, long& error)
{
GLint res = glGetProgramResourceLocationIndex(program, programInterface, name.c_str());
if (res != expected)
{
m_context.getTestContext().getLog() << tcu::TestLog::Message << "ERROR: Got " << res << ", expected "
<< expected << "\nCALL: glGetProgramResourceLocationIndex, with "
<< programInterface << ", " << name << tcu::TestLog::EndMessage;
error = ERROR;
}
}
virtual inline GLint GetProgramivRetValue(GLuint program, GLenum pname)
{
GLint ret;
glGetProgramiv(program, pname, &ret);
return ret;
}
static const GLenum interfaces[];
};
const GLenum PIQBase::interfaces[] = { GL_PROGRAM_INPUT,
GL_PROGRAM_OUTPUT,
GL_UNIFORM,
GL_UNIFORM_BLOCK,
GL_BUFFER_VARIABLE,
GL_SHADER_STORAGE_BLOCK,
GL_VERTEX_SUBROUTINE,
GL_TESS_CONTROL_SUBROUTINE,
GL_TESS_EVALUATION_SUBROUTINE,
GL_GEOMETRY_SUBROUTINE,
GL_FRAGMENT_SUBROUTINE,
GL_COMPUTE_SUBROUTINE,
GL_VERTEX_SUBROUTINE_UNIFORM,
GL_TESS_CONTROL_SUBROUTINE_UNIFORM,
GL_TESS_EVALUATION_SUBROUTINE_UNIFORM,
GL_GEOMETRY_SUBROUTINE_UNIFORM,
GL_FRAGMENT_SUBROUTINE_UNIFORM,
GL_COMPUTE_SUBROUTINE_UNIFORM,
GL_TRANSFORM_FEEDBACK_VARYING };
class NoShaders : public PIQBase
{
virtual std::string Title()
{
return "No Shaders Test";
}
virtual std::string ShadersDesc()
{
return "no shaders";
}
virtual long Run()
{
const GLuint program = glCreateProgram();
long error = NO_ERROR;
int size = sizeof(PIQBase::interfaces) / sizeof(PIQBase::interfaces[0]);
for (int i = 0; i < size; ++i)
{
VerifyGetProgramInterfaceiv(program, PIQBase::interfaces[i], GL_ACTIVE_RESOURCES, 0, error);
if (PIQBase::interfaces[i] == GL_ATOMIC_COUNTER_BUFFER)
continue;
VerifyGetProgramInterfaceiv(program, PIQBase::interfaces[i], GL_MAX_NAME_LENGTH, 0, error);
}
VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
VerifyGetProgramInterfaceiv(program, GL_SHADER_STORAGE_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, 0, error);
VerifyGetProgramInterfaceiv(program, GL_COMPUTE_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
error);
VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
error);
VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
error);
VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES,
0, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0,
error);
VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 0, error);
for (int i = 0; i < size; ++i)
{
if (PIQBase::interfaces[i] == GL_ATOMIC_COUNTER_BUFFER)
continue;
VerifyGetProgramResourceIndex(program, PIQBase::interfaces[i], "", GL_INVALID_INDEX, error);
}
// can't test GetProgramResourceLocation* here since program has to be linked
// can't test GetProgramResourceiv, need valid index
glDeleteProgram(program);
return error;
}
};
class SimpleShaders : public PIQBase
{
public:
virtual std::string Title()
{
return "Simple Shaders Test";
}
virtual std::string ShadersDesc()
{
return "fallthrough fragment and vertex shaders";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in vec4 position; \n"
"void main(void) \n"
"{ \n"
" gl_Position = position; \n"
"}";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"out vec4 color; \n"
"void main() { \n"
" color = vec4(0, 1, 0, 1); \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 9, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 6, error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, "position", 0, error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, 0, "color", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, 0, "position", error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "position", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 0, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH };
GLint expected[] = { 9, GL_FLOAT_VEC4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, 0, 11, props, 11, expected, error);
GLenum props2[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH,
GL_LOCATION_INDEX };
GLint expected2[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props2, 12, expected2, error);
glDeleteProgram(program);
return error;
}
};
class InputTypes : public SimpleShaders
{
virtual std::string Title()
{
return "Input Types Test";
}
virtual std::string ShadersDesc()
{
return "vertex shader with different `in` types and a fallthrough fragment shader";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in mat4 a; \n"
"in ivec4 b; \n"
"in float c[2]; \n"
"in mat2x3 d[2]; \n"
"in uvec2 e; \n"
"in uint f; \n"
"in vec3 g[2]; \n"
"in int h; \n"
"void main(void) \n"
"{ \n"
" vec4 pos; \n"
" pos.w = h + g[0].x + g[1].y + d[1][1].y; \n"
" pos.y = b.x * c[0] + c[1] + d[0][0].x; \n"
" pos.x = a[0].x + a[1].y + a[2].z + a[3].w; \n"
" pos.z = d[0][1].z + e.x * f + d[1][0].z; \n"
" gl_Position = pos; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "a");
glBindAttribLocation(program, 4, "b");
glBindAttribLocation(program, 5, "c");
glBindAttribLocation(program, 7, "d");
glBindAttribLocation(program, 11, "e");
glBindAttribLocation(program, 12, "f");
glBindAttribLocation(program, 13, "g");
glBindAttribLocation(program, 15, "h");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 8, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 5, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "a", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "b", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "c[0]", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "d", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "e", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "f", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "g", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "h", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["a"], "a", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["b"], "b", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["c[0]"], "c[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["d"], "d[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["e"], "e", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["f"], "f", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["g"], "g[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["h"], "h", error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "a", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "b", 4, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[0]", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[1]", 6, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d[0]", 7, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d", 7, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "e", 11, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "f", 12, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[0]", 13, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g", 13, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[1]", 14, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "h", 15, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH };
GLint expected[] = { 2, GL_FLOAT_MAT4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["a"], 11, props, 11, expected, error);
GLint expected2[] = { 2, GL_INT_VEC4, 1, 0, 0, 0, 0, 0, 1, 4, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["b"], 11, props, 11, expected2, error);
GLint expected3[] = { 5, GL_FLOAT, 2, 0, 0, 0, 0, 0, 1, 5, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["c[0]"], 11, props, 11, expected3, error);
GLint expected4[] = { 5, GL_FLOAT_MAT2x3, 2, 0, 0, 0, 0, 0, 1, 7, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["d"], 11, props, 11, expected4, error);
GLint expected5[] = { 2, GL_UNSIGNED_INT_VEC2, 1, 0, 0, 0, 0, 0, 1, 11, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["e"], 11, props, 11, expected5, error);
GLint expected6[] = { 2, GL_UNSIGNED_INT, 1, 0, 0, 0, 0, 0, 1, 12, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["f"], 11, props, 11, expected6, error);
GLint expected7[] = { 5, GL_FLOAT_VEC3, 2, 0, 0, 0, 0, 0, 1, 13, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["g"], 11, props, 11, expected7, error);
GLint expected8[] = { 2, GL_INT, 1, 0, 0, 0, 0, 0, 1, 15, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["h"], 11, props, 11, expected8, error);
glDeleteProgram(program);
return error;
}
};
class OutputTypes : public SimpleShaders
{
virtual std::string Title()
{
return "Output Types Test";
}
virtual std::string ShadersDesc()
{
return "fragment shader with different `out` types and a fallthrough vertex shader";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"out vec3 a[2]; \n"
"out uint b; \n"
"out float c[2]; \n"
"out int d[2]; \n"
"out vec2 e; \n"
"void main() { \n"
" c[1] = -0.6; \n"
" d[0] = 0; \n"
" b = 12u; \n"
" c[0] = 1.1; \n"
" e = vec2(0, 1); \n"
" d[1] = -19; \n"
" a[1] = vec3(0, 1, 0); \n"
" a[0] = vec3(0, 1, 0); \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "a");
glBindFragDataLocation(program, 2, "b");
glBindFragDataLocation(program, 3, "c");
glBindFragDataLocation(program, 5, "d");
glBindFragDataLocation(program, 7, "e");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 5, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "a", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "b", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "c[0]", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "d", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "e", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["a"], "a[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["b"], "b", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["c[0]"], "c[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["d"], "d[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["e"], "e", error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[1]", 1, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "b", 2, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[0]", 3, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c", 3, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[1]", 4, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[0]", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[1]", 6, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "e", 7, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "b", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c[0]", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d[0]", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "e", 0, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH,
GL_LOCATION_INDEX };
GLint expected[] = { 5, GL_FLOAT_VEC3, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["a"], 12, props, 12, expected, error);
GLint expected2[] = { 2, GL_UNSIGNED_INT, 1, 0, 1, 0, 0, 0, 0, 2, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["b"], 12, props, 12, expected2, error);
GLint expected3[] = { 5, GL_FLOAT, 2, 0, 1, 0, 0, 0, 0, 3, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["c[0]"], 12, props, 12, expected3, error);
GLint expected4[] = { 5, GL_INT, 2, 0, 1, 0, 0, 0, 0, 5, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["d"], 12, props, 12, expected4, error);
GLint expected5[] = { 2, GL_FLOAT_VEC2, 1, 0, 1, 0, 0, 0, 0, 7, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["e"], 12, props, 12, expected5, error);
glDeleteProgram(program);
return error;
}
};
class OutputLocationIndex : public SimpleShaders
{
virtual std::string Title()
{
return "Output Location Index Test";
}
virtual std::string ShadersDesc()
{
return "fragment shader with `out` location index different from 0 and a fallthrough vertex shader";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocationIndexed(program, 0, 1, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 1, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH,
GL_LOCATION_INDEX };
GLint expected[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props, 12, expected, error);
glDeleteProgram(program);
return error;
}
};
class InputBuiltIn : public SimpleShaders
{
virtual std::string Title()
{
return "Input Built-ins Test";
}
virtual std::string ShadersDesc()
{
return "vertex shader using built-in variables and a fallthrough fragment shader";
}
virtual std::string Expectations()
{
return ".\n\n In this case we ask for information about built-in variables for the input interface.";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"void main(void) \n"
"{ \n"
" gl_Position = (gl_VertexID + gl_InstanceID) * vec4(0.1); \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 2, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 14, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "gl_VertexID", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "gl_InstanceID", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["gl_VertexID"], "gl_VertexID", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["gl_InstanceID"], "gl_InstanceID", error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "gl_VertexID", -1, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "gl_InstanceID", -1, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH };
GLint expected[] = { 12, GL_INT, 1, 0, 0, 0, 0, 0, 1, -1, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["gl_VertexID"], 11, props, 11, expected, error);
GLint expected2[] = { 14, GL_INT, 1, 0, 0, 0, 0, 0, 1, -1, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["gl_InstanceID"], 11, props, 11, expected2,
error);
glDeleteProgram(program);
return error;
}
};
class OutputBuiltIn : public SimpleShaders
{
virtual std::string Title()
{
return "Output Built-ins Test";
}
virtual std::string ShadersDesc()
{
return "fragment shader using built-in variables and a fallthrough vertex shader";
}
virtual std::string Expectations()
{
return ".\n\n In this case we ask for information about built-in variables for the output interface.";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"void main(void) \n"
"{ \n"
" gl_FragDepth = 0.1; \n"
" gl_SampleMask[0] = 1; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), true);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 2, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 17, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "gl_FragDepth", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "gl_SampleMask[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["gl_FragDepth"], "gl_FragDepth", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["gl_SampleMask[0]"], "gl_SampleMask[0]",
error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_FragDepth", -1, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_SampleMask", -1, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "gl_SampleMask[0]", -1, error);
// spec is not clear what to require here
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "gl_FragDepth", -1, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "gl_SampleMask", -1, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "gl_SampleMask[0]", -1, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH,
GL_LOCATION_INDEX };
GLint expected[] = { 13, GL_FLOAT, 1, 0, 1, 0, 0, 0, 0, -1, 0, -1 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["gl_FragDepth"], 12, props, 12, expected, error);
GLint expected2[] = { 17, GL_INT, 1, 0, 1, 0, 0, 0, 0, -1, 0, -1 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["gl_SampleMask[0]"], 12, props, 12, expected2,
error);
glDeleteProgram(program);
return error;
}
};
class InputLayout : public SimpleShaders
{
virtual std::string Title()
{
return "Input Layout Test";
}
virtual std::string ShadersDesc()
{
return "vertex shader with different `in` variables locations set through layout and a fallthrough fragment "
"shader";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"layout(location = 4) in ivec4 b; \n"
"layout(location = 7) in mat2x3 d[2]; \n"
"layout(location = 5) in float c[2]; \n"
"layout(location = 12) in uint f; \n"
"layout(location = 13) in vec3 g[2]; \n"
"layout(location = 0) in mat4 a; \n"
"layout(location = 15) in int h; \n"
"layout(location = 11) in uvec2 e; \n"
"void main(void) \n"
"{ \n"
" vec4 pos; \n"
" pos.w = h + g[0].x + g[1].y + d[1][1].y; \n"
" pos.y = b.x * c[0] + c[1] + d[0][0].x; \n"
" pos.x = a[0].x + a[1].y + a[2].z + a[3].w; \n"
" pos.z = d[0][1].z + e.x * f + d[1][0].z; \n"
" gl_Position = pos; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_ACTIVE_RESOURCES, 8, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_INPUT, GL_MAX_NAME_LENGTH, 5, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "a", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "b", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "c[0]", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "d", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "e", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "f", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "g", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_INPUT, indices, "h", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["a"], "a", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["b"], "b", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["c[0]"], "c[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["d"], "d[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["e"], "e", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["f"], "f", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["g"], "g[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_INPUT, indices["h"], "h", error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "a", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "b", 4, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[0]", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "c[1]", 6, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d[0]", 7, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "d", 7, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "e", 11, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "f", 12, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[0]", 13, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g", 13, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "g[1]", 14, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_INPUT, "h", 15, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH };
GLint expected[] = { 2, GL_FLOAT_MAT4, 1, 0, 0, 0, 0, 0, 1, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["a"], 11, props, 11, expected, error);
GLint expected2[] = { 2, GL_INT_VEC4, 1, 0, 0, 0, 0, 0, 1, 4, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["b"], 11, props, 11, expected2, error);
GLint expected3[] = { 5, GL_FLOAT, 2, 0, 0, 0, 0, 0, 1, 5, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["c[0]"], 11, props, 11, expected3, error);
GLint expected4[] = { 5, GL_FLOAT_MAT2x3, 2, 0, 0, 0, 0, 0, 1, 7, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["d"], 11, props, 11, expected4, error);
GLint expected5[] = { 2, GL_UNSIGNED_INT_VEC2, 1, 0, 0, 0, 0, 0, 1, 11, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["e"], 11, props, 11, expected5, error);
GLint expected6[] = { 2, GL_UNSIGNED_INT, 1, 0, 0, 0, 0, 0, 1, 12, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["f"], 11, props, 11, expected6, error);
GLint expected7[] = { 5, GL_FLOAT_VEC3, 2, 0, 0, 0, 0, 0, 1, 13, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["g"], 11, props, 11, expected7, error);
GLint expected8[] = { 2, GL_INT, 1, 0, 0, 0, 0, 0, 1, 15, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_INPUT, indices["h"], 11, props, 11, expected8, error);
glDeleteProgram(program);
return error;
}
};
class OutputLayout : public SimpleShaders
{
virtual std::string Title()
{
return "Output Layout Test";
}
virtual std::string ShadersDesc()
{
return "fragment shader with different `out` variables locations set through layout and a fallthrough vertex "
"shader";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"layout(location = 2) out uint b; \n"
"layout(location = 7) out vec2 e; \n"
"layout(location = 3) out float c[2]; \n"
"layout(location = 5) out int d[2]; \n"
"layout(location = 0) out vec3 a[2]; \n"
"void main() { \n"
" c[1] = -0.6; \n"
" d[0] = 0; \n"
" b = 12u; \n"
" c[0] = 1.1; \n"
" e = vec2(0, 1); \n"
" d[1] = -19; \n"
" a[1] = vec3(0, 1, 0); \n"
" a[0] = vec3(0, 1, 0); \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_ACTIVE_RESOURCES, 5, error);
VerifyGetProgramInterfaceiv(program, GL_PROGRAM_OUTPUT, GL_MAX_NAME_LENGTH, 5, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "a", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "b", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "c[0]", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "d", error);
VerifyGetProgramResourceIndex(program, GL_PROGRAM_OUTPUT, indices, "e", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["a"], "a[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["b"], "b", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["c[0]"], "c[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["d"], "d[0]", error);
VerifyGetProgramResourceName(program, GL_PROGRAM_OUTPUT, indices["e"], "e", error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a", 0, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "a[1]", 1, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "b", 2, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[0]", 3, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c", 3, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "c[1]", 4, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[0]", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d", 5, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "d[1]", 6, error);
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "e", 7, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a[0]", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "a", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "b", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c[0]", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "c", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d[0]", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "d", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "e", 0, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH,
GL_LOCATION_INDEX };
GLint expected[] = { 5, GL_FLOAT_VEC3, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["a"], 12, props, 12, expected, error);
GLint expected2[] = { 2, GL_UNSIGNED_INT, 1, 0, 1, 0, 0, 0, 0, 2, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["b"], 12, props, 12, expected2, error);
GLint expected3[] = { 5, GL_FLOAT, 2, 0, 1, 0, 0, 0, 0, 3, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["c[0]"], 12, props, 12, expected3, error);
GLint expected4[] = { 5, GL_INT, 2, 0, 1, 0, 0, 0, 0, 5, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["d"], 12, props, 12, expected4, error);
GLint expected5[] = { 2, GL_FLOAT_VEC2, 1, 0, 1, 0, 0, 0, 0, 7, 0, 0 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, indices["e"], 12, props, 12, expected5, error);
glDeleteProgram(program);
return error;
}
};
class OutputLayoutIndex : public SimpleShaders
{
virtual std::string Title()
{
return "Output Layout Index Test";
}
virtual std::string ShadersDesc()
{
return "fragment shader with different `out` variables fragment color index\n"
"locations set through layout and a fallthrough vertex shader";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"layout(location = 0, index = 1) out vec4 color; \n"
"void main() { \n"
" color = vec4(0, 1, 0, 1); \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramResourceLocation(program, GL_PROGRAM_OUTPUT, "color", 0, error);
VerifyGetProgramResourceLocationIndex(program, GL_PROGRAM_OUTPUT, "color", 1, error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION,
GL_IS_PER_PATCH,
GL_LOCATION_INDEX };
GLint expected[] = { 6, GL_FLOAT_VEC4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
VerifyGetProgramResourceiv(program, GL_PROGRAM_OUTPUT, 0, 12, props, 12, expected, error);
glDeleteProgram(program);
return error;
}
};
class UniformSimple : public PIQBase
{
virtual std::string Title()
{
return "Uniform Simple Test";
}
virtual std::string ShadersDesc()
{
return "fallthrough fragment and vertex shaders with uniforms used";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using GL_UNIFORM as an interface param.";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in vec4 position; \n"
"uniform vec4 repos; \n"
"void main(void) \n"
"{ \n"
" gl_Position = position + repos; \n"
"}";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"uniform vec4 recolor; \n"
"out vec4 color; \n"
"void main() { \n"
" color = vec4(0, 1, 0, 1) + recolor; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 8, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "repos", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "recolor", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["repos"], "repos", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["recolor"], "recolor", error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "repos", glGetUniformLocation(program, "repos"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "recolor", glGetUniformLocation(program, "recolor"),
error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_OFFSET,
GL_BLOCK_INDEX,
GL_ARRAY_STRIDE,
GL_MATRIX_STRIDE,
GL_IS_ROW_MAJOR,
GL_ATOMIC_COUNTER_BUFFER_INDEX,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION };
GLint expected[] = {
6, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "repos")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["repos"], 16, props, 16, expected, error);
GLint expected2[] = {
8, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "recolor")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["recolor"], 16, props, 16, expected2, error);
glDeleteProgram(program);
return error;
}
};
class UniformTypes : public PIQBase
{
virtual std::string Title()
{
return "Uniform Types Test";
}
virtual std::string ShadersDesc()
{
return "fallthrough fragment and vertex shaders with different uniform types used";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using GL_UNIFORM as an interface param.\n";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in vec4 position; \n"
"uniform vec4 a; \n"
"uniform ivec3 b; \n"
"uniform uvec2 c[3]; \n"
"uniform mat2 g[8]; \n"
"uniform mat3x2 i; \n"
"void main(void) \n"
"{ \n"
" float tmp; \n"
" tmp = g[0][1][1] + a.z + b.y + c[0].x; \n"
" tmp += g[1][1][1] + c[1].x; \n"
" tmp += g[2][1][1] + c[2].x; \n"
" for (int i = 3; i < 8; ++i) \n"
" tmp += g[i][1][1]; \n"
" tmp = tmp + i[1][1]; \n"
" gl_Position = position * tmp; \n"
"}";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"struct U { \n"
" bool a[3]; \n"
" vec4 b; \n"
" mat3 c; \n"
" float d[2]; \n"
"}; \n"
"struct UU { \n"
" U a; \n"
" U b[2]; \n"
" uvec2 c; \n"
"}; \n"
"uniform mat4 d; \n"
"uniform mat3 e; \n"
"uniform float h; \n"
"uniform int f; \n"
"uniform U j; \n"
"uniform UU k; \n"
"uniform UU l[3]; \n"
"out vec4 color; \n"
"void main() { \n"
" float tmp; \n"
" tmp = h + f + e[2][2]; \n"
" tmp = tmp + d[0][0] + j.b.x; \n"
" tmp = tmp + k.b[0].c[0][0]; \n"
" tmp = tmp + l[2].a.c[0][1]; \n"
" tmp = tmp + l[2].b[1].d[0]; \n"
" tmp = tmp + l[2].b[1].d[1]; \n"
" tmp = tmp + l[0].c.x; \n"
" color = vec4(0, 1, 0, 1) * tmp; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
// only active structure members
VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
// l[2].b[1].d[0] and \0
VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_MAX_NAME_LENGTH, 15, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "a", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "b", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "c", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "d", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "e", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "f", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "g", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "h", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "i", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "j.b", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "k.b[0].c", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[0].c", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[2].b[1].d[0]", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indices, "l[2].a.c", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["a"], "a", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["b"], "b", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["c"], "c[0]", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["d"], "d", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["e"], "e", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["f"], "f", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["g"], "g[0]", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["h"], "h", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["i"], "i", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["j.b"], "j.b", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["k.b[0].c"], "k.b[0].c", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[0].c"], "l[0].c", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[2].b[1].d[0]"], "l[2].b[1].d[0]", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indices["l[2].a.c"], "l[2].a.c", error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", glGetUniformLocation(program, "a"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", glGetUniformLocation(program, "b"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", glGetUniformLocation(program, "c"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d", glGetUniformLocation(program, "d"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "e", glGetUniformLocation(program, "e"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "f", glGetUniformLocation(program, "f"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "g", glGetUniformLocation(program, "g"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "h", glGetUniformLocation(program, "h"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "i", glGetUniformLocation(program, "i"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "j.b", glGetUniformLocation(program, "j.b"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "k.b[0].c", glGetUniformLocation(program, "k.b[0].c"),
error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[0].c", glGetUniformLocation(program, "l[0].c"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[2].b[1].d[0]",
glGetUniformLocation(program, "l[2].b[1].d[0]"), error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "l[2].a.c", glGetUniformLocation(program, "l[2].a.c"),
error);
GLenum props[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_OFFSET,
GL_BLOCK_INDEX,
GL_ARRAY_STRIDE,
GL_MATRIX_STRIDE,
GL_IS_ROW_MAJOR,
GL_ATOMIC_COUNTER_BUFFER_INDEX,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION };
GLint expected[] = {
2, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "a")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["a"], 16, props, 16, expected, error);
GLint expected2[] = { 2, GL_INT_VEC3, 1, -1, -1, -1, -1, 0,
-1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "b") };
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["b"], 16, props, 16, expected2, error);
GLint expected3[] = {
5, GL_UNSIGNED_INT_VEC2, 3, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "c")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["c"], 16, props, 16, expected3, error);
GLint expected4[] = {
2, GL_FLOAT_MAT4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "d")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["d"], 16, props, 16, expected4, error);
GLint expected5[] = {
2, GL_FLOAT_MAT3, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "e")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["e"], 16, props, 16, expected5, error);
GLint expected6[] = {
2, GL_INT, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "f")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["f"], 16, props, 16, expected6, error);
GLint expected7[] = {
5, GL_FLOAT_MAT2, 8, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "g")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["g"], 16, props, 16, expected7, error);
GLint expected8[] = { 2, GL_FLOAT, 1, -1, -1, -1, -1, 0,
-1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "h") };
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["h"], 16, props, 16, expected8, error);
GLint expected9[] = {
2, GL_FLOAT_MAT3x2, 1, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 1, glGetUniformLocation(program, "i")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["i"], 16, props, 16, expected9, error);
GLint expected10[] = {
4, GL_FLOAT_VEC4, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "j.b")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["j.b"], 16, props, 16, expected10, error);
GLint expected11[] = {
9, GL_FLOAT_MAT3, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "k.b[0].c")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["k.b[0].c"], 16, props, 16, expected11, error);
GLint expected12[] = { 7, GL_UNSIGNED_INT_VEC2,
1, -1,
-1, -1,
-1, 0,
-1, 0,
1, 0,
0, 0,
0, glGetUniformLocation(program, "l[0].c") };
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[0].c"], 16, props, 16, expected12, error);
GLint expected13[] = { 15, GL_FLOAT, 2, -1, -1, -1, -1, 0,
-1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "l[2].b[1].d[0]") };
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[2].b[1].d[0]"], 16, props, 16, expected13, error);
GLint expected14[] = {
9, GL_FLOAT_MAT3, 1, -1, -1, -1, -1, 0, -1, 0, 1, 0, 0, 0, 0, glGetUniformLocation(program, "l[2].a.c")
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indices["l[2].a.c"], 16, props, 16, expected14, error);
glDeleteProgram(program);
return error;
}
};
class UniformBlockTypes : public PIQBase
{
virtual std::string Title()
{
return "Uniform Block Types Test";
}
virtual std::string ShadersDesc()
{
return "fallthrough fragment and vertex shaders with different types of uniform blocks used";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using GL_UNIFORM_BLOCK as an interface param.\n";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in vec4 position; \n"
""
"uniform SimpleBlock { \n"
" mat3x2 a; \n"
" mat4 b; \n"
" vec4 c; \n"
"}; \n"
""
"uniform NotSoSimpleBlockk { \n"
" ivec2 a[4]; \n"
" mat3 b[2]; \n"
" mat2 c; \n"
"} d; \n"
""
"void main(void) \n"
"{ \n"
" float tmp; \n"
" tmp = a[0][1] * b[1][2] * c.x; \n"
" tmp = tmp + d.a[2].y + d.b[0][1][1] + d.c[1][1]; \n"
" gl_Position = position * tmp; \n"
"}";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"struct U { \n"
" bool a[3]; \n"
" vec4 b; \n"
" mat3 c; \n"
" float d[2]; \n"
"}; \n"
"struct UU { \n"
" U a; \n"
" U b[2]; \n"
" uvec2 c; \n"
"}; \n"
""
"uniform TrickyBlock { \n"
" UU a[3]; \n"
" mat4 b; \n"
" uint c; \n"
"} e[2]; \n"
""
"out vec4 color; \n"
"void main() { \n"
" float tmp; \n"
" tmp = e[0].a[2].b[0].d[1]; \n"
" color = vec4(0, 1, 0, 1) * tmp; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_UNIFORM, GL_ACTIVE_RESOURCES,
GetProgramivRetValue(program, GL_ACTIVE_UNIFORMS), error);
VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, 4, error);
VerifyGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NAME_LENGTH, 18, error);
std::map<std::string, GLuint> indicesUB;
std::map<std::string, GLuint> indicesU;
VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "SimpleBlock", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "NotSoSimpleBlockk", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TrickyBlock", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM_BLOCK, indicesUB, "TrickyBlock[1]", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.a[0]", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.c", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "NotSoSimpleBlockk.b[0]", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "TrickyBlock.a[2].b[0].d", error);
glUniformBlockBinding(program, indicesUB["SimpleBlock"], 0);
glUniformBlockBinding(program, indicesUB["NotSoSimpleBlockk"], 2);
glUniformBlockBinding(program, indicesUB["TrickyBlock"], 3);
glUniformBlockBinding(program, indicesUB["TrickyBlock[1]"], 4);
VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], "SimpleBlock", error);
VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], "NotSoSimpleBlockk",
error);
VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock"], "TrickyBlock[0]", error);
VerifyGetProgramResourceName(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock[1]"], "TrickyBlock[1]", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.a[0]"], "NotSoSimpleBlockk.a[0]",
error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.c"], "NotSoSimpleBlockk.c",
error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["NotSoSimpleBlockk.b[0]"], "NotSoSimpleBlockk.b[0]",
error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["TrickyBlock.a[2].b[0].d"],
"TrickyBlock.a[2].b[0].d[0]", error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
GLenum props[] = {
GL_NAME_LENGTH,
GL_BUFFER_BINDING,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_BUFFER_DATA_SIZE,
};
GLint size;
glGetActiveUniformBlockiv(program, indicesUB["SimpleBlock"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
GLint expected[] = { 12, 0, 0, 0, 0, 0, 0, 1, size };
VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], 9, props, 9, expected, error);
glGetActiveUniformBlockiv(program, indicesUB["NotSoSimpleBlockk"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
GLint expected2[] = { 18, 2, 0, 0, 0, 0, 0, 1, size };
VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], 9, props, 9, expected2,
error);
glGetActiveUniformBlockiv(program, indicesUB["TrickyBlock"], GL_UNIFORM_BLOCK_DATA_SIZE, &size);
GLint expected3[] = { 15, 3, 0, 1, 0, 0, 0, 0, size };
VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock"], 9, props, 9, expected3, error);
GLint expected4[] = { 15, 4, 0, 0, 0, 0, 0, 0, size };
VerifyGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["TrickyBlock[1]"], 9, props, 9, expected4,
error);
GLenum props2[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_BLOCK_INDEX,
GL_ARRAY_STRIDE,
GL_IS_ROW_MAJOR,
GL_ATOMIC_COUNTER_BUFFER_INDEX,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION };
GLint expected5[] = {
2, GL_FLOAT_MAT3x2, 1, static_cast<GLint>(indicesUB["SimpleBlock"]), 0, 0, -1, 0, 0, 0, 0, 0, 1, -1
};
VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 14, props2, 14, expected5, error);
GLenum props3[] = { GL_NAME_LENGTH,
GL_TYPE,
GL_ARRAY_SIZE,
GL_BLOCK_INDEX,
GL_MATRIX_STRIDE,
GL_IS_ROW_MAJOR,
GL_ATOMIC_COUNTER_BUFFER_INDEX,
GL_REFERENCED_BY_COMPUTE_SHADER,
GL_REFERENCED_BY_FRAGMENT_SHADER,
GL_REFERENCED_BY_GEOMETRY_SHADER,
GL_REFERENCED_BY_TESS_CONTROL_SHADER,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER,
GL_REFERENCED_BY_VERTEX_SHADER,
GL_LOCATION };
GLint expected6[] = { 27, GL_FLOAT, 2, static_cast<GLint>(indicesUB["TrickyBlock"]), 0, 0, -1, 0, 1, 0, 0,
0, 0, -1 };
VerifyGetProgramResourceiv(program, GL_UNIFORM, indicesU["TrickyBlock.a[2].b[0].d"], 14, props3, 14, expected6,
error);
GLenum prop = GL_ACTIVE_VARIABLES;
const GLsizei bufSize = 1000;
GLsizei length;
GLint param[bufSize];
std::set<GLuint> exp;
exp.insert(indicesU["a"]);
exp.insert(indicesU["b"]);
exp.insert(indicesU["c"]);
glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["SimpleBlock"], 1, &prop, bufSize, &length, param);
for (int i = 0; i < length; ++i)
{
if (exp.find(param[i]) == exp.end())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "Unexpected index found in active variables of SimpleBlock: " << param[i]
<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
<< tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
else if (length != 3)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK\n"
<< "Expected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
}
std::set<GLuint> exp2;
exp2.insert(indicesU["NotSoSimpleBlockk.a[0]"]);
exp2.insert(indicesU["NotSoSimpleBlockk.b[0]"]);
exp2.insert(indicesU["NotSoSimpleBlockk.c"]);
glGetProgramResourceiv(program, GL_UNIFORM_BLOCK, indicesUB["NotSoSimpleBlockk"], 1, &prop, bufSize, &length,
param);
for (int i = 0; i < length; ++i)
{
if (exp2.find(param[i]) == exp2.end())
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "Unexpected index found in active variables of NotSoSimpleBlockk: " << param[i]
<< "\nCall: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
<< tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
else if (length != 3)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message
<< "Call: glGetProgramResourceiv, property: GL_ACTIVE_VARIABLES interface: GL_UNIFORM_BLOCK"
<< "\nExpected length: 3, actual length: " << length << tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
}
GLint res;
glGetProgramInterfaceiv(program, GL_UNIFORM_BLOCK, GL_MAX_NUM_ACTIVE_VARIABLES, &res);
if (res < 3)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Value of GL_MAX_NUM_ACTIVE_VARIABLES less than 3!"
<< tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
glDeleteProgram(program);
return error;
}
};
class TransformFeedbackTypes : public SimpleShaders
{
virtual std::string Title()
{
return "Transform Feedback Varying Types";
}
virtual std::string ShadersDesc()
{
return "fallthrough fragment and vertex shaders with different types of out variables used";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using GL_TRANSFORM_FEEDBACK_VARYING as an interface param.\n";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in vec4 position; \n"
""
"flat out ivec4 a; \n"
"out float b[2]; \n"
"flat out uvec2 c; \n"
"flat out uint d; \n"
"out vec3 e[2]; \n"
"flat out int f; \n"
""
"void main(void) \n"
"{ \n"
" vec4 pos; \n"
" a = ivec4(1); \n"
" b[0] = 1.1; \n"
" b[1] = 1.1; \n"
" c = uvec2(1u); \n"
" d = 1u; \n"
" e[0] = vec3(1.1); \n"
" e[1] = vec3(1.1); \n"
" f = 1; \n"
" gl_Position = position; \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
const char* varyings[6] = { "a", "b[0]", "b[1]", "c", "d", "e" };
glTransformFeedbackVaryings(program, 6, varyings, GL_INTERLEAVED_ATTRIBS);
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_ACTIVE_RESOURCES, 6, error);
VerifyGetProgramInterfaceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, GL_MAX_NAME_LENGTH, 5, error);
std::map<std::string, GLuint> indices;
VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "a", error);
VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "b[0]", error);
VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "b[1]", error);
VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "c", error);
VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "d", error);
VerifyGetProgramResourceIndex(program, GL_TRANSFORM_FEEDBACK_VARYING, indices, "e", error);
VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["a"], "a", error);
VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[0]"], "b[0]", error);
VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[1]"], "b[1]", error);
VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["c"], "c", error);
VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["d"], "d", error);
VerifyGetProgramResourceName(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["e"], "e", error);
GLenum props[] = { GL_NAME_LENGTH, GL_TYPE, GL_ARRAY_SIZE };
GLint expected[] = { 2, GL_INT_VEC4, 1 };
VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["a"], 3, props, 3, expected, error);
GLint expected2[] = { 5, GL_FLOAT, 1 };
VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[0]"], 3, props, 3, expected2,
error);
GLint expected3[] = { 5, GL_FLOAT, 1 };
VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["b[1]"], 3, props, 3, expected3,
error);
GLint expected4[] = { 2, GL_UNSIGNED_INT_VEC2, 1 };
VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["c"], 3, props, 3, expected4, error);
GLint expected5[] = { 2, GL_UNSIGNED_INT, 1 };
VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["d"], 3, props, 3, expected5, error);
GLint expected6[] = { 2, GL_FLOAT_VEC3, 2 };
VerifyGetProgramResourceiv(program, GL_TRANSFORM_FEEDBACK_VARYING, indices["e"], 3, props, 3, expected6, error);
glDeleteProgram(program);
return error;
}
};
class AtomicCounterSimple : public SimpleShaders
{
public:
virtual std::string Title()
{
return "Atomic Counter Buffer Simple Test";
}
virtual std::string ShadersDesc()
{
return "fallthrough fragment and vertex shaders with atomic counters used";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using GL_ATOMIC_COUNTER_BUFFER as an interface param.\n";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"out vec4 color; \n"
""
"layout (binding = 1, offset = 0) uniform atomic_uint a; \n"
"layout (binding = 2, offset = 0) uniform atomic_uint b; \n"
"layout (binding = 2, offset = 4) uniform atomic_uint c; \n"
"layout (binding = 5, offset = 0) uniform atomic_uint d[3]; \n"
"layout (binding = 5, offset = 12) uniform atomic_uint e; \n"
""
"void main() { \n"
" uint x = atomicCounterIncrement(d[0]) + atomicCounterIncrement(a); \n"
" uint y = atomicCounterIncrement(d[1]) + atomicCounterIncrement(b); \n"
" uint z = atomicCounterIncrement(d[2]) + atomicCounterIncrement(c); \n"
" uint w = atomicCounterIncrement(e); \n"
" color = vec4(float(x), float(y), float(z), float(w)); \n"
"}";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES, 3, error);
VerifyGetProgramInterfaceiv(program, GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NUM_ACTIVE_VARIABLES, 2, error);
std::map<std::string, GLuint> indicesU;
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "a", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "b", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "c", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "d", error);
VerifyGetProgramResourceIndex(program, GL_UNIFORM, indicesU, "e", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["a"], "a", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["b"], "b", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["c"], "c", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["d"], "d[0]", error);
VerifyGetProgramResourceName(program, GL_UNIFORM, indicesU["e"], "e", error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "a", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "b", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "c", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "e", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[0]", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[1]", -1, error);
VerifyGetProgramResourceLocation(program, GL_UNIFORM, "d[2]", -1, error);
GLenum prop = GL_ATOMIC_COUNTER_BUFFER_INDEX;
const GLsizei bufSize = 1000;
GLsizei length;
GLint res;
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
GLenum props[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES, GL_ACTIVE_VARIABLES };
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, &res);
GLint expected[] = { 1, 4, 1, static_cast<GLint>(indicesU["a"]) };
VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 4, props, 4, expected, error);
GLenum props2[] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE, GL_NUM_ACTIVE_VARIABLES };
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
GLint expected2[] = { 2, 8, 2 };
VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected2, error);
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["c"], 1, &prop, bufSize, &length, &res);
VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected2, error);
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["d"], 1, &prop, bufSize, &length, &res);
GLint expected3[] = { 5, 16, 2 };
VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected3, error);
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["e"], 1, &prop, bufSize, &length, &res);
VerifyGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 3, props2, 3, expected3, error);
GLenum prop2 = GL_ACTIVE_VARIABLES;
GLint param[bufSize];
std::set<GLuint> exp;
exp.insert(indicesU["b"]);
exp.insert(indicesU["c"]);
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["b"], 1, &prop, bufSize, &length, &res);
glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param);
for (int i = 0; i < length; ++i)
{
if (exp.find(param[i]) == exp.end() || length != 2)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Length: " << length
<< "\nUnexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param[i]
<< tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
}
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "GL_ACTIVE_VARIABLES ok for 1st ATOMIC_COUNTER_BUFFER"
<< tcu::TestLog::EndMessage;
std::set<GLuint> exp2;
GLint param2[bufSize];
exp2.insert(indicesU["d"]);
exp2.insert(indicesU["e"]);
glGetProgramResourceiv(program, GL_UNIFORM, indicesU["d"], 1, &prop, bufSize, &length, &res);
glGetProgramResourceiv(program, GL_ATOMIC_COUNTER_BUFFER, res, 1, &prop2, bufSize, &length, param2);
for (int i = 0; i < length; ++i)
{
if (exp2.find(param2[i]) == exp2.end() || length != 2)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Length: " << length
<< "\nUnexpected index/length found in active variables of ATOMIC_COUNTER_BUFFER: " << param2[i]
<< tcu::TestLog::EndMessage;
glDeleteProgram(program);
return ERROR;
}
}
glDeleteProgram(program);
return error;
}
};
class SubroutinesBase : public SimpleShaders
{
protected:
virtual std::string ShadersDesc()
{
return "fallthrough vertex, geometry, tesselation and fragment shaders with subroutines used";
}
virtual std::string VertexShader()
{
return "#version 430 \n"
"in vec4 position; \n"
""
"subroutine vec4 a_t(); \n"
"subroutine uniform a_t a; \n"
"subroutine(a_t) vec4 x() { \n"
" return vec4(1); \n"
"} \n"
"subroutine(a_t) vec4 y() { \n"
" return vec4(0); \n"
"} \n"
"void main(void) \n"
"{ \n"
" gl_Position = a(); \n"
"}";
}
virtual std::string TessControlShader()
{
return "#version 430 \n"
"layout(vertices = 3) out; \n"
""
"subroutine vec4 a_t(); \n"
"subroutine uniform a_t a; \n"
"subroutine(a_t) vec4 x() { \n"
" return vec4(1); \n"
"} \n"
""
"void main() { \n"
" gl_out[gl_InvocationID].gl_Position = a(); \n"
" gl_TessLevelInner[0] = 1.0; \n"
" gl_TessLevelInner[1] = 1.0; \n"
" gl_TessLevelOuter[0] = 1.0; \n"
" gl_TessLevelOuter[1] = 1.0; \n"
" gl_TessLevelOuter[2] = 1.0; \n"
"}";
};
virtual std::string TessEvalShader()
{
return "#version 430 \n"
"layout(triangles, equal_spacing) in; \n"
""
"subroutine vec4 a_t(); \n"
"subroutine uniform a_t a; \n"
"subroutine(a_t) vec4 x() { \n"
" return vec4(1); \n"
"} \n"
""
"void main() { \n"
" vec4 p0 = gl_in[0].gl_Position; \n"
" vec4 p1 = gl_in[1].gl_Position; \n"
" vec4 p2 = gl_in[2].gl_Position; \n"
" vec3 p = gl_TessCoord.xyz; \n"
" gl_Position = a(); \n"
"}";
}
virtual std::string GeometryShader()
{
return "#version 430 \n"
"layout(triangles) in; \n"
"layout(triangle_strip, max_vertices = 4) out; \n"
""
"subroutine vec4 a_t(); \n"
"subroutine uniform a_t a; \n"
"subroutine(a_t) vec4 x() { \n"
" return vec4(1); \n"
"} \n"
""
"void main() { \n"
" gl_Position = vec4(-1, 1, 0, 1); \n"
" EmitVertex(); \n"
" gl_Position = vec4(-1, -1, 0, 1); \n"
" EmitVertex(); \n"
" gl_Position = vec4(1, 1, 0, 1); \n"
" EmitVertex(); \n"
" gl_Position = a(); \n"
" EmitVertex(); \n"
" EndPrimitive(); \n"
"}";
}
virtual std::string FragmentShader()
{
return "#version 430 \n"
"out vec4 color; \n"
""
"subroutine vec4 a_t(); \n"
"subroutine uniform a_t a; \n"
"subroutine(a_t) vec4 x() { \n"
" return vec4(1); \n"
"} \n"
""
"void main() { \n"
" color = a(); \n"
"}";
}
virtual void inline VerifyVS(GLuint program, long& error)
{
VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE, GL_ACTIVE_RESOURCES, 2, error);
VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 2, error);
std::map<std::string, GLuint> indicesS;
VerifyGetProgramResourceIndex(program, GL_VERTEX_SUBROUTINE, indicesS, "x", error);
VerifyGetProgramResourceIndex(program, GL_VERTEX_SUBROUTINE, indicesS, "y", error);
std::map<std::string, GLuint> indicesU;
VerifyGetProgramResourceIndex(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU, "a", error);
VerifyGetProgramResourceName(program, GL_VERTEX_SUBROUTINE, indicesS["x"], "x", error);
VerifyGetProgramResourceName(program, GL_VERTEX_SUBROUTINE, indicesS["y"], "y", error);
VerifyGetProgramResourceName(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU["a"], "a", error);
VerifyGetProgramResourceLocation(program, GL_VERTEX_SUBROUTINE_UNIFORM, "a",
glGetSubroutineUniformLocation(program, GL_VERTEX_SHADER, "a"), error);
GLenum propsS[] = { GL_NAME_LENGTH };
GLint expectedS[] = { 2 };
VerifyGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE, indicesS["x"], 1, propsS, 1, expectedS, error);
VerifyGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE, indicesS["y"], 1, propsS, 1, expectedS, error);
GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION };
GLint expectedU[] = { 2, 1, 2, glGetSubroutineUniformLocation(program, GL_VERTEX_SHADER, "a") };
VerifyGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU["a"], 4, propsU, 4, expectedU,
error);
GLenum prop = GL_COMPATIBLE_SUBROUTINES;
const GLsizei bufSize = 1000;
GLint param[bufSize];
GLsizei length;
std::set<GLuint> exp;
exp.insert(indicesS["x"]);
exp.insert(indicesS["y"]);
glGetProgramResourceiv(program, GL_VERTEX_SUBROUTINE_UNIFORM, indicesU["a"], 1, &prop, bufSize, &length, param);
for (int i = 0; i < length; ++i)
{
if (exp.find(param[i]) == exp.end() || length != 2)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Length: " << length
<< "\nUnexpected index/length found in active variables of GL_VERTEX_SUBROUTINE_UNIFORM: "
<< param[i] << tcu::TestLog::EndMessage;
error = ERROR;
}
}
}
virtual void inline VerifyTCS(GLuint program, long& error)
{
VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 1,
error);
std::map<std::string, GLuint> indicesTS;
VerifyGetProgramResourceIndex(program, GL_TESS_CONTROL_SUBROUTINE, indicesTS, "x", error);
std::map<std::string, GLuint> indicesTU;
VerifyGetProgramResourceIndex(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, indicesTU, "a", error);
VerifyGetProgramResourceName(program, GL_TESS_CONTROL_SUBROUTINE, indicesTS["x"], "x", error);
VerifyGetProgramResourceName(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
VerifyGetProgramResourceLocation(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, "a",
glGetSubroutineUniformLocation(program, GL_TESS_CONTROL_SHADER, "a"), error);
GLenum propsS[] = { GL_NAME_LENGTH };
GLint expectedS[] = { 2 };
VerifyGetProgramResourceiv(program, GL_TESS_CONTROL_SUBROUTINE, static_cast<GLint>(indicesTS["x"]), 1, propsS,
1, expectedS, error);
GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
GL_COMPATIBLE_SUBROUTINES };
GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_TESS_CONTROL_SHADER, "a"),
static_cast<GLint>(indicesTS["x"]) };
VerifyGetProgramResourceiv(program, GL_TESS_CONTROL_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5, expectedU,
error);
}
};
class SubroutinesVertex : public SubroutinesBase
{
virtual std::string Title()
{
return "Vertex Shader Subroutines Test";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using *VERTEX_SUBROUTINE* as an interface params.\n";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
GeometryShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyVS(program, error);
glDeleteProgram(program);
return error;
}
};
class SubroutinesTessControl : public SubroutinesBase
{
virtual std::string Title()
{
return "Tess Control Subroutines Test";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using *TESS_CONTROL_SUBROUTINE* as an interface params.\n";
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
GeometryShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyTCS(program, error);
glDeleteProgram(program);
return error;
}
};
class SubroutinesTessEval : public SubroutinesBase
{
virtual std::string Title()
{
return "Tess Evaluation Subroutines Test";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using *TESS_EVALUATION_SUBROUTINE* as an interface params.\n";
}
virtual void inline VerifyTES(GLuint program, long& error)
{
VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES,
1, error);
std::map<std::string, GLuint> indicesTS;
VerifyGetProgramResourceIndex(program, GL_TESS_EVALUATION_SUBROUTINE, indicesTS, "x", error);
std::map<std::string, GLuint> indicesTU;
VerifyGetProgramResourceIndex(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, indicesTU, "a", error);
VerifyGetProgramResourceName(program, GL_TESS_EVALUATION_SUBROUTINE, indicesTS["x"], "x", error);
VerifyGetProgramResourceName(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
VerifyGetProgramResourceLocation(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, "a",
glGetSubroutineUniformLocation(program, GL_TESS_EVALUATION_SHADER, "a"),
error);
GLenum propsS[] = { GL_NAME_LENGTH };
GLint expectedS[] = { 2 };
VerifyGetProgramResourceiv(program, GL_TESS_EVALUATION_SUBROUTINE, indicesTS["x"], 1, propsS, 1, expectedS,
error);
GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
GL_COMPATIBLE_SUBROUTINES };
GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_TESS_EVALUATION_SHADER, "a"),
static_cast<GLint>(indicesTS["x"]) };
VerifyGetProgramResourceiv(program, GL_TESS_EVALUATION_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5,
expectedU, error);
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
GeometryShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyTES(program, error);
glDeleteProgram(program);
return error;
}
};
class SubroutinesGeometry : public SubroutinesBase
{
virtual std::string Title()
{
return "Geometry Shader Subroutines Test";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using *GEOMETRY_SUBROUTINE* as an interface params.\n";
}
virtual void inline VerifyGEO(GLuint program, long& error)
{
VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 1,
error);
std::map<std::string, GLuint> indicesTS;
VerifyGetProgramResourceIndex(program, GL_GEOMETRY_SUBROUTINE, indicesTS, "x", error);
std::map<std::string, GLuint> indicesTU;
VerifyGetProgramResourceIndex(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, indicesTU, "a", error);
VerifyGetProgramResourceName(program, GL_GEOMETRY_SUBROUTINE, indicesTS["x"], "x", error);
VerifyGetProgramResourceName(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
VerifyGetProgramResourceLocation(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, "a",
glGetSubroutineUniformLocation(program, GL_GEOMETRY_SHADER, "a"), error);
GLenum propsS[] = { GL_NAME_LENGTH };
GLint expectedS[] = { 2 };
VerifyGetProgramResourceiv(program, GL_GEOMETRY_SUBROUTINE, indicesTS["x"], 1, propsS, 1, expectedS, error);
GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
GL_COMPATIBLE_SUBROUTINES };
GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_GEOMETRY_SHADER, "a"),
static_cast<GLint>(indicesTS["x"]) };
VerifyGetProgramResourceiv(program, GL_GEOMETRY_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5, expectedU,
error);
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
GeometryShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyGEO(program, error);
glDeleteProgram(program);
return error;
}
};
class SubroutinesFragment : public SubroutinesBase
{
virtual std::string Title()
{
return "Fragment Shader Subroutines Test";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using *FRAGMENT_SUBROUTINE* as an interface params.\n";
}
virtual void inline VerifyFS(GLuint program, long& error)
{
VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_ACTIVE_RESOURCES, 1, error);
VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_MAX_NAME_LENGTH, 2, error);
VerifyGetProgramInterfaceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, 1,
error);
std::map<std::string, GLuint> indicesTS;
VerifyGetProgramResourceIndex(program, GL_FRAGMENT_SUBROUTINE, indicesTS, "x", error);
std::map<std::string, GLuint> indicesTU;
VerifyGetProgramResourceIndex(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, indicesTU, "a", error);
VerifyGetProgramResourceName(program, GL_FRAGMENT_SUBROUTINE, indicesTS["x"], "x", error);
VerifyGetProgramResourceName(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, indicesTU["a"], "a", error);
VerifyGetProgramResourceLocation(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, "a",
glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "a"), error);
GLenum propsS[] = { GL_NAME_LENGTH };
GLint expectedS[] = { 2 };
VerifyGetProgramResourceiv(program, GL_FRAGMENT_SUBROUTINE, indicesTS["x"], 1, propsS, 1, expectedS, error);
GLenum propsU[] = { GL_NAME_LENGTH, GL_ARRAY_SIZE, GL_NUM_COMPATIBLE_SUBROUTINES, GL_LOCATION,
GL_COMPATIBLE_SUBROUTINES };
GLint expectedU[] = { 2, 1, 1, glGetSubroutineUniformLocation(program, GL_FRAGMENT_SHADER, "a"),
static_cast<GLint>(indicesTS["x"]) };
VerifyGetProgramResourceiv(program, GL_FRAGMENT_SUBROUTINE_UNIFORM, indicesTU["a"], 5, propsU, 5, expectedU,
error);
}
virtual long Run()
{
GLuint program = CreateProgram(VertexShader().c_str(), TessControlShader().c_str(), TessEvalShader().c_str(),
GeometryShader().c_str(), FragmentShader().c_str(), false);
glBindAttribLocation(program, 0, "position");
glBindFragDataLocation(program, 0, "color");
LinkProgram(program);
long error = NO_ERROR;
VerifyFS(program, error);
glDeleteProgram(program);
return error;
}
};
class SoubroutinesCompute : public PIQBase
{
virtual std::string Title()
{
return "Compute Shader Subroutines Test";
}
virtual std::string ShadersDesc()
{
return "compute shader with subroutines used";
}
virtual std::string PurposeExt()
{
return "\n\n Purpose is to verify calls using *COMPUTE_SUBROUTINE* as an interface params.\n";
}
virtual std::string ComputeShader()
{
return "layout(local_size_x = 1, local_size_y = 1) in; \n"
"layout(std430) buffer Output { \n"
" vec4 data; \n"
"} g_out; \n"
""
"subroutine vec4 a_t(); \n"
"subroutine uniform a_t a; \n"
"subroutine(a_t) vec4 ax() { \n"
" return vec4(1); \n"
"} \n"
"subroutine(a_t) vec4 ay() { \n"
" return vec4(0); \n"
"} \n"
""
<