• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
2 #define _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
3 /*-------------------------------------------------------------------------
4  * OpenGL Conformance Test Suite
5  * -----------------------------
6  *
7  * Copyright (c) 2014-2016 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file
23  * \brief
24  */ /*-------------------------------------------------------------------*/
25 
26 /*!
27  * \file esextcGPUShader5TextureGatherOffset.hpp
28  * \brief gpu_shader5 extension - texture gather offset tests (Test 9 and 10)
29  */ /*-------------------------------------------------------------------*/
30 
31 #include "../esextcTestCaseBase.hpp"
32 
33 #include <string>
34 #include <vector>
35 
36 namespace glcts
37 {
38 /** Base class for texture gather offset tests (9, 10 and 11)
39  *
40  **/
41 class GPUShader5TextureGatherOffsetTestBase : public TestCaseBase
42 {
43 public:
44 	/* Public methods */
45 	virtual void		  deinit(void);
46 	virtual IterateResult iterate(void);
47 
48 protected:
49 	/* Protected types */
50 	struct VertexBufferInfo
51 	{
52 		const glw::GLchar* attribute_name;
53 		glw::GLuint		   n_components;
54 		glw::GLenum		   type;
55 		glw::GLvoid*	   data;
56 		glw::GLuint		   data_size;
57 	};
58 
59 	/* Protected methods */
60 	GPUShader5TextureGatherOffsetTestBase(Context& context, const ExtParameters& extParams, const char* name,
61 										  const char* description);
62 
~GPUShader5TextureGatherOffsetTestBase(void)63 	virtual ~GPUShader5TextureGatherOffsetTestBase(void)
64 	{
65 	}
66 
67 	virtual void initTest(void);
68 
69 	/* To be implemented by inheriting classes */
70 	virtual void getBorderColor(glw::GLfloat out_color[4])								  = 0;
71 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts) = 0;
72 
73 	virtual void getTextureInfo(glw::GLuint& out_width, glw::GLenum& out_texture_internal_format,
74 								glw::GLenum& out_texture_format, glw::GLenum& out_texture_type,
75 								glw::GLuint& out_bytes_per_pixel) = 0;
76 
77 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode) = 0;
78 
79 	virtual void getTransformFeedBackDetails(glw::GLuint&					  buffer_size,
80 											 std::vector<const glw::GLchar*>& captured_varyings) = 0;
81 
82 	virtual void isTextureArray(bool& out_is_texture_array)									  = 0;
83 	virtual void prepareTextureData(glw::GLubyte* data)										  = 0;
84 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos) = 0;
85 	virtual bool verifyResult(const void* result_data)										  = 0;
86 
87 	/* Utilities */
88 	void logArray(const glw::GLint* data, unsigned int length, const char* description);
89 
90 	void logCoordinates(unsigned int index);
91 
92 	/* Protected fields */
93 	/* GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET and GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET pname values */
94 	glw::GLint m_min_texture_gather_offset;
95 	glw::GLint m_max_texture_gather_offset;
96 
97 	/* Number of drawn vertices */
98 	static const unsigned int m_n_vertices;
99 
100 	/* Number of components in captured varyings */
101 	static const unsigned int m_n_components_per_varying;
102 
103 private:
104 	/* Private methods */
105 	void prepareProgramInput();
106 	void prepareTexture();
107 	void prepareVertexBufferInfoForCoordinates();
108 	void setCoordinatesData(glw::GLfloat x, glw::GLfloat y, unsigned int index);
109 	void setCoordinatesData(glw::GLfloat x, glw::GLfloat y, glw::GLfloat z, unsigned int index);
110 
111 	/* Private fields */
112 	/* Program and shader ids */
113 	glw::GLuint m_fragment_shader_id;
114 	glw::GLuint m_program_object_id;
115 	glw::GLuint m_vertex_shader_id;
116 
117 	/* Vertex array object */
118 	glw::GLuint m_vertex_array_object_id;
119 
120 	/* Texture id */
121 	glw::GLuint m_texture_object_id;
122 
123 	/* Sampler id */
124 	glw::GLuint m_sampler_object_id;
125 
126 	/* Shaders' code */
127 	static const glw::GLchar* const m_fragment_shader_code;
128 	std::vector<const glw::GLchar*> m_vertex_shader_parts;
129 
130 	/* Name of uniforms */
131 	static const glw::GLchar* const m_sampler_uniform_name;
132 	static const glw::GLchar* const m_reference_sampler_uniform_name;
133 
134 	/* Vertex buffer infos */
135 	std::vector<VertexBufferInfo> m_vertex_buffer_infos;
136 	std::vector<glw::GLuint>	  m_vertex_buffer_ids;
137 
138 	/* Texture info */
139 	bool		m_is_texture_array;
140 	glw::GLuint m_texture_bytes_per_pixel;
141 	glw::GLenum m_texture_format;
142 	glw::GLenum m_texture_internal_format;
143 	glw::GLenum m_texture_type;
144 	glw::GLuint m_texture_size;
145 	glw::GLenum m_texture_wrap_mode;
146 
147 	/* Texture array length */
148 	static const unsigned int m_n_texture_array_length;
149 
150 	/* Name of varyings */
151 	std::vector<const glw::GLchar*> m_captured_varying_names;
152 
153 	/* Size of buffer used for transform feedback */
154 	glw::GLuint m_transform_feedback_buffer_size;
155 
156 	/* Buffer object used in transform feedback */
157 	glw::GLuint m_transform_feedback_buffer_object_id;
158 
159 	/* Storage for texture coordinates */
160 	std::vector<glw::GLfloat> m_coordinates_buffer_data;
161 
162 	/* Number of texture coordinates per vertex */
163 	unsigned int m_n_coordinates_components;
164 
165 	/* Name of texture coordinate attribute */
166 	static const glw::GLchar* const m_coordinates_attribute_name;
167 
168 	/* Configuration of texture coordinate values generation */
169 	static const int m_max_coordinate_value;
170 	static const int m_min_coordinate_value;
171 	static const int m_coordinate_resolution;
172 };
173 
174 /** Base class for test 9 and 11
175  *
176  **/
177 class GPUShader5TextureGatherOffsetColorTestBase : public GPUShader5TextureGatherOffsetTestBase
178 {
179 protected:
180 	/* Protected types */
181 	struct CapturedVaryings
182 	{
183 		glw::GLint without_offset_0[4];
184 		glw::GLint without_offset_1[4];
185 		glw::GLint without_offset_2[4];
186 		glw::GLint without_offset_3[4];
187 
188 		glw::GLint with_offset_0[4];
189 		glw::GLint with_offset_1[4];
190 		glw::GLint with_offset_2[4];
191 		glw::GLint with_offset_3[4];
192 	};
193 
194 	/* Protected methods */
195 	GPUShader5TextureGatherOffsetColorTestBase(Context& context, const ExtParameters& extParams, const char* name,
196 											   const char* description);
197 
~GPUShader5TextureGatherOffsetColorTestBase(void)198 	virtual ~GPUShader5TextureGatherOffsetColorTestBase(void)
199 	{
200 	}
201 
202 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
203 	virtual void getBorderColor(glw::GLfloat out_color[4]);
204 
205 	virtual void getTextureInfo(glw::GLuint& out_size, glw::GLenum& out_texture_internal_format,
206 								glw::GLenum& out_texture_format, glw::GLenum& out_texture_type,
207 								glw::GLuint& out_bytes_per_pixel);
208 
209 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
210 
211 	virtual void getTransformFeedBackDetails(glw::GLuint&					  out_buffer_size,
212 											 std::vector<const glw::GLchar*>& out_captured_varyings);
213 
214 	virtual void isTextureArray(bool& out_is_texture_array);
215 	virtual void prepareTextureData(glw::GLubyte* data);
216 	virtual bool verifyResult(const void* result_data);
217 
218 	/* Methods to be implemented by child classes */
219 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index,
220 							 unsigned int m_texture_size) = 0;
221 
222 	/* Utilities */
223 	void logVaryings(const CapturedVaryings& varyings);
224 
225 private:
226 	/* Texture size */
227 	static const glw::GLuint m_texture_size;
228 
229 	/* Number of varyings captured per vertex */
230 	unsigned int m_n_varyings_per_vertex;
231 };
232 
233 /** Base class for test 10 and 11
234  *
235  **/
236 class GPUShader5TextureGatherOffsetDepthTestBase : public GPUShader5TextureGatherOffsetTestBase
237 {
238 protected:
239 	/* Protected types */
240 	struct CapturedVaryings
241 	{
242 		glw::GLint floor_tex_coord[4];
243 		glw::GLint without_offset[4];
244 		glw::GLint with_offset[4];
245 	};
246 
247 	/* Protected methods */
248 	GPUShader5TextureGatherOffsetDepthTestBase(Context& context, const ExtParameters& extParams, const char* name,
249 											   const char* description);
250 
~GPUShader5TextureGatherOffsetDepthTestBase(void)251 	virtual ~GPUShader5TextureGatherOffsetDepthTestBase(void)
252 	{
253 	}
254 
255 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
256 	virtual void getBorderColor(glw::GLfloat out_color[4]);
257 
258 	virtual void getTextureInfo(glw::GLuint& out_width, glw::GLenum& out_texture_internal_format,
259 								glw::GLenum& out_texture_format, glw::GLenum& out_texture_type,
260 								glw::GLuint& out_bytes_per_pixel);
261 
262 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
263 
264 	virtual void getTransformFeedBackDetails(glw::GLuint&					  out_buffer_size,
265 											 std::vector<const glw::GLchar*>& out_captured_varyings);
266 
267 	virtual void isTextureArray(bool& out_is_texture_array);
268 	virtual void prepareTextureData(glw::GLubyte* data);
269 	virtual bool verifyResult(const void* result_data);
270 
271 	/* Methods to be implemented by child classes */
272 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size) = 0;
273 
274 	virtual void getVaryings(std::vector<const glw::GLchar*>& out_captured_varyings);
275 
276 	/* Utilities */
277 	void logVaryings(const CapturedVaryings& varyings);
278 
279 private:
280 	/* Texture size */
281 	static const glw::GLuint m_texture_size;
282 
283 	/* Number of varyings captured per vertex */
284 	unsigned int m_n_varyings_per_vertex;
285 };
286 
287 /** Implementation of "Test 9" from CTS_EXT_gpu_shader5. Test description follows:
288  *
289  *  Test whether using non constant offsets in the textureGatherOffset
290  *  and constant offsets in the textureGatherOffsets family of
291  *  functions works as expected for sampler2D and sampler2DArray and
292  *  GL_REPEAT wrap mode.
293  *
294  *  Category:   API,
295  *              Functional Test.
296  *
297  *  Create a 64 x 64 texture with internal format GL_RGBA32I.
298  *
299  *  Set both GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_NEAREST.
300  *
301  *  Set both GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T to GL_REPEAT.
302  *
303  *  Fill the 4 components of each texel with values corresponding to texel
304  *  row and column number (x,y) -> (x,y,x,y)
305  *
306  *  Write a vertex shader that defines:
307  *
308  *  uniform isampler2D sampler;
309  *
310  *  in ivec2 tgoOffset;
311  *  in  vec2 texCoords;
312  *
313  *  out ivec4 withoutOffset0;
314  *  out ivec4 withOffset0;
315  *
316  *  out ivec4 withoutOffset1;
317  *  out ivec4 withOffset1;
318  *
319  *  out ivec4 withoutOffset2;
320  *  out ivec4 withOffset2;
321  *
322  *  out ivec4 withoutOffset3;
323  *  out ivec4 withOffset3;
324  *
325  *  Bind the sampler to texture unit the texture we created is assigned to.
326  *
327  *  Initialize a buffer object to be assigned as input attribute tgoOffset
328  *  data source. The buffer object should hold 128 integer tuples. Fill it
329  *  with some random integer values but falling into a range of
330  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,
331  *   MAX_PROGRAM_TEXTURE_GATHER_OFFSET).
332  *
333  *  Initialize a buffer object to be assigned as input attribute texCoords
334  *  data source. The buffer object should hold 128 elements. Fill the first
335  *  4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the
336  *  rest with some random float values in the range [-8.0..8.0].
337  *
338  *  In the vertex shader perform the following operation:
339  *
340  *  withoutOffset0 = textureGather(sampler, texCoords, 0);
341  *  withOffset0 = textureGatherOffset(sampler, texCoords, tgoOffset, 0);
342  *
343  *  withoutOffset1 = textureGather(sampler, texCoords, 1);
344  *  withOffset1 = textureGatherOffset(sampler, texCoords, tgoOffset, 1);
345  *
346  *  withoutOffset2 = textureGather(sampler, texCoords, 2);
347  *  withOffset2 = textureGatherOffset(sampler, texCoords, tgoOffset, 2);
348  *
349  *  withoutOffset3 = textureGather(sampler, texCoords, 3);
350  *  withOffset3 = textureGatherOffset(sampler, texCoords, tgoOffset, 3);
351  *
352  *  Configure transform feedback to capture the values of withoutOffset*
353  *  and withOffset*.
354  *
355  *  Write a boilerplate fragment shader.
356  *
357  *  Create a program from the above vertex shader and fragment shader
358  *  and use it.
359  *
360  *  Execute a draw call glDrawArrays(GL_POINTS, 0, 128).
361  *
362  *  Copy the captured results from the buffer objects bound to transform
363  *  feedback binding points.
364  *
365  *  Using the captured values for each of the 128 results compute
366  *
367  *  (Pseudocode)
368  *
369  *  i = 0...127
370  *
371  *  ivec2 referenceOffset = offsets[i];
372  *
373  *  if(referenceOffset[0] < 0 )
374  *  {
375  *      referenceOffset[0] = sizeX - (referenceOffset[0] % sizeX);
376  *  }
377  *  if(referenceOffset[1] < 0 )
378  *  {
379  *      referenceOffset[1] = sizeY - (referenceOffset[1] % sizeY);
380  *  }
381  *
382  *  for(int tNr = 0 tNr < 4; ++tNr)
383  *  {
384  *      ivec2 referenceTexelValue01 = ivec2(
385  *       ((tgoResults[i].withoutOffset0[tNr] + referenceOffset[0]) % sizeX),
386  *       ((tgoResults[i].withoutOffset1[tNr] + referenceOffset[1]) % sizeY));
387  *
388  *      ivec2 referenceTexelValue23 = ivec2(
389  *       ((tgoResults[i].withoutOffset2[tNr] + referenceOffset[0]) % sizeX),
390  *       ((tgoResults[i].withoutOffset3[tNr] + referenceOffset[1]) % sizeY));
391  *
392  *      ivec2 texelValue01 = ivec2(
393  *       tgoResults[i].withOffset0[tNr], tgoResults[i].withOffset1[tNr]);
394  *
395  *      ivec2 texelValue23 = ivec2(
396  *       tgoResults[i].withOffset2[tNr], tgoResults[i].withOffset3[tNr]);
397  *  }
398  *
399  *  The test passes if in all cases we have
400  *  referenceTexelValue01 == texelValue01 and
401  *  referenceTexelValue23 == texelValue23.
402  *
403  *  Repeat the same type of test for sampler2DArray.
404  *
405  *  Repeat the same type of test using textureGatherOffsets instead of
406  *  textureGatherOffset inputing constant offsets
407  *  offsets[4] = {
408  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
409  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, MAX_PROGRAM_TEXTURE_GATHER_OFFSET),
410  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET, MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
411  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET, MAX_PROGRAM_TEXTURE_GATHER_OFFSET)
412  *  };
413  **/
414 
415 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2D, function textureGatherOffset
416  */
417 class GPUShader5TextureGatherOffsetColor2DRepeatCaseTest : public GPUShader5TextureGatherOffsetColorTestBase
418 {
419 public:
420 	/* Public methods */
421 	GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(Context& context, const ExtParameters& extParams,
422 													   const char* name, const char* description);
423 
~GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(void)424 	virtual ~GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(void)
425 	{
426 	}
427 
428 protected:
429 	/* Protected methods */
430 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
431 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
432 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
433 
434 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
435 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
436 
437 	/* Utilities */
438 	void getOffsets(glw::GLint& out_x_offset, glw::GLint& out_y_offset, unsigned int index);
439 
440 private:
441 	/* Private fields */
442 	/* Vertex shader code */
443 	static const glw::GLchar* const m_vertex_shader_code;
444 
445 	/* Number of offsets per vertex */
446 	static const unsigned int m_n_offsets_components;
447 
448 	/* Name of offset attribute */
449 	static const glw::GLchar* const m_offsets_attribute_name;
450 
451 	/* Storage for offsets */
452 	std::vector<glw::GLint> m_offsets_buffer_data;
453 };
454 
455 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DArray, function textureGatherOffset
456  */
457 class GPUShader5TextureGatherOffsetColor2DArrayCaseTest : public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
458 {
459 public:
460 	/* Public methods */
461 	GPUShader5TextureGatherOffsetColor2DArrayCaseTest(Context& context, const ExtParameters& extParams,
462 													  const char* name, const char* description);
463 
~GPUShader5TextureGatherOffsetColor2DArrayCaseTest(void)464 	virtual ~GPUShader5TextureGatherOffsetColor2DArrayCaseTest(void)
465 	{
466 	}
467 
468 protected:
469 	/* Protected methods */
470 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
471 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
472 	virtual void isTextureArray(bool& out_is_texture_array);
473 
474 private:
475 	/* Private fields */
476 	/* Vertex shader code */
477 	static const glw::GLchar* const m_vertex_shader_code;
478 };
479 
480 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2D, function textureGatherOffsets
481  */
482 class GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetColorTestBase
483 {
484 public:
485 	/* Public methods */
486 	GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(Context& context, const ExtParameters& extParams,
487 														const char* name, const char* description);
488 
~GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(void)489 	virtual ~GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(void)
490 	{
491 	}
492 
493 protected:
494 	/* Protected methods */
495 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
496 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
497 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
498 
499 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
500 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
501 
502 private:
503 	/* Private fields */
504 	/* Vertex shader code */
505 	static const glw::GLchar* const m_vertex_shader_code_preamble;
506 	static const glw::GLchar* const m_vertex_shader_code_body;
507 
508 	/* String used for definition of constant offsets */
509 	std::string m_vertex_shader_code_offsets;
510 };
511 
512 /** Implementation of "Test 10" from CTS_EXT_gpu_shader5. Test description follows:
513  *
514  *  Test whether using non constant offsets in the textureGatherOffset
515  *  and constant offsets in the textureGatherOffsets family of
516  *  functions works as expected for sampler2DShadow
517  *  and sampler2DArrayShadow and GL_REPEAT wrap mode.
518  *
519  *  Category:   API,
520  *              Functional Test.
521  *
522  *  Create a 64 x 64 texture with internal format GL_DEPTH_COMPONENT and
523  *  type GL_FLOAT.
524  *
525  *  Set both GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_NEAREST.
526  *
527  *  Set both GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T to GL_REPEAT.
528  *
529  *  Setup the texture parameters
530  *
531  *  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
532  *                  COMPARE_REF_TO_TEXTURE);
533  *
534  *  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
535  *
536  *  Fill each texel with depth value corresponding to its position
537  *  in the texture for the X axis: (x, y) -> (x / sizeX);
538  *
539  *  Write a vertex shader that defines:
540  *
541  *  uniform sampler2DShadow sampler;
542  *
543  *  in ivec2 tgoOffset;
544  *  in  vec2 texCoords;
545  *
546  *  out ivec4 withoutOffset;
547  *  out ivec4 withOffset;
548  *
549  *  Bind the sampler to texture unit the texture we created is assigned to.
550  *
551  *  Initialize a buffer object to be assigned as input attribute tgoOffset
552  *  data source. The buffer object should hold 128 integer tuples. Fill it
553  *  with some random integer values but falling into a range of
554  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,
555  *   MAX_PROGRAM_TEXTURE_GATHER_OFFSET).
556  *
557  *  Initialize a buffer object to be assigned as input attribute texCoords
558  *  data source. The buffer object should hold 128 elements. Fill the first
559  *  4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the
560  *  rest with some random float values in the range [-8.0..8.0].
561  *
562  *  In the vertex shader perform the following operation:
563  *
564  *  withoutOffset = ivec4(0,0,0,0);
565  *  withOffset    = ivec4(0,0,0,0);
566  *
567  *  ivec2 texSize = textureSize2D(sampler, 0);
568  *
569  *  for(int texelNr = 0 texelNr < texSize.x; ++texelNr)
570  *  {
571  *      float refZ =  float(texelNr) / float(texSize.x);
572  *
573  *      withoutOffset += textureGather( sampler, texCoords, refZ );
574  *      withOffset += textureGatherOffset(sampler,texCoords,offset,refZ);
575  *  }
576  *
577  *  Configure transform feedback to capture the values of withoutOffset
578  *  and withOffset.
579  *
580  *  Write a boilerplate fragment shader.
581  *
582  *  Create a program from the above vertex shader and fragment shader
583  *  and use it.
584  *
585  *  Execute a draw call glDrawArrays(GL_POINTS, 0, 128).
586  *
587  *  Copy the captured results from the buffer objects bound to transform
588  *  feedback binding points.
589  *
590  *  Using the captured values for each of the 128 results compute
591  *
592  *  (Pseudocode)
593  *
594  *  i = 0...127
595  *
596  *  int referenceOffsetX = offsets[i].x;
597  *
598  *  if(referenceOffsetX < 0 )
599  *  {
600  *      referenceOffsetX = sizeX - (referenceOffsetX % sizeX);
601  *  }
602  *
603  *  for(int tNr = 0 tNr < 4; ++tNr)
604  *  {
605  *      int referenceTexelValueX =
606  *       (tgoResults[i].withoutOffset[tNr] + referenceOffsetX) % sizeX;
607  *
608  *      int texelValueX = tgoResults[i].withOffset[tNr];
609  *  }
610  *
611  *  The test passes if in all cases we have
612  *  referenceTexelValueX == texelValueX.
613  *
614  *  Repeat the same test for Y axis.
615  *
616  *  Repeat the same type of test for sampler2DArrayShadow.
617  *
618  *  Repeat the same type of test using textureGatherOffsets instead of
619  *  textureGatherOffset inputting constant offsets
620  *  offsets[4] = {
621  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
622  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,MAX_PROGRAM_TEXTURE_GATHER_OFFSET),
623  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET,MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
624  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET,MAX_PROGRAM_TEXTURE_GATHER_OFFSET)
625  *  };
626  *
627  **/
628 
629 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffset, axis X
630  */
631 class GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase
632 {
633 public:
634 	/* Public methods */
635 	GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(Context& context, const ExtParameters& extParams,
636 													   const char* name, const char* description);
637 
~GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(void)638 	virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(void)
639 	{
640 	}
641 
642 protected:
643 	/* Protected methods */
644 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
645 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
646 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
647 
648 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
649 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
650 
651 	/* Utilities */
652 	void getOffsets(glw::GLint& out_x_offset, glw::GLint& out_y_offset, unsigned int index);
653 
654 	/* Number of offsets per vertex */
655 	static const unsigned int m_n_offsets_components;
656 
657 	/* Name of offset attribute */
658 	static const glw::GLchar* const m_offsets_attribute_name;
659 
660 	/* Storage for offsets */
661 	std::vector<glw::GLint> m_offsets_buffer_data;
662 
663 private:
664 	/* Private fields */
665 	/* Vertex shader code */
666 	static const glw::GLchar* const m_vertex_shader_code;
667 };
668 
669 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffset, axis Y
670  */
671 class GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
672 {
673 public:
674 	/* Public methods */
675 	GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(Context& context, const ExtParameters& extParams,
676 														const char* name, const char* description);
677 
~GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(void)678 	virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(void)
679 	{
680 	}
681 
682 protected:
683 	/* Protected methods */
684 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
685 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
686 	virtual void prepareTextureData(glw::GLubyte* data);
687 
688 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
689 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
690 
691 private:
692 	/* Private fields */
693 	/* Vertex shader code */
694 	static const glw::GLchar* const m_vertex_shader_code;
695 };
696 
697 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadowArray, function textureGatherOffset, axis X
698  */
699 class GPUShader5TextureGatherOffsetDepth2DArrayCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
700 {
701 public:
702 	/* Public methods */
703 	GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(Context& context, const ExtParameters& extParams,
704 													  const char* name, const char* description);
705 
~GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(void)706 	virtual ~GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(void)
707 	{
708 	}
709 
710 protected:
711 	/* Protected methods */
712 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
713 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
714 	virtual void isTextureArray(bool& out_is_texture_array);
715 
716 private:
717 	/* Private fields */
718 	/* Vertex shader code */
719 	static const glw::GLchar* const m_vertex_shader_code;
720 };
721 
722 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffsets, axis X
723  */
724 class GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase
725 {
726 public:
727 	/* Public methods */
728 	GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(Context& context, const ExtParameters& extParams,
729 														const char* name, const char* description);
730 
~GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(void)731 	virtual ~GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(void)
732 	{
733 	}
734 
735 protected:
736 	/* Protected methods */
737 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
738 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
739 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
740 
741 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
742 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
743 
744 private:
745 	/* Private fields */
746 	/* Vertex shader code */
747 	static const glw::GLchar* const m_vertex_shader_code_preamble;
748 	static const glw::GLchar* const m_vertex_shader_code_body;
749 
750 	/* String used for definition of constant offsets */
751 	std::string m_vertex_shader_code_offsets;
752 };
753 
754 /** Implementation of "Test 11" from CTS_EXT_gpu_shader5. Test description follows:
755  *
756  * Test whether using non constant offsets in the textureGatherOffset
757  * function works as expected for sampler2D and CLAMP_TO_BORDER_EXT
758  * ( CLAMP_TO_EDGE ) wrap mode.
759  *
760  * Category:   API,
761  *             Functional Test,
762  *             dependency with EXT_texture_border_clamp.
763  *
764  * Create two (lets name them A and B) 64 (texWidth) x 64 (texHeight)
765  * textures with internal format GL_RGBA32I.
766  *
767  * Bind texture A to texture unit 0.
768  * Bind texture B to texture unit 1.
769  *
770  * Set for both textures GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER
771  * to GL_NEAREST.
772  *
773  * For the A texture set GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T
774  * to CLAMP_TO_BORDER_EXT.
775  * For the B texture set GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T
776  * to CLAMP_TO_BORDER_EXT ( CLAMP TO EDGE ).
777  *
778  * For both textures fill the 4 components of each texel with values
779  * corresponding to texel row and column number (x,y) -> (x,y,x,y)
780  *
781  * Set the GL_TEXTURE_BORDER_COLOR_EXT to (-1,-1,-1,-1).
782  *
783  * Write a vertex shader that defines:
784  *
785  * uniform isampler2D samplerWithoutOffset;
786  * uniform isampler2D samplerWithOffset;
787  *
788  * in ivec2 tgoOffset;
789  * in  vec2 texCoords;
790  *
791  * out ivec4 withoutOffset0;
792  * out ivec4 withoutOffset1;
793  * out ivec2 intFloorTexCoords;
794  *
795  * out ivec4 withOffset0;
796  * out ivec4 withOffset1;
797  * out ivec4 withOffset2;
798  * out ivec4 withOffset3;
799  *
800  * Bind samplerWithoutOffset to texture unit 0.
801  * Bind samplerWithOffset to texture unit 1.
802  *
803  * Initialize a buffer object to be assigned as input attribute tgoOffset
804  * data source. The buffer object should hold 128 integer tuples. Fill it
805  * with some random integer values but falling into a range of
806  * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,
807  *  MAX_PROGRAM_TEXTURE_GATHER_OFFSET).
808  *
809  * Initialize a buffer object to be assigned as input attribute texCoords
810  * data source. The buffer object should hold 128 elements. Fill the first
811  * 4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the
812  * rest with some random float values in the range [-8.0..8.0].
813  *
814  * In the vertex shader perform the following operation:
815  *
816  * vec2 floorTexCoords = floor(texCoords);
817  * vec2 fractTexCoords = texCoords - floorTexCoords;
818  *
819  * withoutOffset0 = textureGather(samplerWithoutOffset,fractTexCoords, 0);
820  * withoutOffset1 = textureGather(samplerWithoutOffset,fractTexCoords, 1);
821  * intFloorTexCoords  = ivec2(int(floorTexCoords.x),int(floorTexCoords.y));
822  *
823  * withOffset0 = textureGatherOffset(samplerWithOffset,
824  *                 texCoords, tgoOffset, 0);
825  * withOffset1 = textureGatherOffset(samplerWithOffset,
826  *                 texCoords, tgoOffset, 1);
827  * withOffset2 = textureGatherOffset(samplerWithOffset,
828  *                 texCoords, tgoOffset, 2);
829  * withOffset3 = textureGatherOffset(samplerWithOffset,
830  *                 texCoords, tgoOffset, 3);
831  *
832  * Configure transform feedback to capture the values of withoutOffset*,
833  * withOffset* and intFloorTexCoords.
834  *
835  * Write a boilerplate fragment shader.
836  *
837  * Create a program from the above vertex shader and fragment shader
838  * and use it.
839  *
840  * Execute a draw call glDrawArrays(GL_POINTS, 0, 128).
841  *
842  * Copy the captured results from the buffer objects bound to transform
843  * feedback binding points.
844  *
845  * Using the captured values for each of the 128 results perform
846  * the following algorithm:
847  *
848  * From the captured withoutOffset0 and withoutOffset1 variables extract
849  * 4 texelPos values
850  *
851  * (Pseudocode)
852  *
853  * texelPos[i] = ivec2( withoutOffset0[i] , withoutOffset1[i] );
854  *
855  * Find a texel that has not been clamped. It's value should be
856  * different than (texWidth, texHeight). Let's asume that the found
857  * texel has index 'foundIndex'.
858  *
859  * If we can't find such texel we must throw an exception, because it means
860  * that the sampling algorithm has failed.
861  *
862  * Extract the offset that has to be applied to the chosen texel to get it's
863  * absolute position (the one we would get if we haven't clamped the texture
864  * coordinates for textureGather to the range [0,1])
865  *
866  * (Pseudocode)
867  *
868  * ivec2 absoluteOffset = ivec2( intFloorTexCoords.x * texWidth ,
869  *                               intFloorTexCoords.y * texHeight );
870  *
871  * Next apply the offset to the texel position
872  *
873  * (Pseudocode)
874  *
875  * texelAbsolutePos[foundIndex] = texelPos[foundIndex] + absoluteOffset;
876  *
877  * Now we have to set the absolute positions of the remaining 3 texels.
878  * We can do this because the foundIndex gives us information which
879  * texel we are dealing with in a 2x2 texel matrix returned by
880  * textureGather. The remaining texels will have their absolute positions
881  * computed by adding or substacting 1 to their x and y components
882  * depending on their position in the matrix relative to foundIndex.
883  *
884  * In the next step we have to apply the offset used in
885  * textureGatherOffset function to each of the absolute positions.
886  *
887  * (Pseudocode)
888  *
889  * texelAbsolutePos[i] += tgoOffset;
890  *
891  * We have to examine each absolute position in order to know if it should
892  * been clamped or not.
893  *
894  * In case of CLAMP_TO_BORDER_EXT if the absolute position goes beyond the
895  * texture bounds set it to value of GL_TEXTURE_BORDER_COLOR_EXT -> (-1,-1)
896  *
897  * In case of CLAMP_TO_EDGE if the absolute position goes beyond the
898  * texture bounds we have to clamp the value of absolute position
899  * to the edge that has been crossed.
900  *
901  * The test passes for each of the 4 absolute positions we have
902  *
903  * (Pseudocode)
904  *
905  * texelAbsolutePos[i] == ivec2( withOffset0[i], withOffset1[i] ) and
906  * texelAbsolutePos[i] == ivec2( withOffset2[i], withOffset3[i] ).
907  **/
908 
909 /** Test configuration: wrap mode GL_CLAMP_TO_BORDER_EXT, sampler isampler2D, function textureGatherOffset
910  */
911 class GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest
912 	: public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
913 {
914 public:
915 	/* Public methods */
916 	GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams,
917 															  const char* name, const char* description);
918 
~GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(void)919 	virtual ~GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(void)
920 	{
921 	}
922 
923 protected:
924 	/* Protected methods */
925 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
926 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
927 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
928 
929 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
930 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
931 
932 	virtual void initTest(void);
933 
934 private:
935 	/* Private fields */
936 	/* Vertex shader code */
937 	static const glw::GLchar* const m_vertex_shader_code;
938 };
939 
940 /** Test configuration: wrap mode GL_CLAMP_TO_EDGE, sampler isampler2D, function textureGatherOffset
941  */
942 class GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest
943 	: public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
944 {
945 public:
946 	/* Public methods */
947 	GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams,
948 															const char* name, const char* description);
949 
~GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(void)950 	virtual ~GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(void)
951 	{
952 	}
953 
954 protected:
955 	/* Protected methods */
956 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
957 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
958 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
959 
960 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
961 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
962 	virtual void initTest(void);
963 
964 private:
965 	/* Private fields */
966 	/* Vertex shader code */
967 	static const glw::GLchar* const m_vertex_shader_code;
968 };
969 
970 /** Test configuration: wrap mode GL_CLAMP_TO_BORDER_EXT, sampler isampler2DShadow, function textureGatherOffset, axis X
971  */
972 class GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest
973 	: public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
974 {
975 public:
976 	/* Public methods */
977 	GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams,
978 															  const char* name, const char* description);
979 
~GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(void)980 	virtual ~GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(void)
981 	{
982 	}
983 
984 protected:
985 	/* Protected methods */
986 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
987 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
988 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
989 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
990 
991 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
992 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
993 
994 	virtual void getVaryings(std::vector<const glw::GLchar*>& out_captured_varyings);
995 	virtual void initTest(void);
996 
997 private:
998 	/* Private fields */
999 	/* Vertex shader code */
1000 	static const glw::GLchar* const m_vertex_shader_code;
1001 };
1002 
1003 /** Test configuration: wrap mode GL_CLAMP_TO_EDGE, sampler isampler2DShadow, function textureGatherOffset, axis X
1004  */
1005 class GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest
1006 	: public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
1007 {
1008 public:
1009 	/* Public methods */
1010 	GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams,
1011 															const char* name, const char* description);
1012 
~GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(void)1013 	virtual ~GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(void)
1014 	{
1015 	}
1016 
1017 protected:
1018 	/* Protected methods */
1019 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
1020 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
1021 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
1022 
1023 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
1024 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
1025 
1026 	virtual void getVaryings(std::vector<const glw::GLchar*>& out_captured_varyings);
1027 	virtual void initTest(void);
1028 
1029 private:
1030 	/* Private fields */
1031 	/* Vertex shader code */
1032 	static const glw::GLchar* const m_vertex_shader_code;
1033 };
1034 
1035 } /* glcts */
1036 
1037 #endif // _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
1038