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 } // namespace glcts
1036 
1037 #endif // _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
1038