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
36namespace glcts
37{
38/** Base class for texture gather offset tests (9, 10 and 11)
39 *
40 **/
41class GPUShader5TextureGatherOffsetTestBase : public TestCaseBase
42{
43public:
44	/* Public methods */
45	virtual void		  deinit(void);
46	virtual IterateResult iterate(void);
47
48protected:
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
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
103private:
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 **/
177class GPUShader5TextureGatherOffsetColorTestBase : public GPUShader5TextureGatherOffsetTestBase
178{
179protected:
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
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
225private:
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 **/
236class GPUShader5TextureGatherOffsetDepthTestBase : public GPUShader5TextureGatherOffsetTestBase
237{
238protected:
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
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
279private:
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 */
417class GPUShader5TextureGatherOffsetColor2DRepeatCaseTest : public GPUShader5TextureGatherOffsetColorTestBase
418{
419public:
420	/* Public methods */
421	GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(Context& context, const ExtParameters& extParams,
422													   const char* name, const char* description);
423
424	virtual ~GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(void)
425	{
426	}
427
428protected:
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
440private:
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 */
457class GPUShader5TextureGatherOffsetColor2DArrayCaseTest : public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
458{
459public:
460	/* Public methods */
461	GPUShader5TextureGatherOffsetColor2DArrayCaseTest(Context& context, const ExtParameters& extParams,
462													  const char* name, const char* description);
463
464	virtual ~GPUShader5TextureGatherOffsetColor2DArrayCaseTest(void)
465	{
466	}
467
468protected:
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
474private:
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 */
482class GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetColorTestBase
483{
484public:
485	/* Public methods */
486	GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(Context& context, const ExtParameters& extParams,
487														const char* name, const char* description);
488
489	virtual ~GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(void)
490	{
491	}
492
493protected:
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
502private:
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 */
631class GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase
632{
633public:
634	/* Public methods */
635	GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(Context& context, const ExtParameters& extParams,
636													   const char* name, const char* description);
637
638	virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(void)
639	{
640	}
641
642protected:
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
663private:
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 */
671class GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
672{
673public:
674	/* Public methods */
675	GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(Context& context, const ExtParameters& extParams,
676														const char* name, const char* description);
677
678	virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(void)
679	{
680	}
681
682protected:
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
691private:
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 */
699class GPUShader5TextureGatherOffsetDepth2DArrayCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
700{
701public:
702	/* Public methods */
703	GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(Context& context, const ExtParameters& extParams,
704													  const char* name, const char* description);
705
706	virtual ~GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(void)
707	{
708	}
709
710protected:
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
716private:
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 */
724class GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase
725{
726public:
727	/* Public methods */
728	GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(Context& context, const ExtParameters& extParams,
729														const char* name, const char* description);
730
731	virtual ~GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(void)
732	{
733	}
734
735protected:
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
744private:
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 */
911class GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest
912	: public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
913{
914public:
915	/* Public methods */
916	GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams,
917															  const char* name, const char* description);
918
919	virtual ~GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(void)
920	{
921	}
922
923protected:
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
934private:
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 */
942class GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest
943	: public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
944{
945public:
946	/* Public methods */
947	GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams,
948															const char* name, const char* description);
949
950	virtual ~GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(void)
951	{
952	}
953
954protected:
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
964private:
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 */
972class GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest
973	: public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
974{
975public:
976	/* Public methods */
977	GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams,
978															  const char* name, const char* description);
979
980	virtual ~GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(void)
981	{
982	}
983
984protected:
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
997private:
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 */
1005class GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest
1006	: public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
1007{
1008public:
1009	/* Public methods */
1010	GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams,
1011															const char* name, const char* description);
1012
1013	virtual ~GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(void)
1014	{
1015	}
1016
1017protected:
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
1029private:
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