blob: e6ebdde85aa6e595b060810bf10e4426c4c3836b [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 "es31cTextureGatherTests.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuMatrix.hpp"
#include "tcuMatrixUtil.hpp"
#include "tcuRenderTarget.hpp"
#include <cstdarg>
#include <sstream>
#include <string>
#include <vector>
namespace glcts
{
using namespace glw;
using tcu::Vec4;
using tcu::Vec3;
using tcu::Vec2;
using tcu::IVec4;
using tcu::UVec4;
namespace
{
class TGBase : public glcts::SubcaseBase
{
public:
virtual ~TGBase()
{
}
TGBase() : renderTarget(m_context.getRenderContext().getRenderTarget()), pixelFormat(renderTarget.getPixelFormat())
{
}
const tcu::RenderTarget& renderTarget;
const tcu::PixelFormat& pixelFormat;
int GetWindowWidth()
{
return renderTarget.getWidth();
}
int GetWindowHeight()
{
return renderTarget.getHeight();
}
virtual std::string Title()
{
return "";
}
virtual std::string Purpose()
{
return "";
}
virtual std::string Method()
{
return "";
}
virtual std::string PassCriteria()
{
return "";
}
GLuint CreateProgram(const char* src_vs, const char* src_fs)
{
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);
}
return p;
}
GLuint CreateComputeProgram(const std::string& cs)
{
const GLuint p = glCreateProgram();
if (!cs.empty())
{
const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
glAttachShader(p, sh);
glDeleteShader(sh);
const char* const src[1] = { cs.c_str() };
glShaderSource(sh, 1, src, NULL);
glCompileShader(sh);
}
return p;
}
bool CheckProgram(GLuint program, bool* compile_error = NULL)
{
GLint compile_status = GL_TRUE;
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint attached_shaders;
glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
if (attached_shaders > 0)
{
std::vector<GLuint> shaders(attached_shaders);
glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
for (GLint i = 0; i < attached_shaders; ++i)
{
GLenum type;
glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
switch (type)
{
case GL_VERTEX_SHADER:
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
break;
case GL_FRAGMENT_SHADER:
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
break;
case GL_COMPUTE_SHADER:
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
break;
default:
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
}
GLint res;
glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
if (res != GL_TRUE)
compile_status = res;
GLint length;
glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
if (length > 0)
{
std::vector<GLchar> source(length);
glGetShaderSource(shaders[i], length, NULL, &source[0]);
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
}
glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
if (length > 0)
{
std::vector<GLchar> log(length);
glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
}
}
}
GLint length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
if (length > 0)
{
std::vector<GLchar> log(length);
glGetProgramInfoLog(program, length, NULL, &log[0]);
m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
}
}
if (compile_error)
*compile_error = (compile_status == GL_TRUE ? false : true);
if (compile_status != GL_TRUE)
return false;
return status == GL_TRUE ? true : false;
}
virtual long Setup()
{
return NO_ERROR;
}
virtual long Cleanup()
{
return NO_ERROR;
}
};
class GatherEnumsTest : public TGBase
{
virtual std::string Title()
{
return "Basic Enum Test";
}
virtual std::string Purpose()
{
return "Verify that gather related enums are correct.";
}
virtual std::string Method()
{
return "Query GL_*_TEXTURE_GATHER_OFFSET enums.";
}
virtual std::string PassCriteria()
{
return "Values of enums meet GL spec requirements.";
}
virtual long Run()
{
GLint res;
glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &res);
if (res > -8)
{
return ERROR;
}
glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &res);
if (res < 7)
{
return ERROR;
}
return NO_ERROR;
}
};
class GatherGLSLCompile : public TGBase
{
GLuint program;
virtual std::string Title()
{
return "GLSL Compile Test";
}
virtual std::string Purpose()
{
return "Verify that gather functions are visible in the shaders.";
}
virtual std::string Method()
{
return "Create shaders which use all types of gather functions.";
}
virtual std::string PassCriteria()
{
return "Programs compile and link successfuly.";
}
virtual std::string Uniforms()
{
return "uniform mediump sampler2D tex_2d; \n"
"uniform mediump isamplerCube itex_cube; \n"
"uniform mediump usampler2DArray utex_2da; \n"
""
"uniform mediump sampler2DShadow tex_2ds; \n"
"uniform mediump samplerCubeShadow tex_cubes; \n"
"uniform mediump sampler2DArrayShadow tex_2das; \n";
}
virtual std::string Sampling()
{
return " textureGather(tex_2d,vec2(1)); \n"
" textureGather(itex_cube,vec3(1)); \n"
" textureGather(utex_2da,vec3(1)); \n"
""
" textureGather(tex_2ds,vec2(1), 0.5); \n"
" textureGather(tex_cubes,vec3(1), 0.5); \n"
" textureGather(tex_2das,vec3(1), 0.5); \n"
""
" textureGatherOffset(tex_2d,vec2(1), ivec2(0)); \n"
" textureGatherOffset(utex_2da,vec3(1), ivec2(0)); \n"
""
" textureGatherOffset(tex_2ds,vec2(1), 0.5, ivec2(0)); \n"
" textureGatherOffset(tex_2das,vec3(1), 0.5, ivec2(0)); \n";
}
virtual std::string VertexShader()
{
return "#version 310 es \n" + Uniforms() +
" void main() { \n" + Sampling() +
" gl_Position = vec4(1); \n"
" } \n";
}
virtual std::string FragmentShader()
{
return "#version 310 es \n"
"precision highp float; \n"
"out mediump vec4 color; \n" +
Uniforms() + " void main() { \n" + Sampling() +
" color = vec4(1); \n"
" } \n";
}
virtual long Run()
{
program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str());
glLinkProgram(program);
if (!CheckProgram(program))
return ERROR;
return NO_ERROR;
}
virtual long Cleanup()
{
glDeleteProgram(program);
return NO_ERROR;
}
};
class GatherBase : public TGBase
{
public:
GLuint tex, fbo, rbo, program, vao, vbo;
bool IsFloatingPointTexture(GLenum internal_format)
{
switch (internal_format)
{
case GL_R32F:
case GL_RG32F:
case GL_RGB32F:
case GL_RGBA32F:
case GL_DEPTH_COMPONENT32F:
return true;
}
return false;
}
virtual GLvoid CreateTexture2DRgb(bool base_level = false)
{
GLenum internal_format = GL_RGB32F;
GLenum format = GL_RGB;
const GLint csize = base_level ? 64 : 32;
GLint size = csize;
GLenum target = GL_TEXTURE_2D;
GLenum tex_type = GL_FLOAT;
glGenTextures(1, &tex);
glBindTexture(target, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
std::vector<Vec3> pixels(size * size, Vec3(1.0));
glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
}
Vec3 data[4] = { Vec3(12. / 16, 13. / 16, 14. / 16), Vec3(8. / 16, 9. / 16, 10. / 16),
Vec3(0. / 16, 1. / 16, 2. / 16), Vec3(4. / 16, 5. / 16, 6. / 16) };
glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if (IsFloatingPointTexture(internal_format))
{
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
}
virtual GLvoid CreateTexture2DRg(bool base_level = false)
{
GLenum internal_format = GL_RG32F;
GLenum format = GL_RG;
const GLint csize = base_level ? 64 : 32;
GLint size = csize;
GLenum target = GL_TEXTURE_2D;
GLenum tex_type = GL_FLOAT;
glGenTextures(1, &tex);
glBindTexture(target, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
std::vector<Vec2> pixels(size * size, Vec2(1.0));
glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
}
Vec2 data[4] = { Vec2(12. / 16, 13. / 16), Vec2(8. / 16, 9. / 16), Vec2(0. / 16, 1. / 16),
Vec2(4. / 16, 5. / 16) };
glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if (IsFloatingPointTexture(internal_format))
{
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
}
virtual GLvoid CreateTexture2DR(bool base_level = false)
{
GLenum internal_format = GL_R32F;
GLenum format = GL_RED;
const GLint csize = base_level ? 64 : 32;
GLint size = csize;
GLenum target = GL_TEXTURE_2D;
GLenum tex_type = GL_FLOAT;
glGenTextures(1, &tex);
glBindTexture(target, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
std::vector<GLfloat> pixels(size * size, 1.0);
glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
}
GLfloat data[4] = { 12. / 16., 8. / 16., 0. / 16., 4. / 16. };
glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if (IsFloatingPointTexture(internal_format))
{
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
}
virtual GLvoid CreateTexture2DInt()
{
GLenum internal_format = InternalFormat();
const GLint csize = 32;
GLint size = csize;
GLenum target = GL_TEXTURE_2D;
GLenum tex_type = Type().find('u') != std::string::npos ? GL_UNSIGNED_INT : GL_INT;
glGenTextures(1, &tex);
glBindTexture(target, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
glTexImage2D(target, i, internal_format, size, size, 0, GL_RGBA_INTEGER, tex_type, 0);
}
std::vector<IVec4> pixels(csize * csize, IVec4(999));
glTexSubImage2D(target, 0, 0, 0, csize, csize, GL_RGBA_INTEGER, tex_type, &pixels[0]);
IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
glTexSubImage2D(target, 0, 22, 25, 2, 2, GL_RGBA_INTEGER, tex_type, data);
glTexSubImage2D(target, 0, 16, 10, 1, 1, GL_RGBA_INTEGER, tex_type, data + 0);
glTexSubImage2D(target, 0, 11, 2, 1, 1, GL_RGBA_INTEGER, tex_type, data + 1);
glTexSubImage2D(target, 0, 24, 13, 1, 1, GL_RGBA_INTEGER, tex_type, data + 2);
glTexSubImage2D(target, 0, 9, 14, 1, 1, GL_RGBA_INTEGER, tex_type, data + 3);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
virtual GLvoid CreateTexture2DArrayInt(int slices, int data_slice)
{
GLenum internal_format = InternalFormat();
const GLint csize = 32;
GLint size = csize;
GLenum tex_type = Type().find('u') != std::string::npos ? GL_UNSIGNED_INT : GL_INT;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, size, size, slices, 0, GL_RGBA_INTEGER, tex_type, 0);
}
std::vector<IVec4> pixels(csize * csize, IVec4(999));
for (int i = 0; i < slices; ++i)
{
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, csize, csize, 1, GL_RGBA_INTEGER, tex_type, &pixels[0]);
}
IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 22, 25, data_slice, 2, 2, 1, GL_RGBA_INTEGER, tex_type, data);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 16, 10, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 0);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 11, 2, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 1);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 24, 13, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 2);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 9, 14, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 3);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
virtual GLvoid CreateTexture2DArray(int slices, int data_slice)
{
GLenum internal_format = InternalFormat();
GLenum format = Format();
const GLint csize = 32;
GLint size = csize;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
std::vector<Vec4> pixels(size * size * slices, Vec4(1.0));
glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, size, size, slices, 0, format, GL_FLOAT, &pixels[0]);
}
Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 22, 25, data_slice, 2, 2, 1, format, GL_FLOAT, data);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 16, 10, data_slice, 1, 1, 1, format, GL_FLOAT, data + 0);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 11, 2, data_slice, 1, 1, 1, format, GL_FLOAT, data + 1);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 24, 13, data_slice, 1, 1, 1, format, GL_FLOAT, data + 2);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 9, 14, data_slice, 1, 1, 1, format, GL_FLOAT, data + 3);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if (IsFloatingPointTexture(internal_format))
{
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
}
virtual GLvoid CreateTextureCubeInt()
{
GLenum internal_format = InternalFormat();
const GLint csize = 32;
GLint size = csize;
GLenum tex_type = Type().find('u') != std::string::npos ? GL_UNSIGNED_INT : GL_INT;
const GLenum faces[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
for (int j = 0; j < 6; ++j)
{
glTexImage2D(faces[j], i, internal_format, size, size, 0, GL_RGBA_INTEGER, tex_type, 0);
}
}
std::vector<IVec4> pixels(csize * csize, IVec4(999));
for (int j = 0; j < 6; ++j)
{
glTexSubImage2D(faces[j], 0, 0, 0, csize, csize, GL_RGBA_INTEGER, tex_type, &pixels[0]);
}
IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
for (int j = 0; j < 6; ++j)
{
glTexSubImage2D(faces[j], 0, 22, 25, 2, 2, GL_RGBA_INTEGER, tex_type, data);
glTexSubImage2D(faces[j], 0, 16, 10, 1, 1, GL_RGBA_INTEGER, tex_type, data + 0);
glTexSubImage2D(faces[j], 0, 11, 2, 1, 1, GL_RGBA_INTEGER, tex_type, data + 1);
glTexSubImage2D(faces[j], 0, 24, 13, 1, 1, GL_RGBA_INTEGER, tex_type, data + 2);
glTexSubImage2D(faces[j], 0, 9, 14, 1, 1, GL_RGBA_INTEGER, tex_type, data + 3);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
virtual GLvoid CreateTextureCube()
{
GLenum internal_format = InternalFormat();
GLenum format = Format();
const GLint csize = 32;
GLint size = csize;
const GLenum faces[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
std::vector<Vec4> pixels(size * size, Vec4(1.0));
for (int j = 0; j < 6; ++j)
{
glTexImage2D(faces[j], i, internal_format, size, size, 0, format, GL_FLOAT, &pixels[0]);
}
}
Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
Vec4 depthData(data[0][0], data[1][0], data[2][0], data[3][0]);
Vec4* packedData = (format == GL_DEPTH_COMPONENT) ? &depthData : data;
for (int j = 0; j < 6; ++j)
{
glTexSubImage2D(faces[j], 0, 22, 25, 2, 2, format, GL_FLOAT, packedData);
glTexSubImage2D(faces[j], 0, 16, 10, 1, 1, format, GL_FLOAT, data + 0);
glTexSubImage2D(faces[j], 0, 11, 2, 1, 1, format, GL_FLOAT, data + 1);
glTexSubImage2D(faces[j], 0, 24, 13, 1, 1, format, GL_FLOAT, data + 2);
glTexSubImage2D(faces[j], 0, 9, 14, 1, 1, format, GL_FLOAT, data + 3);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if (IsFloatingPointTexture(internal_format))
{
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
}
virtual GLvoid CreateTextureSRGB()
{
GLenum internal_format = InternalFormat();
GLenum format = Format();
const GLint csize = 32;
GLint size = csize;
GLenum target = GL_TEXTURE_2D;
GLenum tex_type = GL_UNSIGNED_BYTE;
glGenTextures(1, &tex);
glBindTexture(target, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
}
std::vector<GLubyte> pixels(csize * csize * 4, 255);
glTexSubImage2D(target, 0, 0, 0, csize, csize, format, tex_type, &pixels[0]);
if (format != GL_DEPTH_COMPONENT)
{
glGenerateMipmap(target);
}
GLubyte data[16] = { 240, 13, 14, 15, 160, 9, 10, 11, 0, 1, 2, 3, 80, 5, 6, 7 };
glTexSubImage2D(target, 0, 22, 25, 2, 2, format, tex_type, data);
glTexSubImage2D(target, 0, 16, 10, 1, 1, format, tex_type, data + 0);
glTexSubImage2D(target, 0, 11, 2, 1, 1, format, tex_type, data + 4);
glTexSubImage2D(target, 0, 24, 13, 1, 1, format, tex_type, data + 8);
glTexSubImage2D(target, 0, 9, 14, 1, 1, format, tex_type, data + 12);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
virtual GLvoid CreateTexture2D(bool base_level = false)
{
GLenum internal_format = InternalFormat();
GLenum format = Format();
const GLint csize = base_level ? 64 : 32;
GLint size = csize;
GLenum target = GL_TEXTURE_2D;
GLenum tex_type = InternalFormat() == GL_SRGB8_ALPHA8 ? GL_UNSIGNED_BYTE : GL_FLOAT;
glGenTextures(1, &tex);
glBindTexture(target, tex);
for (int i = 0; size > 0; ++i, size /= 2)
{
std::vector<Vec4> pixels(size * size, Vec4(1.0));
glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
}
Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if (IsFloatingPointTexture(internal_format))
{
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
}
if (base_level)
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 1);
}
virtual std::string FallthroughVertexShader()
{
return "#version 310 es \n"
"in vec4 v_in_0; \n"
"flat out vec4 v_out_0; \n"
"void main() { \n"
" gl_Position = vec4(0,0,0,1); \n"
"#ifdef GL_ES \n"
" gl_PointSize = 1.0f; \n"
"#endif \n"
" v_out_0 = v_in_0; \n"
"}";
}
virtual std::string FallthroughFragmentShader()
{
return "#version 310 es \n"
"precision highp float; \n"
"out mediump vec4 f_out_0; \n"
"flat in mediump vec4 v_out_0; \n"
"void main() { \n"
" f_out_0 = v_out_0; \n"
"}";
}
virtual std::string TestFunction()
{
return Sampler() + TextBody();
}
virtual std::string Sampler()
{
return "uniform mediump sampler2D my_sampler; \n";
}
virtual std::string Type()
{
return "vec4";
}
virtual std::string TextBody()
{
std::string str_if = " if (all(lessThanEqual(abs(tmp - " + Expected() + "), vec4(0.039)))) { \n";
if (Type().find('u') != std::string::npos || Type().find('i') != std::string::npos)
{
str_if = " if (tmp == " + Expected() + ") { \n";
}
return "vec4 test_function(vec4 p) { "
"\n" +
Offset() + " mediump " + Type() + " tmp = " + Gather() +
"; \n" + str_if +
" return vec4(0.0, 1.0, 0.0, 1.0); \n"
" } else { \n"
" return vec4(float(tmp.x), float(tmp.y), float(tmp.z), float(tmp.w)); \n"
" } \n"
"}\n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec2(p.x, p.y))";
}
virtual std::string Offset()
{
return "";
}
virtual std::string VertexShader()
{
return "#version 310 es \n"
""
"in mediump vec4 v_in_0; \n"
"flat out mediump vec4 v_out_0; \n" +
TestFunction() + "void main() { \n"
" gl_Position = vec4(0, 0, 0, 1); \n"
"#ifdef GL_ES \n"
" gl_PointSize = 1.0f; \n"
"#endif \n"
" v_out_0 = test_function(v_in_0); \n"
"}";
}
virtual std::string FragmentShader()
{
return "#version 310 es \n"
""
"precision highp float; \n"
"flat in mediump vec4 v_out_0; \n"
"out mediump vec4 f_out_0; \n" +
TestFunction() + "void main() { \n"
" f_out_0 = test_function(v_out_0); \n"
"}";
}
virtual std::string ComputeShader()
{
return "#version 310 es \n"
"layout(local_size_x = 1, local_size_y = 1) in; \n"
"layout(std430) buffer Output { \n"
" mediump vec4 data; \n"
"} g_out; \n"
"uniform mediump vec4 cs_in; \n" +
TestFunction() + "void main() { \n"
" g_out.data = test_function(cs_in); \n"
"} \n";
}
virtual void Init()
{
CreateTexture2D();
}
virtual long Verify()
{
std::vector<GLubyte> data(4);
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
if (data[0] != 0 || data[1] != 255 || data[2] != 0 || data[3] != 255)
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Expected Vec4(0, 255, 0, 255), got: " << data[0] << ", " << data[1] << ", "
<< data[2] << ", " << data[3] << tcu::TestLog::EndMessage;
return ERROR;
}
return NO_ERROR;
}
virtual std::string Expected()
{
return "vec4(0./16., 4./16., 8./16., 12./16.)";
}
virtual GLenum InternalFormat()
{
return GL_RGBA32F;
}
virtual GLenum Format()
{
return GL_RGBA;
}
virtual Vec4 BufferData()
{
return Vec4(23. / 32, 26. / 32, 5, 3);
}
virtual bool Supported()
{
return true;
}
virtual long Run()
{
if (!Supported())
return NO_ERROR;
Init();
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, &drawBuffer);
GLfloat colorf[4] = { 0, 0, 0, 0 };
glClearBufferfv(GL_COLOR, 0, colorf);
glViewport(0, 0, 1, 1);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
Vec4 buffData = BufferData();
glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
for (int i = 0; i < 2; ++i)
{
if (i == 0)
program = CreateProgram(VertexShader().c_str(), FallthroughFragmentShader().c_str());
else
program = CreateProgram(FallthroughVertexShader().c_str(), FragmentShader().c_str());
glBindAttribLocation(program, 0, "v_in_0");
glLinkProgram(program);
if (!CheckProgram(program))
return ERROR;
glUseProgram(program);
glDrawArrays(GL_POINTS, 0, 1);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDeleteProgram(program);
if (Verify() == ERROR)
return ERROR;
}
return TestCompute();
}
virtual long TestCompute()
{
GLuint m_buffer;
program = CreateComputeProgram(ComputeShader());
glLinkProgram(program);
if (!CheckProgram(program))
return ERROR;
glUseProgram(program);
glUniform4f(glGetUniformLocation(program, "cs_in"), BufferData().x(), BufferData().y(), BufferData().z(),
BufferData().w());
glGenBuffers(1, &m_buffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Vec4), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glDispatchCompute(1, 1, 1);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
long error = VerifyCompute();
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glDeleteBuffers(1, &m_buffer);
return error;
}
virtual long VerifyCompute()
{
Vec4* data;
data = static_cast<Vec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Vec4), GL_MAP_READ_BIT));
if (data[0] != Vec4(0, 1, 0, 1))
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Expected Vec4(0, 1, 0, 1), got: " << data[0].x() << ", " << data[0].y()
<< ", " << data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
return ERROR;
}
return NO_ERROR;
}
virtual long Cleanup()
{
glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
glDisableVertexAttribArray(0);
glDeleteTextures(1, &tex);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteRenderbuffers(1, &rbo);
glDeleteFramebuffers(1, &fbo);
glDeleteProgram(program);
return NO_ERROR;
}
};
class PlainGatherFloat2D : public GatherBase
{
};
class PlainGatherInt2D : public GatherBase
{
public:
virtual GLenum InternalFormat()
{
return GL_RGBA32I;
}
virtual void Init()
{
CreateTexture2DInt();
}
virtual std::string Expected()
{
return "ivec4(0, 4, 8, 12)";
}
virtual std::string Sampler()
{
return "uniform mediump isampler2D my_sampler; \n";
}
virtual std::string Type()
{
return "ivec4";
}
};
class PlainGatherUint2D : public GatherBase
{
public:
virtual GLenum InternalFormat()
{
return GL_RGBA32UI;
}
virtual void Init()
{
CreateTexture2DInt();
}
virtual std::string Expected()
{
return "uvec4(2u, 6u, 10u, 14u)";
}
virtual std::string Sampler()
{
return "uniform mediump usampler2D my_sampler; \n";
}
virtual Vec4 BufferData()
{
return Vec4(22.9f / 32, 25.9f / 32, 2, 2);
}
virtual std::string Type()
{
return "uvec4";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec2(p.x, p.y), 2)";
}
};
class PlainGatherDepth2D : public GatherBase
{
public:
virtual GLenum InternalFormat()
{
return GL_DEPTH_COMPONENT32F;
}
virtual GLenum Format()
{
return GL_DEPTH_COMPONENT;
}
virtual void Init()
{
CreateTexture2D();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
}
virtual std::string Expected()
{
return "vec4(1.0, 1.0, 0.0, 0.0)";
}
virtual Vec4 BufferData()
{
return Vec4(23. / 32, 26. / 32, 13.5 / 16, 3);
}
virtual std::string Sampler()
{
return "uniform mediump sampler2DShadow my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec2(p.x, p.y), p.z)";
}
};
class PlainGatherFloat2DArray : public GatherBase
{
public:
virtual void Init()
{
CreateTexture2DArray(9, 5);
}
virtual std::string Sampler()
{
return "uniform mediump sampler2DArray my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
}
};
class PlainGatherInt2DArray : public GatherBase
{
public:
virtual void Init()
{
CreateTexture2DArrayInt(20, 11);
}
virtual GLenum InternalFormat()
{
return GL_RGBA32I;
}
virtual std::string Expected()
{
return "ivec4(3, 7, 11, 15)";
}
virtual std::string Type()
{
return "ivec4";
}
virtual Vec4 BufferData()
{
return Vec4(23. / 32, 26. / 32, 11, 3);
}
virtual std::string Sampler()
{
return "uniform mediump isampler2DArray my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z), 3)";
}
};
class PlainGatherUint2DArray : public GatherBase
{
public:
virtual void Init()
{
CreateTexture2DArrayInt(3, 1);
}
virtual GLenum InternalFormat()
{
return GL_RGBA32UI;
}
virtual std::string Expected()
{
return "uvec4(0u, 4u, 8u, 12u)";
}
virtual std::string Type()
{
return "uvec4";
}
virtual Vec4 BufferData()
{
return Vec4(23. / 32, 26. / 32, 1, 3);
}
virtual std::string Sampler()
{
return "uniform mediump usampler2DArray my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
}
};
class PlainGatherDepth2DArray : public GatherBase
{
public:
virtual GLenum InternalFormat()
{
return GL_DEPTH_COMPONENT32F;
}
virtual GLenum Format()
{
return GL_DEPTH_COMPONENT;
}
virtual void Init()
{
CreateTexture2DArray(9, 5);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
}
virtual std::string Expected()
{
return "vec4(1.0, 1.0, 0.0, 0.0)";
}
virtual Vec4 BufferData()
{
return Vec4(23. / 32, 26. / 32, 5, 13.5 / 16);
}
virtual std::string Sampler()
{
return "uniform mediump sampler2DArrayShadow my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w)";
}
};
class PlainGatherFloatCube : public GatherBase
{
public:
virtual void Init()
{
CreateTextureCube();
}
virtual Vec4 BufferData()
{
return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
}
virtual std::string Sampler()
{
return "uniform mediump samplerCube my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
}
};
class PlainGatherIntCube : public GatherBase
{
public:
virtual void Init()
{
CreateTextureCubeInt();
}
virtual Vec4 BufferData()
{
return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
}
virtual std::string Sampler()
{
return "uniform mediump isamplerCube my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
}
virtual GLenum InternalFormat()
{
return GL_RGBA32I;
}
virtual std::string Expected()
{
return "ivec4(0, 4, 8, 12)";
}
virtual std::string Type()
{
return "ivec4";
}
};
class PlainGatherUintCube : public GatherBase
{
public:
virtual void Init()
{
CreateTextureCubeInt();
}
virtual Vec4 BufferData()
{
return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
}
virtual std::string Sampler()
{
return "uniform mediump usamplerCube my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z), 0)";
}
virtual GLenum InternalFormat()
{
return GL_RGBA32UI;
}
virtual std::string Expected()
{
return "uvec4(0u, 4u, 8u, 12u)";
}
virtual std::string Type()
{
return "uvec4";
}
};
class PlainGatherDepthCube : public GatherBase
{
public:
virtual void Init()
{
CreateTextureCube();
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
}
virtual GLenum InternalFormat()
{
return GL_DEPTH_COMPONENT32F;
}
virtual GLenum Format()
{
return GL_DEPTH_COMPONENT;
}
virtual Vec4 BufferData()
{
return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
}
virtual std::string Sampler()
{
return "uniform mediump samplerCubeShadow my_sampler; \n";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w)";
}
virtual std::string Expected()
{
return "vec4(0.0, 0.0, 1.0, 1.0)";
}
};
class OffsetGatherFloat2D : public GatherBase
{
virtual Vec4 BufferData()
{
return Vec4(19. / 32, 22. / 32, 4, 4);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec2(p.x, p.y), offset)";
}
};
class OffsetGatherInt2D : public PlainGatherInt2D
{
virtual Vec4 BufferData()
{
return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 4);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec2(p.x, p.y), offset)";
}
};
class OffsetGatherUint2D : public PlainGatherUint2D
{
virtual Vec4 BufferData()
{
return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 2);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec2(p.x, p.y), offset, 2)";
}
};
class OffsetGatherDepth2D : public PlainGatherDepth2D
{
virtual Vec4 BufferData()
{
return Vec4(19. / 32, 22. / 32, 4, 13.5 / 16);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec2(p.x, p.y), p.w, offset)";
}
};
class OffsetGatherFloat2DArray : public PlainGatherFloat2DArray
{
virtual Vec4 BufferData()
{
return Vec4(19. / 32, 22. / 32, 5, 4);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), offset)";
}
};
class OffsetGatherInt2DArray : public PlainGatherInt2DArray
{
virtual Vec4 BufferData()
{
return Vec4(19. / 32, 22. / 32, 11, 4);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), offset, 3)";
}
};
class OffsetGatherUint2DArray : public PlainGatherUint2DArray
{
virtual Vec4 BufferData()
{
return Vec4(19. / 32, 22. / 32, 1, 4);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), offset, 0)";
}
};
class OffsetGatherDepth2DArray : public PlainGatherDepth2DArray
{
virtual void Init()
{
CreateTexture2DArray(7, 3);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
}
virtual Vec4 BufferData()
{
return Vec4(19. / 32, 22. / 32, 3, 4);
}
virtual std::string Offset()
{
return "const mediump ivec2 offset = ivec2(4); \n";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), p.y + (5.0/32.0), offset)";
}
};
class Swizzle : public PlainGatherFloat2D
{
virtual std::string Gather()
{
return "textureGather(my_sampler, vec2(p.x, p.y), 1).yzww";
}
virtual std::string Expected()
{
return "vec4(5./16., 9./16., 13./16., 13./16.)";
}
};
class BaseLevel : public PlainGatherFloat2D
{
virtual void Init()
{
CreateTexture2D(true);
}
};
class IncompleteTexture : public PlainGatherFloat2D
{
virtual void Init()
{
CreateTexture2D();
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
}
virtual std::string Expected()
{
return "vec4(0)";
}
virtual std::string Gather()
{
return "textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(0), 1)";
}
};
class IncompleteTextureLastComp : public PlainGatherFloat2D
{
virtual void Init()
{
CreateTexture2D();
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
}
virtual std::string Expected()
{
return "vec4(1.0)";
}
virtual std::string Gather()
{
return "textureGather(my_sampler, vec2(p.x, p.y), 3)";
}
};
class TriangleDraw : public GatherBase
{
GLuint program, rbo, fbo, vao, vbo;
virtual std::string VertexShader()
{
return "#version 310 es \n"
"flat out mediump vec2 texcoords; \n"
"in mediump vec4 Vertex; \n"
"void main() { \n"
" gl_Position = Vertex; \n"
" texcoords = (Vertex.xy + vec2(1.0)) / 2.0; \n"
"}\n";
}
virtual std::string FragmentShader()
{
return "#version 310 es \n"
"precision highp float; \n"
"flat in mediump vec2 texcoords; \n"
"out highp uvec4 FragColor; \n"
"uniform mediump sampler2D tex; \n"
"void main() { \n"
" vec4 data = textureGather(tex, texcoords, 2); \n"
" FragColor = floatBitsToUint(data); \n"
"}\n";
}
virtual long Run()
{
glGenFramebuffers(1, &fbo);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 100, 100);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, &drawBuffer);
GLfloat colorf[4] = { 0, 0, 0, 0 };
glClearBufferfv(GL_COLOR, 0, colorf);
glViewport(0, 0, 100, 100);
program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str());
glBindAttribLocation(program, 0, "Vertex");
glLinkProgram(program);
if (!CheckProgram(program))
return ERROR;
glUseProgram(program);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
std::vector<Vec4> data(100 * 100, Vec4(0.25, 0.5, 0.75, 1));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 100, 100, 0, GL_RGBA, GL_FLOAT, &data[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLfloat buffData[16] = { -1, 1, 0, 1, -1, -1, 0, 1, 1, 1, 0, 1, 1, -1, 0, 1 };
glBufferData(GL_ARRAY_BUFFER, sizeof(buffData), buffData, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(0);
glDeleteVertexArrays(1, &vao);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
std::vector<unsigned int> read(100 * 100 * 4, 0);
glReadPixels(0, 0, 100, 100, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &read[0]);
for (unsigned int i = 0; i < read.size() / 4; i += 4)
{
const GLfloat* rdata = (const GLfloat*)&read[i];
Vec4 rvec(rdata[0], rdata[1], rdata[2], rdata[3]);
if (rvec != Vec4(0.75))
{
m_context.getTestContext().getLog()
<< tcu::TestLog::Message << "Got: " << rvec.x() << " " << rvec.y() << " " << rvec.z() << " "
<< rvec.w() << ", expected vec4(0.75)" << tcu::TestLog::EndMessage;
return ERROR;
}
}
return NO_ERROR;
}
virtual long Cleanup()
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glDisableVertexAttribArray(0);
glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
glDeleteTextures(1, &tex);
glDeleteFramebuffers(1, &fbo);
glDeleteRenderbuffers(1, &rbo);
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteProgram(program);
return NO_ERROR;
}
};
class PlainGatherFloat2DSrgb : public GatherBase
{
public:
virtual std::string Expected()
{
return "vec4(0, 20.0/255.0, 90.0/255.0, 222.0/255.0)";
}
virtual GLenum InternalFormat()
{
return GL_SRGB8_ALPHA8;
}
virtual void Init()
{
CreateTextureSRGB();
}
};
class PlainGatherFloat2DSrgbAlpha : public GatherBase
{
public:
virtual std::string Gather()
{
return "textureGather(my_sampler, vec2(p.x, p.y), 3)";
}
virtual std::string Expected()
{
return "vec4(3.0/255.0, 7.0/255.0, 11.0/255.0, 15.0/255.0)";
}
virtual GLenum InternalFormat()
{
return GL_SRGB8_ALPHA8;
}
virtual void Init()
{
CreateTextureSRGB();
}
};
class PlainGatherFloat2DRgb : public GatherBase
{
public:
virtual void Init()
{
CreateTexture2DRgb();
}
};
class PlainGatherFloat2DRg : public GatherBase
{
public:
virtual void Init()
{
CreateTexture2DRg();
}
};
class PlainGatherFloat2DR : public GatherBase
{
public:
virtual void Init()
{
CreateTexture2DR();
}
};
class OffsetGatherFloat2DRgb : public OffsetGatherFloat2D
{
public:
virtual void Init()
{
CreateTexture2DRgb();
}
};
class OffsetGatherFloat2DRg : public OffsetGatherFloat2D
{
public:
virtual void Init()
{
CreateTexture2DRg();
}
};
class OffsetGatherFloat2DR : public OffsetGatherFloat2D
{
public:
virtual void Init()
{
CreateTexture2DR();
}
};
} // anonymous namespace
TextureGatherTests::TextureGatherTests(glcts::Context& context) : TestCaseGroup(context, "texture_gather", "")
{
}
TextureGatherTests::~TextureGatherTests(void)
{
}
void TextureGatherTests::init()
{
using namespace glcts;
addChild(new TestSubcase(m_context, "api-enums", TestSubcase::Create<GatherEnumsTest>));
addChild(new TestSubcase(m_context, "gather-glsl-compile", TestSubcase::Create<GatherGLSLCompile>));
addChild(new TestSubcase(m_context, "plain-gather-float-2d", TestSubcase::Create<PlainGatherFloat2D>));
addChild(new TestSubcase(m_context, "plain-gather-int-2d", TestSubcase::Create<PlainGatherInt2D>));
addChild(new TestSubcase(m_context, "plain-gather-uint-2d", TestSubcase::Create<PlainGatherUint2D>));
addChild(new TestSubcase(m_context, "plain-gather-depth-2d", TestSubcase::Create<PlainGatherDepth2D>));
addChild(new TestSubcase(m_context, "plain-gather-float-2darray", TestSubcase::Create<PlainGatherFloat2DArray>));
addChild(new TestSubcase(m_context, "plain-gather-int-2darray", TestSubcase::Create<PlainGatherInt2DArray>));
addChild(new TestSubcase(m_context, "plain-gather-uint-2darray", TestSubcase::Create<PlainGatherUint2DArray>));
addChild(new TestSubcase(m_context, "plain-gather-depth-2darray", TestSubcase::Create<PlainGatherDepth2DArray>));
addChild(new TestSubcase(m_context, "plain-gather-float-cube-rgba", TestSubcase::Create<PlainGatherFloatCube>));
addChild(new TestSubcase(m_context, "plain-gather-int-cube-rgba", TestSubcase::Create<PlainGatherIntCube>));
addChild(new TestSubcase(m_context, "plain-gather-uint-cube", TestSubcase::Create<PlainGatherUintCube>));
addChild(new TestSubcase(m_context, "plain-gather-depth-cube", TestSubcase::Create<PlainGatherDepthCube>));
addChild(new TestSubcase(m_context, "offset-gather-float-2d", TestSubcase::Create<OffsetGatherFloat2D>));
addChild(new TestSubcase(m_context, "offset-gather-int-2d", TestSubcase::Create<OffsetGatherInt2D>));
addChild(new TestSubcase(m_context, "offset-gather-uint-2d", TestSubcase::Create<OffsetGatherUint2D>));
addChild(new TestSubcase(m_context, "offset-gather-depth-2d", TestSubcase::Create<OffsetGatherDepth2D>));
addChild(new TestSubcase(m_context, "offset-gather-float-2darray", TestSubcase::Create<OffsetGatherFloat2DArray>));
addChild(new TestSubcase(m_context, "offset-gather-int-2darray", TestSubcase::Create<OffsetGatherInt2DArray>));
addChild(new TestSubcase(m_context, "offset-gather-uint-2darray", TestSubcase::Create<OffsetGatherUint2DArray>));
addChild(new TestSubcase(m_context, "offset-gather-depth-2darray", TestSubcase::Create<OffsetGatherDepth2DArray>));
addChild(new TestSubcase(m_context, "swizzle", TestSubcase::Create<Swizzle>));
addChild(new TestSubcase(m_context, "base-level", TestSubcase::Create<BaseLevel>));
addChild(new TestSubcase(m_context, "incomplete-texture", TestSubcase::Create<IncompleteTexture>));
addChild(
new TestSubcase(m_context, "incomplete-texture-last-comp", TestSubcase::Create<IncompleteTextureLastComp>));
addChild(new TestSubcase(m_context, "triangle-draw", TestSubcase::Create<TriangleDraw>));
addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb", TestSubcase::Create<PlainGatherFloat2DSrgb>));
addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb-alpha",
TestSubcase::Create<PlainGatherFloat2DSrgbAlpha>));
addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgb", TestSubcase::Create<PlainGatherFloat2DRgb>));
addChild(new TestSubcase(m_context, "plain-gather-float-2d-rg", TestSubcase::Create<PlainGatherFloat2DRg>));
addChild(new TestSubcase(m_context, "plain-gather-float-2d-r", TestSubcase::Create<PlainGatherFloat2DR>));
addChild(new TestSubcase(m_context, "offset-gather-float-2d-rgb", TestSubcase::Create<OffsetGatherFloat2DRgb>));
addChild(new TestSubcase(m_context, "offset-gather-float-2d-rg", TestSubcase::Create<OffsetGatherFloat2DRg>));
addChild(new TestSubcase(m_context, "offset-gather-float-2d-r", TestSubcase::Create<OffsetGatherFloat2DR>));
}
} // glcts namespace