#ifndef _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP #define _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP /*------------------------------------------------------------------------- * 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 */ /*-------------------------------------------------------------------*/ /*! * \file esextcGPUShader5TextureGatherOffset.hpp * \brief gpu_shader5 extension - texture gather offset tests (Test 9 and 10) */ /*-------------------------------------------------------------------*/ #include "../esextcTestCaseBase.hpp" #include #include namespace glcts { /** Base class for texture gather offset tests (9, 10 and 11) * **/ class GPUShader5TextureGatherOffsetTestBase : public TestCaseBase { public: /* Public methods */ virtual void deinit(void); virtual IterateResult iterate(void); protected: /* Protected types */ struct VertexBufferInfo { const glw::GLchar* attribute_name; glw::GLuint n_components; glw::GLenum type; glw::GLvoid* data; glw::GLuint data_size; }; /* Protected methods */ GPUShader5TextureGatherOffsetTestBase(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetTestBase(void) { } virtual void initTest(void); /* To be implemented by inheriting classes */ virtual void getBorderColor(glw::GLfloat out_color[4]) = 0; virtual void getShaderParts(std::vector& out_vertex_shader_parts) = 0; virtual void getTextureInfo(glw::GLuint& out_width, glw::GLenum& out_texture_internal_format, glw::GLenum& out_texture_format, glw::GLenum& out_texture_type, glw::GLuint& out_bytes_per_pixel) = 0; virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode) = 0; virtual void getTransformFeedBackDetails(glw::GLuint& buffer_size, std::vector& captured_varyings) = 0; virtual void isTextureArray(bool& out_is_texture_array) = 0; virtual void prepareTextureData(glw::GLubyte* data) = 0; virtual void prepareVertexBuffersData(std::vector& vertex_buffer_infos) = 0; virtual bool verifyResult(const void* result_data) = 0; /* Utilities */ void logArray(const glw::GLint* data, unsigned int length, const char* description); void logCoordinates(unsigned int index); /* Protected fields */ /* GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET and GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET pname values */ glw::GLint m_min_texture_gather_offset; glw::GLint m_max_texture_gather_offset; /* Number of drawn vertices */ static const unsigned int m_n_vertices; /* Number of components in captured varyings */ static const unsigned int m_n_components_per_varying; private: /* Private methods */ void prepareProgramInput(); void prepareTexture(); void prepareVertexBufferInfoForCoordinates(); void setCoordinatesData(glw::GLfloat x, glw::GLfloat y, unsigned int index); void setCoordinatesData(glw::GLfloat x, glw::GLfloat y, glw::GLfloat z, unsigned int index); /* Private fields */ /* Program and shader ids */ glw::GLuint m_fragment_shader_id; glw::GLuint m_program_object_id; glw::GLuint m_vertex_shader_id; /* Vertex array object */ glw::GLuint m_vertex_array_object_id; /* Texture id */ glw::GLuint m_texture_object_id; /* Sampler id */ glw::GLuint m_sampler_object_id; /* Shaders' code */ static const glw::GLchar* const m_fragment_shader_code; std::vector m_vertex_shader_parts; /* Name of uniforms */ static const glw::GLchar* const m_sampler_uniform_name; static const glw::GLchar* const m_reference_sampler_uniform_name; /* Vertex buffer infos */ std::vector m_vertex_buffer_infos; std::vector m_vertex_buffer_ids; /* Texture info */ bool m_is_texture_array; glw::GLuint m_texture_bytes_per_pixel; glw::GLenum m_texture_format; glw::GLenum m_texture_internal_format; glw::GLenum m_texture_type; glw::GLuint m_texture_size; glw::GLenum m_texture_wrap_mode; /* Texture array length */ static const unsigned int m_n_texture_array_length; /* Name of varyings */ std::vector m_captured_varying_names; /* Size of buffer used for transform feedback */ glw::GLuint m_transform_feedback_buffer_size; /* Buffer object used in transform feedback */ glw::GLuint m_transform_feedback_buffer_object_id; /* Storage for texture coordinates */ std::vector m_coordinates_buffer_data; /* Number of texture coordinates per vertex */ unsigned int m_n_coordinates_components; /* Name of texture coordinate attribute */ static const glw::GLchar* const m_coordinates_attribute_name; /* Configuration of texture coordinate values generation */ static const int m_max_coordinate_value; static const int m_min_coordinate_value; static const int m_coordinate_resolution; }; /** Base class for test 9 and 11 * **/ class GPUShader5TextureGatherOffsetColorTestBase : public GPUShader5TextureGatherOffsetTestBase { protected: /* Protected types */ struct CapturedVaryings { glw::GLint without_offset_0[4]; glw::GLint without_offset_1[4]; glw::GLint without_offset_2[4]; glw::GLint without_offset_3[4]; glw::GLint with_offset_0[4]; glw::GLint with_offset_1[4]; glw::GLint with_offset_2[4]; glw::GLint with_offset_3[4]; }; /* Protected methods */ GPUShader5TextureGatherOffsetColorTestBase(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetColorTestBase(void) { } /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getBorderColor(glw::GLfloat out_color[4]); virtual void getTextureInfo(glw::GLuint& out_size, glw::GLenum& out_texture_internal_format, glw::GLenum& out_texture_format, glw::GLenum& out_texture_type, glw::GLuint& out_bytes_per_pixel); virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode); virtual void getTransformFeedBackDetails(glw::GLuint& out_buffer_size, std::vector& out_captured_varyings); virtual void isTextureArray(bool& out_is_texture_array); virtual void prepareTextureData(glw::GLubyte* data); virtual bool verifyResult(const void* result_data); /* Methods to be implemented by child classes */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int m_texture_size) = 0; /* Utilities */ void logVaryings(const CapturedVaryings& varyings); private: /* Texture size */ static const glw::GLuint m_texture_size; /* Number of varyings captured per vertex */ unsigned int m_n_varyings_per_vertex; }; /** Base class for test 10 and 11 * **/ class GPUShader5TextureGatherOffsetDepthTestBase : public GPUShader5TextureGatherOffsetTestBase { protected: /* Protected types */ struct CapturedVaryings { glw::GLint floor_tex_coord[4]; glw::GLint without_offset[4]; glw::GLint with_offset[4]; }; /* Protected methods */ GPUShader5TextureGatherOffsetDepthTestBase(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepthTestBase(void) { } /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getBorderColor(glw::GLfloat out_color[4]); virtual void getTextureInfo(glw::GLuint& out_width, glw::GLenum& out_texture_internal_format, glw::GLenum& out_texture_format, glw::GLenum& out_texture_type, glw::GLuint& out_bytes_per_pixel); virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode); virtual void getTransformFeedBackDetails(glw::GLuint& out_buffer_size, std::vector& out_captured_varyings); virtual void isTextureArray(bool& out_is_texture_array); virtual void prepareTextureData(glw::GLubyte* data); virtual bool verifyResult(const void* result_data); /* Methods to be implemented by child classes */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size) = 0; virtual void getVaryings(std::vector& out_captured_varyings); /* Utilities */ void logVaryings(const CapturedVaryings& varyings); private: /* Texture size */ static const glw::GLuint m_texture_size; /* Number of varyings captured per vertex */ unsigned int m_n_varyings_per_vertex; }; /** Implementation of "Test 9" from CTS_EXT_gpu_shader5. Test description follows: * * Test whether using non constant offsets in the textureGatherOffset * and constant offsets in the textureGatherOffsets family of * functions works as expected for sampler2D and sampler2DArray and * GL_REPEAT wrap mode. * * Category: API, * Functional Test. * * Create a 64 x 64 texture with internal format GL_RGBA32I. * * Set both GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_NEAREST. * * Set both GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T to GL_REPEAT. * * Fill the 4 components of each texel with values corresponding to texel * row and column number (x,y) -> (x,y,x,y) * * Write a vertex shader that defines: * * uniform isampler2D sampler; * * in ivec2 tgoOffset; * in vec2 texCoords; * * out ivec4 withoutOffset0; * out ivec4 withOffset0; * * out ivec4 withoutOffset1; * out ivec4 withOffset1; * * out ivec4 withoutOffset2; * out ivec4 withOffset2; * * out ivec4 withoutOffset3; * out ivec4 withOffset3; * * Bind the sampler to texture unit the texture we created is assigned to. * * Initialize a buffer object to be assigned as input attribute tgoOffset * data source. The buffer object should hold 128 integer tuples. Fill it * with some random integer values but falling into a range of * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, * MAX_PROGRAM_TEXTURE_GATHER_OFFSET). * * Initialize a buffer object to be assigned as input attribute texCoords * data source. The buffer object should hold 128 elements. Fill the first * 4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the * rest with some random float values in the range [-8.0..8.0]. * * In the vertex shader perform the following operation: * * withoutOffset0 = textureGather(sampler, texCoords, 0); * withOffset0 = textureGatherOffset(sampler, texCoords, tgoOffset, 0); * * withoutOffset1 = textureGather(sampler, texCoords, 1); * withOffset1 = textureGatherOffset(sampler, texCoords, tgoOffset, 1); * * withoutOffset2 = textureGather(sampler, texCoords, 2); * withOffset2 = textureGatherOffset(sampler, texCoords, tgoOffset, 2); * * withoutOffset3 = textureGather(sampler, texCoords, 3); * withOffset3 = textureGatherOffset(sampler, texCoords, tgoOffset, 3); * * Configure transform feedback to capture the values of withoutOffset* * and withOffset*. * * Write a boilerplate fragment shader. * * Create a program from the above vertex shader and fragment shader * and use it. * * Execute a draw call glDrawArrays(GL_POINTS, 0, 128). * * Copy the captured results from the buffer objects bound to transform * feedback binding points. * * Using the captured values for each of the 128 results compute * * (Pseudocode) * * i = 0...127 * * ivec2 referenceOffset = offsets[i]; * * if(referenceOffset[0] < 0 ) * { * referenceOffset[0] = sizeX - (referenceOffset[0] % sizeX); * } * if(referenceOffset[1] < 0 ) * { * referenceOffset[1] = sizeY - (referenceOffset[1] % sizeY); * } * * for(int tNr = 0 tNr < 4; ++tNr) * { * ivec2 referenceTexelValue01 = ivec2( * ((tgoResults[i].withoutOffset0[tNr] + referenceOffset[0]) % sizeX), * ((tgoResults[i].withoutOffset1[tNr] + referenceOffset[1]) % sizeY)); * * ivec2 referenceTexelValue23 = ivec2( * ((tgoResults[i].withoutOffset2[tNr] + referenceOffset[0]) % sizeX), * ((tgoResults[i].withoutOffset3[tNr] + referenceOffset[1]) % sizeY)); * * ivec2 texelValue01 = ivec2( * tgoResults[i].withOffset0[tNr], tgoResults[i].withOffset1[tNr]); * * ivec2 texelValue23 = ivec2( * tgoResults[i].withOffset2[tNr], tgoResults[i].withOffset3[tNr]); * } * * The test passes if in all cases we have * referenceTexelValue01 == texelValue01 and * referenceTexelValue23 == texelValue23. * * Repeat the same type of test for sampler2DArray. * * Repeat the same type of test using textureGatherOffsets instead of * textureGatherOffset inputing constant offsets * offsets[4] = { * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, MIN_PROGRAM_TEXTURE_GATHER_OFFSET), * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, MAX_PROGRAM_TEXTURE_GATHER_OFFSET), * (MAX_PROGRAM_TEXTURE_GATHER_OFFSET, MIN_PROGRAM_TEXTURE_GATHER_OFFSET), * (MAX_PROGRAM_TEXTURE_GATHER_OFFSET, MAX_PROGRAM_TEXTURE_GATHER_OFFSET) * }; **/ /** Test configuration: wrap mode GL_REPEAT, sampler isampler2D, function textureGatherOffset */ class GPUShader5TextureGatherOffsetColor2DRepeatCaseTest : public GPUShader5TextureGatherOffsetColorTestBase { public: /* Public methods */ GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void prepareVertexBuffersData(std::vector& vertex_buffer_infos); /* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); /* Utilities */ void getOffsets(glw::GLint& out_x_offset, glw::GLint& out_y_offset, unsigned int index); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; /* Number of offsets per vertex */ static const unsigned int m_n_offsets_components; /* Name of offset attribute */ static const glw::GLchar* const m_offsets_attribute_name; /* Storage for offsets */ std::vector m_offsets_buffer_data; }; /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DArray, function textureGatherOffset */ class GPUShader5TextureGatherOffsetColor2DArrayCaseTest : public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetColor2DArrayCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetColor2DArrayCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void isTextureArray(bool& out_is_texture_array); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_REPEAT, sampler isampler2D, function textureGatherOffsets */ class GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetColorTestBase { public: /* Public methods */ GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void prepareVertexBuffersData(std::vector& vertex_buffer_infos); /* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code_preamble; static const glw::GLchar* const m_vertex_shader_code_body; /* String used for definition of constant offsets */ std::string m_vertex_shader_code_offsets; }; /** Implementation of "Test 10" from CTS_EXT_gpu_shader5. Test description follows: * * Test whether using non constant offsets in the textureGatherOffset * and constant offsets in the textureGatherOffsets family of * functions works as expected for sampler2DShadow * and sampler2DArrayShadow and GL_REPEAT wrap mode. * * Category: API, * Functional Test. * * Create a 64 x 64 texture with internal format GL_DEPTH_COMPONENT and * type GL_FLOAT. * * Set both GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_NEAREST. * * Set both GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T to GL_REPEAT. * * Setup the texture parameters * * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, * COMPARE_REF_TO_TEXTURE); * * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); * * Fill each texel with depth value corresponding to its position * in the texture for the X axis: (x, y) -> (x / sizeX); * * Write a vertex shader that defines: * * uniform sampler2DShadow sampler; * * in ivec2 tgoOffset; * in vec2 texCoords; * * out ivec4 withoutOffset; * out ivec4 withOffset; * * Bind the sampler to texture unit the texture we created is assigned to. * * Initialize a buffer object to be assigned as input attribute tgoOffset * data source. The buffer object should hold 128 integer tuples. Fill it * with some random integer values but falling into a range of * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, * MAX_PROGRAM_TEXTURE_GATHER_OFFSET). * * Initialize a buffer object to be assigned as input attribute texCoords * data source. The buffer object should hold 128 elements. Fill the first * 4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the * rest with some random float values in the range [-8.0..8.0]. * * In the vertex shader perform the following operation: * * withoutOffset = ivec4(0,0,0,0); * withOffset = ivec4(0,0,0,0); * * ivec2 texSize = textureSize2D(sampler, 0); * * for(int texelNr = 0 texelNr < texSize.x; ++texelNr) * { * float refZ = float(texelNr) / float(texSize.x); * * withoutOffset += textureGather( sampler, texCoords, refZ ); * withOffset += textureGatherOffset(sampler,texCoords,offset,refZ); * } * * Configure transform feedback to capture the values of withoutOffset * and withOffset. * * Write a boilerplate fragment shader. * * Create a program from the above vertex shader and fragment shader * and use it. * * Execute a draw call glDrawArrays(GL_POINTS, 0, 128). * * Copy the captured results from the buffer objects bound to transform * feedback binding points. * * Using the captured values for each of the 128 results compute * * (Pseudocode) * * i = 0...127 * * int referenceOffsetX = offsets[i].x; * * if(referenceOffsetX < 0 ) * { * referenceOffsetX = sizeX - (referenceOffsetX % sizeX); * } * * for(int tNr = 0 tNr < 4; ++tNr) * { * int referenceTexelValueX = * (tgoResults[i].withoutOffset[tNr] + referenceOffsetX) % sizeX; * * int texelValueX = tgoResults[i].withOffset[tNr]; * } * * The test passes if in all cases we have * referenceTexelValueX == texelValueX. * * Repeat the same test for Y axis. * * Repeat the same type of test for sampler2DArrayShadow. * * Repeat the same type of test using textureGatherOffsets instead of * textureGatherOffset inputting constant offsets * offsets[4] = { * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,MIN_PROGRAM_TEXTURE_GATHER_OFFSET), * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,MAX_PROGRAM_TEXTURE_GATHER_OFFSET), * (MAX_PROGRAM_TEXTURE_GATHER_OFFSET,MIN_PROGRAM_TEXTURE_GATHER_OFFSET), * (MAX_PROGRAM_TEXTURE_GATHER_OFFSET,MAX_PROGRAM_TEXTURE_GATHER_OFFSET) * }; * **/ /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffset, axis X */ class GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase { public: /* Public methods */ GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void prepareVertexBuffersData(std::vector& vertex_buffer_infos); /* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); /* Utilities */ void getOffsets(glw::GLint& out_x_offset, glw::GLint& out_y_offset, unsigned int index); /* Number of offsets per vertex */ static const unsigned int m_n_offsets_components; /* Name of offset attribute */ static const glw::GLchar* const m_offsets_attribute_name; /* Storage for offsets */ std::vector m_offsets_buffer_data; private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffset, axis Y */ class GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void prepareTextureData(glw::GLubyte* data); /* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadowArray, function textureGatherOffset, axis X */ class GPUShader5TextureGatherOffsetDepth2DArrayCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void isTextureArray(bool& out_is_texture_array); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffsets, axis X */ class GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase { public: /* Public methods */ GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void prepareVertexBuffersData(std::vector& vertex_buffer_infos); /* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code_preamble; static const glw::GLchar* const m_vertex_shader_code_body; /* String used for definition of constant offsets */ std::string m_vertex_shader_code_offsets; }; /** Implementation of "Test 11" from CTS_EXT_gpu_shader5. Test description follows: * * Test whether using non constant offsets in the textureGatherOffset * function works as expected for sampler2D and CLAMP_TO_BORDER_EXT * ( CLAMP_TO_EDGE ) wrap mode. * * Category: API, * Functional Test, * dependency with EXT_texture_border_clamp. * * Create two (lets name them A and B) 64 (texWidth) x 64 (texHeight) * textures with internal format GL_RGBA32I. * * Bind texture A to texture unit 0. * Bind texture B to texture unit 1. * * Set for both textures GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER * to GL_NEAREST. * * For the A texture set GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T * to CLAMP_TO_BORDER_EXT. * For the B texture set GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T * to CLAMP_TO_BORDER_EXT ( CLAMP TO EDGE ). * * For both textures fill the 4 components of each texel with values * corresponding to texel row and column number (x,y) -> (x,y,x,y) * * Set the GL_TEXTURE_BORDER_COLOR_EXT to (-1,-1,-1,-1). * * Write a vertex shader that defines: * * uniform isampler2D samplerWithoutOffset; * uniform isampler2D samplerWithOffset; * * in ivec2 tgoOffset; * in vec2 texCoords; * * out ivec4 withoutOffset0; * out ivec4 withoutOffset1; * out ivec2 intFloorTexCoords; * * out ivec4 withOffset0; * out ivec4 withOffset1; * out ivec4 withOffset2; * out ivec4 withOffset3; * * Bind samplerWithoutOffset to texture unit 0. * Bind samplerWithOffset to texture unit 1. * * Initialize a buffer object to be assigned as input attribute tgoOffset * data source. The buffer object should hold 128 integer tuples. Fill it * with some random integer values but falling into a range of * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, * MAX_PROGRAM_TEXTURE_GATHER_OFFSET). * * Initialize a buffer object to be assigned as input attribute texCoords * data source. The buffer object should hold 128 elements. Fill the first * 4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the * rest with some random float values in the range [-8.0..8.0]. * * In the vertex shader perform the following operation: * * vec2 floorTexCoords = floor(texCoords); * vec2 fractTexCoords = texCoords - floorTexCoords; * * withoutOffset0 = textureGather(samplerWithoutOffset,fractTexCoords, 0); * withoutOffset1 = textureGather(samplerWithoutOffset,fractTexCoords, 1); * intFloorTexCoords = ivec2(int(floorTexCoords.x),int(floorTexCoords.y)); * * withOffset0 = textureGatherOffset(samplerWithOffset, * texCoords, tgoOffset, 0); * withOffset1 = textureGatherOffset(samplerWithOffset, * texCoords, tgoOffset, 1); * withOffset2 = textureGatherOffset(samplerWithOffset, * texCoords, tgoOffset, 2); * withOffset3 = textureGatherOffset(samplerWithOffset, * texCoords, tgoOffset, 3); * * Configure transform feedback to capture the values of withoutOffset*, * withOffset* and intFloorTexCoords. * * Write a boilerplate fragment shader. * * Create a program from the above vertex shader and fragment shader * and use it. * * Execute a draw call glDrawArrays(GL_POINTS, 0, 128). * * Copy the captured results from the buffer objects bound to transform * feedback binding points. * * Using the captured values for each of the 128 results perform * the following algorithm: * * From the captured withoutOffset0 and withoutOffset1 variables extract * 4 texelPos values * * (Pseudocode) * * texelPos[i] = ivec2( withoutOffset0[i] , withoutOffset1[i] ); * * Find a texel that has not been clamped. It's value should be * different than (texWidth, texHeight). Let's asume that the found * texel has index 'foundIndex'. * * If we can't find such texel we must throw an exception, because it means * that the sampling algorithm has failed. * * Extract the offset that has to be applied to the chosen texel to get it's * absolute position (the one we would get if we haven't clamped the texture * coordinates for textureGather to the range [0,1]) * * (Pseudocode) * * ivec2 absoluteOffset = ivec2( intFloorTexCoords.x * texWidth , * intFloorTexCoords.y * texHeight ); * * Next apply the offset to the texel position * * (Pseudocode) * * texelAbsolutePos[foundIndex] = texelPos[foundIndex] + absoluteOffset; * * Now we have to set the absolute positions of the remaining 3 texels. * We can do this because the foundIndex gives us information which * texel we are dealing with in a 2x2 texel matrix returned by * textureGather. The remaining texels will have their absolute positions * computed by adding or substacting 1 to their x and y components * depending on their position in the matrix relative to foundIndex. * * In the next step we have to apply the offset used in * textureGatherOffset function to each of the absolute positions. * * (Pseudocode) * * texelAbsolutePos[i] += tgoOffset; * * We have to examine each absolute position in order to know if it should * been clamped or not. * * In case of CLAMP_TO_BORDER_EXT if the absolute position goes beyond the * texture bounds set it to value of GL_TEXTURE_BORDER_COLOR_EXT -> (-1,-1) * * In case of CLAMP_TO_EDGE if the absolute position goes beyond the * texture bounds we have to clamp the value of absolute position * to the edge that has been crossed. * * The test passes for each of the 4 absolute positions we have * * (Pseudocode) * * texelAbsolutePos[i] == ivec2( withOffset0[i], withOffset1[i] ) and * texelAbsolutePos[i] == ivec2( withOffset2[i], withOffset3[i] ). **/ /** Test configuration: wrap mode GL_CLAMP_TO_BORDER_EXT, sampler isampler2D, function textureGatherOffset */ class GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest : public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode); virtual void getShaderParts(std::vector& out_vertex_shader_parts); /* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); virtual void initTest(void); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_CLAMP_TO_EDGE, sampler isampler2D, function textureGatherOffset */ class GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest : public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode); virtual void getShaderParts(std::vector& out_vertex_shader_parts); /* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); virtual void initTest(void); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_CLAMP_TO_BORDER_EXT, sampler isampler2DShadow, function textureGatherOffset, axis X */ class GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode); virtual void getShaderParts(std::vector& out_vertex_shader_parts); virtual void prepareVertexBuffersData(std::vector& vertex_buffer_infos); /* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); virtual void getVaryings(std::vector& out_captured_varyings); virtual void initTest(void); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; /** Test configuration: wrap mode GL_CLAMP_TO_EDGE, sampler isampler2DShadow, function textureGatherOffset, axis X */ class GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest { public: /* Public methods */ GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams, const char* name, const char* description); virtual ~GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(void) { } protected: /* Protected methods */ /* Virtual methods from GPUShader5TextureGatherOffsetTestBase */ virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode); virtual void getShaderParts(std::vector& out_vertex_shader_parts); /* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */ virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size); virtual void getVaryings(std::vector& out_captured_varyings); virtual void initTest(void); private: /* Private fields */ /* Vertex shader code */ static const glw::GLchar* const m_vertex_shader_code; }; } /* glcts */ #endif // _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP