/*------------------------------------------------------------------------- * 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 #include #include #include 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 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(&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 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 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 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 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 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 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 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 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 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 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 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 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 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 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(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 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 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)); addChild(new TestSubcase(m_context, "gather-glsl-compile", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-int-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-uint-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-depth-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-int-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-uint-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-depth-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-cube-rgba", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-int-cube-rgba", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-uint-cube", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-depth-cube", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-float-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-int-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-uint-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-depth-2d", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-float-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-int-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-uint-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-depth-2darray", TestSubcase::Create)); addChild(new TestSubcase(m_context, "swizzle", TestSubcase::Create)); addChild(new TestSubcase(m_context, "base-level", TestSubcase::Create)); addChild(new TestSubcase(m_context, "incomplete-texture", TestSubcase::Create)); addChild( new TestSubcase(m_context, "incomplete-texture-last-comp", TestSubcase::Create)); addChild(new TestSubcase(m_context, "triangle-draw", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb-alpha", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgb", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2d-rg", TestSubcase::Create)); addChild(new TestSubcase(m_context, "plain-gather-float-2d-r", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-float-2d-rgb", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-float-2d-rg", TestSubcase::Create)); addChild(new TestSubcase(m_context, "offset-gather-float-2d-r", TestSubcase::Create)); } } // glcts namespace