1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /*!
25  * \file  esextcTextureCubeMapArraySampling.cpp
26  * \brief Texture Cube Map Array Sampling (Test 1)
27  */ /*-------------------------------------------------------------------*/
28 
29 /* Control logging of positive results. 0 disabled, 1 enabled */
30 #define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_LOG 0
31 
32 /* Control logging of program source for positive results. 0 disabled, 1 enabled */
33 #define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_PROGRAM_LOG 1
34 
35 /* Control logging of negative results. 0 disabled, 1 enabled */
36 #define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG 1
37 
38 /* Control logging of program source for negative results. 0 disabled, 1 enabled */
39 #define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_PROGRAM_LOG 1
40 
41 /* When enabled, textures will be stored as TGA files. Test will not be executed. 0 disabled, 1 enabled */
42 #define TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION 0
43 
44 /* Output path for TGA files */
45 #define TEXTURECUBEMAPARRAYSAMPLINGTEST_PATH_FOR_COMPRESSION "c:\\textures\\"
46 
47 #include "esextcTextureCubeMapArraySampling.hpp"
48 #include "esextcTextureCubeMapArraySamplingResources.hpp"
49 
50 #include "gluContextInfo.hpp"
51 #include "glwEnums.hpp"
52 #include "glwFunctions.hpp"
53 #include "tcuTestLog.hpp"
54 
55 #include <cmath>
56 #include <sstream>
57 #include <vector>
58 
59 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION
60 #include <fstream>
61 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION */
62 
63 namespace glcts
64 {
65 /** Structure used to write shaders' variables to stream
66  *
67  **/
68 struct var2str
69 {
70 public:
71     /** Constructor. Stores strings used to create variable name
72      *  prefixName[index]
73      *
74      *  @param prefix Prefix part. Can be null.
75      *  @param name   Name part. Must not be null.
76      *  @param index  Index part. Can be null.
77      **/
var2strglcts::var2str78     var2str(const glw::GLchar *prefix, const glw::GLchar *name, const glw::GLchar *index)
79         : m_prefix(prefix)
80         , m_name(name)
81         , m_index(index)
82     {
83         /* Nothing to be done here */
84     }
85 
86     const glw::GLchar *m_prefix;
87     const glw::GLchar *m_name;
88     const glw::GLchar *m_index;
89 };
90 
91 /* Attribute names */
92 const glw::GLchar *const TextureCubeMapArraySamplingTest::attribute_grad_x             = "grad_x";
93 const glw::GLchar *const TextureCubeMapArraySamplingTest::attribute_grad_y             = "grad_y";
94 const glw::GLchar *const TextureCubeMapArraySamplingTest::attribute_lod                = "lod";
95 const glw::GLchar *const TextureCubeMapArraySamplingTest::attribute_refZ               = "refZ";
96 const glw::GLchar *const TextureCubeMapArraySamplingTest::attribute_texture_coordinate = "texture_coordinates";
97 
98 /* Compute shader parts */
99 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_body =
100     "void main()\n"
101     "{\n"
102     "    const int face_width         = 3;\n"
103     "    const int face_height        = 3;\n"
104     "    const int vertices_per_face  = face_width * face_height;\n"
105     "    const int faces_per_layer    = 6;\n"
106     "    const int layer_width        = faces_per_layer * face_width;\n"
107     "    const int vertices_per_layer = vertices_per_face * faces_per_layer;\n"
108     "\n"
109     "    ivec2 image_coord            = ivec2(gl_WorkGroupID.xy);\n"
110     "    ivec3 texture_size           = textureSize(sampler, 0);\n"
111     "\n"
112     "    int layer                    = image_coord.x / layer_width;\n"
113     "    int layer_offset             = layer * layer_width;\n"
114     "    int layer_index              = layer * vertices_per_layer;\n"
115     "    int face                     = (image_coord.x - layer_offset) / face_width;\n"
116     "    int face_offset              = face * face_width;\n"
117     "    int face_index               = face * vertices_per_face;\n"
118     "    int vertex                   = image_coord.x - layer_offset - face_offset;\n"
119     "    int vertex_index             = layer_index + face_index + vertex + (face_height - image_coord.y - 1) * "
120     "face_width;\n"
121     "\n";
122 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_layout_binding = "layout(std430, binding=";
123 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_buffer         = ") buffer ";
124 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_color          = "color";
125 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_image_store =
126     "    imageStore(image, image_coord, ";
127 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_layout =
128     "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
129 const glw::GLchar *const TextureCubeMapArraySamplingTest::compute_shader_param = "cs_";
130 
131 /* Fragment shader parts */
132 const glw::GLchar *const TextureCubeMapArraySamplingTest::fragment_shader_input  = "fs_in_color";
133 const glw::GLchar *const TextureCubeMapArraySamplingTest::fragment_shader_output = "fs_out_color";
134 const glw::GLchar *const TextureCubeMapArraySamplingTest::fragment_shader_pass_through_body_code =
135     "void main()\n"
136     "{\n"
137     "    fs_out_color = fs_in_color;\n"
138     "}\n";
139 const glw::GLchar *const TextureCubeMapArraySamplingTest::fragment_shader_sampling_body_code = "void main()\n"
140                                                                                                "{\n";
141 
142 /* Geometry shader parts */
143 const glw::GLchar *const TextureCubeMapArraySamplingTest::geometry_shader_emit_vertex_code = "    EmitVertex();\n"
144                                                                                              "}\n";
145 const glw::GLchar *const TextureCubeMapArraySamplingTest::geometry_shader_extension = "${GEOMETRY_SHADER_REQUIRE}\n";
146 const glw::GLchar *const TextureCubeMapArraySamplingTest::geometry_shader_layout =
147     "layout(points)                 in;\n"
148     "layout(points, max_vertices=1) out;\n"
149     "\n";
150 const glw::GLchar *const TextureCubeMapArraySamplingTest::geometry_shader_sampling_body_code =
151     "void main()\n"
152     "{\n"
153     "    gl_Position = gl_in[0].gl_Position;\n";
154 
155 /* Image types and name */
156 const glw::GLchar *const TextureCubeMapArraySamplingTest::image_float = "image2D ";
157 const glw::GLchar *const TextureCubeMapArraySamplingTest::image_int   = "iimage2D ";
158 const glw::GLchar *const TextureCubeMapArraySamplingTest::image_name  = "image";
159 const glw::GLchar *const TextureCubeMapArraySamplingTest::image_uint  = "uimage2D ";
160 
161 /* Interpolation */
162 const glw::GLchar *const TextureCubeMapArraySamplingTest::interpolation_flat = "flat ";
163 
164 /* Sampler types and name */
165 const glw::GLchar *const TextureCubeMapArraySamplingTest::sampler_depth = "samplerCubeArrayShadow ";
166 const glw::GLchar *const TextureCubeMapArraySamplingTest::sampler_float = "samplerCubeArray ";
167 const glw::GLchar *const TextureCubeMapArraySamplingTest::sampler_int   = "isamplerCubeArray ";
168 const glw::GLchar *const TextureCubeMapArraySamplingTest::sampler_name  = "sampler";
169 const glw::GLchar *const TextureCubeMapArraySamplingTest::sampler_uint  = "usamplerCubeArray ";
170 
171 /* Common shader parts for */
172 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_code_preamble = "${VERSION}\n"
173                                                                                  "${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
174                                                                                  "\n";
175 
176 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_precision = "precision highp float;\n";
177 
178 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_input     = "in ";
179 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_layout    = "layout(location = 0) ";
180 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_output    = "out ";
181 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_uniform   = "uniform ";
182 const glw::GLchar *const TextureCubeMapArraySamplingTest::shader_writeonly = "writeonly ";
183 
184 /* Tesselation control shader parts */
185 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_control_shader_layout =
186     "layout(vertices = 1) out;\n"
187     "\n";
188 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_control_shader_sampling_body_code =
189     "void main()\n"
190     "{\n"
191     "    gl_TessLevelInner[0] = 1.0;\n"
192     "    gl_TessLevelInner[1] = 1.0;\n"
193     "    gl_TessLevelOuter[0] = 1.0;\n"
194     "    gl_TessLevelOuter[1] = 1.0;\n"
195     "    gl_TessLevelOuter[2] = 1.0;\n"
196     "    gl_TessLevelOuter[3] = 1.0;\n"
197     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n";
198 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_control_shader_output = "tcs_out_";
199 
200 /* Tesselation evaluation shader parts */
201 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_input = "tes_in_color";
202 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_layout =
203     "layout(isolines, point_mode) in;\n"
204     "\n";
205 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_pass_through_body_code =
206     "void main()\n"
207     "{\n"
208     "    gl_Position = gl_in[0].gl_Position;\n"
209     "    fs_in_color = tes_in_color[0];\n"
210     "}\n";
211 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_sampling_body_code =
212     "void main()\n"
213     "{\n"
214     "    gl_Position = gl_in[0].gl_Position;\n";
215 const glw::GLchar *const TextureCubeMapArraySamplingTest::tesselation_shader_extension =
216     "${TESSELLATION_SHADER_REQUIRE}\n";
217 
218 /* Texture sampling routines */
219 const glw::GLchar *const TextureCubeMapArraySamplingTest::texture_func       = "texture";
220 const glw::GLchar *const TextureCubeMapArraySamplingTest::textureGather_func = "textureGather";
221 const glw::GLchar *const TextureCubeMapArraySamplingTest::textureGrad_func   = "textureGrad";
222 const glw::GLchar *const TextureCubeMapArraySamplingTest::textureLod_func    = "textureLod";
223 
224 /* Data types */
225 const glw::GLchar *const TextureCubeMapArraySamplingTest::type_float = "float ";
226 const glw::GLchar *const TextureCubeMapArraySamplingTest::type_ivec4 = "ivec4 ";
227 const glw::GLchar *const TextureCubeMapArraySamplingTest::type_uint  = "uint ";
228 const glw::GLchar *const TextureCubeMapArraySamplingTest::type_uvec4 = "uvec4 ";
229 const glw::GLchar *const TextureCubeMapArraySamplingTest::type_vec3  = "vec3 ";
230 const glw::GLchar *const TextureCubeMapArraySamplingTest::type_vec4  = "vec4 ";
231 
232 /* Vertex shader parts */
233 const glw::GLchar *const TextureCubeMapArraySamplingTest::vertex_shader_body_code =
234     "void main()\n"
235     "{\n"
236     "    gl_PointSize = 1.0f;\n"
237     "    gl_Position = vs_in_position;\n";
238 const glw::GLchar *const TextureCubeMapArraySamplingTest::vertex_shader_input    = "vs_in_";
239 const glw::GLchar *const TextureCubeMapArraySamplingTest::vertex_shader_output   = "vs_out_";
240 const glw::GLchar *const TextureCubeMapArraySamplingTest::vertex_shader_position = "position";
241 
242 /* Static constants */
243 const glw::GLuint TextureCubeMapArraySamplingTest::m_get_type_api_status_program_resource                        = 0x02;
244 const glw::GLuint TextureCubeMapArraySamplingTest::m_get_type_api_status_uniform                                 = 0x01;
245 const glw::GLuint TextureCubeMapArraySamplingTest::bufferDefinition::m_invalid_buffer_object_id                  = -1;
246 const glw::GLuint TextureCubeMapArraySamplingTest::programDefinition::m_invalid_program_object_id                = 0;
247 const glw::GLuint TextureCubeMapArraySamplingTest::shaderDefinition::m_invalid_shader_object_id                  = 0;
248 const glw::GLuint TextureCubeMapArraySamplingTest::textureDefinition::m_invalid_texture_object_id                = -1;
249 const glw::GLuint TextureCubeMapArraySamplingTest::textureDefinition::m_invalid_uniform_location                 = -1;
250 const glw::GLuint TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::m_invalid_attribute_location     = -1;
251 const glw::GLuint TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::m_invalid_vertex_array_object_id = -1;
252 
253 /* Functions */
254 
255 /** Fill image with specified color
256  *  @tparam T               Image component type
257  *  @tparam N_Components    Number of image components
258  *
259  *  @param image_width      Width of image
260  *  @param image_height     Height of image
261  *  @param pixel_components Image will be filled with that color
262  *  @param out_data         Image data, storage must be allocated
263  **/
264 template <typename T, unsigned int N_Components>
fillImage(glw::GLsizei image_width,glw::GLsizei image_height,const T * pixel_components,T * out_data)265 void fillImage(glw::GLsizei image_width, glw::GLsizei image_height, const T *pixel_components, T *out_data)
266 {
267     const glw::GLuint n_components_per_pixel = N_Components;
268     const glw::GLuint n_components_per_line  = n_components_per_pixel * image_width;
269 
270     for (glw::GLsizei y = 0; y < image_height; ++y)
271     {
272         const glw::GLuint line_offset = y * n_components_per_line;
273 
274         for (glw::GLsizei x = 0; x < image_width; ++x)
275         {
276             for (glw::GLuint component = 0; component < n_components_per_pixel; ++component)
277             {
278                 out_data[line_offset + x * n_components_per_pixel + component] = pixel_components[component];
279             }
280         }
281     }
282 }
283 
284 /* Out of alphabetical order due to use in other functions */
285 /** Normalize vector stored in array. Only first N_NormalizedComponents will be normalized.
286  *
287  *  @tparam N_NormalizedComponents Number of coordinates to normalize
288  *  @tparam N_Components           Number of coordinates in vector
289  *
290  *  @param data                    Pointer to first coordinate of first vector in array
291  *  @param index                   Index of vector to be normalized
292  **/
293 template <unsigned int N_NormalizedComponents, unsigned int N_Components>
vectorNormalize(glw::GLfloat * data,glw::GLuint index)294 void vectorNormalize(glw::GLfloat *data, glw::GLuint index)
295 {
296     glw::GLfloat *components = data + index * N_Components;
297 
298     glw::GLfloat sqr_length = 0.0f;
299 
300     for (glw::GLuint i = 0; i < N_NormalizedComponents; ++i)
301     {
302         const glw::GLfloat component = components[i];
303 
304         sqr_length += component * component;
305     }
306 
307     const glw::GLfloat length = sqrtf(sqr_length);
308     const glw::GLfloat factor = 1.0f / length;
309 
310     for (glw::GLuint i = 0; i < N_NormalizedComponents; ++i)
311     {
312         components[i] *= factor;
313     }
314 }
315 
316 /* Out of alphabetical order due to use in other functions */
317 /** Set coordinates of 4 element vector stored in array
318  *
319  *  @param data  Pointer to first coordinate of first vector in array
320  *  @param index Index of vector to be normalized
321  *  @param x     1st coordinate value
322  *  @param y     2nd coordinate value
323  *  @param z     3rd coordinate value
324  *  @param w     4th coordinate value
325  **/
vectorSet4(glw::GLfloat * data,glw::GLuint index,glw::GLfloat x,glw::GLfloat y,glw::GLfloat z,glw::GLfloat w)326 void vectorSet4(glw::GLfloat *data, glw::GLuint index, glw::GLfloat x, glw::GLfloat y, glw::GLfloat z, glw::GLfloat w)
327 {
328     const glw::GLuint n_components_per_vertex = 4;
329     const glw::GLuint vector_offset           = n_components_per_vertex * index;
330 
331     data[vector_offset + 0] = x;
332     data[vector_offset + 1] = y;
333     data[vector_offset + 2] = z;
334     data[vector_offset + 3] = w;
335 }
336 
337 /* Out of alphabetical order due to use in other functions */
338 /** Subtract vectors: a = b - a
339  *
340  *  @tparam N_Components Number of coordinates in vector
341  *
342  *  @param a             Pointer to vector a
343  *  @param b             Pointer to vector b
344  **/
345 template <unsigned int N_Components>
vectorSubtractInPlace(glw::GLfloat * a,const glw::GLfloat * b)346 void vectorSubtractInPlace(glw::GLfloat *a, const glw::GLfloat *b)
347 {
348     const glw::GLuint n_components = N_Components;
349 
350     for (glw::GLuint i = 0; i < n_components; ++i)
351     {
352         a[i] -= b[i];
353     }
354 }
355 
356 /** Prepare color for rgba float textures
357  *
358  *  @param cube_face       Index of cube's face
359  *  @param element_index   Index of element in array
360  *  @param mipmap_level    Mipmap level
361  *  @param n_elements      Number of elements in array
362  *  @param n_mipmap_levels Number of mipmap levels
363  *  @param out_data        Pointer to components storage
364  **/
getColorFloatComponents(glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLfloat * out_data)365 void getColorFloatComponents(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level,
366                              glw::GLint n_elements, glw::GLint n_mipmap_levels, glw::GLfloat *out_data)
367 {
368     static const glw::GLfloat n_faces = 6.0f;
369 
370     out_data[0] = ((glw::GLfloat)(mipmap_level + 1)) / ((glw::GLfloat)n_mipmap_levels);
371     out_data[1] = ((glw::GLfloat)(cube_face + 1)) / n_faces;
372     out_data[2] = ((glw::GLfloat)(element_index + 1)) / ((glw::GLfloat)n_elements);
373     out_data[3] = 1.0f / 4.0f;
374 }
375 
376 /** Prepare color for rgba integer textures
377  *
378  *  @tparam T             Type of components
379  *
380  *  @param cube_face       Index of cube's face
381  *  @param element_index   Index of element in array
382  *  @param mipmap_level    Mipmap level
383  *  @param n_elements      Number of elements in array, ignored
384  *  @param n_mipmap_levels Number of mipmap levels, ignored
385  *  @param out_data        Pointer to components storage
386  **/
387 template <typename T>
getColorIntComponents(glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint,glw::GLint,T * out_data)388 void getColorIntComponents(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level,
389                            glw::GLint /* n_elements */, glw::GLint /* n_mipmap_levels */, T *out_data)
390 {
391     out_data[0] = static_cast<T>(mipmap_level + 1);
392     out_data[1] = static_cast<T>(cube_face + 1);
393     out_data[2] = static_cast<T>(element_index + 1);
394     out_data[3] = 1;
395 }
396 
397 /** Prepare color for rgba compressed textures
398  *
399  *  @param cube_face       Index of cube's face
400  *  @param element_index   Index of element in array
401  *  @param mipmap_level    Mipmap level
402  *  @param n_elements      Number of elements in array
403  *  @param n_mipmap_levels Number of mipmap levels
404  *  @param out_data        Pointer to components storage
405  **/
getCompressedColorUByteComponents(glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLubyte * out_data)406 void getCompressedColorUByteComponents(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level,
407                                        glw::GLint n_elements, glw::GLint n_mipmap_levels, glw::GLubyte *out_data)
408 {
409     (void)n_mipmap_levels;
410 
411     static const glw::GLuint n_faces = 6;
412 
413     const glw::GLuint n_faces_per_level = n_elements * n_faces;
414     const glw::GLubyte value =
415         static_cast<glw::GLubyte>(mipmap_level * n_faces_per_level + element_index * n_faces + cube_face + 1);
416 
417     out_data[0] = value;
418     out_data[1] = value;
419     out_data[2] = value;
420     out_data[3] = value;
421 }
422 
423 /** Get compressed texture data and size from resources. Width, height, number of array elements and mipmap level are used to identify image.
424  *  Width and height are dimmensions of base level image, same values are used to identify all mipmap levels.
425  *
426  *  @param width            Width of texture
427  *  @param height           Height of texture
428  *  @param n_array_elements Number of elemnts in array
429  *  @param mipmap_level     Level
430  *  @param out_image_data   Image data
431  *  @param out_image_size   Image size
432  **/
getCompressedTexture(glw::GLuint width,glw::GLuint height,glw::GLuint n_array_elements,glw::GLuint mipmap_level,const glw::GLubyte * & out_image_data,glw::GLuint & out_image_size)433 void getCompressedTexture(glw::GLuint width, glw::GLuint height, glw::GLuint n_array_elements, glw::GLuint mipmap_level,
434                           const glw::GLubyte *&out_image_data, glw::GLuint &out_image_size)
435 {
436     for (glw::GLuint i = 0; i < n_compressed_images; ++i)
437     {
438         const compressedImage &image = compressed_images[i];
439 
440         if ((image.width == width) && (image.height == height) && (image.length == n_array_elements) &&
441             (image.level == mipmap_level))
442         {
443             out_image_data = image.image_data;
444             out_image_size = image.image_size;
445 
446             return;
447         }
448     }
449 
450     out_image_data = 0;
451     out_image_size = 0;
452 }
453 
454 /** Prepare color for depth textures
455  *
456  *  @param cube_face       Index of cube's face
457  *  @param element_index   Index of element in array
458  *  @param mipmap_level    Mipmap level
459  *  @param n_elements      Number of elements in array
460  *  @param n_mipmap_levels Number of mipmap levels
461  *  @param out_depth       Depth value
462  **/
getDepthComponent(glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLfloat & out_depth)463 void getDepthComponent(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level, glw::GLint n_elements,
464                        glw::GLint n_mipmap_levels, glw::GLfloat &out_depth)
465 {
466     static const glw::GLuint n_faces = 6;
467 
468     out_depth = ((glw::GLfloat)(mipmap_level + 1 + cube_face + 1 + element_index + 1)) /
469                 ((glw::GLfloat)(n_mipmap_levels + n_faces + n_elements));
470 }
471 
472 /** Get expected color sampled by texture or textureGather from rgba float textures
473  *
474  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
475  *  @param cube_face       Index of cube's face
476  *  @param element_index   Index of element in array
477  *  @param n_layers        Number of elements in array
478  *  @param n_mipmap_levels Number of mipmap levels
479  *  @param out_components  Pointer to components storage
480  **/
getExpectedColorFloatComponentsForTexture(glw::GLuint,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,glw::GLfloat * out_components)481 void getExpectedColorFloatComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
482                                                glw::GLint element_index, glw::GLint n_layers,
483                                                glw::GLint n_mipmap_levels, glw::GLfloat *out_components)
484 {
485     getColorFloatComponents(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels, out_components);
486 }
487 
488 /** Get expected color sampled by textureLod or textureGrad from rgba float textures
489  *
490  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
491  *  @param cube_face       Index of cube's face
492  *  @param element_index   Index of element in array
493  *  @param n_layers        Number of elements in array
494  *  @param n_mipmap_levels Number of mipmap levels
495  *  @param out_components  Pointer to components storage
496  **/
getExpectedColorFloatComponentsForTextureLod(glw::GLuint pixel_index,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,glw::GLfloat * out_components)497 void getExpectedColorFloatComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face,
498                                                   glw::GLint element_index, glw::GLint n_layers,
499                                                   glw::GLint n_mipmap_levels, glw::GLfloat *out_components)
500 {
501     glw::GLint mipmap_level = 0;
502 
503     if (1 == pixel_index % 2)
504     {
505         mipmap_level = n_mipmap_levels - 1;
506     }
507 
508     getColorFloatComponents(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels, out_components);
509 }
510 
511 /** Get expected color sampled by texture or textureGather from rgba integer textures
512  *
513  *  @tparam T              Type of image components
514  *
515  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
516  *  @param cube_face       Index of cube's face
517  *  @param element_index   Index of element in array
518  *  @param n_layers        Number of elements in array
519  *  @param n_mipmap_levels Number of mipmap levels
520  *  @param out_components  Pointer to components storage
521  **/
522 template <typename T>
getExpectedColorIntComponentsForTexture(glw::GLuint,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,T * out_components)523 void getExpectedColorIntComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
524                                              glw::GLint element_index, glw::GLint n_layers, glw::GLint n_mipmap_levels,
525                                              T *out_components)
526 {
527     getColorIntComponents<T>(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels, out_components);
528 }
529 
530 /** Get expected color sampled by textureLod or textureGrad from rgba integer textures
531  *
532  *  @tparam T              Type of image components
533  *
534  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
535  *  @param cube_face       Index of cube's face
536  *  @param element_index   Index of element in array
537  *  @param n_layers        Number of elements in array
538  *  @param n_mipmap_levels Number of mipmap levels
539  *  @param out_components  Pointer to components storage
540  **/
541 template <typename T>
getExpectedColorIntComponentsForTextureLod(glw::GLuint pixel_index,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,T * out_components)542 void getExpectedColorIntComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face, glw::GLint element_index,
543                                                 glw::GLint n_layers, glw::GLint n_mipmap_levels, T *out_components)
544 {
545     glw::GLint mipmap_level = 0;
546 
547     if (1 == pixel_index % 2)
548     {
549         mipmap_level = n_mipmap_levels - 1;
550     }
551 
552     getColorIntComponents<T>(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels, out_components);
553 }
554 
555 /** Get expected color sampled by texture or textureGather from rgba compressed textures
556  *
557  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
558  *  @param cube_face       Index of cube's face
559  *  @param element_index   Index of element in array
560  *  @param n_layers        Number of elements in array
561  *  @param n_mipmap_levels Number of mipmap levels
562  *  @param out_components  Pointer to components storage
563  **/
getExpectedCompressedComponentsForTexture(glw::GLuint,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,glw::GLubyte * out_components)564 void getExpectedCompressedComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
565                                                glw::GLint element_index, glw::GLint n_layers,
566                                                glw::GLint n_mipmap_levels, glw::GLubyte *out_components)
567 {
568     getCompressedColorUByteComponents(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels,
569                                       out_components);
570 }
571 
572 /** Get expected color sampled by textureLod or textureGrad from rgba compressed textures
573  *
574  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
575  *  @param cube_face       Index of cube's face
576  *  @param element_index   Index of element in array
577  *  @param n_layers        Number of elements in array
578  *  @param n_mipmap_levels Number of mipmap levels
579  *  @param out_components  Pointer to components storage
580  **/
getExpectedCompressedComponentsForTextureLod(glw::GLuint pixel_index,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,glw::GLubyte * out_components)581 void getExpectedCompressedComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face,
582                                                   glw::GLint element_index, glw::GLint n_layers,
583                                                   glw::GLint n_mipmap_levels, glw::GLubyte *out_components)
584 {
585     glw::GLint mipmap_level = 0;
586 
587     if (1 == pixel_index % 2)
588     {
589         mipmap_level = n_mipmap_levels - 1;
590     }
591 
592     getCompressedColorUByteComponents(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels,
593                                       out_components);
594 }
595 
596 /** Get expected color sampled by texture or textureGather from depth textures
597  *
598  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>
599  *  @param cube_face       Index of cube's face. Ignored.
600  *  @param element_index   Index of element in array. Ignored.
601  *  @param n_layers        Number of elements in array. Ignored.
602  *  @param n_mipmap_levels Number of mipmap levels. Ignored.
603  *  @param out_components  Pointer to components storage
604  **/
getExpectedDepthComponentsForTexture(glw::GLuint pixel_index,glw::GLint,glw::GLint,glw::GLint,glw::GLint,glw::GLfloat * out_components)605 void getExpectedDepthComponentsForTexture(glw::GLuint pixel_index, glw::GLint /* cube_face */,
606                                           glw::GLint /* element_index */, glw::GLint /* n_layers */,
607                                           glw::GLint /* n_mipmap_levels */, glw::GLfloat *out_components)
608 {
609     const glw::GLfloat results[9] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
610 
611     out_components[0] = results[pixel_index];
612 }
613 
614 /** Get expected color sampled by textureLod or textureGrad from depth textures
615  *
616  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
617  *  @param cube_face       Index of cube's face. Ignored.
618  *  @param element_index   Index of element in array. Ignored.
619  *  @param n_layers        Number of elements in array. Ignored.
620  *  @param n_mipmap_levels Number of mipmap levels. Ignored.
621  *  @param out_components  Pointer to components storage
622  **/
getExpectedDepthComponentsForTextureLod(glw::GLuint pixel_index,glw::GLint,glw::GLint,glw::GLint,glw::GLint,glw::GLfloat * out_components)623 void getExpectedDepthComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint /* cube_face */,
624                                              glw::GLint /* element_index */, glw::GLint /* n_layers */,
625                                              glw::GLint /* n_mipmap_levels */, glw::GLfloat *out_components)
626 {
627     if (0 == pixel_index % 2)
628     {
629         out_components[0] = 0.0f;
630     }
631     else
632     {
633         out_components[0] = 1.0f;
634     }
635 }
636 
637 /* Out of alphabetical order due to use in other functions */
638 /** Prepare color for stencil textures
639  *
640  *  @param cube_face       Index of cube's face
641  *  @param element_index   Index of element in array
642  *  @param mipmap_level    Mipmap level
643  *  @param n_elements      Number of elements in array
644  *  @param n_mipmap_levels Number of mipmap levels
645  *  @param out_stencil     Stencil value
646  **/
getStencilComponent(glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLubyte & out_stencil)647 void getStencilComponent(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level, glw::GLint n_elements,
648                          glw::GLint n_mipmap_levels, glw::GLubyte &out_stencil)
649 {
650     static const glw::GLint n_faces = 6;
651 
652     out_stencil = (glw::GLubyte)((mipmap_level + 1 + cube_face + 1 + element_index + 1) * 255 /
653                                  (n_mipmap_levels + n_faces + n_elements));
654 }
655 
656 /** Get expected color sampled by texture or textureGather from stencil textures
657  *
658  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
659  *  @param cube_face       Index of cube's face
660  *  @param element_index   Index of element in array
661  *  @param n_layers        Number of elements in array
662  *  @param n_mipmap_levels Number of mipmap levels
663  *  @param out_components  Pointer to components storage
664  **/
getExpectedStencilComponentsForTexture(glw::GLuint,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,glw::GLuint * out_components)665 void getExpectedStencilComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
666                                             glw::GLint element_index, glw::GLint n_layers, glw::GLint n_mipmap_levels,
667                                             glw::GLuint *out_components)
668 {
669     glw::GLubyte value = 0;
670 
671     getStencilComponent(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels, value);
672 
673     out_components[0] = value;
674 }
675 
676 /** Get expected color sampled by textureLod or textureGrad from stencil textures
677  *
678  *  @param pixel_index     Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
679  *  @param cube_face       Index of cube's face
680  *  @param element_index   Index of element in array
681  *  @param n_layers        Number of elements in array
682  *  @param n_mipmap_levels Number of mipmap levels
683  *  @param out_components  Pointer to components storage
684  **/
getExpectedStencilComponentsForTextureLod(glw::GLuint pixel_index,glw::GLint cube_face,glw::GLint element_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,glw::GLuint * out_components)685 void getExpectedStencilComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face, glw::GLint element_index,
686                                                glw::GLint n_layers, glw::GLint n_mipmap_levels,
687                                                glw::GLuint *out_components)
688 {
689     glw::GLubyte value      = 0;
690     glw::GLint mipmap_level = 0;
691 
692     if (1 == pixel_index % 2)
693     {
694         mipmap_level = n_mipmap_levels - 1;
695     }
696 
697     getStencilComponent(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels, value);
698 
699     out_components[0] = value;
700 }
701 
702 /** Returns number of mipmaps for given image dimmensions
703  *
704  *  @param texture_width  Width of image
705  *  @param texture_height Height of image
706  *
707  *  @returns Number of mipmaps
708  **/
getMipmapLevelCount(glw::GLsizei texture_width,glw::GLsizei texture_height)709 glw::GLubyte getMipmapLevelCount(glw::GLsizei texture_width, glw::GLsizei texture_height)
710 {
711     glw::GLsizei size = de::max(texture_width, texture_height);
712     glw::GLuint count = 1;
713 
714     while (1 < size)
715     {
716         size /= 2;
717         count += 1;
718     }
719 
720     return (glw::GLubyte)count;
721 }
722 
723 /** Calculate texture coordinates for "right neighbour" of given texture coordinates
724  *
725  *  @param texture_coordinates Texture coordinates of original point
726  *  @param face                Cube map's face index
727  *  @param offset              Offset of "neighbour" in "right" direction
728  *  @param width               Image width
729  *  @param out_neighbour       Texture coordinates of "neighbour" point
730  **/
getRightNeighbour(const glw::GLfloat * texture_coordinates,glw::GLuint face,glw::GLuint offset,glw::GLuint width,glw::GLfloat * out_neighbour)731 void getRightNeighbour(const glw::GLfloat *texture_coordinates, glw::GLuint face, glw::GLuint offset, glw::GLuint width,
732                        glw::GLfloat *out_neighbour)
733 {
734     const glw::GLfloat step = (float)offset / (float)width;
735 
736     glw::GLfloat &x = out_neighbour[0];
737     glw::GLfloat &y = out_neighbour[1];
738     glw::GLfloat &z = out_neighbour[2];
739 
740     const glw::GLfloat coord_x = texture_coordinates[0];
741     const glw::GLfloat coord_y = texture_coordinates[1];
742     const glw::GLfloat coord_z = texture_coordinates[2];
743 
744     switch (face)
745     {
746     case 0: // +X
747         x = coord_x;
748         y = coord_y - step;
749         z = coord_z;
750         break;
751     case 1: // -X
752         x = coord_x;
753         y = coord_y + step;
754         z = coord_z;
755         break;
756     case 2: // +Y
757         x = coord_x + step;
758         y = coord_y;
759         z = coord_z;
760         break;
761     case 3: // -Y
762         x = coord_x - step;
763         y = coord_y;
764         z = coord_z;
765         break;
766     case 4: // +Z
767         x = coord_x + step;
768         y = coord_y;
769         z = coord_z;
770         break;
771     case 5: // -Z
772         x = coord_x - step;
773         y = coord_y;
774         z = coord_z;
775         break;
776     }
777 }
778 
779 /** Calculate texture coordinates for "top neighbour" of given texture coordinates
780  *
781  *  @param texture_coordinates Texture coordinates of original point
782  *  @param face                Cube map's face index
783  *  @param offset              Offset of "neighbour" in "top" direction
784  *  @param width               Image width
785  *  @param out_neighbour       Texture coordinates of "neighbour" point
786  **/
getTopNeighbour(const glw::GLfloat * texture_coordinates,glw::GLuint face,glw::GLuint offset,glw::GLuint width,glw::GLfloat * out_neighbour)787 void getTopNeighbour(const glw::GLfloat *texture_coordinates, glw::GLuint face, glw::GLuint offset, glw::GLuint width,
788                      glw::GLfloat *out_neighbour)
789 {
790     glw::GLfloat step = (float)offset / (float)width;
791 
792     glw::GLfloat &x = out_neighbour[0];
793     glw::GLfloat &y = out_neighbour[1];
794     glw::GLfloat &z = out_neighbour[2];
795 
796     const glw::GLfloat coord_x = texture_coordinates[0];
797     const glw::GLfloat coord_y = texture_coordinates[1];
798     const glw::GLfloat coord_z = texture_coordinates[2];
799 
800     switch (face)
801     {
802     case 0: // +X
803         x = coord_x;
804         y = coord_y;
805         z = coord_z + step;
806         break;
807     case 1: // -X
808         x = coord_x;
809         y = coord_y;
810         z = coord_z + step;
811         break;
812     case 2: // +Y
813         x = coord_x;
814         y = coord_y;
815         z = coord_z + step;
816         break;
817     case 3: // -Y
818         x = coord_x;
819         y = coord_y;
820         z = coord_z + step;
821         break;
822     case 4: // +Z
823         x = coord_x;
824         y = coord_y - step;
825         z = coord_z;
826         break;
827     case 5: // -Z
828         x = coord_x;
829         y = coord_y + step;
830         z = coord_z;
831         break;
832     }
833 }
834 
835 /** Write var2str instance to output stream
836  *
837  *  @param stream Stream instance
838  *  @param var    var2str instance
839  *
840  *  @returns Stream instance
841  **/
operator <<(std::ostream & stream,const var2str & var)842 std::ostream &operator<<(std::ostream &stream, const var2str &var)
843 {
844     if (0 != var.m_prefix)
845     {
846         stream << var.m_prefix;
847     }
848 
849     stream << var.m_name;
850 
851     if (0 != var.m_index)
852     {
853         stream << "[" << var.m_index << "]";
854     }
855 
856     return stream;
857 }
858 
859 /* Out of alphabetical order due to use in other functions */
860 /** Fill texture's face at given index and level with given color
861  *
862  *  @tparam T                 Type of image component
863  *  @tparam N_Components      Number of components
864  *
865  *  @param gl                 GL functions
866  *  @param cube_face          Index of cube map's face
867  *  @param element_index      Index of element in array
868  *  @param mipmap_level       Mipmap level
869  *  @param texture_format     Texture format
870  *  @param texture_width      Texture width
871  *  @param texture_height     Texture height
872  *  @param components         Color used to fill texture
873  **/
874 template <typename T, unsigned int N_Components>
prepareDataForTexture(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height,const T * components)875 void prepareDataForTexture(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
876                            glw::GLint mipmap_level, glw::GLenum texture_format, glw::GLenum texture_type,
877                            glw::GLsizei texture_width, glw::GLsizei texture_height, const T *components)
878 {
879     static const glw::GLuint n_components_per_pixel = N_Components;
880 
881     const glw::GLuint n_pixels            = texture_width * texture_height;
882     const glw::GLuint n_total_componenets = n_components_per_pixel * n_pixels;
883     const glw::GLuint z_offset            = element_index * 6 + cube_face;
884 
885     std::vector<T> texture_data;
886     texture_data.resize(n_total_componenets);
887 
888     fillImage<T, N_Components>(texture_width, texture_height, components, &texture_data[0]);
889 
890     gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipmap_level, 0 /* x */, 0 /* y */, z_offset, texture_width,
891                      texture_height, 1 /* depth */, texture_format, texture_type, &texture_data[0]);
892 
893     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update texture data");
894 }
895 
896 /** Prepare texture's face at given index and level, for rgba float textures.
897  *
898  *  @param gl                 GL functions
899  *  @param cube_face          Index of cube map's face
900  *  @param element_index      Index of element in array
901  *  @param mipmap_level       Mipmap level
902  *  @param n_elements         Number of elements in array
903  *  @param n_mipmap_levels    Number of mipmap levels
904  *  @param texture_format     Texture format
905  *  @param texture_width      Texture width
906  *  @param texture_height     Texture height
907  **/
prepareDataForColorFloatTexture(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)908 void prepareDataForColorFloatTexture(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
909                                      glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
910                                      glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
911                                      glw::GLsizei texture_height)
912 {
913     glw::GLfloat components[4];
914 
915     getColorFloatComponents(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, components);
916 
917     prepareDataForTexture<glw::GLfloat, 4>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type,
918                                            texture_width, texture_height, components);
919 }
920 
921 /** Prepare texture's face at given index and level, for rgba integer textures.
922  *
923  *  @tparam T                 Type of image component
924  *
925  *  @param gl                 GL functions
926  *  @param cube_face          Index of cube map's face
927  *  @param element_index      Index of element in array
928  *  @param mipmap_level       Mipmap level
929  *  @param n_elements         Number of elements in array
930  *  @param n_mipmap_levels    Number of mipmap levels
931  *  @param texture_format     Texture format
932  *  @param texture_width      Texture width
933  *  @param texture_height     Texture height
934  **/
935 template <typename T>
prepareDataForColorIntTexture(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)936 void prepareDataForColorIntTexture(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
937                                    glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
938                                    glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
939                                    glw::GLsizei texture_height)
940 {
941     T components[4];
942 
943     getColorIntComponents<T>(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, components);
944 
945     prepareDataForTexture<T, 4>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type, texture_width,
946                                 texture_height, components);
947 }
948 
949 /** Prepare texture's face at given index and level, for depth textures.
950  *
951  *  @param gl                 GL functions
952  *  @param cube_face          Index of cube map's face
953  *  @param element_index      Index of element in array
954  *  @param mipmap_level       Mipmap level
955  *  @param n_elements         Number of elements in array
956  *  @param n_mipmap_levels    Number of mipmap levels
957  *  @param texture_format     Texture format
958  *  @param texture_width      Texture width
959  *  @param texture_height     Texture height
960  **/
prepareDataForDepthFloatTexture(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)961 void prepareDataForDepthFloatTexture(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
962                                      glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
963                                      glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
964                                      glw::GLsizei texture_height)
965 {
966     glw::GLfloat component = 0;
967 
968     getDepthComponent(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, component);
969 
970     prepareDataForTexture<glw::GLfloat, 1>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type,
971                                            texture_width, texture_height, &component);
972 }
973 
974 /** Prepare texture's face at given index and level, for stencil textures.
975  *
976  *  @param gl                 GL functions
977  *  @param cube_face          Index of cube map's face
978  *  @param element_index      Index of element in array
979  *  @param mipmap_level       Mipmap level
980  *  @param n_elements         Number of elements in array
981  *  @param n_mipmap_levels    Number of mipmap levels
982  *  @param texture_format     Texture format
983  *  @param texture_width      Texture width
984  *  @param texture_height     Texture height
985  **/
prepareDataForStencilUIntTexture(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)986 void prepareDataForStencilUIntTexture(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
987                                       glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
988                                       glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
989                                       glw::GLsizei texture_height)
990 {
991     glw::GLubyte component = 0;
992 
993     getStencilComponent(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, component);
994 
995     prepareDataForTexture<glw::GLubyte, 1>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type,
996                                            texture_width, texture_height, &component);
997 }
998 
999 /** Prepare texture's face at given index and level, for depth textures.
1000  *
1001  *  @param gl                 GL functions
1002  *  @param cube_face          Index of cube map's face
1003  *  @param element_index      Index of element in array
1004  *  @param mipmap_level       Mipmap level
1005  *  @param n_elements         Number of elements in array
1006  *  @param n_mipmap_levels    Number of mipmap levels
1007  *  @param texture_format     Texture format
1008  *  @param texture_width      Texture width
1009  *  @param texture_height     Texture height
1010  **/
prepareDepthTextureFace(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)1011 void prepareDepthTextureFace(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
1012                              glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
1013                              glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
1014                              glw::GLsizei texture_height)
1015 {
1016     switch (texture_type)
1017     {
1018     case GL_FLOAT:
1019         prepareDataForDepthFloatTexture(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
1020                                         texture_format, texture_type, texture_width, texture_height);
1021         break;
1022 
1023     default:
1024         TCU_FAIL("Not implemented case !");
1025     }
1026 }
1027 
1028 /** Prepare grad_x vector for given texture_coordinates
1029  *
1030  *  @param grad_x              Storage for grad_x
1031  *  @param face                Cube map's face index
1032  *  @param texture_coordinates Texture coordinate
1033  *  @param width               Image width
1034  **/
prepareGradXForFace(glw::GLfloat * grad_x,glw::GLuint face,glw::GLfloat * texture_coordinates,glw::GLuint width)1035 void prepareGradXForFace(glw::GLfloat *grad_x, glw::GLuint face, glw::GLfloat *texture_coordinates, glw::GLuint width)
1036 {
1037     static const glw::GLuint n_points_per_face                = 9;
1038     static const glw::GLuint n_texture_coordinates_components = 4;
1039     static const glw::GLuint n_grad_components                = 4;
1040 
1041     for (glw::GLuint i = 0; i < n_points_per_face; i += 2)
1042     {
1043         const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
1044         const glw::GLuint grad_offset                = i * n_grad_components;
1045 
1046         getRightNeighbour(texture_coordinates + texture_coordinates_offset, face, 1, width, grad_x + grad_offset);
1047     }
1048 
1049     for (glw::GLuint i = 1; i < n_points_per_face; i += 2)
1050     {
1051         const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
1052         const glw::GLuint grad_offset                = i * n_grad_components;
1053 
1054         getRightNeighbour(texture_coordinates + texture_coordinates_offset, face, 4 * width, width,
1055                           grad_x + grad_offset);
1056     }
1057 
1058     for (glw::GLuint i = 0; i < n_points_per_face; ++i)
1059     {
1060         const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
1061         const glw::GLuint grad_offset                = i * n_grad_components;
1062 
1063         vectorSubtractInPlace<3>(grad_x + grad_offset, texture_coordinates + texture_coordinates_offset);
1064     }
1065 }
1066 
1067 /** Prepare grad_y vector for given texture_coordinates
1068  *
1069  *  @param grad_y              Storage for grad_x
1070  *  @param face                Cube map's face index
1071  *  @param texture_coordinates Texture coordinate
1072  *  @param width               Image width
1073  **/
prepareGradYForFace(glw::GLfloat * grad_y,glw::GLuint face,glw::GLfloat * texture_coordinates,glw::GLuint width)1074 void prepareGradYForFace(glw::GLfloat *grad_y, glw::GLuint face, glw::GLfloat *texture_coordinates, glw::GLuint width)
1075 {
1076     static const glw::GLuint n_points_per_face                = 9;
1077     static const glw::GLuint n_texture_coordinates_components = 4;
1078     static const glw::GLuint n_grad_components                = 4;
1079 
1080     for (glw::GLuint i = 0; i < n_points_per_face; i += 2)
1081     {
1082         const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
1083         const glw::GLuint grad_offset                = i * n_grad_components;
1084 
1085         getTopNeighbour(texture_coordinates + texture_coordinates_offset, face, 1, width, grad_y + grad_offset);
1086     }
1087 
1088     for (glw::GLuint i = 1; i < n_points_per_face; i += 2)
1089     {
1090         const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
1091         const glw::GLuint grad_offset                = i * n_grad_components;
1092 
1093         getTopNeighbour(texture_coordinates + texture_coordinates_offset, face, 4 * width, width, grad_y + grad_offset);
1094     }
1095 
1096     for (glw::GLuint i = 0; i < n_points_per_face; ++i)
1097     {
1098         const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
1099         const glw::GLuint grad_offset                = i * n_grad_components;
1100 
1101         vectorSubtractInPlace<3>(grad_y + grad_offset, texture_coordinates + texture_coordinates_offset);
1102     }
1103 }
1104 
1105 /** Prepare "lods" for face.
1106  *  Pattern is: B T B
1107  *              T B T
1108  *              B T B
1109  *  B - base, T - top
1110  *
1111  *  @param lods            Storage for lods
1112  *  @param n_mipmap_levels Number of mipmap levels
1113  **/
prepareLodForFace(glw::GLfloat * lods,glw::GLuint n_mipmap_levels)1114 void prepareLodForFace(glw::GLfloat *lods, glw::GLuint n_mipmap_levels)
1115 {
1116     const glw::GLfloat base_level = 0.0f;
1117     const glw::GLfloat top_level  = (glw::GLfloat)(n_mipmap_levels - 1);
1118 
1119     lods[0] = base_level;
1120     lods[1] = top_level;
1121     lods[2] = base_level;
1122     lods[3] = top_level;
1123     lods[4] = base_level;
1124     lods[5] = top_level;
1125     lods[6] = base_level;
1126     lods[7] = top_level;
1127     lods[8] = base_level;
1128 }
1129 
1130 /** Prepare position for vertices. Each vertex is placed on a unique pixel of output image.
1131  *
1132  *  @param positions     Storage for positions
1133  *  @param cube_face     Texture coordinate
1134  *  @param element_index Index of element in array
1135  *  @param n_layers      Image width
1136  **/
preparePositionForFace(glw::GLfloat * positions,glw::GLuint cube_face,glw::GLuint element_index,glw::GLuint n_layers)1137 void preparePositionForFace(glw::GLfloat *positions, glw::GLuint cube_face, glw::GLuint element_index,
1138                             glw::GLuint n_layers)
1139 {
1140     static const glw::GLuint x_offset_per_face = 3;
1141     static const glw::GLuint n_faces           = 6;
1142 
1143     const glw::GLuint x_offset_for_face = (element_index * n_faces + cube_face) * x_offset_per_face;
1144 
1145     const glw::GLfloat x_step     = 2.0f / ((glw::GLfloat)(n_layers * 3));
1146     const glw::GLfloat x_mid_step = x_step / 2.0f;
1147     const glw::GLfloat y_step     = 2.0f / 3.0f;
1148     const glw::GLfloat y_mid_step = y_step / 2.0f;
1149 
1150     const glw::GLfloat x_left   = -1.0f + x_mid_step + ((glw::GLfloat)x_offset_for_face) * x_step;
1151     const glw::GLfloat x_middle = x_left + x_step;
1152     const glw::GLfloat x_right  = x_middle + x_step;
1153 
1154     const glw::GLfloat y_top    = 1.0f - y_mid_step;
1155     const glw::GLfloat y_middle = y_top - y_step;
1156     const glw::GLfloat y_bottom = y_middle - y_step;
1157 
1158     vectorSet4(positions, 0, x_left, y_top, 0.0f, 1.0f);
1159     vectorSet4(positions, 1, x_middle, y_top, 0.0f, 1.0f);
1160     vectorSet4(positions, 2, x_right, y_top, 0.0f, 1.0f);
1161     vectorSet4(positions, 3, x_left, y_middle, 0.0f, 1.0f);
1162     vectorSet4(positions, 4, x_middle, y_middle, 0.0f, 1.0f);
1163     vectorSet4(positions, 5, x_right, y_middle, 0.0f, 1.0f);
1164     vectorSet4(positions, 6, x_left, y_bottom, 0.0f, 1.0f);
1165     vectorSet4(positions, 7, x_middle, y_bottom, 0.0f, 1.0f);
1166     vectorSet4(positions, 8, x_right, y_bottom, 0.0f, 1.0f);
1167 }
1168 
1169 /** Prepare "refZ" for face.
1170  *  Pattern is: - = +
1171  *              - = +
1172  *              - = +
1173  *  '-' - lower than depth
1174  *   =  - eqaul to depth
1175  *   +  - higher thatn depth
1176  *
1177  *  @param refZs     Storage for refZs
1178  *  @param n_mipmaps Number of mipmap levels
1179  *  @param face      Cube map's face index
1180  *  @param layer     Index of element in array
1181  *  @param n_layers  Number of elements in array
1182  **/
prepareRefZForFace(glw::GLfloat * refZs,glw::GLuint n_mipmaps,glw::GLuint face,glw::GLuint layer,glw::GLuint n_layers)1183 void prepareRefZForFace(glw::GLfloat *refZs, glw::GLuint n_mipmaps, glw::GLuint face, glw::GLuint layer,
1184                         glw::GLuint n_layers)
1185 {
1186     glw::GLfloat expected_base_depth_value = 0;
1187     glw::GLfloat expected_top_depth_value  = 0;
1188 
1189     /* Get depth for top and base levles */
1190     getDepthComponent(face, layer, 0, n_layers, n_mipmaps, expected_base_depth_value);
1191     getDepthComponent(face, layer, n_mipmaps - 1, n_layers, n_mipmaps, expected_top_depth_value);
1192 
1193     /* Use step of 10% */
1194     const glw::GLfloat base_depth_step = expected_base_depth_value * 0.1f;
1195     const glw::GLfloat top_depth_step  = expected_top_depth_value * 0.1f;
1196 
1197     /* Top row */
1198     refZs[0] = expected_base_depth_value - base_depth_step;
1199     refZs[1] = expected_top_depth_value;
1200     refZs[2] = expected_base_depth_value + base_depth_step;
1201 
1202     /* Center row */
1203     refZs[3] = expected_top_depth_value - top_depth_step;
1204     refZs[4] = expected_base_depth_value;
1205     refZs[5] = expected_top_depth_value + top_depth_step;
1206 
1207     /* Bottom row */
1208     refZs[6] = expected_base_depth_value - base_depth_step;
1209     refZs[7] = expected_top_depth_value;
1210     refZs[8] = expected_base_depth_value + base_depth_step;
1211 }
1212 
1213 /** Prepare texture's face at given index and level, for rgba integer textures.
1214  *
1215  *  @param gl                 GL functions
1216  *  @param cube_face          Index of cube map's face
1217  *  @param element_index      Index of element in array
1218  *  @param mipmap_level       Mipmap level
1219  *  @param n_elements         Number of elements in array
1220  *  @param n_mipmap_levels    Number of mipmap levels
1221  *  @param texture_format     Texture format
1222  *  @param texture_width      Texture width
1223  *  @param texture_height     Texture height
1224  **/
prepareRGBAIntegerTextureFace(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)1225 void prepareRGBAIntegerTextureFace(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
1226                                    glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
1227                                    glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
1228                                    glw::GLsizei texture_height)
1229 {
1230     switch (texture_type)
1231     {
1232     case GL_UNSIGNED_INT:
1233         prepareDataForColorIntTexture<glw::GLuint>(gl, cube_face, element_index, mipmap_level, n_elements,
1234                                                    n_mipmap_levels, texture_format, texture_type, texture_width,
1235                                                    texture_height);
1236         break;
1237 
1238     case GL_INT:
1239         prepareDataForColorIntTexture<glw::GLint>(gl, cube_face, element_index, mipmap_level, n_elements,
1240                                                   n_mipmap_levels, texture_format, texture_type, texture_width,
1241                                                   texture_height);
1242         break;
1243 
1244     default:
1245         TCU_FAIL("Not implemented case !");
1246     }
1247 }
1248 
1249 /** Prepare texture's face at given index and level, for rgba textures.
1250  *
1251  *  @param gl                 GL functions
1252  *  @param cube_face          Index of cube map's face
1253  *  @param element_index      Index of element in array
1254  *  @param mipmap_level       Mipmap level
1255  *  @param n_elements         Number of elements in array
1256  *  @param n_mipmap_levels    Number of mipmap levels
1257  *  @param texture_format     Texture format
1258  *  @param texture_width      Texture width
1259  *  @param texture_height     Texture height
1260  **/
prepareRGBATextureFace(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)1261 void prepareRGBATextureFace(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
1262                             glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
1263                             glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
1264                             glw::GLsizei texture_height)
1265 {
1266     switch (texture_type)
1267     {
1268     case GL_UNSIGNED_BYTE:
1269         prepareDataForColorIntTexture<glw::GLubyte>(gl, cube_face, element_index, mipmap_level, n_elements,
1270                                                     n_mipmap_levels, texture_format, texture_type, texture_width,
1271                                                     texture_height);
1272         break;
1273 
1274     case GL_FLOAT:
1275         prepareDataForColorFloatTexture(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
1276                                         texture_format, texture_type, texture_width, texture_height);
1277         break;
1278 
1279     default:
1280         TCU_FAIL("Not implemented case !");
1281     }
1282 }
1283 
1284 /** Prepare texture's face at given index and level, for stencil textures.
1285  *
1286  *  @param gl                 GL functions
1287  *  @param cube_face          Index of cube map's face
1288  *  @param element_index      Index of element in array
1289  *  @param mipmap_level       Mipmap level
1290  *  @param n_elements         Number of elements in array
1291  *  @param n_mipmap_levels    Number of mipmap levels
1292  *  @param texture_format     Texture format
1293  *  @param texture_width      Texture width
1294  *  @param texture_height     Texture height
1295  **/
prepareStencilTextureFace(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)1296 void prepareStencilTextureFace(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
1297                                glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
1298                                glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
1299                                glw::GLsizei texture_height)
1300 {
1301     switch (texture_type)
1302     {
1303     case GL_UNSIGNED_BYTE:
1304         prepareDataForStencilUIntTexture(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
1305                                          texture_format, texture_type, texture_width, texture_height);
1306         break;
1307 
1308     default:
1309         TCU_FAIL("Not implemented case !");
1310     }
1311 }
1312 
1313 /** Prepare texture coordinates for vertices.
1314  *  Each vertex has unique value. 4 corners, centers of 4 edges and central points are selected.
1315  *
1316  *  @param positions     Storage for positions
1317  *  @param cube_face     Texture coordinate
1318  *  @param element_index Index of element in array
1319  *  @param n_layers      Image width
1320  **/
prepareTextureCoordinatesForFace(glw::GLfloat * data,glw::GLuint width,glw::GLuint height,glw::GLfloat layer,glw::GLuint face)1321 void prepareTextureCoordinatesForFace(glw::GLfloat *data, glw::GLuint width, glw::GLuint height, glw::GLfloat layer,
1322                                       glw::GLuint face)
1323 {
1324     const glw::GLfloat x_range = (glw::GLfloat)width;
1325     const glw::GLfloat y_range = (glw::GLfloat)height;
1326 
1327     const glw::GLfloat x_step = 2.0f / x_range;
1328     const glw::GLfloat y_step = 2.0f / y_range;
1329 
1330     const glw::GLfloat x_mid_step = x_step / 2.0f;
1331     const glw::GLfloat y_mid_step = y_step / 2.0f;
1332 
1333     const glw::GLfloat left     = -1.0f + x_mid_step;
1334     const glw::GLfloat right    = 1.0f - x_mid_step;
1335     const glw::GLfloat top      = 1.0f - y_mid_step;
1336     const glw::GLfloat bottom   = -1.0f + y_mid_step;
1337     const glw::GLfloat middle   = 0.0f;
1338     const glw::GLfloat negative = -1.0f;
1339     const glw::GLfloat positive = 1.0f;
1340 
1341     switch (face)
1342     {
1343     case 0:
1344         vectorSet4(data, 0, positive, left, top, layer);
1345         vectorSet4(data, 1, positive, middle, top, layer);
1346         vectorSet4(data, 2, positive, right, top, layer);
1347         vectorSet4(data, 3, positive, left, middle, layer);
1348         vectorSet4(data, 4, positive, middle, middle, layer);
1349         vectorSet4(data, 5, positive, right, middle, layer);
1350         vectorSet4(data, 6, positive, left, bottom, layer);
1351         vectorSet4(data, 7, positive, middle, bottom, layer);
1352         vectorSet4(data, 8, positive, right, bottom, layer);
1353         break;
1354     case 1:
1355         vectorSet4(data, 0, negative, left, top, layer);
1356         vectorSet4(data, 1, negative, middle, top, layer);
1357         vectorSet4(data, 2, negative, right, top, layer);
1358         vectorSet4(data, 3, negative, left, middle, layer);
1359         vectorSet4(data, 4, negative, middle, middle, layer);
1360         vectorSet4(data, 5, negative, right, middle, layer);
1361         vectorSet4(data, 6, negative, left, bottom, layer);
1362         vectorSet4(data, 7, negative, middle, bottom, layer);
1363         vectorSet4(data, 8, negative, right, bottom, layer);
1364         break;
1365     case 2:
1366         vectorSet4(data, 0, left, positive, top, layer);
1367         vectorSet4(data, 1, middle, positive, top, layer);
1368         vectorSet4(data, 2, right, positive, top, layer);
1369         vectorSet4(data, 3, left, positive, middle, layer);
1370         vectorSet4(data, 4, middle, positive, middle, layer);
1371         vectorSet4(data, 5, right, positive, middle, layer);
1372         vectorSet4(data, 6, left, positive, bottom, layer);
1373         vectorSet4(data, 7, middle, positive, bottom, layer);
1374         vectorSet4(data, 8, right, positive, bottom, layer);
1375         break;
1376     case 3:
1377         vectorSet4(data, 0, left, negative, top, layer);
1378         vectorSet4(data, 1, middle, negative, top, layer);
1379         vectorSet4(data, 2, right, negative, top, layer);
1380         vectorSet4(data, 3, left, negative, middle, layer);
1381         vectorSet4(data, 4, middle, negative, middle, layer);
1382         vectorSet4(data, 5, right, negative, middle, layer);
1383         vectorSet4(data, 6, left, negative, bottom, layer);
1384         vectorSet4(data, 7, middle, negative, bottom, layer);
1385         vectorSet4(data, 8, right, negative, bottom, layer);
1386         break;
1387     case 4:
1388         vectorSet4(data, 0, left, top, positive, layer);
1389         vectorSet4(data, 1, middle, top, positive, layer);
1390         vectorSet4(data, 2, right, top, positive, layer);
1391         vectorSet4(data, 3, left, middle, positive, layer);
1392         vectorSet4(data, 4, middle, middle, positive, layer);
1393         vectorSet4(data, 5, right, middle, positive, layer);
1394         vectorSet4(data, 6, left, bottom, positive, layer);
1395         vectorSet4(data, 7, middle, bottom, positive, layer);
1396         vectorSet4(data, 8, right, bottom, positive, layer);
1397         break;
1398     case 5:
1399         vectorSet4(data, 0, left, top, negative, layer);
1400         vectorSet4(data, 1, middle, top, negative, layer);
1401         vectorSet4(data, 2, right, top, negative, layer);
1402         vectorSet4(data, 3, left, middle, negative, layer);
1403         vectorSet4(data, 4, middle, middle, negative, layer);
1404         vectorSet4(data, 5, right, middle, negative, layer);
1405         vectorSet4(data, 6, left, bottom, negative, layer);
1406         vectorSet4(data, 7, middle, bottom, negative, layer);
1407         vectorSet4(data, 8, right, bottom, negative, layer);
1408         break;
1409     }
1410 
1411     vectorNormalize<3, 4>(data, 0);
1412     vectorNormalize<3, 4>(data, 1);
1413     vectorNormalize<3, 4>(data, 2);
1414     vectorNormalize<3, 4>(data, 3);
1415     vectorNormalize<3, 4>(data, 4);
1416     vectorNormalize<3, 4>(data, 5);
1417     vectorNormalize<3, 4>(data, 6);
1418     vectorNormalize<3, 4>(data, 7);
1419     vectorNormalize<3, 4>(data, 8);
1420 }
1421 
1422 /** Prepare texture coordinates for vertices. For sampling with textureGather routine.
1423  *  Each vertex has unique value. 4 corners, centers of 4 edges and central points are selected.
1424  *
1425  *  @param positions     Storage for positions
1426  *  @param cube_face     Texture coordinate
1427  *  @param element_index Index of element in array
1428  *  @param n_layers      Image width
1429  **/
prepareTextureCoordinatesForGatherForFace(glw::GLfloat * data,glw::GLuint width,glw::GLuint height,glw::GLfloat layer,glw::GLuint face)1430 void prepareTextureCoordinatesForGatherForFace(glw::GLfloat *data, glw::GLuint width, glw::GLuint height,
1431                                                glw::GLfloat layer, glw::GLuint face)
1432 {
1433     const glw::GLfloat x_range = (glw::GLfloat)width;
1434     const glw::GLfloat y_range = (glw::GLfloat)height;
1435 
1436     const glw::GLfloat x_step = 2.0f / x_range;
1437     const glw::GLfloat y_step = 2.0f / y_range;
1438 
1439     const glw::GLfloat x_mid_step = x_step / 2.0f;
1440     const glw::GLfloat y_mid_step = y_step / 2.0f;
1441 
1442     const glw::GLfloat left     = -1.0f + x_mid_step + x_step;
1443     const glw::GLfloat right    = 1.0f - x_mid_step - x_step;
1444     const glw::GLfloat top      = 1.0f - y_mid_step - y_step;
1445     const glw::GLfloat bottom   = -1.0f + y_mid_step + y_step;
1446     const glw::GLfloat middle   = 0.0f;
1447     const glw::GLfloat negative = -1.0f;
1448     const glw::GLfloat positive = 1.0f;
1449 
1450     switch (face)
1451     {
1452     case 0:
1453         vectorSet4(data, 0, positive, left, top, layer);
1454         vectorSet4(data, 1, positive, middle, top, layer);
1455         vectorSet4(data, 2, positive, right, top, layer);
1456         vectorSet4(data, 3, positive, left, middle, layer);
1457         vectorSet4(data, 4, positive, middle, middle, layer);
1458         vectorSet4(data, 5, positive, right, middle, layer);
1459         vectorSet4(data, 6, positive, left, bottom, layer);
1460         vectorSet4(data, 7, positive, middle, bottom, layer);
1461         vectorSet4(data, 8, positive, right, bottom, layer);
1462         break;
1463     case 1:
1464         vectorSet4(data, 0, negative, left, top, layer);
1465         vectorSet4(data, 1, negative, middle, top, layer);
1466         vectorSet4(data, 2, negative, right, top, layer);
1467         vectorSet4(data, 3, negative, left, middle, layer);
1468         vectorSet4(data, 4, negative, middle, middle, layer);
1469         vectorSet4(data, 5, negative, right, middle, layer);
1470         vectorSet4(data, 6, negative, left, bottom, layer);
1471         vectorSet4(data, 7, negative, middle, bottom, layer);
1472         vectorSet4(data, 8, negative, right, bottom, layer);
1473         break;
1474     case 2:
1475         vectorSet4(data, 0, left, positive, top, layer);
1476         vectorSet4(data, 1, middle, positive, top, layer);
1477         vectorSet4(data, 2, right, positive, top, layer);
1478         vectorSet4(data, 3, left, positive, middle, layer);
1479         vectorSet4(data, 4, middle, positive, middle, layer);
1480         vectorSet4(data, 5, right, positive, middle, layer);
1481         vectorSet4(data, 6, left, positive, bottom, layer);
1482         vectorSet4(data, 7, middle, positive, bottom, layer);
1483         vectorSet4(data, 8, right, positive, bottom, layer);
1484         break;
1485     case 3:
1486         vectorSet4(data, 0, left, negative, top, layer);
1487         vectorSet4(data, 1, middle, negative, top, layer);
1488         vectorSet4(data, 2, right, negative, top, layer);
1489         vectorSet4(data, 3, left, negative, middle, layer);
1490         vectorSet4(data, 4, middle, negative, middle, layer);
1491         vectorSet4(data, 5, right, negative, middle, layer);
1492         vectorSet4(data, 6, left, negative, bottom, layer);
1493         vectorSet4(data, 7, middle, negative, bottom, layer);
1494         vectorSet4(data, 8, right, negative, bottom, layer);
1495         break;
1496     case 4:
1497         vectorSet4(data, 0, left, top, positive, layer);
1498         vectorSet4(data, 1, middle, top, positive, layer);
1499         vectorSet4(data, 2, right, top, positive, layer);
1500         vectorSet4(data, 3, left, middle, positive, layer);
1501         vectorSet4(data, 4, middle, middle, positive, layer);
1502         vectorSet4(data, 5, right, middle, positive, layer);
1503         vectorSet4(data, 6, left, bottom, positive, layer);
1504         vectorSet4(data, 7, middle, bottom, positive, layer);
1505         vectorSet4(data, 8, right, bottom, positive, layer);
1506         break;
1507     case 5:
1508         vectorSet4(data, 0, left, top, negative, layer);
1509         vectorSet4(data, 1, middle, top, negative, layer);
1510         vectorSet4(data, 2, right, top, negative, layer);
1511         vectorSet4(data, 3, left, middle, negative, layer);
1512         vectorSet4(data, 4, middle, middle, negative, layer);
1513         vectorSet4(data, 5, right, middle, negative, layer);
1514         vectorSet4(data, 6, left, bottom, negative, layer);
1515         vectorSet4(data, 7, middle, bottom, negative, layer);
1516         vectorSet4(data, 8, right, bottom, negative, layer);
1517         break;
1518     }
1519 
1520     vectorNormalize<3, 4>(data, 0);
1521     vectorNormalize<3, 4>(data, 1);
1522     vectorNormalize<3, 4>(data, 2);
1523     vectorNormalize<3, 4>(data, 3);
1524     vectorNormalize<3, 4>(data, 4);
1525     vectorNormalize<3, 4>(data, 5);
1526     vectorNormalize<3, 4>(data, 6);
1527     vectorNormalize<3, 4>(data, 7);
1528     vectorNormalize<3, 4>(data, 8);
1529 }
1530 
1531 /** Prepare texture's face at given index and level.
1532  *
1533  *  @param gl                 GL functions
1534  *  @param cube_face          Index of cube map's face
1535  *  @param element_index      Index of element in array
1536  *  @param mipmap_level       Mipmap level
1537  *  @param n_elements         Number of elements in array
1538  *  @param n_mipmap_levels    Number of mipmap levels
1539  *  @param texture_format     Texture format
1540  *  @param texture_width      Texture width
1541  *  @param texture_height     Texture height
1542  **/
prepareTextureFace(const glw::Functions & gl,glw::GLint cube_face,glw::GLint element_index,glw::GLint mipmap_level,glw::GLint n_elements,glw::GLint n_mipmap_levels,glw::GLenum texture_format,glw::GLenum texture_type,glw::GLsizei texture_width,glw::GLsizei texture_height)1543 void prepareTextureFace(const glw::Functions &gl, glw::GLint cube_face, glw::GLint element_index,
1544                         glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
1545                         glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
1546                         glw::GLsizei texture_height)
1547 {
1548     switch (texture_format)
1549     {
1550     case GL_RGBA:
1551         prepareRGBATextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, texture_format,
1552                                texture_type, texture_width, texture_height);
1553         break;
1554 
1555     case GL_RGBA_INTEGER:
1556         prepareRGBAIntegerTextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
1557                                       texture_format, texture_type, texture_width, texture_height);
1558         break;
1559 
1560     case GL_DEPTH_COMPONENT:
1561         prepareDepthTextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, texture_format,
1562                                 texture_type, texture_width, texture_height);
1563         break;
1564 
1565     case GL_STENCIL_INDEX:
1566         prepareStencilTextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
1567                                   texture_format, texture_type, texture_width, texture_height);
1568         break;
1569 
1570     default:
1571         TCU_FAIL("Not implemented case !");
1572     }
1573 }
1574 
1575 /** Verifies that all pixels rendered for specific face match expectations
1576  *
1577  *  @tparam T            Type of image component
1578  *  @tparam N_Components Number of image components
1579  *  @tparam Width        Width of single face
1580  *  @tparam Height       Height of single face
1581  *
1582  *  @param data            Rendered data
1583  *  @param cube_face       Index of face in array
1584  *  @param expected_values Expected values
1585  *  @param image_width     Widht of whole image
1586  **/
1587 template <typename T, unsigned int N_Components, unsigned int Width, unsigned int Height>
verifyFace(const T * data,const glw::GLuint cube_face,const T * expected_values,const glw::GLuint image_width)1588 bool verifyFace(const T *data, const glw::GLuint cube_face, const T *expected_values, const glw::GLuint image_width)
1589 {
1590     static const glw::GLuint size_of_pixel = N_Components;
1591 
1592     const glw::GLuint data_face_offset  = N_Components * Width * cube_face;
1593     const glw::GLuint exp_face_offset   = N_Components * Width * Height * cube_face;
1594     const glw::GLuint data_size_of_line = image_width * size_of_pixel;
1595     const glw::GLuint exp_size_of_line  = Width * size_of_pixel;
1596 
1597     for (glw::GLuint y = 0; y < Height; ++y)
1598     {
1599         const glw::GLuint data_line_offset = y * data_size_of_line;
1600         const glw::GLuint exp_line_offset  = y * exp_size_of_line;
1601 
1602         for (glw::GLuint x = 0; x < Width; ++x)
1603         {
1604             const glw::GLuint data_pixel_offset = data_line_offset + data_face_offset + x * size_of_pixel;
1605             const glw::GLuint exp_pixel_offset  = exp_line_offset + exp_face_offset + x * size_of_pixel;
1606 
1607             for (glw::GLuint component = 0; component < N_Components; ++component)
1608             {
1609                 if (data[data_pixel_offset + component] != expected_values[exp_pixel_offset + component])
1610                 {
1611                     return false;
1612                 }
1613             }
1614         }
1615     }
1616 
1617     return true;
1618 }
1619 
1620 /** Verifies that all rendered pixels match expectation
1621  *
1622  *  @tparam T            Type of image component
1623  *  @tparam N_Components Number of image components
1624  *  @tparam Width        Width of single face
1625  *  @tparam Height       Height of single face
1626  *
1627  *  @param data            Rendered data
1628  *  @param expected_values Expected values
1629  *  @param n_layers        Number of elements in array
1630  **/
1631 template <typename T, unsigned int N_Components, unsigned int Width, unsigned int Height>
verifyImage(const T * data,const T * expected_values,const glw::GLuint n_layers)1632 bool verifyImage(const T *data, const T *expected_values, const glw::GLuint n_layers)
1633 {
1634     static const glw::GLuint n_faces = 6;
1635 
1636     const glw::GLuint n_total_faces = n_layers * n_faces;
1637 
1638     for (glw::GLuint face = 0; face < n_total_faces; ++face)
1639     {
1640         if (false == verifyFace<T, N_Components, Width, Height>(data, face, expected_values, n_total_faces * Width))
1641         {
1642             return false;
1643         }
1644     }
1645 
1646     return true;
1647 }
1648 
1649 /** Verifies that all rendered pixels match expectation
1650  *
1651  *  @tparam T            Type of image component
1652  *  @tparam N_Components Number of image components
1653  *  @tparam Width        Width of single face
1654  *  @tparam Height       Height of single face
1655  *
1656  *  @param n_mipmap_levels Number of mipmap levels
1657  *  @param n_layers        Number of elements in array
1658  *  @param getComponents   Routine which is used to obtain components
1659  *  @param data            Rendered data
1660  **/
1661 template <typename T, unsigned int N_Components, unsigned int Width, unsigned int Height>
verifyResultImage(glw::GLuint n_mipmap_levels,glw::GLuint n_layers,void (* getComponents)(glw::GLuint pixel_index,glw::GLint cube_face,glw::GLint layer_index,glw::GLint n_layers,glw::GLint n_mipmap_levels,T * out_components),const glw::GLubyte * data)1662 bool verifyResultImage(glw::GLuint n_mipmap_levels, glw::GLuint n_layers,
1663                        void (*getComponents)(glw::GLuint pixel_index, glw::GLint cube_face, glw::GLint layer_index,
1664                                              glw::GLint n_layers, glw::GLint n_mipmap_levels, T *out_components),
1665                        const glw::GLubyte *data)
1666 {
1667     const glw::GLuint n_components          = N_Components;
1668     const glw::GLuint face_width            = Width;
1669     const glw::GLuint face_height           = Height;
1670     const glw::GLuint n_pixels_per_face     = face_width * face_height;
1671     const glw::GLuint n_components_per_face = n_pixels_per_face * n_components;
1672     const glw::GLuint n_faces               = 6;
1673     const glw::GLuint n_total_faces         = n_layers * n_faces;
1674     const glw::GLuint n_total_components    = n_total_faces * n_components_per_face;
1675     const T *result_image                   = (const T *)data;
1676 
1677     std::vector<T> expected_values;
1678     expected_values.resize(n_total_components);
1679 
1680     for (glw::GLuint layer = 0; layer < n_layers; ++layer)
1681     {
1682         const glw::GLuint layer_offset = layer * n_faces * n_components_per_face;
1683 
1684         for (glw::GLuint face = 0; face < n_faces; ++face)
1685         {
1686             const glw::GLuint face_offset = face * n_components_per_face + layer_offset;
1687 
1688             for (glw::GLuint pixel = 0; pixel < n_pixels_per_face; ++pixel)
1689             {
1690                 const glw::GLuint pixel_offset = pixel * n_components + face_offset;
1691 
1692                 T components[n_components];
1693 
1694                 getComponents(pixel, face, layer, n_layers, n_mipmap_levels, components);
1695 
1696                 for (glw::GLuint component = 0; component < n_components; ++component)
1697                 {
1698                     const glw::GLuint component_offset = pixel_offset + component;
1699 
1700                     expected_values[component_offset] = components[component];
1701                 }
1702             }
1703         }
1704     }
1705 
1706     return verifyImage<T, N_Components, Width, Height>(result_image, &expected_values[0], n_layers);
1707 }
1708 
1709 /** Constructor
1710  *
1711  * @param context       Test context
1712  * @param name          Test case's name
1713  * @param description   Test case's desricption
1714  **/
TextureCubeMapArraySamplingTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1715 TextureCubeMapArraySamplingTest::TextureCubeMapArraySamplingTest(Context &context, const ExtParameters &extParams,
1716                                                                  const char *name, const char *description)
1717     : TestCaseBase(context, extParams, name, description)
1718     , m_framebuffer_object_id(0)
1719     , compiled_shaders(0)
1720     , invalid_shaders(0)
1721     , linked_programs(0)
1722     , invalid_programs(0)
1723     , tested_cases(0)
1724     , failed_cases(0)
1725     , invalid_type_cases(0)
1726 {
1727     /* Prepare formats set */
1728     m_formats.push_back(formatDefinition(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, Float, "GL_RGBA8"));
1729     m_formats.push_back(formatDefinition(GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, false, Int, "GL_RGBA32I"));
1730     m_formats.push_back(formatDefinition(GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, false, UInt, "GL_RGBA32UI"));
1731 
1732     m_formats.push_back(formatDefinition(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false, GL_RGBA8, GL_RGBA,
1733                                          GL_UNSIGNED_BYTE, Depth, "GL_DEPTH_COMPONENT32F"));
1734     m_formats.push_back(formatDefinition(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, false, GL_R32UI,
1735                                          GL_RGBA_INTEGER, GL_UNSIGNED_INT, Stencil, "GL_STENCIL_INDEX8"));
1736 
1737     /* Prepare sampling functions set */
1738     m_functions.push_back(samplingFunctionDefinition(Texture, "Texture"));
1739     m_functions.push_back(samplingFunctionDefinition(TextureLod, "TextureLod"));
1740     m_functions.push_back(samplingFunctionDefinition(TextureGrad, "TextureGrad"));
1741     m_functions.push_back(samplingFunctionDefinition(TextureGather, "TextureGather"));
1742 
1743     /* Prepare mutabilities set */
1744     m_mutabilities.push_back(true);
1745     m_mutabilities.push_back(false);
1746 
1747     /* Prepare resolutions set */
1748     m_resolutions.push_back(resolutionDefinition(64, 64, 18));
1749     m_resolutions.push_back(resolutionDefinition(117, 117, 6));
1750     m_resolutions.push_back(resolutionDefinition(256, 256, 6));
1751     m_resolutions.push_back(resolutionDefinition(173, 173, 12));
1752 
1753     /* Prepare resolutions set for compressed formats */
1754     m_compressed_resolutions.push_back(resolutionDefinition(8, 8, 12));
1755     m_compressed_resolutions.push_back(resolutionDefinition(13, 13, 12));
1756 }
1757 
1758 /** Check if getActiveUniform and glGetProgramResourceiv returns correct type for cube array samplers.
1759  *
1760  *  @param program_id   Program id
1761  *  @param sampler_name_p Name of sampler
1762  *  @param sampler_type Expected type of sampler
1763  *
1764  *  @return Status. 1st LSB - glGetActiveUniform, second LSB glGetProgramResourceiv, 0 valid, 1 invalid.
1765  **/
checkUniformAndResourceApi(glw::GLuint program_id,const glw::GLchar * sampler_name_p,samplerType sampler_type)1766 glw::GLuint TextureCubeMapArraySamplingTest::checkUniformAndResourceApi(glw::GLuint program_id,
1767                                                                         const glw::GLchar *sampler_name_p,
1768                                                                         samplerType sampler_type)
1769 {
1770     /* GL functions */
1771     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1772 
1773     glw::GLenum expected_type              = 0;
1774     glw::GLuint index_getActiveUniform     = GL_INVALID_INDEX;
1775     glw::GLuint index_getProgramResourceiv = GL_INVALID_INDEX;
1776     glw::GLenum props                      = GL_TYPE;
1777     glw::GLuint result                     = 0;
1778     glw::GLchar *name                      = 0;
1779     glw::GLint size                        = 0;
1780     glw::GLenum type_getActiveUniform      = 0;
1781     glw::GLint type_getProgramResourceiv   = 0;
1782 
1783     // Get type by getActiveUniform
1784     gl.getUniformIndices(program_id, 1, &sampler_name_p, &index_getActiveUniform);
1785 
1786     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformIndices");
1787 
1788     if (GL_INVALID_INDEX == index_getActiveUniform)
1789     {
1790         throw tcu::InternalError("glGetUniformIndices: GL_INVALID_INDEX", "", __FILE__, __LINE__);
1791     }
1792 
1793     gl.getActiveUniform(program_id, index_getActiveUniform, 0, 0, &size, &type_getActiveUniform, name);
1794     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveUniform");
1795 
1796     // Get type by gl.getProgramResourceiv
1797     index_getProgramResourceiv = gl.getProgramResourceIndex(program_id, GL_UNIFORM, sampler_name_p);
1798 
1799     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex");
1800 
1801     if (GL_INVALID_INDEX == index_getProgramResourceiv)
1802     {
1803         throw tcu::InternalError("glGetProgramResourceIndex: GL_INVALID_INDEX", "", __FILE__, __LINE__);
1804     }
1805 
1806     gl.getProgramResourceiv(program_id, GL_UNIFORM, index_getProgramResourceiv, 1, &props, 1, 0,
1807                             &type_getProgramResourceiv);
1808     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv");
1809 
1810     // Verification
1811     switch (sampler_type)
1812     {
1813     case Float:
1814         expected_type = GL_SAMPLER_CUBE_MAP_ARRAY;
1815         break;
1816     case Int:
1817         expected_type = GL_INT_SAMPLER_CUBE_MAP_ARRAY;
1818         break;
1819     case UInt:
1820         expected_type = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
1821         break;
1822     case Depth:
1823         expected_type = GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW;
1824         break;
1825     case Stencil:
1826         expected_type = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
1827         break;
1828     }
1829 
1830     if (expected_type != type_getActiveUniform)
1831     {
1832         result |= m_get_type_api_status_uniform;
1833     }
1834     if (expected_type != (glw::GLuint)type_getProgramResourceiv)
1835     {
1836         result |= m_get_type_api_status_program_resource;
1837     }
1838 
1839     return result;
1840 }
1841 
1842 /** Compile shader
1843  *
1844  *  @param info Shader info
1845  **/
compile(shaderDefinition & info)1846 void TextureCubeMapArraySamplingTest::compile(shaderDefinition &info)
1847 {
1848     compiled_shaders += 1;
1849 
1850     if (false == info.compile())
1851     {
1852         invalid_shaders += 1;
1853 
1854         logCompilationLog(info);
1855     }
1856 }
1857 
1858 /** Execute compute shader
1859  *
1860  *  @param program_id Program id
1861  *  @param width      Width of result image
1862  *  @param height     Height of result image
1863  **/
dispatch(glw::GLuint program_id,glw::GLuint width,glw::GLuint height)1864 void TextureCubeMapArraySamplingTest::dispatch(glw::GLuint program_id, glw::GLuint width, glw::GLuint height)
1865 {
1866     (void)program_id;
1867 
1868     /* GL functions */
1869     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1870 
1871     gl.dispatchCompute(width, height, 1);
1872     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glDispatchCompute call.");
1873 }
1874 
1875 /** Execute render call
1876  *
1877  *  @param program_id     Program id
1878  *  @param primitive_type Type of primitive
1879  *  @param n_vertices     Number of vertices
1880  **/
draw(glw::GLuint program_id,glw::GLenum primitive_type,glw::GLuint n_vertices,glw::GLenum format)1881 void TextureCubeMapArraySamplingTest::draw(glw::GLuint program_id, glw::GLenum primitive_type, glw::GLuint n_vertices,
1882                                            glw::GLenum format)
1883 {
1884     (void)program_id;
1885 
1886     /* GL functions */
1887     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1888 
1889     const glw::GLenum framebuffer_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
1890     if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status)
1891     {
1892         throw tcu::InternalError("Framebuffer is incomplete", "", __FILE__, __LINE__);
1893     }
1894 
1895     switch (format)
1896     {
1897     case GL_RGBA32I:
1898     {
1899         const glw::GLint clearValue[4] = {255, 255, 255, 255};
1900         gl.clearBufferiv(GL_COLOR, 0, clearValue);
1901         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearBufferiv call.");
1902     }
1903     break;
1904     case GL_RGBA32UI:
1905     case GL_R32UI:
1906     {
1907         const glw::GLuint clearValue[4] = {255, 255, 255, 255};
1908         gl.clearBufferuiv(GL_COLOR, 0, clearValue);
1909         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearBufferuiv call.");
1910     }
1911     break;
1912     case GL_DEPTH_COMPONENT32F:
1913         gl.clearDepthf(1.0f);
1914         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearDepthf call.");
1915         break;
1916     case GL_STENCIL_INDEX8:
1917         gl.clearStencil(1);
1918         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearStencil call.");
1919         break;
1920 
1921     default:
1922         gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
1923         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearColor call.");
1924 
1925         gl.clear(GL_COLOR_BUFFER_BIT);
1926         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClear call.");
1927     }
1928 
1929     gl.drawArrays(primitive_type, 0, n_vertices);
1930     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glDrawArrays call.");
1931 }
1932 
1933 /** Get attributes specific for type of sampler
1934  *
1935  *  @param sampler_type              Type of sampler
1936  *  @param out_attribute_definitions Array of attributes
1937  *  @param out_n_attributes          Number of attributes
1938  **/
getAttributes(samplerType sampler_type,const attributeDefinition * & out_attribute_definitions,glw::GLuint & out_n_attributes)1939 void TextureCubeMapArraySamplingTest::getAttributes(samplerType sampler_type,
1940                                                     const attributeDefinition *&out_attribute_definitions,
1941                                                     glw::GLuint &out_n_attributes)
1942 {
1943     static attributeDefinition depth_attributes[] = {{attribute_refZ, type_float, RefZ, 1}};
1944 
1945     static const glw::GLuint n_depth_attributes = sizeof(depth_attributes) / sizeof(depth_attributes[0]);
1946 
1947     switch (sampler_type)
1948     {
1949     case Depth:
1950         out_attribute_definitions = depth_attributes;
1951         out_n_attributes          = n_depth_attributes;
1952         break;
1953     default:
1954         out_attribute_definitions = 0;
1955         out_n_attributes          = 0;
1956         break;
1957     }
1958 }
1959 
1960 /** Get attributes specific for sampling function
1961  *
1962  *  @param sampling_function         Sampling function
1963  *  @param out_attribute_definitions Array of attributes
1964  *  @param out_n_attributes          Number of attributes
1965  **/
getAttributes(samplingFunction sampling_function,const attributeDefinition * & out_attribute_definitions,glw::GLuint & out_n_attributes)1966 void TextureCubeMapArraySamplingTest::getAttributes(samplingFunction sampling_function,
1967                                                     const attributeDefinition *&out_attribute_definitions,
1968                                                     glw::GLuint &out_n_attributes)
1969 {
1970     static attributeDefinition texture_attributes[] = {
1971         {attribute_texture_coordinate, type_vec4, TextureCoordinates, 0}};
1972 
1973     static attributeDefinition textureLod_attributes[] = {
1974         {attribute_texture_coordinate, type_vec4, TextureCoordinates, 0}, {attribute_lod, type_float, Lod, 1}};
1975 
1976     static attributeDefinition textureGrad_attributes[] = {
1977         {attribute_texture_coordinate, type_vec4, TextureCoordinates, 0},
1978         {attribute_grad_x, type_vec3, GradX, 1},
1979         {attribute_grad_y, type_vec3, GradY, 2}};
1980 
1981     static attributeDefinition textureGather_attributes[] = {
1982         {attribute_texture_coordinate, type_vec4, TextureCoordinatesForGather, 0}};
1983 
1984     static const glw::GLuint n_texture_attributes    = sizeof(texture_attributes) / sizeof(texture_attributes[0]);
1985     static const glw::GLuint n_textureLod_attributes = sizeof(textureLod_attributes) / sizeof(textureLod_attributes[0]);
1986     static const glw::GLuint n_textureGrad_attributes =
1987         sizeof(textureGrad_attributes) / sizeof(textureGrad_attributes[0]);
1988     static const glw::GLuint n_textureGather_attributes =
1989         sizeof(textureGather_attributes) / sizeof(textureGather_attributes[0]);
1990 
1991     switch (sampling_function)
1992     {
1993     case Texture:
1994         out_attribute_definitions = texture_attributes;
1995         out_n_attributes          = n_texture_attributes;
1996         break;
1997     case TextureLod:
1998         out_attribute_definitions = textureLod_attributes;
1999         out_n_attributes          = n_textureLod_attributes;
2000         break;
2001     case TextureGrad:
2002         out_attribute_definitions = textureGrad_attributes;
2003         out_n_attributes          = n_textureGrad_attributes;
2004         break;
2005     case TextureGather:
2006         out_attribute_definitions = textureGather_attributes;
2007         out_n_attributes          = n_textureGather_attributes;
2008         break;
2009     }
2010 }
2011 
2012 /** Get information about color type for type of sampler
2013  *
2014  *  @param sampler_type           Type of sampler
2015  *  @param out_color_type         Type used for color storage
2016  *  @param out_interpolation_type Type of interpolation
2017  *  @param out_sampler_type       Type of sampler
2018  *  @param out_n_components       Number of components in color
2019  *  @param out_is_shadow          If shadow sampler
2020  **/
getColorType(samplerType sampler_type,const glw::GLchar * & out_color_type,const glw::GLchar * & out_interpolation_type,const glw::GLchar * & out_sampler_type,glw::GLuint & out_n_components,bool & out_is_shadow)2021 void TextureCubeMapArraySamplingTest::getColorType(samplerType sampler_type, const glw::GLchar *&out_color_type,
2022                                                    const glw::GLchar *&out_interpolation_type,
2023                                                    const glw::GLchar *&out_sampler_type, glw::GLuint &out_n_components,
2024                                                    bool &out_is_shadow)
2025 {
2026     switch (sampler_type)
2027     {
2028     case Float:
2029         out_color_type         = type_vec4;
2030         out_interpolation_type = "";
2031         out_sampler_type       = sampler_float;
2032         out_n_components       = 4;
2033         out_is_shadow          = false;
2034         break;
2035     case Int:
2036         out_color_type         = type_ivec4;
2037         out_interpolation_type = interpolation_flat;
2038         out_sampler_type       = sampler_int;
2039         out_n_components       = 4;
2040         out_is_shadow          = false;
2041         break;
2042     case UInt:
2043         out_color_type         = type_uvec4;
2044         out_interpolation_type = interpolation_flat;
2045         out_sampler_type       = sampler_uint;
2046         out_n_components       = 4;
2047         out_is_shadow          = false;
2048         break;
2049     case Depth:
2050         out_color_type         = type_float;
2051         out_interpolation_type = "";
2052         out_sampler_type       = sampler_depth;
2053         out_n_components       = 1;
2054         out_is_shadow          = true;
2055         break;
2056     case Stencil:
2057         out_color_type         = type_uint;
2058         out_interpolation_type = interpolation_flat;
2059         out_sampler_type       = sampler_uint;
2060         out_n_components       = 1;
2061         out_is_shadow          = false;
2062         break;
2063     }
2064 }
2065 
2066 /** Get information about color type for type of sampler
2067  *
2068  *  @param sampler_type           Type of sampler
2069  *  @param out_color_type         Type used for color storage
2070  *  @param out_interpolation_type Type of interpolation
2071  *  @param out_sampler_type       Type of sampler
2072  *  @param out_image_type         Type of image
2073  *  @param out_n_components       Number of components in color
2074  *  @param out_is_shadow          If shadow sampler
2075  **/
getColorType(samplerType sampler_type,const glw::GLchar * & out_color_type,const glw::GLchar * & out_interpolation_type,const glw::GLchar * & out_sampler_type,const glw::GLchar * & out_image_type,const glw::GLchar * & out_image_layout,glw::GLuint & out_n_components,bool & out_is_shadow)2076 void TextureCubeMapArraySamplingTest::getColorType(samplerType sampler_type, const glw::GLchar *&out_color_type,
2077                                                    const glw::GLchar *&out_interpolation_type,
2078                                                    const glw::GLchar *&out_sampler_type,
2079                                                    const glw::GLchar *&out_image_type,
2080                                                    const glw::GLchar *&out_image_layout, glw::GLuint &out_n_components,
2081                                                    bool &out_is_shadow)
2082 {
2083     getColorType(sampler_type, out_color_type, out_interpolation_type, out_sampler_type, out_n_components,
2084                  out_is_shadow);
2085 
2086     switch (sampler_type)
2087     {
2088     case Float:
2089         out_image_type   = image_float;
2090         out_image_layout = "rgba8";
2091         break;
2092     case Depth:
2093         out_image_type   = image_float;
2094         out_image_layout = "rgba8";
2095         break;
2096     case Int:
2097         out_image_type   = image_int;
2098         out_image_layout = "rgba32i";
2099         break;
2100     case UInt:
2101         out_image_type   = image_uint;
2102         out_image_layout = "rgba32ui";
2103         break;
2104     case Stencil:
2105         out_image_type   = image_uint;
2106         out_image_layout = "r32ui";
2107         break;
2108     }
2109 }
2110 
2111 /** Prepare code for passthrough fragment shader
2112  *
2113  *  @param sampler_type             Type of sampler
2114  *  @param out_fragment_shader_code Storage for code
2115  **/
getPassThroughFragmentShaderCode(samplerType sampler_type,std::string & out_fragment_shader_code)2116 void TextureCubeMapArraySamplingTest::getPassThroughFragmentShaderCode(samplerType sampler_type,
2117                                                                        std::string &out_fragment_shader_code)
2118 {
2119     std::stringstream stream;
2120     const glw::GLchar *color_type;
2121     const glw::GLchar *interpolation_type;
2122     const glw::GLchar *ignored_sampler_type;
2123     glw::GLuint ignored_n_components;
2124     bool ignored_is_shadow;
2125 
2126     /* Get type for color variables */
2127     getColorType(sampler_type, color_type, interpolation_type, ignored_sampler_type, ignored_n_components,
2128                  ignored_is_shadow);
2129 
2130     /* Preamble */
2131     stream << shader_code_preamble << shader_precision << "/* Pass through fragment shader */" << std::endl;
2132 
2133     /* in vec4 fs_in_color */
2134     stream << interpolation_type << shader_input << color_type << fragment_shader_input << ";" << std::endl;
2135 
2136     stream << std::endl;
2137 
2138     /* layout(location = 0) out vec4 fs_out_color */
2139     stream << shader_layout << shader_output << color_type << fragment_shader_output << ";" << std::endl;
2140 
2141     stream << std::endl;
2142 
2143     /* Body */
2144     stream << fragment_shader_pass_through_body_code << std::endl;
2145 
2146     /* Store result */
2147     out_fragment_shader_code = stream.str();
2148 }
2149 
2150 /** Prepare code for passthrough tesselation control shader
2151  *
2152  *  @param sampler_type                        Type of sampler
2153  *  @param out_tesselation_control_shader_code Storage for code
2154  **/
getPassThroughTesselationControlShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_tesselation_control_shader_code)2155 void TextureCubeMapArraySamplingTest::getPassThroughTesselationControlShaderCode(
2156     const samplerType &sampler_type, const samplingFunction &sampling_function,
2157     std::string &out_tesselation_control_shader_code)
2158 {
2159     std::stringstream stream;
2160     glw::GLuint n_routine_attributes                         = 0;
2161     glw::GLuint n_type_attributes                            = 0;
2162     const attributeDefinition *routine_attribute_definitions = 0;
2163     const attributeDefinition *type_attribute_definitions    = 0;
2164 
2165     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2166     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2167 
2168     /* Preamble, extension : require  */
2169     stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
2170            << "/* Passthrough tesselation control shader */" << std::endl;
2171 
2172     /* layout(vertices = 1) out */
2173     stream << tesselation_control_shader_layout;
2174 
2175     /* in type attribute*/
2176     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2177     {
2178         stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
2179                << routine_attribute_definitions[i].name << "[];" << std::endl;
2180         stream << shader_output << routine_attribute_definitions[i].type << tesselation_control_shader_output
2181                << routine_attribute_definitions[i].name << "[];" << std::endl;
2182     }
2183     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2184     {
2185         stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
2186                << type_attribute_definitions[i].name << "[];" << std::endl;
2187         stream << shader_output << type_attribute_definitions[i].type << tesselation_control_shader_output
2188                << type_attribute_definitions[i].name << "[];" << std::endl;
2189     }
2190 
2191     /* Body */
2192     stream << tesselation_control_shader_sampling_body_code;
2193 
2194     /* tcs_out[gl_InvocationID] = vs_out[gl_InvocationID] */
2195     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2196     {
2197         stream << "    " << tesselation_control_shader_output << routine_attribute_definitions[i].name
2198                << "[gl_InvocationID] = " << vertex_shader_output << routine_attribute_definitions[i].name
2199                << "[gl_InvocationID];" << std::endl;
2200     }
2201 
2202     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2203     {
2204         stream << "    " << tesselation_control_shader_output << type_attribute_definitions[i].name
2205                << "[gl_InvocationID] = " << vertex_shader_output << type_attribute_definitions[i].name
2206                << "[gl_InvocationID];" << std::endl;
2207     }
2208 
2209     stream << "}" << std::endl << std::endl;
2210 
2211     /* Store result */
2212     out_tesselation_control_shader_code = stream.str();
2213 }
2214 
2215 /** Prepare code for passthrough tesselation evaluation shader
2216  *
2217  *  @param sampler_type                           Type of sampler
2218  *  @param out_tesselation_evaluation_shader_code Storage for code
2219  **/
getPassThroughTesselationEvaluationShaderCode(samplerType sampler_type,std::string & out_tesselation_evaluation_shader_code)2220 void TextureCubeMapArraySamplingTest::getPassThroughTesselationEvaluationShaderCode(
2221     samplerType sampler_type, std::string &out_tesselation_evaluation_shader_code)
2222 {
2223     const glw::GLchar *color_type           = 0;
2224     bool ignored_is_shadow                  = false;
2225     glw::GLuint ignored_n_components        = 0;
2226     const glw::GLchar *ignored_sampler_type = 0;
2227     const glw::GLchar *interpolation_type   = 0;
2228     std::stringstream stream;
2229 
2230     /* Get type for color variables */
2231     getColorType(sampler_type, color_type, interpolation_type, ignored_sampler_type, ignored_n_components,
2232                  ignored_is_shadow);
2233 
2234     /* Preamble, extension : require */
2235     stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
2236            << "/* Pass through tesselation evaluation shader */" << std::endl;
2237 
2238     /* layout(point_mode) in; */
2239     stream << tesselation_evaluation_shader_layout;
2240 
2241     /* in vec4 tes_in_color[] */
2242     stream << interpolation_type << shader_input << color_type << tesselation_evaluation_shader_input << "[];"
2243            << std::endl;
2244 
2245     stream << std::endl;
2246 
2247     /* out vec4 fs_in_color[] */
2248     stream << interpolation_type << shader_output << color_type << fragment_shader_input << ";" << std::endl;
2249 
2250     stream << std::endl;
2251 
2252     /* Body */
2253     stream << tesselation_evaluation_shader_pass_through_body_code << std::endl;
2254 
2255     /* Store result */
2256     out_tesselation_evaluation_shader_code = stream.str();
2257 }
2258 
2259 /** Prepare code for passthrough vertex shader
2260  *
2261  *  @param sampler_type           Type of sampler
2262  *  @param sampling_function      Type of sampling function
2263  *  @param out_vertex_shader_code Storage for code
2264  **/
getPassThroughVertexShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_vertex_shader_code)2265 void TextureCubeMapArraySamplingTest::getPassThroughVertexShaderCode(const samplerType &sampler_type,
2266                                                                      const samplingFunction &sampling_function,
2267                                                                      std::string &out_vertex_shader_code)
2268 {
2269     glw::GLuint n_routine_attributes                         = 0;
2270     glw::GLuint n_type_attributes                            = 0;
2271     const attributeDefinition *routine_attribute_definitions = 0;
2272     std::stringstream stream;
2273     const attributeDefinition *type_attribute_definitions = 0;
2274 
2275     /* Get attributes for sampling function */
2276     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2277     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2278 
2279     /* Preamble */
2280     stream << shader_code_preamble << "/* Pass through vertex shader */" << std::endl << shader_precision;
2281 
2282     /* in vec4 vs_in_position */
2283     stream << shader_input << type_vec4 << vertex_shader_input << vertex_shader_position << ";" << std::endl;
2284 
2285     /* in type vs_in_attribute */
2286     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2287     {
2288         stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_input
2289                << routine_attribute_definitions[i].name << ";" << std::endl;
2290     }
2291 
2292     /* in float vs_in_refZ */
2293     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2294     {
2295         stream << shader_input << type_attribute_definitions[i].type << vertex_shader_input
2296                << type_attribute_definitions[i].name << ";" << std::endl;
2297     }
2298 
2299     stream << std::endl;
2300 
2301     /* out type vs_out_attribute */
2302     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2303     {
2304         stream << shader_output << routine_attribute_definitions[i].type << vertex_shader_output
2305                << routine_attribute_definitions[i].name << ";" << std::endl;
2306     }
2307 
2308     /* out float vs_out_refZ */
2309     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2310     {
2311         stream << shader_output << type_attribute_definitions[i].type << vertex_shader_output
2312                << type_attribute_definitions[i].name << ";" << std::endl;
2313     }
2314 
2315     stream << std::endl;
2316 
2317     /* Body */
2318     stream << vertex_shader_body_code;
2319 
2320     /* vs_out = vs_in */
2321     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2322     {
2323         stream << "    " << vertex_shader_output << routine_attribute_definitions[i].name << " = "
2324                << vertex_shader_input << routine_attribute_definitions[i].name << ";" << std::endl;
2325     }
2326 
2327     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2328     {
2329         stream << "    " << vertex_shader_output << type_attribute_definitions[i].name << " = " << vertex_shader_input
2330                << type_attribute_definitions[i].name << ";" << std::endl;
2331     }
2332 
2333     stream << "}" << std::endl << std::endl;
2334 
2335     /* Store result */
2336     out_vertex_shader_code = stream.str();
2337 }
2338 
2339 /** Prepare code for sampling compute shader
2340  *
2341  *  @param sampler_type            Type of sampler
2342  *  @param sampling_function       Type of sampling function
2343  *  @param out_compute_shader_code Storage for code
2344  **/
getSamplingComputeShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_compute_shader_code)2345 void TextureCubeMapArraySamplingTest::getSamplingComputeShaderCode(const samplerType &sampler_type,
2346                                                                    const samplingFunction &sampling_function,
2347                                                                    std::string &out_compute_shader_code)
2348 {
2349     const glw::GLchar *color_type                            = 0;
2350     const glw::GLchar *image_type_str                        = 0;
2351     const glw::GLchar *image_layout_str                      = 0;
2352     const glw::GLchar *interpolation_type                    = 0;
2353     bool is_shadow_sampler                                   = false;
2354     glw::GLuint n_components                                 = 0;
2355     glw::GLuint n_routine_attributes                         = 0;
2356     glw::GLuint n_type_attributes                            = 0;
2357     const attributeDefinition *routine_attribute_definitions = 0;
2358     const attributeDefinition *type_attribute_definitions    = 0;
2359     const glw::GLchar *sampler_type_str                      = 0;
2360     std::string sampling_code;
2361     std::stringstream stream;
2362 
2363     /* Get attributes for sampling function */
2364     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2365     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2366 
2367     /* Get type for color variables */
2368     getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, image_type_str, image_layout_str,
2369                  n_components, is_shadow_sampler);
2370 
2371     /* Get sampling code */
2372     if (false == is_shadow_sampler)
2373     {
2374         getSamplingFunctionCall(sampling_function, color_type, n_components, compute_shader_param, 0,
2375                                 compute_shader_color, 0, sampler_name, sampling_code);
2376     }
2377     else
2378     {
2379         getShadowSamplingFunctionCall(sampling_function, color_type, n_components, compute_shader_param, 0,
2380                                       compute_shader_color, 0, sampler_name, sampling_code);
2381     }
2382 
2383     /* Preamble */
2384     stream << shader_code_preamble << shader_precision << "/* Sampling compute shader */" << std::endl;
2385 
2386     /* uniform samplerType sampler */
2387     stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
2388 
2389     /* uniform writeonly image2D image*/
2390     stream << "layout(" << image_layout_str << ") " << shader_uniform << shader_writeonly << "highp " << image_type_str
2391            << image_name << ";" << std::endl;
2392 
2393     /* layout(shared) buffer attribute { type attribute_data[]; }; */
2394     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2395     {
2396         stream << compute_shader_layout_binding << routine_attribute_definitions[i].binding << compute_shader_buffer
2397                << routine_attribute_definitions[i].name << std::endl;
2398 
2399         stream << "{\n";
2400         stream << "    " << routine_attribute_definitions[i].type << " " << routine_attribute_definitions[i].name
2401                << "_data[];\n";
2402         stream << "};\n";
2403     }
2404     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2405     {
2406         stream << compute_shader_layout_binding << type_attribute_definitions[i].binding << compute_shader_buffer
2407                << type_attribute_definitions[i].name << std::endl;
2408 
2409         stream << "{\n";
2410         stream << "    " << type_attribute_definitions[i].type << " " << type_attribute_definitions[i].name
2411                << "_data[];\n";
2412         stream << "};\n";
2413     }
2414 
2415     /* layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; */
2416     stream << compute_shader_layout << std::endl;
2417 
2418     /* main + body */
2419     stream << compute_shader_body;
2420 
2421     /* type cs_attribute = attribute_data[vertex_index] */
2422     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2423     {
2424         stream << "    " << routine_attribute_definitions[i].type << compute_shader_param
2425                << routine_attribute_definitions[i].name << " = " << routine_attribute_definitions[i].name
2426                << "_data[vertex_index];" << std::endl;
2427     }
2428     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2429     {
2430         stream << "    " << type_attribute_definitions[i].type << compute_shader_param
2431                << type_attribute_definitions[i].name << " = " << type_attribute_definitions[i].name
2432                << "_data[vertex_index];" << std::endl;
2433     }
2434 
2435     /* type color */
2436     stream << std::endl << "    " << color_type << compute_shader_color << ";" << std::endl;
2437 
2438     /* color = texture*/
2439     stream << std::endl << sampling_code << std::endl;
2440     //stream << std::endl << compute_shader_color << " = vec4(cs_grad_x, 255.0);" << std::endl;
2441 
2442     /* imageStore */
2443     stream << compute_shader_image_store;
2444     switch (n_components)
2445     {
2446     case 1:
2447         /* imageStore(image, image_coord, color.r);*/
2448         if (sampler_type == Depth)
2449         {
2450             stream << "vec4(" << compute_shader_color << ")";
2451         }
2452         else if (sampler_type == Stencil)
2453         {
2454             stream << "uvec4(" << compute_shader_color << ")";
2455         }
2456         else
2457         {
2458             // unexpected case
2459             DE_ASSERT(false);
2460         }
2461         break;
2462     case 4:
2463         /* imageStore(image, image_coord, color);*/
2464         stream << compute_shader_color;
2465         break;
2466     }
2467 
2468     stream << ");\n";
2469 
2470     stream << "}\n" << std::endl;
2471 
2472     out_compute_shader_code = stream.str();
2473 }
2474 
2475 /** Prepare code for sampling fragment shader
2476  *
2477  *  @param sampler_type             Type of sampler
2478  *  @param sampling_function        Type of sampling function
2479  *  @param out_fragment_shader_code Storage for code
2480  **/
getSamplingFragmentShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_fragment_shader_code)2481 void TextureCubeMapArraySamplingTest::getSamplingFragmentShaderCode(const samplerType &sampler_type,
2482                                                                     const samplingFunction &sampling_function,
2483                                                                     std::string &out_fragment_shader_code)
2484 {
2485     const glw::GLchar *color_type                            = 0;
2486     const glw::GLchar *interpolation_type                    = 0;
2487     bool is_shadow_sampler                                   = false;
2488     glw::GLuint n_components                                 = 0;
2489     glw::GLuint n_routine_attributes                         = 0;
2490     glw::GLuint n_type_attributes                            = 0;
2491     const attributeDefinition *routine_attribute_definitions = 0;
2492     const attributeDefinition *type_attribute_definitions    = 0;
2493     const glw::GLchar *sampler_type_str                      = 0;
2494     std::string sampling_code;
2495     std::stringstream stream;
2496 
2497     /* Get attributes for sampling function */
2498     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2499     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2500 
2501     /* Get type for color variables */
2502     getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
2503 
2504     /* Get sampling code */
2505     if (false == is_shadow_sampler)
2506     {
2507         getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, 0,
2508                                 fragment_shader_output, 0, sampler_name, sampling_code);
2509     }
2510     else
2511     {
2512         getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, 0,
2513                                       fragment_shader_output, 0, sampler_name, sampling_code);
2514     }
2515 
2516     /* Preamble */
2517     stream << shader_code_preamble << shader_precision << "/* Sampling fragment shader */" << std::endl;
2518 
2519     /* uniform samplerType sampler */
2520     stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
2521 
2522     stream << std::endl;
2523 
2524     /* in type attribute */
2525     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2526     {
2527         stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
2528                << routine_attribute_definitions[i].name << ";" << std::endl;
2529     }
2530     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2531     {
2532         stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
2533                << type_attribute_definitions[i].name << ";" << std::endl;
2534     }
2535 
2536     stream << std::endl;
2537 
2538     /* layout(location = 0) out vec4 fs_out_color */
2539     stream << shader_layout << shader_output << color_type << fragment_shader_output << ";" << std::endl;
2540 
2541     stream << std::endl;
2542 
2543     /* Body */
2544     stream << fragment_shader_sampling_body_code;
2545 
2546     /* Sampling code */
2547     stream << sampling_code;
2548 
2549     stream << "}" << std::endl << std::endl;
2550 
2551     /* Store result */
2552     out_fragment_shader_code = stream.str();
2553 }
2554 
2555 /** Prepare sampling code
2556  *
2557  *  @param sampling_function     Type of sampling function
2558  *  @param color_type            Type of color
2559  *  @param n_components          Number of components
2560  *  @param attribute_name_prefix Prefix for attributes
2561  *  @param attribute_index       Index for attributes
2562  *  @param color_variable_name   Name of color variable
2563  *  @param color_variable_index  Index for color variable
2564  *  @param sampler_name_p        Name of sampler
2565  *  @param out_code              Result code
2566  **/
getSamplingFunctionCall(samplingFunction sampling_function,const glw::GLchar * color_type,glw::GLuint n_components,const glw::GLchar * attribute_name_prefix,const glw::GLchar * attribute_index,const glw::GLchar * color_variable_name,const glw::GLchar * color_variable_index,const glw::GLchar * sampler_name_p,std::string & out_code)2567 void TextureCubeMapArraySamplingTest::getSamplingFunctionCall(samplingFunction sampling_function,
2568                                                               const glw::GLchar *color_type, glw::GLuint n_components,
2569                                                               const glw::GLchar *attribute_name_prefix,
2570                                                               const glw::GLchar *attribute_index,
2571                                                               const glw::GLchar *color_variable_name,
2572                                                               const glw::GLchar *color_variable_index,
2573                                                               const glw::GLchar *sampler_name_p, std::string &out_code)
2574 {
2575     std::stringstream stream;
2576 
2577     switch (sampling_function)
2578     {
2579     case Texture:
2580         /* fs_in_color = texture(sampler, vs_out_texture_coordinates); */
2581         stream << "    " << var2str(0, color_variable_name, color_variable_index);
2582 
2583         stream << " = " << texture_func << "(" << sampler_name_p;
2584 
2585         stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index);
2586 
2587         if (1 == n_components)
2588         {
2589             stream << ").x;" << std::endl;
2590         }
2591         else
2592         {
2593             stream << ");" << std::endl;
2594         }
2595         break;
2596 
2597     case TextureLod:
2598         /* fs_in_color = textureLod(sampler, vs_out_texture_coordinates, lod); */
2599         stream << "    " << var2str(0, color_variable_name, color_variable_index);
2600         stream << " = " << textureLod_func << "(" << sampler_name_p;
2601 
2602         stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
2603                << var2str(attribute_name_prefix, attribute_lod, attribute_index);
2604 
2605         if (1 == n_components)
2606         {
2607             stream << ").x;" << std::endl;
2608         }
2609         else
2610         {
2611             stream << ");" << std::endl;
2612         }
2613         break;
2614 
2615     case TextureGrad:
2616         /* fs_in_color = textureGrad(sampler, vs_out_texture_coordinates, vs_out_grad_x, vs_out_grad_y); */
2617         stream << "    " << var2str(0, color_variable_name, color_variable_index);
2618 
2619         stream << " = " << textureGrad_func << "(" << sampler_name_p;
2620 
2621         stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
2622                << var2str(attribute_name_prefix, attribute_grad_x, attribute_index) << ", "
2623                << var2str(attribute_name_prefix, attribute_grad_y, attribute_index);
2624 
2625         if (1 == n_components)
2626         {
2627             stream << ").x;" << std::endl;
2628         }
2629         else
2630         {
2631             stream << ");" << std::endl;
2632         }
2633         break;
2634 
2635     case TextureGather:
2636         if (4 == n_components)
2637         {
2638             /**
2639              *  color_type component_0 = textureGather(sampler, vs_out_texture_coordinates, 0);
2640              *  color_type component_1 = textureGather(sampler, vs_out_texture_coordinates, 1);
2641              *  color_type component_2 = textureGather(sampler, vs_out_texture_coordinates, 2);
2642              *  color_type component_3 = textureGather(sampler, vs_out_texture_coordinates, 3);
2643              *  fs_in_color = color_type(component_0.r, component_1.g, component_2.b, component_3.a);
2644              **/
2645             for (glw::GLuint i = 0; i < 4; ++i)
2646             {
2647                 stream << "    " << color_type << "component_" << i << " = " << textureGather_func << "("
2648                        << sampler_name_p;
2649 
2650                 stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index);
2651 
2652                 stream << ", " << i << ");" << std::endl;
2653             }
2654 
2655             stream << "    " << var2str(0, color_variable_name, color_variable_index);
2656 
2657             stream << " = " << color_type << "(component_0.r, "
2658                    << "component_1.g, "
2659                    << "component_2.b, "
2660                    << "component_3.a);" << std::endl;
2661         }
2662         else
2663         {
2664             stream << "    " << var2str(0, color_variable_name, color_variable_index);
2665 
2666             stream << " = " << textureGather_func << "(" << sampler_name_p;
2667 
2668             stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index);
2669 
2670             stream << ").x;" << std::endl;
2671         }
2672         break;
2673     }
2674 
2675     out_code = stream.str();
2676 }
2677 
2678 /** Prepare code for sampling geometry shader
2679  *
2680  *  @param sampler_type             Type of sampler
2681  *  @param sampling_function        Type of sampling function
2682  *  @param out_geometry_shader_code Storage for code
2683  **/
getSamplingGeometryShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_geometry_shader_code)2684 void TextureCubeMapArraySamplingTest::getSamplingGeometryShaderCode(const samplerType &sampler_type,
2685                                                                     const samplingFunction &sampling_function,
2686                                                                     std::string &out_geometry_shader_code)
2687 {
2688     const glw::GLchar *color_type                            = 0;
2689     const glw::GLchar *interpolation_type                    = 0;
2690     bool is_shadow_sampler                                   = false;
2691     glw::GLuint n_components                                 = 0;
2692     glw::GLuint n_routine_attributes                         = 0;
2693     glw::GLuint n_type_attributes                            = 0;
2694     const attributeDefinition *routine_attribute_definitions = 0;
2695     const attributeDefinition *type_attribute_definitions    = 0;
2696     const glw::GLchar *sampler_type_str                      = 0;
2697     std::string sampling_code;
2698     std::stringstream stream;
2699 
2700     /* Get attributes for sampling function */
2701     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2702     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2703 
2704     /* Get type for color variables */
2705     getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
2706 
2707     /* Get sampling code */
2708     if (false == is_shadow_sampler)
2709     {
2710         getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, "0",
2711                                 fragment_shader_input, 0, sampler_name, sampling_code);
2712     }
2713     else
2714     {
2715         getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, "0",
2716                                       fragment_shader_input, 0, sampler_name, sampling_code);
2717     }
2718 
2719     /* Preamble, extension : require  */
2720     stream << shader_code_preamble << geometry_shader_extension << shader_precision << std::endl
2721            << "/* Sampling geometry shader */" << std::endl;
2722 
2723     /* In out layout */
2724     stream << geometry_shader_layout;
2725 
2726     /* uniform samplerType sampler */
2727     stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
2728 
2729     stream << std::endl;
2730 
2731     /* in type attribute[]*/
2732     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2733     {
2734         stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
2735                << routine_attribute_definitions[i].name << "[];" << std::endl;
2736     }
2737     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2738     {
2739         stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
2740                << type_attribute_definitions[i].name << "[];" << std::endl;
2741     }
2742 
2743     stream << std::endl;
2744 
2745     /* out vec4 fs_in_color */
2746     stream << interpolation_type << shader_output << color_type << fragment_shader_input << ";" << std::endl;
2747 
2748     stream << std::endl;
2749 
2750     /* Body */
2751     stream << geometry_shader_sampling_body_code;
2752 
2753     /* Sampling code */
2754     stream << sampling_code;
2755 
2756     stream << geometry_shader_emit_vertex_code << std::endl;
2757 
2758     /* Store result */
2759     out_geometry_shader_code = stream.str();
2760 }
2761 
2762 /** Prepare code for sampling tesselation control shader
2763  *
2764  *  @param sampler_type                        Type of sampler
2765  *  @param sampling_function                   Type of sampling function
2766  *  @param out_tesselation_control_shader_code Storage for code
2767  **/
getSamplingTesselationControlShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_tesselation_control_shader_code)2768 void TextureCubeMapArraySamplingTest::getSamplingTesselationControlShaderCode(
2769     const samplerType &sampler_type, const samplingFunction &sampling_function,
2770     std::string &out_tesselation_control_shader_code)
2771 {
2772     const glw::GLchar *color_type                            = 0;
2773     const glw::GLchar *interpolation_type                    = 0;
2774     bool is_shadow_sampler                                   = false;
2775     glw::GLuint n_components                                 = 0;
2776     glw::GLuint n_routine_attributes                         = 0;
2777     glw::GLuint n_type_attributes                            = 0;
2778     const attributeDefinition *routine_attribute_definitions = 0;
2779     const attributeDefinition *type_attribute_definitions    = 0;
2780     const glw::GLchar *sampler_type_str                      = 0;
2781     std::string sampling_code;
2782     std::stringstream stream;
2783 
2784     /* Get attributes for sampling function */
2785     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2786     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2787 
2788     /* Get type for color variables */
2789     getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
2790 
2791     /* Get sampling code */
2792     if (false == is_shadow_sampler)
2793     {
2794         getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, "gl_InvocationID",
2795                                 tesselation_evaluation_shader_input, "gl_InvocationID", sampler_name, sampling_code);
2796     }
2797     else
2798     {
2799         getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output,
2800                                       "gl_InvocationID", tesselation_evaluation_shader_input, "gl_InvocationID",
2801                                       sampler_name, sampling_code);
2802     }
2803 
2804     /* Preamble, extension : require  */
2805     stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
2806            << "/* Sampling tesselation control shader */" << std::endl;
2807 
2808     /* layout(vertices = 1) out */
2809     stream << tesselation_control_shader_layout;
2810 
2811     /* uniform samplerType sampler */
2812     stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
2813 
2814     stream << std::endl;
2815 
2816     /* in type attribute[]*/
2817     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2818     {
2819         stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
2820                << routine_attribute_definitions[i].name << "[];" << std::endl;
2821     }
2822     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2823     {
2824         stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
2825                << type_attribute_definitions[i].name << "[];" << std::endl;
2826     }
2827 
2828     stream << std::endl;
2829 
2830     /* out vec4 tes_in_color */
2831     stream << interpolation_type << shader_output << color_type << tesselation_evaluation_shader_input << "[];"
2832            << std::endl;
2833 
2834     stream << std::endl;
2835 
2836     /* Body */
2837     stream << tesselation_control_shader_sampling_body_code;
2838 
2839     /* Sampling code */
2840     stream << sampling_code;
2841 
2842     stream << "}" << std::endl << std::endl;
2843 
2844     /* Store result */
2845     out_tesselation_control_shader_code = stream.str();
2846 }
2847 
2848 /** Prepare code for sampling tesselation evaluation shader
2849  *
2850  *  @param sampler_type                           Type of sampler
2851  *  @param sampling_function                      Type of sampling function
2852  *  @param out_tesselation_evaluation_shader_code Storage for code
2853  **/
getSamplingTesselationEvaluationShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_tesselation_evaluation_shader_code)2854 void TextureCubeMapArraySamplingTest::getSamplingTesselationEvaluationShaderCode(
2855     const samplerType &sampler_type, const samplingFunction &sampling_function,
2856     std::string &out_tesselation_evaluation_shader_code)
2857 {
2858     const glw::GLchar *color_type                            = 0;
2859     const glw::GLchar *interpolation_type                    = 0;
2860     bool is_shadow_sampler                                   = false;
2861     glw::GLuint n_components                                 = 0;
2862     glw::GLuint n_routine_attributes                         = 0;
2863     glw::GLuint n_type_attributes                            = 0;
2864     const attributeDefinition *routine_attribute_definitions = 0;
2865     const attributeDefinition *type_attribute_definitions    = 0;
2866     const glw::GLchar *sampler_type_str                      = 0;
2867     std::string sampling_code;
2868     std::stringstream stream;
2869     const glw::GLchar *prev_stage_output = (glu::isContextTypeES(m_context.getRenderContext().getType())) ?
2870                                                tesselation_control_shader_output :
2871                                                vertex_shader_output;
2872 
2873     /* Get attributes for sampling function */
2874     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2875     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2876 
2877     /* Get type for color variables */
2878     getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
2879 
2880     /* Get sampling code */
2881     if (false == is_shadow_sampler)
2882     {
2883         getSamplingFunctionCall(sampling_function, color_type, n_components, prev_stage_output, "0",
2884                                 fragment_shader_input, 0, sampler_name, sampling_code);
2885     }
2886     else
2887     {
2888         getShadowSamplingFunctionCall(sampling_function, color_type, n_components, prev_stage_output, "0",
2889                                       fragment_shader_input, 0, sampler_name, sampling_code);
2890     }
2891 
2892     /* Preamble, extension : require */
2893     stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
2894            << "/* Sampling tesselation evaluation shader */" << std::endl;
2895 
2896     /* layout(point_mode) in; */
2897     stream << tesselation_evaluation_shader_layout;
2898 
2899     /* uniform samplerType sampler */
2900     stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
2901 
2902     stream << std::endl;
2903 
2904     /* in type attribute[]*/
2905     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2906     {
2907         stream << shader_input << routine_attribute_definitions[i].type << prev_stage_output
2908                << routine_attribute_definitions[i].name << "[];" << std::endl;
2909     }
2910     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2911     {
2912         stream << shader_input << type_attribute_definitions[i].type << prev_stage_output
2913                << type_attribute_definitions[i].name << "[];" << std::endl;
2914     }
2915 
2916     stream << std::endl;
2917 
2918     /* out vec4 tes_in_color */
2919     stream << interpolation_type << shader_output << color_type << fragment_shader_input << ";" << std::endl;
2920 
2921     stream << std::endl;
2922 
2923     /* Body */
2924     stream << tesselation_evaluation_shader_sampling_body_code;
2925 
2926     /* Sampling code */
2927     stream << sampling_code;
2928 
2929     stream << "}" << std::endl << std::endl;
2930 
2931     /* Store result */
2932     out_tesselation_evaluation_shader_code = stream.str();
2933 }
2934 
2935 /** Prepare code for sampling vertex shader
2936  *
2937  *  @param sampler_type           Type of sampler
2938  *  @param sampling_function      Type of sampling function
2939  *  @param out_vertex_shader_code Storage for code
2940  **/
getSamplingVertexShaderCode(const samplerType & sampler_type,const samplingFunction & sampling_function,std::string & out_vertex_shader_code)2941 void TextureCubeMapArraySamplingTest::getSamplingVertexShaderCode(const samplerType &sampler_type,
2942                                                                   const samplingFunction &sampling_function,
2943                                                                   std::string &out_vertex_shader_code)
2944 {
2945     const glw::GLchar *color_type                            = 0;
2946     const glw::GLchar *interpolation_type                    = 0;
2947     bool is_shadow_sampler                                   = false;
2948     glw::GLuint n_components                                 = 0;
2949     glw::GLuint n_routine_attributes                         = 0;
2950     glw::GLuint n_type_attributes                            = 0;
2951     const attributeDefinition *routine_attribute_definitions = 0;
2952     const attributeDefinition *type_attribute_definitions    = 0;
2953     const glw::GLchar *sampler_type_str                      = 0;
2954     std::string sampling_code;
2955     std::stringstream stream;
2956 
2957     /* Get attributes for sampling function */
2958     getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
2959     getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
2960 
2961     /* Get type for color variables */
2962     getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
2963 
2964     /* Get sampling code */
2965     if (false == is_shadow_sampler)
2966     {
2967         getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_input, 0,
2968                                 fragment_shader_input, 0, sampler_name, sampling_code);
2969     }
2970     else
2971     {
2972         getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_input, 0,
2973                                       fragment_shader_input, 0, sampler_name, sampling_code);
2974     }
2975 
2976     /* Preamble */
2977     stream << shader_code_preamble << shader_precision << "/* Sampling vertex shader */" << std::endl;
2978 
2979     /* uniform samplerType sampler */
2980     stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
2981 
2982     stream << std::endl;
2983 
2984     /* in vec4 vs_in_position */
2985     stream << shader_input << type_vec4 << vertex_shader_input << vertex_shader_position << ";" << std::endl;
2986 
2987     /* in type attribute */
2988     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
2989     {
2990         stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_input
2991                << routine_attribute_definitions[i].name << ";" << std::endl;
2992     }
2993     for (glw::GLuint i = 0; i < n_type_attributes; ++i)
2994     {
2995         stream << shader_input << type_attribute_definitions[i].type << vertex_shader_input
2996                << type_attribute_definitions[i].name << ";" << std::endl;
2997     }
2998 
2999     stream << std::endl;
3000 
3001     /* out vec4 fs_in_color; */
3002     stream << interpolation_type << shader_output << color_type << fragment_shader_input << ";" << std::endl;
3003 
3004     stream << std::endl;
3005 
3006     /* Body */
3007     stream << vertex_shader_body_code;
3008 
3009     /* Sampling code */
3010     stream << sampling_code;
3011 
3012     stream << "}" << std::endl << std::endl;
3013 
3014     /* Store result */
3015     out_vertex_shader_code = stream.str();
3016 }
3017 
3018 /** Prepare shadow sampling code
3019  *
3020  *  @param sampling_function     Type of sampling function
3021  *  @param color_type            Type of color
3022  *  @param n_components          Number of components
3023  *  @param attribute_name_prefix Prefix for attributes
3024  *  @param attribute_index       Index for attributes
3025  *  @param color_variable_name   Name of color variable
3026  *  @param color_variable_index  Index for color variable
3027  *  @param sampler_name_p        Name of sampler
3028  *  @param out_code              Result code
3029  **/
getShadowSamplingFunctionCall(samplingFunction sampling_function,const glw::GLchar * color_type,glw::GLuint n_components,const glw::GLchar * attribute_name_prefix,const glw::GLchar * attribute_index,const glw::GLchar * color_variable_name,const glw::GLchar * color_variable_index,const glw::GLchar * sampler_name_p,std::string & out_code)3030 void TextureCubeMapArraySamplingTest::getShadowSamplingFunctionCall(
3031     samplingFunction sampling_function, const glw::GLchar *color_type, glw::GLuint n_components,
3032     const glw::GLchar *attribute_name_prefix, const glw::GLchar *attribute_index,
3033     const glw::GLchar *color_variable_name, const glw::GLchar *color_variable_index, const glw::GLchar *sampler_name_p,
3034     std::string &out_code)
3035 {
3036     std::stringstream stream;
3037 
3038     switch (sampling_function)
3039     {
3040     case Texture:
3041         /* fs_in_color = texture(sampler, vs_out_texture_coordinates); */
3042         stream << "    " << var2str(0, color_variable_name, color_variable_index);
3043 
3044         stream << " = " << texture_func << "(" << sampler_name_p;
3045 
3046         stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
3047                << var2str(attribute_name_prefix, attribute_refZ, attribute_index);
3048 
3049         stream << ");" << std::endl;
3050         break;
3051     case TextureLod:
3052         /* fs_in_color = textureLod(sampler, vs_out_texture_coordinates, lod); */
3053         stream << "    " << var2str(0, color_variable_name, color_variable_index);
3054 
3055         stream << " = " << textureLod_func << "(" << sampler_name_p;
3056 
3057         stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
3058                << var2str(attribute_name_prefix, attribute_lod, attribute_index) << ", "
3059                << var2str(attribute_name_prefix, attribute_refZ, attribute_index);
3060 
3061         stream << ");" << std::endl;
3062         break;
3063     case TextureGrad:
3064         /* fs_in_color = textureGrad(sampler, vs_out_texture_coordinates, vs_out_grad_x, vs_out_grad_y); */
3065         throw tcu::NotSupportedError("textureGrad operation is not available for samplerCubeArrayShadow", "", __FILE__,
3066                                      __LINE__);
3067     case TextureGather:
3068         if (4 == n_components)
3069         {
3070             /**
3071              *  color_type component_0 = textureGather(sampler, vs_out_texture_coordinates, 0);
3072              *  color_type component_1 = textureGather(sampler, vs_out_texture_coordinates, 1);
3073              *  color_type component_2 = textureGather(sampler, vs_out_texture_coordinates, 2);
3074              *  color_type component_3 = textureGather(sampler, vs_out_texture_coordinates, 3);
3075              *  fs_in_color = color_type(component_0.r, component_1.g, component_2.b, component_3.a);
3076              **/
3077             for (glw::GLuint i = 0; i < 4; ++i)
3078             {
3079                 stream << "    " << color_type << "component_" << i;
3080 
3081                 stream << " = " << textureGather_func << "(" << sampler_name_p;
3082 
3083                 stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
3084                        << var2str(attribute_name_prefix, attribute_refZ, attribute_index);
3085 
3086                 stream << ");" << std::endl;
3087             }
3088 
3089             stream << "    " << var2str(0, color_variable_name, color_variable_index);
3090 
3091             stream << " = " << color_type << "(component_0.r, "
3092                    << "component_1.g, "
3093                    << "component_2.b, "
3094                    << "component_3.a);" << std::endl;
3095         }
3096         else
3097         {
3098             stream << "    " << var2str(0, color_variable_name, color_variable_index);
3099 
3100             stream << " = " << textureGather_func << "(" << sampler_name_p;
3101 
3102             stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
3103                    << var2str(attribute_name_prefix, attribute_refZ, attribute_index);
3104 
3105             stream << ").x;" << std::endl;
3106         }
3107         break;
3108     }
3109 
3110     out_code = stream.str();
3111 }
3112 
3113 /** Check if combination of sampler type and sampling function is supported
3114  *
3115  *  @param sampler_type      Type of sampler
3116  *  @param sampling_function Type of sampling function
3117  *
3118  *  @return true  When supported
3119  *          false When not supported
3120  **/
isSamplerSupportedByFunction(const samplerType sampler_type,const samplingFunction sampling_function)3121 bool TextureCubeMapArraySamplingTest::isSamplerSupportedByFunction(const samplerType sampler_type,
3122                                                                    const samplingFunction sampling_function)
3123 {
3124     if ((Depth == sampler_type) && ((TextureLod == sampling_function) || (TextureGrad == sampling_function)))
3125     {
3126         return false;
3127     }
3128 
3129     return true;
3130 }
3131 
3132 /** Executes the test.
3133  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3134  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3135  *  Note the function throws exception should an error occur!
3136  **/
iterate()3137 tcu::TestNode::IterateResult TextureCubeMapArraySamplingTest::iterate()
3138 {
3139 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION
3140 
3141     for (resolutionsVectorType::iterator resolution     = m_compressed_resolutions.begin(),
3142                                          end_resolution = m_compressed_resolutions.end();
3143          end_resolution != resolution; ++resolution)
3144     {
3145         prepareDumpForTextureCompression(*resolution);
3146     }
3147 
3148     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3149 
3150     return STOP;
3151 
3152 #else  /* TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION */
3153 
3154     if (false == m_is_texture_cube_map_array_supported)
3155     {
3156         throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3157     }
3158 
3159     // These shader stages are always supported
3160     m_shaders.push_back(shaderConfiguration(Compute, GL_POINTS, "Compute"));
3161     m_shaders.push_back(shaderConfiguration(Fragment, GL_POINTS, "Fragment"));
3162     m_shaders.push_back(shaderConfiguration(Vertex, GL_POINTS, "Vertex"));
3163 
3164     // Check if geometry shader is supported
3165     if (true == m_is_geometry_shader_extension_supported)
3166     {
3167         m_shaders.push_back(shaderConfiguration(Geometry, GL_POINTS, "Geometry"));
3168     }
3169 
3170     // Check if tesselation shaders are supported
3171     if (true == m_is_tessellation_shader_supported)
3172     {
3173         m_shaders.push_back(shaderConfiguration(Tesselation_Control, m_glExtTokens.PATCHES, "Tesselation_Control"));
3174         m_shaders.push_back(
3175             shaderConfiguration(Tesselation_Evaluation, m_glExtTokens.PATCHES, "Tesselation_Evaluation"));
3176     }
3177 
3178     /* GL functions */
3179     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3180 
3181     gl.genFramebuffers(1, &m_framebuffer_object_id);
3182 
3183     if (true == m_is_tessellation_shader_supported)
3184     {
3185         gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
3186     }
3187 
3188     gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
3189     gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
3190 
3191     testFormats(m_formats, m_resolutions);
3192     testFormats(m_compressed_formats, m_compressed_resolutions);
3193 
3194     if (true == m_is_tessellation_shader_supported)
3195     {
3196         gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
3197     }
3198 
3199     gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
3200     gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
3201 
3202     gl.deleteFramebuffers(1, &m_framebuffer_object_id);
3203     m_framebuffer_object_id = 0;
3204 
3205     m_testCtx.getLog() << tcu::TestLog::Section("Summary", "");
3206     if ((0 != failed_cases) || (0 != invalid_type_cases))
3207     {
3208         m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! Number of found errors: " << failed_cases
3209                            << tcu::TestLog::EndMessage;
3210 
3211         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid shaders: " << invalid_shaders
3212                            << tcu::TestLog::EndMessage;
3213 
3214         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid programs: " << invalid_programs
3215                            << tcu::TestLog::EndMessage;
3216 
3217         m_testCtx.getLog() << tcu::TestLog::Message
3218                            << "glGetActiveUniform or glGetProgramResourceiv reported invalid type: "
3219                            << invalid_type_cases << tcu::TestLog::EndMessage;
3220 
3221         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3222     }
3223     else
3224     {
3225         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3226     }
3227 
3228     m_testCtx.getLog() << tcu::TestLog::Message << "Number of executed test cases: " << tested_cases
3229                        << tcu::TestLog::EndMessage;
3230 
3231     m_testCtx.getLog() << tcu::TestLog::Message << "Total shaders: " << compiled_shaders << tcu::TestLog::EndMessage;
3232 
3233     m_testCtx.getLog() << tcu::TestLog::Message << "Total programs: " << linked_programs << tcu::TestLog::EndMessage;
3234 
3235     m_testCtx.getLog() << tcu::TestLog::EndSection;
3236 
3237     return STOP;
3238 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION */
3239 }
3240 
3241 /** Link program
3242  *
3243  *  @param info Program information
3244  **/
link(programDefinition & info)3245 void TextureCubeMapArraySamplingTest::link(programDefinition &info)
3246 {
3247     linked_programs += 1;
3248 
3249     /* Not supported format */
3250     if (programDefinition::m_invalid_program_object_id == info.getProgramId())
3251     {
3252         return;
3253     }
3254 
3255     if (false == info.link())
3256     {
3257         invalid_programs += 1;
3258 
3259         logLinkingLog(info);
3260         logProgram(info);
3261     }
3262 }
3263 
3264 /** Logs compilation log
3265  *
3266  *  @param info Shader information
3267  **/
logCompilationLog(const shaderDefinition & info)3268 void TextureCubeMapArraySamplingTest::logCompilationLog(const shaderDefinition &info)
3269 {
3270     std::string info_log = getCompilationInfoLog(info.getShaderId());
3271     m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failure:\n\n"
3272                        << info_log << tcu::TestLog::EndMessage;
3273     m_testCtx.getLog() << tcu::TestLog::Message << "Shader source:\n\n" << info.getSource() << tcu::TestLog::EndMessage;
3274 }
3275 
3276 /** Logs linkig log
3277  *
3278  *  @param info Program information
3279  **/
logLinkingLog(const programDefinition & info)3280 void TextureCubeMapArraySamplingTest::logLinkingLog(const programDefinition &info)
3281 {
3282     glw::GLuint program_object_id = info.getProgramId();
3283 
3284     if (programDefinition::m_invalid_program_object_id == program_object_id)
3285     {
3286         return;
3287     }
3288 
3289     std::string info_log = getLinkingInfoLog(program_object_id);
3290     m_testCtx.getLog() << tcu::TestLog::Message << "Program linking failure:\n\n"
3291                        << info_log << tcu::TestLog::EndMessage;
3292 }
3293 
3294 /** Logs shaders used by program
3295  *
3296  *  @param info Program information
3297  **/
logProgram(const programDefinition & info)3298 void TextureCubeMapArraySamplingTest::logProgram(const programDefinition &info)
3299 {
3300     glw::GLuint program_object_id = info.getProgramId();
3301 
3302     if (programDefinition::m_invalid_program_object_id == program_object_id)
3303     {
3304         return;
3305     }
3306 
3307     tcu::MessageBuilder message = m_testCtx.getLog() << tcu::TestLog::Message;
3308 
3309     message << "Program id: " << program_object_id;
3310 
3311     const shaderDefinition *compute  = info.getShader(Compute);
3312     const shaderDefinition *fragment = info.getShader(Fragment);
3313     const shaderDefinition *geometry = info.getShader(Geometry);
3314     const shaderDefinition *tcs      = info.getShader(Tesselation_Control);
3315     const shaderDefinition *tes      = info.getShader(Tesselation_Evaluation);
3316     const shaderDefinition *vertex   = info.getShader(Vertex);
3317 
3318     if (0 != compute)
3319     {
3320         message << "\nCompute shader:\n" << compute->getSource();
3321     }
3322 
3323     if (0 != vertex)
3324     {
3325         message << "\nVertex shader:\n" << vertex->getSource();
3326     }
3327 
3328     if (0 != geometry)
3329     {
3330         message << "\nGeometry shader:\n" << geometry->getSource();
3331     }
3332 
3333     if (0 != tcs)
3334     {
3335         message << "\nTCS shader:\n" << tcs->getSource();
3336     }
3337 
3338     if (0 != tes)
3339     {
3340         message << "\nTES shader:\n" << tes->getSource();
3341     }
3342 
3343     if (0 != fragment)
3344     {
3345         message << "\nFragment shader:\n" << fragment->getSource();
3346     }
3347 
3348     message << tcu::TestLog::EndMessage;
3349 }
3350 
3351 /** Prepare compressed textures
3352  *
3353  *  @param texture    Texture information
3354  *  @param format     Texture format
3355  *  @param resolution Texture resolution
3356  *  @param mutability Texture mutability
3357  **/
prepareCompresedTexture(const textureDefinition & texture,const formatDefinition & format,const resolutionDefinition & resolution,bool mutability)3358 void TextureCubeMapArraySamplingTest::prepareCompresedTexture(const textureDefinition &texture,
3359                                                               const formatDefinition &format,
3360                                                               const resolutionDefinition &resolution, bool mutability)
3361 {
3362     static const glw::GLint n_faces = 6;
3363 
3364     const glw::GLint array_length    = resolution.m_depth / n_faces;
3365     const glw::GLint n_mipmap_levels = getMipmapLevelCount(resolution.m_width, resolution.m_height);
3366     glw::GLsizei texture_width       = 0;
3367     glw::GLsizei texture_height      = 0;
3368 
3369     /* GL functions */
3370     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3371 
3372     texture.bind(GL_TEXTURE_CUBE_MAP_ARRAY);
3373 
3374     if (false == mutability)
3375     {
3376         gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, n_mipmap_levels, format.m_source.m_internal_format,
3377                         resolution.m_width, resolution.m_height, resolution.m_depth);
3378 
3379         GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage3D");
3380 
3381         texture_width  = resolution.m_width;
3382         texture_height = resolution.m_height;
3383 
3384         for (glw::GLint mipmap_level = 0; mipmap_level < n_mipmap_levels; ++mipmap_level)
3385         {
3386             const glw::GLubyte *image_data = 0;
3387             glw::GLuint image_size         = 0;
3388 
3389             getCompressedTexture(resolution.m_width, resolution.m_height, array_length, mipmap_level, image_data,
3390                                  image_size);
3391 
3392             if (0 == image_data)
3393             {
3394                 throw tcu::InternalError("Invalid compressed texture", "", __FILE__, __LINE__);
3395             }
3396 
3397             gl.compressedTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipmap_level, 0, /* x_offset */
3398                                        0,                                          /* y offset */
3399                                        0,                                          /* z offset */
3400                                        texture_width, texture_height, resolution.m_depth,
3401                                        format.m_source.m_internal_format, image_size, image_data);
3402 
3403             GLU_EXPECT_NO_ERROR(gl.getError(), "compressedTexSubImage3D");
3404 
3405             texture_width  = de::max(1, texture_width / 2);
3406             texture_height = de::max(1, texture_height / 2);
3407         }
3408     }
3409     else
3410     {
3411         texture_width  = resolution.m_width;
3412         texture_height = resolution.m_height;
3413 
3414         for (glw::GLint mipmap_level = 0; mipmap_level < n_mipmap_levels; ++mipmap_level)
3415         {
3416             const glw::GLubyte *image_data = 0;
3417             glw::GLuint image_size         = 0;
3418 
3419             getCompressedTexture(resolution.m_width, resolution.m_height, array_length, mipmap_level, image_data,
3420                                  image_size);
3421 
3422             if (0 == image_data)
3423             {
3424                 throw tcu::InternalError("Invalid compressed texture", "", __FILE__, __LINE__);
3425             }
3426 
3427             gl.compressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipmap_level, format.m_source.m_internal_format,
3428                                     texture_width, texture_height, resolution.m_depth, 0 /* border */, image_size,
3429                                     image_data);
3430 
3431             GLU_EXPECT_NO_ERROR(gl.getError(), "compressedTexImage3D");
3432 
3433             texture_width  = de::max(1, texture_width / 2);
3434             texture_height = de::max(1, texture_height / 2);
3435         }
3436     }
3437 }
3438 
3439 /** Prepare not comporessed textures
3440  *
3441  *  @param texture    Texture information
3442  *  @param format     Texture format
3443  *  @param resolution Texture resolution
3444  *  @param mutability Texture mutability
3445  **/
prepareTexture(const textureDefinition & texture,const formatDefinition & texture_format,const resolutionDefinition & resolution,bool mutability)3446 void TextureCubeMapArraySamplingTest::prepareTexture(const textureDefinition &texture,
3447                                                      const formatDefinition &texture_format,
3448                                                      const resolutionDefinition &resolution, bool mutability)
3449 {
3450     static const glw::GLint n_faces = 6;
3451 
3452     const glw::GLint n_elements      = resolution.m_depth / n_faces;
3453     const glw::GLint n_mipmap_levels = getMipmapLevelCount(resolution.m_width, resolution.m_height);
3454     glw::GLsizei texture_width       = 0;
3455     glw::GLsizei texture_height      = 0;
3456 
3457     /* GL functions */
3458     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3459 
3460     texture.bind(GL_TEXTURE_CUBE_MAP_ARRAY);
3461 
3462     if (false == mutability)
3463     {
3464         gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, n_mipmap_levels, texture_format.m_source.m_internal_format,
3465                         resolution.m_width, resolution.m_height, resolution.m_depth);
3466     }
3467     else
3468     {
3469         texture_width  = resolution.m_width;
3470         texture_height = resolution.m_height;
3471 
3472         for (glw::GLint mipmap_level = 0; mipmap_level < n_mipmap_levels; ++mipmap_level)
3473         {
3474             gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipmap_level, texture_format.m_source.m_internal_format,
3475                           texture_width, texture_height, resolution.m_depth, 0 /* border */,
3476                           texture_format.m_source.m_format, texture_format.m_source.m_type, 0 /* data */);
3477 
3478             texture_width  = de::max(1, texture_width / 2);
3479             texture_height = de::max(1, texture_height / 2);
3480         }
3481     }
3482 
3483     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate storage for texture");
3484 
3485     texture_width  = resolution.m_width;
3486     texture_height = resolution.m_height;
3487 
3488     for (glw::GLint mipmap_level = 0; mipmap_level < n_mipmap_levels; ++mipmap_level)
3489     {
3490         for (glw::GLint element_index = 0; element_index < n_elements; ++element_index)
3491         {
3492             for (glw::GLint face = 0; face < n_faces; ++face)
3493             {
3494                 prepareTextureFace(gl, face, element_index, mipmap_level, n_elements, n_mipmap_levels,
3495                                    texture_format.m_source.m_format, texture_format.m_source.m_type, texture_width,
3496                                    texture_height);
3497             }
3498         }
3499 
3500         texture_width  = de::max(1, texture_width / 2);
3501         texture_height = de::max(1, texture_height / 2);
3502     }
3503 
3504     // not texture filterable formats
3505     if ((texture_format.m_source.m_internal_format == GL_RGBA32UI) ||
3506         (texture_format.m_source.m_internal_format == GL_RGBA32I) ||
3507         (texture_format.m_source.m_internal_format == GL_STENCIL_INDEX8) ||
3508         (texture_format.m_source.m_internal_format == GL_DEPTH_COMPONENT32F))
3509     {
3510         gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3511         gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
3512     }
3513 }
3514 
3515 /** Setup shader storabe buffer for use with compute shader
3516  *
3517  *  @param attribute  Attribute information
3518  *  @param buffers    Collection of buffers
3519  *  @param program_id Program id
3520  **/
setupSharedStorageBuffer(const attributeDefinition & attribute,const bufferCollection & buffers,glw::GLuint program_id)3521 void TextureCubeMapArraySamplingTest::setupSharedStorageBuffer(const attributeDefinition &attribute,
3522                                                                const bufferCollection &buffers, glw::GLuint program_id)
3523 {
3524     (void)program_id;
3525 
3526     /* GL functions */
3527     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3528 
3529     std::string attribute_name     = attribute.name;
3530     const bufferDefinition *buffer = 0;
3531 
3532     switch (attribute.attribute_id)
3533     {
3534     case Position:
3535         buffer = &buffers.postion;
3536         break;
3537     case TextureCoordinates:
3538         buffer = &buffers.texture_coordinate;
3539         break;
3540     case TextureCoordinatesForGather:
3541         buffer = &buffers.texture_coordinate_for_gather;
3542         break;
3543     case Lod:
3544         buffer = &buffers.lod;
3545         break;
3546     case GradX:
3547         buffer = &buffers.grad_x;
3548         break;
3549     case GradY:
3550         buffer = &buffers.grad_y;
3551         break;
3552     case RefZ:
3553         buffer = &buffers.refZ;
3554         break;
3555     }
3556 
3557     buffer->bind(GL_SHADER_STORAGE_BUFFER, attribute.binding);
3558     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shared storage block");
3559 }
3560 
3561 /** Setup shader storabe buffers for use with compute shader
3562  *
3563  *  @param format            Texture format
3564  *  @param sampling_function Sampling routine
3565  *  @param buffers           Collection of buffers
3566  *  @param program_id        Program id
3567  **/
setupSharedStorageBuffers(const formatDefinition & format,const samplingFunction & sampling_function,const bufferCollection & buffers,glw::GLuint program_id)3568 void TextureCubeMapArraySamplingTest::setupSharedStorageBuffers(const formatDefinition &format,
3569                                                                 const samplingFunction &sampling_function,
3570                                                                 const bufferCollection &buffers, glw::GLuint program_id)
3571 {
3572     const attributeDefinition *format_attributes  = 0;
3573     glw::GLuint n_format_attributes               = 0;
3574     glw::GLuint n_routine_attributes              = 0;
3575     const attributeDefinition *routine_attributes = 0;
3576 
3577     getAttributes(format.m_sampler_type, format_attributes, n_format_attributes);
3578     getAttributes(sampling_function, routine_attributes, n_routine_attributes);
3579 
3580     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
3581     {
3582         setupSharedStorageBuffer(routine_attributes[i], buffers, program_id);
3583     }
3584 
3585     for (glw::GLuint i = 0; i < n_format_attributes; ++i)
3586     {
3587         setupSharedStorageBuffer(format_attributes[i], buffers, program_id);
3588     }
3589 }
3590 
3591 /** Execute tests for set of formats and resolutions
3592  *
3593  *  @param formats     Set of texture formats
3594  *  @param resolutions Set of texture resolutions
3595  **/
testFormats(formatsVectorType & formats,resolutionsVectorType & resolutions)3596 void TextureCubeMapArraySamplingTest::testFormats(formatsVectorType &formats, resolutionsVectorType &resolutions)
3597 {
3598     /* GL functions */
3599     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3600 
3601     for (formatsVectorType::iterator format = formats.begin(), end_format = formats.end(); end_format != format;
3602          ++format)
3603     {
3604         shaderCollectionForTextureFormat shader_collection;
3605         programCollectionForFormat program_collection;
3606 
3607         shader_collection.init(gl, *format, m_functions, *this);
3608         bool isContextES = (glu::isContextTypeES(m_context.getRenderContext().getType()));
3609         program_collection.init(gl, shader_collection, *this, isContextES);
3610 
3611         for (mutablitiesVectorType::iterator mutability = m_mutabilities.begin(), end_muatbility = m_mutabilities.end();
3612              end_muatbility != mutability; ++mutability)
3613         {
3614             for (resolutionsVectorType::iterator resolution = resolutions.begin(), end_resolution = resolutions.end();
3615                  end_resolution != resolution; ++resolution)
3616             {
3617                 textureDefinition texture;
3618                 texture.init(gl);
3619 
3620                 try
3621                 {
3622                     if (false == format->m_source.m_is_compressed)
3623                     {
3624                         prepareTexture(texture, *format, *resolution, *mutability);
3625                     }
3626                     else
3627                     {
3628                         prepareCompresedTexture(texture, *format, *resolution, *mutability);
3629                     }
3630                 }
3631 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG
3632                 catch (std::exception &exc)
3633                 {
3634                     m_testCtx.getLog() << tcu::TestLog::Section("Exception during texture creation", exc.what());
3635 
3636                     m_testCtx.getLog() << tcu::TestLog::Message << "Format: " << format->m_name
3637                                        << ", Mutability: " << *mutability << ", W: " << resolution->m_width
3638                                        << ", H: " << resolution->m_height << tcu::TestLog::EndMessage;
3639 
3640                     m_testCtx.getLog() << tcu::TestLog::EndSection;
3641 #else  /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG */
3642                 catch (...)
3643                 {
3644 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG */
3645                     continue;
3646                 }
3647 
3648                 testTexture(*format, *mutability, *resolution, texture, program_collection);
3649             }
3650         }
3651     }
3652 }
3653 
3654 /** Execute tests for given texture
3655  *
3656  *  @param format             Texture format
3657  *  @param mutability         Texture mutabilibty
3658  *  @param resolution         Texture resolution
3659  *  @param texture            Textue information
3660  *  @param shader_collection  Collection of shaders
3661  *  @param program_collection Collection of programs
3662  **/
3663 void TextureCubeMapArraySamplingTest::testTexture(const formatDefinition &format, bool mutability,
3664                                                   const resolutionDefinition &resolution, textureDefinition &texture,
3665                                                   programCollectionForFormat &program_collection)
3666 {
3667     std::vector<unsigned char> result_image;
3668 
3669     const glw::GLuint image_width  = 3 * resolution.m_depth;
3670     const glw::GLuint image_height = 3;
3671     const glw::GLuint estimated_image_size =
3672         static_cast<glw::GLuint>(image_width * image_height * 4 /* components */ * sizeof(glw::GLuint));
3673 
3674     result_image.resize(estimated_image_size);
3675 
3676     /* GL functions */
3677     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3678 
3679     bufferCollection buffers;
3680     buffers.init(gl, format, resolution);
3681 
3682     for (samplingFunctionsVectorType::iterator function = m_functions.begin(), end_function = m_functions.end();
3683          end_function != function; ++function)
3684     {
3685         for (shadersVectorType::iterator shader = m_shaders.begin(), end_shader = m_shaders.end(); end_shader != shader;
3686              ++shader)
3687         {
3688             const programCollectionForFunction *programs = 0;
3689             const programDefinition *program             = 0;
3690             glw::GLuint program_object_id                = programDefinition::m_invalid_program_object_id;
3691             textureDefinition color_attachment;
3692 
3693             programs          = program_collection.getPrograms(function->m_function);
3694             program           = programs->getProgram(shader->m_type);
3695             program_object_id = program->getProgramId();
3696 
3697             if (programDefinition::m_invalid_program_object_id == program_object_id)
3698             {
3699                 continue;
3700             }
3701 
3702             tested_cases += 1;
3703 
3704             color_attachment.init(gl);
3705 
3706             if (Compute != shader->m_type)
3707             {
3708                 setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, color_attachment.getTextureId(),
3709                                                         format.m_destination.m_internal_format, image_width,
3710                                                         image_height);
3711             }
3712             else
3713             {
3714                 color_attachment.bind(GL_TEXTURE_2D);
3715                 gl.texStorage2D(GL_TEXTURE_2D, 1, format.m_destination.m_internal_format, image_width, image_height);
3716                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3717                 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3718                 color_attachment.setupImage(0, format.m_destination.m_internal_format);
3719             }
3720 
3721             try
3722             {
3723                 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3724                 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_object_id);
3725 
3726                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
3727 
3728                 gl.useProgram(program_object_id);
3729 
3730                 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glUseProgram call.");
3731 
3732                 texture.setupSampler(0, sampler_name, program_object_id, format.m_sampler_type == Depth);
3733 
3734                 if (Compute != shader->m_type)
3735                 {
3736                     vertexArrayObjectDefinition vao;
3737                     vao.init(gl, format, function->m_function, buffers, program_object_id);
3738                     draw(program_object_id, shader->m_primitive_type, image_width * image_height,
3739                          format.m_destination.m_internal_format);
3740                 }
3741                 else
3742                 {
3743                     setupSharedStorageBuffers(format, function->m_function, buffers, program_object_id);
3744                     dispatch(program_object_id, image_width, image_height);
3745                 }
3746 
3747                 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3748                 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer_object_id);
3749 
3750                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
3751 
3752                 color_attachment.bind(GL_TEXTURE_2D);
3753                 gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3754                                         color_attachment.getTextureId(), 0);
3755                 GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
3756 
3757                 gl.viewport(0, 0, 3 * resolution.m_depth, 3);
3758                 GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
3759 
3760                 gl.memoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
3761                 gl.readPixels(0 /* x */, 0 /* y */, image_width, image_height, format.m_destination.m_format,
3762                               format.m_destination.m_type, &result_image[0]);
3763 
3764                 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
3765 
3766                 /* GL_DEPTH_COMPONENT is nominally R32F, however R32F is not renderable, so we convert to
3767                  * RGBA8 instead.  Convert the red channel back to R32F for comparison.
3768                  */
3769                 if (format.m_source.m_format == GL_DEPTH_COMPONENT)
3770                 {
3771                     unsigned char *p = (unsigned char *)&result_image[0];
3772                     float *f         = (float *)&result_image[0];
3773 
3774                     for (unsigned int i = 0; i < image_width * image_height; i++)
3775                     {
3776                         *f = (float)p[0] / 255.0f;
3777                         p += 4;
3778                         f += 1;
3779                     }
3780                 }
3781 
3782                 /* GL_STENCIL_INDEX is nominally one-channel format, however ReadPixels supports only RGBA formats.
3783                  * Convert the RGBA image to R for comparison.
3784                  */
3785                 if (format.m_source.m_format == GL_STENCIL_INDEX && format.m_destination.m_format == GL_RGBA_INTEGER)
3786                 {
3787                     unsigned int *pRGBA = (unsigned int *)&result_image[0];
3788                     unsigned int *pR    = (unsigned int *)&result_image[0];
3789                     for (unsigned int i = 0; i < image_width * image_height; i++)
3790                     {
3791                         *pR = pRGBA[0];
3792                         pR += 1;
3793                         pRGBA += 4;
3794                     }
3795                 }
3796 
3797                 glw::GLuint get_type_api_status =
3798                     checkUniformAndResourceApi(program_object_id, sampler_name, format.m_sampler_type);
3799                 bool verification_result = verifyResult(format, resolution, function->m_function, &result_image[0]);
3800 
3801                 if ((true == verification_result) && (0 == get_type_api_status))
3802                 {
3803 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_LOG
3804                     m_testCtx.getLog() << tcu::TestLog::Message << "Valid result. "
3805                                        << " Format: " << format.m_name << ", Mutability: " << mutability
3806                                        << ", Sampling shader: " << shader->m_name
3807                                        << ", Sampling function: " << function->m_name << ", W: " << resolution.m_width
3808                                        << ", H: " << resolution.m_height << tcu::TestLog::EndMessage;
3809 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_PROGRAM_LOG
3810                     logProgram(*program);
3811 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_PROGRAM_LOG */
3812 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_LOG */
3813                 }
3814                 else
3815                 {
3816 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG
3817                     m_testCtx.getLog() << tcu::TestLog::Section("Invalid result", "");
3818 
3819                     if (true != verification_result)
3820                     {
3821                         m_testCtx.getLog() << tcu::TestLog::Message << "Invalid image" << tcu::TestLog::EndMessage;
3822                     }
3823 
3824                     if (0 != get_type_api_status)
3825                     {
3826                         if (0 != (m_get_type_api_status_uniform & get_type_api_status))
3827                         {
3828                             m_testCtx.getLog()
3829                                 << tcu::TestLog::Message << "glGetActiveUniform returns wrong type for sampler"
3830                                 << tcu::TestLog::EndMessage;
3831                         }
3832 
3833                         if (0 != (m_get_type_api_status_program_resource & get_type_api_status))
3834                         {
3835                             m_testCtx.getLog()
3836                                 << tcu::TestLog::Message << "glGetProgramResourceiv returns wrong type for sampler"
3837                                 << tcu::TestLog::EndMessage;
3838                         }
3839                     }
3840 
3841                     m_testCtx.getLog() << tcu::TestLog::Message << "Format: " << format.m_name
3842                                        << ", Mutability: " << mutability << ", Sampling shader: " << shader->m_name
3843                                        << ", Sampling function: " << function->m_name << ", W: " << resolution.m_width
3844                                        << ", H: " << resolution.m_height << tcu::TestLog::EndMessage;
3845 
3846 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_PROGRAM_LOG
3847                     logProgram(*program);
3848 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_PROGRAM_LOG */
3849 
3850                     m_testCtx.getLog() << tcu::TestLog::EndSection;
3851 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG */
3852 
3853                     if (false == verification_result)
3854                     {
3855                         failed_cases += 1;
3856                     }
3857 
3858                     if (0 != get_type_api_status)
3859                     {
3860                         invalid_type_cases += 1;
3861                     }
3862                 }
3863             }
3864 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG
3865             catch (std::exception &exc)
3866             {
3867                 m_testCtx.getLog() << tcu::TestLog::Section("Exception during test execution", exc.what());
3868 
3869                 m_testCtx.getLog() << tcu::TestLog::Message << "Format: " << format.m_name
3870                                    << ", Mutability: " << mutability << ", W: " << resolution.m_width
3871                                    << ", H: " << resolution.m_height << tcu::TestLog::EndMessage;
3872 
3873 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_PROGRAM_LOG
3874                 logProgram(*program);
3875 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_PROGRAM_LOG */
3876 
3877                 m_testCtx.getLog() << tcu::TestLog::EndSection;
3878 #else  /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG */
3879             catch (...)
3880             {
3881 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG */
3882 
3883                 failed_cases += 1;
3884             }
3885             //run()
3886         }
3887     }
3888 }
3889 
3890 /** Verify that rendered image match expectations
3891  *
3892  *  @param format            Texture format
3893  *  @param resolution        Texture resolution
3894  *  @param shader_type       Shader type
3895  *  @param sampling_function Type of sampling function
3896  *  @param data              Image data
3897  **/
3898 bool TextureCubeMapArraySamplingTest::verifyResult(const formatDefinition &format,
3899                                                    const resolutionDefinition &resolution,
3900                                                    const samplingFunction sampling_function, unsigned char *data)
3901 {
3902     componentProvider component_provider = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
3903 
3904     switch (sampling_function)
3905     {
3906     case Texture:
3907     case TextureGather:
3908         component_provider.getColorFloatComponents = getExpectedColorFloatComponentsForTexture;
3909         component_provider.getColorUByteComponents = getExpectedColorIntComponentsForTexture<glw::GLubyte>;
3910         component_provider.getColorUintComponents  = getExpectedColorIntComponentsForTexture<glw::GLuint>;
3911         component_provider.getColorIntComponents   = getExpectedColorIntComponentsForTexture<glw::GLint>;
3912         component_provider.getDepthComponents      = getExpectedDepthComponentsForTexture;
3913         component_provider.getStencilComponents    = getExpectedStencilComponentsForTexture;
3914         component_provider.getCompressedComponents = getExpectedCompressedComponentsForTexture;
3915         break;
3916     case TextureLod:
3917     case TextureGrad:
3918         component_provider.getColorFloatComponents = getExpectedColorFloatComponentsForTextureLod;
3919         component_provider.getColorUByteComponents = getExpectedColorIntComponentsForTextureLod<glw::GLubyte>;
3920         component_provider.getColorUintComponents  = getExpectedColorIntComponentsForTextureLod<glw::GLuint>;
3921         component_provider.getColorIntComponents   = getExpectedColorIntComponentsForTextureLod<glw::GLint>;
3922         component_provider.getDepthComponents      = getExpectedDepthComponentsForTextureLod;
3923         component_provider.getStencilComponents    = getExpectedStencilComponentsForTextureLod;
3924         component_provider.getCompressedComponents = getExpectedCompressedComponentsForTextureLod;
3925         break;
3926     }
3927 
3928     return verifyResultHelper(format, resolution, component_provider, data);
3929 }
3930 
3931 /** Verify that rendered image match expectations
3932  *
3933  *  @param format            Texture format
3934  *  @param resolution        Texture resolution
3935  *  @param shader_type       Shader type
3936  *  @param sampling_function Type of sampling function
3937  *  @param data              Image data
3938  **/
3939 bool TextureCubeMapArraySamplingTest::verifyResultHelper(const formatDefinition &format,
3940                                                          const resolutionDefinition &resolution,
3941                                                          const componentProvider &component_provider,
3942                                                          unsigned char *data)
3943 {
3944     const glw::GLuint n_mipmap_levels = getMipmapLevelCount(resolution.m_width, resolution.m_height);
3945     const glw::GLuint n_layers        = resolution.m_depth / 6;
3946 
3947     bool result = false;
3948 
3949     if (GL_RGBA == format.m_source.m_format)
3950     {
3951         if (GL_UNSIGNED_BYTE == format.m_source.m_type)
3952         {
3953             result = verifyResultImage<glw::GLubyte, 4, 3, 3>(n_mipmap_levels, n_layers,
3954                                                               component_provider.getColorUByteComponents, data);
3955         }
3956         else if (GL_FLOAT == format.m_source.m_type)
3957         {
3958             result = verifyResultImage<glw::GLfloat, 4, 3, 3>(n_mipmap_levels, n_layers,
3959                                                               component_provider.getColorFloatComponents, data);
3960         }
3961         else if (GL_COMPRESSED_RGBA8_ETC2_EAC == format.m_source.m_type)
3962         {
3963             result = verifyResultImage<glw::GLubyte, 4, 3, 3>(n_mipmap_levels, n_layers,
3964                                                               component_provider.getCompressedComponents, data);
3965         }
3966     }
3967     else if (GL_RGBA_INTEGER == format.m_source.m_format)
3968     {
3969         if (GL_UNSIGNED_INT == format.m_source.m_type)
3970         {
3971             result = verifyResultImage<glw::GLuint, 4, 3, 3>(n_mipmap_levels, n_layers,
3972                                                              component_provider.getColorUintComponents, data);
3973         }
3974         else if (GL_INT == format.m_source.m_type)
3975         {
3976             result = verifyResultImage<glw::GLint, 4, 3, 3>(n_mipmap_levels, n_layers,
3977                                                             component_provider.getColorIntComponents, data);
3978         }
3979     }
3980     if (GL_DEPTH_COMPONENT == format.m_source.m_format)
3981     {
3982         if (GL_FLOAT == format.m_source.m_type)
3983         {
3984             result = verifyResultImage<glw::GLfloat, 1, 3, 3>(n_mipmap_levels, n_layers,
3985                                                               component_provider.getDepthComponents, data);
3986         }
3987     }
3988     if (GL_STENCIL_INDEX == format.m_source.m_format)
3989     {
3990         if (GL_UNSIGNED_BYTE == format.m_source.m_type)
3991         {
3992             result = verifyResultImage<glw::GLuint, 1, 3, 3>(n_mipmap_levels, n_layers,
3993                                                              component_provider.getStencilComponents, data);
3994         }
3995     }
3996 
3997     return result;
3998 }
3999 
4000 /****************************************************************************/
4001 
4002 /** Initialize buffer collection
4003  *
4004  *  @param gl         GL functions
4005  *  @param format     Texture format
4006  *  @param resolution Texture resolution
4007  **/
4008 void TextureCubeMapArraySamplingTest::bufferCollection::init(const glw::Functions &gl, const formatDefinition &format,
4009                                                              const resolutionDefinition &resolution)
4010 {
4011     (void)format;
4012 
4013     static const glw::GLuint n_faces                          = 6;
4014     static const glw::GLuint n_lods_components                = 1;
4015     static const glw::GLuint n_grad_components                = 4;
4016     static const glw::GLuint n_points_per_face                = 9;
4017     static const glw::GLuint n_position_components            = 4;
4018     static const glw::GLuint n_refZ_components                = 1;
4019     static const glw::GLuint n_texture_coordinates_components = 4;
4020 
4021     const glw::GLuint n_layers = resolution.m_depth / n_faces;
4022 
4023     const glw::GLuint n_points_per_layer = n_points_per_face * n_faces;
4024     const glw::GLuint n_total_points     = n_points_per_layer * n_layers;
4025 
4026     const glw::GLuint n_position_step_per_face            = n_position_components * n_points_per_face;
4027     const glw::GLuint n_texture_coordinates_step_per_face = n_texture_coordinates_components * n_points_per_face;
4028     const glw::GLuint n_lods_step_per_face                = n_lods_components * n_points_per_face;
4029     const glw::GLuint n_grad_step_per_face                = n_grad_components * n_points_per_face;
4030     const glw::GLuint n_refZ_step_per_face                = n_refZ_components * n_points_per_face;
4031 
4032     const glw::GLuint n_position_step_per_layer            = n_faces * n_position_step_per_face;
4033     const glw::GLuint n_texture_coordinates_step_per_layer = n_faces * n_texture_coordinates_step_per_face;
4034     const glw::GLuint n_lods_step_per_layer                = n_faces * n_lods_step_per_face;
4035     const glw::GLuint n_grad_step_per_layer                = n_faces * n_grad_step_per_face;
4036     const glw::GLuint n_refZ_step_per_layer                = n_faces * n_refZ_step_per_face;
4037 
4038     const glw::GLuint texture_width    = resolution.m_width;
4039     const glw::GLuint texture_height   = resolution.m_height;
4040     const glw::GLuint n_mip_map_levels = getMipmapLevelCount(texture_width, texture_height);
4041 
4042     std::vector<glw::GLfloat> position_buffer_data;
4043     std::vector<glw::GLfloat> texture_coordinate_buffer_data;
4044     std::vector<glw::GLfloat> texture_coordinate_for_gather_buffer_data;
4045     std::vector<glw::GLfloat> lod_buffer_data;
4046     std::vector<glw::GLfloat> grad_x_buffer_data;
4047     std::vector<glw::GLfloat> grad_y_buffer_data;
4048     std::vector<glw::GLfloat> refZ_buffer_data;
4049 
4050     position_buffer_data.resize(n_total_points * n_position_components);
4051     texture_coordinate_buffer_data.resize(n_total_points * n_texture_coordinates_components);
4052     texture_coordinate_for_gather_buffer_data.resize(n_total_points * n_texture_coordinates_components);
4053     lod_buffer_data.resize(n_total_points * n_lods_components);
4054     grad_x_buffer_data.resize(n_total_points * n_grad_components);
4055     grad_y_buffer_data.resize(n_total_points * n_grad_components);
4056     refZ_buffer_data.resize(n_total_points * n_refZ_components);
4057 
4058     /* Prepare data */
4059     for (glw::GLuint layer = 0; layer < n_layers; ++layer)
4060     {
4061         const glw::GLfloat layer_coordinate = (float)layer;
4062 
4063         for (glw::GLuint face = 0; face < n_faces; ++face)
4064         {
4065             /* Offsets */
4066             const glw::GLuint position_offset = layer * n_position_step_per_layer + face * n_position_step_per_face;
4067             const glw::GLuint texture_coordinates_offset =
4068                 layer * n_texture_coordinates_step_per_layer + face * n_texture_coordinates_step_per_face;
4069             const glw::GLuint lods_offset = layer * n_lods_step_per_layer + face * n_lods_step_per_face;
4070             const glw::GLuint grad_offset = layer * n_grad_step_per_layer + face * n_grad_step_per_face;
4071             const glw::GLuint refZ_offset = layer * n_refZ_step_per_layer + face * n_refZ_step_per_face;
4072 
4073             /* Prepare data */
4074             preparePositionForFace(&position_buffer_data[0] + position_offset, face, layer, n_layers * n_faces);
4075             prepareTextureCoordinatesForFace(&texture_coordinate_buffer_data[0] + texture_coordinates_offset,
4076                                              texture_width, texture_height, layer_coordinate, face);
4077             prepareTextureCoordinatesForGatherForFace(&texture_coordinate_for_gather_buffer_data[0] +
4078                                                           texture_coordinates_offset,
4079                                                       texture_width, texture_height, layer_coordinate, face);
4080             prepareLodForFace(&lod_buffer_data[0] + lods_offset, n_mip_map_levels);
4081             prepareGradXForFace(&grad_x_buffer_data[0] + grad_offset, face,
4082                                 &texture_coordinate_buffer_data[0] + texture_coordinates_offset, texture_width);
4083             prepareGradYForFace(&grad_y_buffer_data[0] + grad_offset, face,
4084                                 &texture_coordinate_buffer_data[0] + texture_coordinates_offset, texture_width);
4085             prepareRefZForFace(&refZ_buffer_data[0] + refZ_offset, n_mip_map_levels, face, layer, n_layers);
4086         }
4087     }
4088 
4089     /* Initialize buffers */
4090     postion.init(gl, (glw::GLsizeiptr)(position_buffer_data.size() * sizeof(glw::GLfloat)), &position_buffer_data[0]);
4091     texture_coordinate.init(gl, (glw::GLsizeiptr)(texture_coordinate_buffer_data.size() * sizeof(glw::GLfloat)),
4092                             &texture_coordinate_buffer_data[0]);
4093     texture_coordinate_for_gather.init(
4094         gl, (glw::GLsizeiptr)(texture_coordinate_for_gather_buffer_data.size() * sizeof(glw::GLfloat)),
4095         &texture_coordinate_for_gather_buffer_data[0]);
4096     lod.init(gl, (glw::GLsizeiptr)(lod_buffer_data.size() * sizeof(glw::GLfloat)), &lod_buffer_data[0]);
4097     grad_x.init(gl, (glw::GLsizeiptr)(grad_x_buffer_data.size() * sizeof(glw::GLfloat)), &grad_x_buffer_data[0]);
4098     grad_y.init(gl, (glw::GLsizeiptr)(grad_y_buffer_data.size() * sizeof(glw::GLfloat)), &grad_y_buffer_data[0]);
4099     refZ.init(gl, (glw::GLsizeiptr)(refZ_buffer_data.size() * sizeof(glw::GLfloat)), &refZ_buffer_data[0]);
4100 }
4101 
4102 /** Constructor.
4103  *
4104  **/
4105 TextureCubeMapArraySamplingTest::bufferDefinition::bufferDefinition()
4106     : m_gl(0)
4107     , m_buffer_object_id(m_invalid_buffer_object_id)
4108 {
4109 }
4110 
4111 /** Destructor
4112  *
4113  **/
4114 TextureCubeMapArraySamplingTest::bufferDefinition::~bufferDefinition()
4115 {
4116     if (m_invalid_buffer_object_id != m_buffer_object_id)
4117     {
4118         if (0 != m_gl)
4119         {
4120             m_gl->deleteBuffers(1, &m_buffer_object_id);
4121 
4122             m_gl = 0;
4123         }
4124 
4125         m_buffer_object_id = m_invalid_buffer_object_id;
4126     }
4127 }
4128 
4129 /** Bind buffer
4130  *
4131  *  @param target Target for bind
4132  **/
4133 void TextureCubeMapArraySamplingTest::bufferDefinition::bind(glw::GLenum target) const
4134 {
4135     if (m_invalid_buffer_object_id == m_buffer_object_id)
4136     {
4137         throw tcu::InternalError("Invalid buffer object id used", "", __FILE__, __LINE__);
4138     }
4139 
4140     m_gl->bindBuffer(target, m_buffer_object_id);
4141     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to bind buffer.");
4142 }
4143 
4144 /** Bind buffer
4145  *
4146  *  @param target Target for bind
4147  *  @param index  Index for target
4148  **/
4149 void TextureCubeMapArraySamplingTest::bufferDefinition::bind(glw::GLenum target, glw::GLuint index) const
4150 {
4151     if (m_invalid_buffer_object_id == m_buffer_object_id)
4152     {
4153         throw tcu::InternalError("Invalid buffer object id used", "", __FILE__, __LINE__);
4154     }
4155 
4156     m_gl->bindBufferBase(target, index, m_buffer_object_id);
4157     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to bind buffer.");
4158 }
4159 
4160 /** Initialize buffer definition
4161  *
4162  *  @param gl          GL functions
4163  *  @param buffer_size Size of buffer
4164  *  @param buffer_data Buffer data
4165  **/
4166 void TextureCubeMapArraySamplingTest::bufferDefinition::init(const glw::Functions &gl, glw::GLsizeiptr buffer_size,
4167                                                              glw::GLvoid *buffer_data)
4168 {
4169     m_gl = &gl;
4170 
4171     m_gl->genBuffers(1, &m_buffer_object_id);
4172     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to generate buffer.");
4173 
4174     m_gl->bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
4175     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to bind buffer.");
4176 
4177     m_gl->bufferData(GL_ARRAY_BUFFER, buffer_size, buffer_data, GL_STATIC_DRAW);
4178     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to update buffer's data.");
4179 
4180     m_gl->bindBuffer(GL_ARRAY_BUFFER, 0);
4181     m_gl->getError();
4182 }
4183 
4184 /** Constructor
4185  *
4186  *  @param internal_format Internal format
4187  *  @param format          Format
4188  *  @param type            Type
4189  *  @param is_compressed   If format is compressed
4190  *  @param sampler_type    Type of sampler
4191  *  @param name            Name of format
4192  **/
4193 TextureCubeMapArraySamplingTest::formatDefinition::formatDefinition(glw::GLenum internal_format, glw::GLenum format,
4194                                                                     glw::GLenum type, bool is_compressed,
4195                                                                     samplerType sampler_type, const glw::GLchar *name)
4196     : m_source(internal_format, format, type, is_compressed)
4197     , m_destination(internal_format, format, type, false /* is_compressed*/)
4198     , m_sampler_type(sampler_type)
4199     , m_name(name)
4200 {
4201 }
4202 
4203 /** Constructor
4204  *
4205  *  @param src_internal_format Internal format of source image
4206  *  @param src_format          Format of source image
4207  *  @param src_type            Type of source image
4208  *  @param src_is_compressed   If format of source image is compressed
4209  *  @param dst_internal_format Internal format of destination image
4210  *  @param dst_format          Format of destination image
4211  *  @param dst_type            Type of destination image
4212  *  @param sampler_type        Type of sampler
4213  *  @param name                Name of format
4214  **/
4215 TextureCubeMapArraySamplingTest::formatDefinition::formatDefinition(glw::GLenum src_internal_format,
4216                                                                     glw::GLenum src_format, glw::GLenum src_type,
4217                                                                     bool src_is_compressed,
4218                                                                     glw::GLenum dst_internal_format,
4219                                                                     glw::GLenum dst_format, glw::GLenum dst_type,
4220                                                                     samplerType sampler_type, const glw::GLchar *name)
4221     : m_source(src_internal_format, src_format, src_type, src_is_compressed)
4222     , m_destination(dst_internal_format, dst_format, dst_type, false /* is_compressed*/)
4223     , m_sampler_type(sampler_type)
4224     , m_name(name)
4225 {
4226 }
4227 
4228 /** Constructor
4229  *
4230  *  @param internal_format Internal format
4231  *  @param format          Format
4232  *  @param type            Type
4233  *  @param is_compressed   If format is compressed
4234  **/
4235 TextureCubeMapArraySamplingTest::formatInfo::formatInfo(glw::GLenum internal_format, glw::GLenum format,
4236                                                         glw::GLenum type, bool is_compressed)
4237     : m_internal_format(internal_format)
4238     , m_format(format)
4239     , m_type(type)
4240     , m_is_compressed(is_compressed)
4241 {
4242 }
4243 
4244 /** Get collection of programs for sampling function
4245  *
4246  *  @param function Type of sampling function
4247  *
4248  *  @return Collection of programs for given sampling function
4249  **/
4250 const TextureCubeMapArraySamplingTest::programCollectionForFunction *TextureCubeMapArraySamplingTest::
4251     programCollectionForFormat::getPrograms(samplingFunction function) const
4252 {
4253     switch (function)
4254     {
4255     case Texture:
4256         return &m_programs_for_texture;
4257     case TextureLod:
4258         return &m_programs_for_textureLod;
4259     case TextureGrad:
4260         return &m_programs_for_textureGrad;
4261     case TextureGather:
4262         return &m_programs_for_textureGather;
4263     }
4264 
4265     return 0;
4266 }
4267 
4268 /** Initialize program collection for format
4269  *
4270  *  @param gl                GL functions
4271  *  @param shader_collection Collection of shaders
4272  *  @param test              Instance of test class
4273  **/
4274 void TextureCubeMapArraySamplingTest::programCollectionForFormat::init(
4275     const glw::Functions &gl, const shaderCollectionForTextureFormat &shader_collection,
4276     TextureCubeMapArraySamplingTest &test, bool isContextES)
4277 {
4278     shaderGroup shader_group;
4279 
4280     shader_collection.getShaderGroup(Texture, shader_group);
4281     m_programs_for_texture.init(gl, shader_group, test, isContextES);
4282 
4283     shader_collection.getShaderGroup(TextureLod, shader_group);
4284     m_programs_for_textureLod.init(gl, shader_group, test, isContextES);
4285 
4286     shader_collection.getShaderGroup(TextureGrad, shader_group);
4287     m_programs_for_textureGrad.init(gl, shader_group, test, isContextES);
4288 
4289     shader_collection.getShaderGroup(TextureGather, shader_group);
4290     m_programs_for_textureGather.init(gl, shader_group, test, isContextES);
4291 }
4292 
4293 /** Get program with specified sampling shader
4294  *
4295  *  @param shader_type Type of shader
4296  *
4297  *  @returns Program information
4298  **/
4299 const TextureCubeMapArraySamplingTest::programDefinition *TextureCubeMapArraySamplingTest::
4300     programCollectionForFunction::getProgram(shaderType shader_type) const
4301 {
4302     switch (shader_type)
4303     {
4304     case Compute:
4305         return &program_with_sampling_compute_shader;
4306     case Fragment:
4307         return &program_with_sampling_fragment_shader;
4308     case Geometry:
4309         return &program_with_sampling_geometry_shader;
4310     case Tesselation_Control:
4311         return &program_with_sampling_tesselation_control_shader;
4312     case Tesselation_Evaluation:
4313         return &program_with_sampling_tesselation_evaluation_shader;
4314     case Vertex:
4315         return &program_with_sampling_vertex_shader;
4316     }
4317 
4318     return 0;
4319 }
4320 
4321 /** Initialize program collection for sampling function
4322  *
4323  *  @param gl           GL functions
4324  *  @param shader_group Group of shader compatible with sampling function
4325  *  @param test         Instance of test class
4326  **/
4327 void TextureCubeMapArraySamplingTest::programCollectionForFunction::init(const glw::Functions &gl,
4328                                                                          const shaderGroup &shader_group,
4329                                                                          TextureCubeMapArraySamplingTest &test,
4330                                                                          bool isContextES)
4331 {
4332     program_with_sampling_compute_shader.init(gl, shader_group, Compute, isContextES);
4333     program_with_sampling_fragment_shader.init(gl, shader_group, Fragment, isContextES);
4334     program_with_sampling_vertex_shader.init(gl, shader_group, Vertex, isContextES);
4335 
4336     test.link(program_with_sampling_compute_shader);
4337     test.link(program_with_sampling_fragment_shader);
4338     test.link(program_with_sampling_vertex_shader);
4339 
4340     if (test.m_is_geometry_shader_extension_supported)
4341     {
4342         program_with_sampling_geometry_shader.init(gl, shader_group, Geometry, isContextES);
4343         test.link(program_with_sampling_geometry_shader);
4344     }
4345 
4346     if (test.m_is_tessellation_shader_supported)
4347     {
4348         program_with_sampling_tesselation_control_shader.init(gl, shader_group, Tesselation_Control, isContextES);
4349         program_with_sampling_tesselation_evaluation_shader.init(gl, shader_group, Tesselation_Evaluation, isContextES);
4350         test.link(program_with_sampling_tesselation_control_shader);
4351         test.link(program_with_sampling_tesselation_evaluation_shader);
4352     }
4353 }
4354 
4355 /** Constructor
4356  *
4357  **/
4358 TextureCubeMapArraySamplingTest::programDefinition::programDefinition()
4359     : compute_shader(0)
4360     , geometry_shader(0)
4361     , fragment_shader(0)
4362     , tesselation_control_shader(0)
4363     , tesselation_evaluation_shader(0)
4364     , vertex_shader(0)
4365     , m_program_object_id(m_invalid_program_object_id)
4366     , m_gl(DE_NULL)
4367 {
4368 }
4369 
4370 /** Destructor
4371  *
4372  **/
4373 TextureCubeMapArraySamplingTest::programDefinition::~programDefinition()
4374 {
4375     if (m_invalid_program_object_id != m_program_object_id)
4376     {
4377         if (0 != m_gl)
4378         {
4379             m_gl->deleteProgram(m_program_object_id);
4380             m_program_object_id = m_invalid_program_object_id;
4381             m_gl                = 0;
4382         }
4383     }
4384 }
4385 
4386 /** Get program id
4387  *
4388  *  @returns Program id
4389  **/
4390 glw::GLuint TextureCubeMapArraySamplingTest::programDefinition::getProgramId() const
4391 {
4392     return m_program_object_id;
4393 }
4394 
4395 /** Get shader
4396  *
4397  *  @param shader_type Requested shader type
4398  *
4399  *  @returns Pointer to shader information. Can be null.
4400  **/
4401 const TextureCubeMapArraySamplingTest::shaderDefinition *TextureCubeMapArraySamplingTest::programDefinition::getShader(
4402     shaderType shader_type) const
4403 {
4404     switch (shader_type)
4405     {
4406     case Compute:
4407         return compute_shader;
4408     case Fragment:
4409         return fragment_shader;
4410     case Geometry:
4411         return geometry_shader;
4412     case Tesselation_Control:
4413         return tesselation_control_shader;
4414     case Tesselation_Evaluation:
4415         return tesselation_evaluation_shader;
4416     case Vertex:
4417         return vertex_shader;
4418     }
4419 
4420     return 0;
4421 }
4422 
4423 /** Initialize program information
4424  *
4425  *  @param gl           GL functions
4426  *  @param shader_group Group of shaders compatible with samplinbg function and texture format
4427  *  @param shader_type  Stage that will execute sampling
4428  **/
4429 void TextureCubeMapArraySamplingTest::programDefinition::init(const glw::Functions &gl, const shaderGroup &shader_group,
4430                                                               shaderType shader_type, bool isContextES)
4431 {
4432     m_gl = &gl;
4433 
4434     bool is_program_defined = false;
4435 
4436     switch (shader_type)
4437     {
4438     case Compute:
4439         compute_shader     = shader_group.sampling_compute_shader;
4440         is_program_defined = (0 != compute_shader);
4441         break;
4442     case Fragment:
4443         fragment_shader    = shader_group.sampling_fragment_shader;
4444         vertex_shader      = shader_group.pass_through_vertex_shader;
4445         is_program_defined = ((0 != fragment_shader) && (0 != vertex_shader));
4446         break;
4447     case Geometry:
4448         fragment_shader    = shader_group.pass_through_fragment_shader;
4449         geometry_shader    = shader_group.sampling_geometry_shader;
4450         vertex_shader      = shader_group.pass_through_vertex_shader;
4451         is_program_defined = ((0 != fragment_shader) && (0 != geometry_shader) && (0 != vertex_shader));
4452         break;
4453     case Tesselation_Control:
4454         fragment_shader               = shader_group.pass_through_fragment_shader;
4455         tesselation_control_shader    = shader_group.sampling_tesselation_control_shader;
4456         tesselation_evaluation_shader = shader_group.pass_through_tesselation_evaluation_shader;
4457         vertex_shader                 = shader_group.pass_through_vertex_shader;
4458         is_program_defined            = ((0 != fragment_shader) && (0 != tesselation_control_shader) &&
4459                               (0 != tesselation_evaluation_shader) && (0 != vertex_shader));
4460         break;
4461     case Tesselation_Evaluation:
4462         fragment_shader = shader_group.pass_through_fragment_shader;
4463         if (isContextES)
4464         {
4465             tesselation_control_shader = shader_group.pass_through_tesselation_control_shader;
4466         }
4467         tesselation_evaluation_shader = shader_group.sampling_tesselation_evaluation_shader;
4468         vertex_shader                 = shader_group.pass_through_vertex_shader;
4469         is_program_defined            = ((0 != fragment_shader) && (0 != tesselation_control_shader) &&
4470                               (0 != tesselation_evaluation_shader) && (0 != vertex_shader));
4471         break;
4472     case Vertex:
4473         fragment_shader    = shader_group.pass_through_fragment_shader;
4474         vertex_shader      = shader_group.sampling_vertex_shader;
4475         is_program_defined = ((0 != fragment_shader) && (0 != vertex_shader));
4476         break;
4477     }
4478 
4479     if (true == is_program_defined)
4480     {
4481         m_program_object_id = m_gl->createProgram();
4482 
4483         GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
4484 
4485         if (m_invalid_program_object_id == m_program_object_id)
4486         {
4487             throw tcu::InternalError("glCreateProgram return invalid id", "", __FILE__, __LINE__);
4488         }
4489     }
4490 }
4491 
4492 /** Link program
4493  *
4494  *  @return  true When linking was successful
4495  *          false When linking failed
4496  **/
4497 bool TextureCubeMapArraySamplingTest::programDefinition::link()
4498 {
4499     if (m_invalid_program_object_id == m_program_object_id)
4500     {
4501         return false;
4502     }
4503 
4504     if (0 != compute_shader)
4505     {
4506         compute_shader->attach(m_program_object_id);
4507     }
4508 
4509     if (0 != geometry_shader)
4510     {
4511         geometry_shader->attach(m_program_object_id);
4512     }
4513 
4514     if (0 != fragment_shader)
4515     {
4516         fragment_shader->attach(m_program_object_id);
4517     }
4518 
4519     if (0 != tesselation_control_shader)
4520     {
4521         tesselation_control_shader->attach(m_program_object_id);
4522     }
4523 
4524     if (0 != tesselation_evaluation_shader)
4525     {
4526         tesselation_evaluation_shader->attach(m_program_object_id);
4527     }
4528 
4529     if (0 != vertex_shader)
4530     {
4531         vertex_shader->attach(m_program_object_id);
4532     }
4533 
4534     /* Link Program */
4535     m_gl->linkProgram(m_program_object_id);
4536     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glLinkProgram() call failed.");
4537 
4538     /* Check linking status */
4539     glw::GLint linkStatus = GL_FALSE;
4540     m_gl->getProgramiv(m_program_object_id, GL_LINK_STATUS, &linkStatus);
4541     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glGetProgramiv() call failed.");
4542 
4543     if (linkStatus == GL_FALSE)
4544     {
4545         return false;
4546     }
4547 
4548     return true;
4549 }
4550 
4551 /** Constructor
4552  *
4553  *  @param width  Width
4554  *  @param height Height
4555  *  @param depth  Depth
4556  **/
4557 TextureCubeMapArraySamplingTest::resolutionDefinition::resolutionDefinition(glw::GLuint width, glw::GLuint height,
4558                                                                             glw::GLuint depth)
4559     : m_width(width)
4560     , m_height(height)
4561     , m_depth(depth)
4562 {
4563 }
4564 
4565 /** Constructor
4566  *
4567  *  @param function Type of sampling function
4568  *  @param name     Name of sampling function
4569  **/
4570 TextureCubeMapArraySamplingTest::samplingFunctionDefinition::samplingFunctionDefinition(samplingFunction function,
4571                                                                                         const glw::GLchar *name)
4572     : m_function(function)
4573     , m_name(name)
4574 {
4575 }
4576 
4577 /** Initialize shader collection for sampling function
4578  *
4579  *  @param gl                GL functions
4580  *  @param format            Texture format
4581  *  @param sampling_function Sampling function
4582  *  @param test              Instance of test class
4583  **/
4584 void TextureCubeMapArraySamplingTest::shaderCollectionForSamplingRoutine::init(
4585     const glw::Functions &gl, const formatDefinition &format, const samplingFunction &sampling_function,
4586     TextureCubeMapArraySamplingTest &test)
4587 {
4588     m_sampling_function = sampling_function;
4589 
4590     std::string pass_through_vertex_shader_source;
4591     std::string pass_through_tesselation_control_shader_source;
4592     std::string sampling_compute_shader_source;
4593     std::string sampling_fragment_shader_source;
4594     std::string sampling_geometry_shader_source;
4595     std::string sampling_tesselation_control_shader_source;
4596     std::string sampling_tesselation_evaluation_shader_source;
4597     std::string sampling_vertex_shader_source;
4598 
4599     test.getPassThroughVertexShaderCode(format.m_sampler_type, m_sampling_function, pass_through_vertex_shader_source);
4600 
4601     test.getPassThroughTesselationControlShaderCode(format.m_sampler_type, m_sampling_function,
4602                                                     pass_through_tesselation_control_shader_source);
4603 
4604     test.getSamplingComputeShaderCode(format.m_sampler_type, m_sampling_function, sampling_compute_shader_source);
4605 
4606     test.getSamplingFragmentShaderCode(format.m_sampler_type, m_sampling_function, sampling_fragment_shader_source);
4607 
4608     test.getSamplingGeometryShaderCode(format.m_sampler_type, m_sampling_function, sampling_geometry_shader_source);
4609 
4610     test.getSamplingTesselationControlShaderCode(format.m_sampler_type, m_sampling_function,
4611                                                  sampling_tesselation_control_shader_source);
4612 
4613     test.getSamplingTesselationEvaluationShaderCode(format.m_sampler_type, m_sampling_function,
4614                                                     sampling_tesselation_evaluation_shader_source);
4615 
4616     test.getSamplingVertexShaderCode(format.m_sampler_type, m_sampling_function, sampling_vertex_shader_source);
4617 
4618     pass_through_vertex_shader.init(gl, GL_VERTEX_SHADER, pass_through_vertex_shader_source, &test);
4619     sampling_compute_shader.init(gl, GL_COMPUTE_SHADER, sampling_compute_shader_source, &test);
4620     sampling_fragment_shader.init(gl, GL_FRAGMENT_SHADER, sampling_fragment_shader_source, &test);
4621     sampling_vertex_shader.init(gl, GL_VERTEX_SHADER, sampling_vertex_shader_source, &test);
4622 
4623     test.compile(pass_through_vertex_shader);
4624     test.compile(sampling_compute_shader);
4625     test.compile(sampling_fragment_shader);
4626     test.compile(sampling_vertex_shader);
4627 
4628     if (test.m_is_tessellation_shader_supported)
4629     {
4630         pass_through_tesselation_control_shader.init(gl, test.m_glExtTokens.TESS_CONTROL_SHADER,
4631                                                      pass_through_tesselation_control_shader_source, &test);
4632         sampling_tesselation_control_shader.init(gl, test.m_glExtTokens.TESS_CONTROL_SHADER,
4633                                                  sampling_tesselation_control_shader_source, &test);
4634         sampling_tesselation_evaluation_shader.init(gl, test.m_glExtTokens.TESS_EVALUATION_SHADER,
4635                                                     sampling_tesselation_evaluation_shader_source, &test);
4636 
4637         test.compile(pass_through_tesselation_control_shader);
4638         test.compile(sampling_tesselation_control_shader);
4639         test.compile(sampling_tesselation_evaluation_shader);
4640     }
4641 
4642     if (test.m_is_geometry_shader_extension_supported)
4643     {
4644         sampling_geometry_shader.init(gl, test.m_glExtTokens.GEOMETRY_SHADER, sampling_geometry_shader_source, &test);
4645 
4646         test.compile(sampling_geometry_shader);
4647     }
4648 }
4649 
4650 /** Get group of shader compatible with sampling function and texture format
4651  *
4652  *  @param function     Sampling function
4653  *  @param shader_group Group of shaders
4654  **/
4655 void TextureCubeMapArraySamplingTest::shaderCollectionForTextureFormat::getShaderGroup(samplingFunction function,
4656                                                                                        shaderGroup &shader_group) const
4657 {
4658     shader_group.init();
4659 
4660     for (shaderCollectionForSamplingFunctionVectorType::const_iterator it  = per_sampling_routine.begin(),
4661                                                                        end = per_sampling_routine.end();
4662          end != it; ++it)
4663     {
4664         if (it->m_sampling_function == function)
4665         {
4666             shader_group.pass_through_fragment_shader               = &pass_through_fragment_shader;
4667             shader_group.pass_through_tesselation_control_shader    = &it->pass_through_tesselation_control_shader;
4668             shader_group.pass_through_tesselation_evaluation_shader = &pass_through_tesselation_evaluation_shader;
4669             shader_group.pass_through_vertex_shader                 = &it->pass_through_vertex_shader;
4670 
4671             shader_group.sampling_compute_shader                = &it->sampling_compute_shader;
4672             shader_group.sampling_fragment_shader               = &it->sampling_fragment_shader;
4673             shader_group.sampling_geometry_shader               = &it->sampling_geometry_shader;
4674             shader_group.sampling_tesselation_control_shader    = &it->sampling_tesselation_control_shader;
4675             shader_group.sampling_tesselation_evaluation_shader = &it->sampling_tesselation_evaluation_shader;
4676             shader_group.sampling_vertex_shader                 = &it->sampling_vertex_shader;
4677 
4678             return;
4679         }
4680     }
4681 }
4682 
4683 /** Initialize shader collection for texture format
4684  *
4685  *  @param gl                GL functions
4686  *  @param format            Texture format
4687  *  @param sampling_routines Set of sampling functions
4688  *  @param test              Instance of test class
4689  **/
4690 void TextureCubeMapArraySamplingTest::shaderCollectionForTextureFormat::init(
4691     const glw::Functions &gl, const formatDefinition &format, const samplingFunctionsVectorType &sampling_routines,
4692     TextureCubeMapArraySamplingTest &test)
4693 {
4694     std::string pass_through_fragment_shader_source;
4695     std::string pass_through_tesselation_evaluation_shader_source;
4696     glw::GLuint n_routines_supporting_format = 0;
4697 
4698     test.getPassThroughFragmentShaderCode(format.m_sampler_type, pass_through_fragment_shader_source);
4699     test.getPassThroughTesselationEvaluationShaderCode(format.m_sampler_type,
4700                                                        pass_through_tesselation_evaluation_shader_source);
4701 
4702     pass_through_fragment_shader.init(gl, GL_FRAGMENT_SHADER, pass_through_fragment_shader_source, &test);
4703 
4704     if (test.m_is_tessellation_shader_supported)
4705     {
4706         pass_through_tesselation_evaluation_shader.init(gl, test.m_glExtTokens.TESS_EVALUATION_SHADER,
4707                                                         pass_through_tesselation_evaluation_shader_source, &test);
4708     }
4709 
4710     test.compile(pass_through_fragment_shader);
4711 
4712     if (test.m_is_tessellation_shader_supported)
4713     {
4714         test.compile(pass_through_tesselation_evaluation_shader);
4715     }
4716 
4717     for (samplingFunctionsVectorType::const_iterator it = sampling_routines.begin(), end = sampling_routines.end();
4718          end != it; ++it)
4719     {
4720         if (TextureCubeMapArraySamplingTest::isSamplerSupportedByFunction(format.m_sampler_type, it->m_function))
4721         {
4722             n_routines_supporting_format += 1;
4723         }
4724     }
4725 
4726     per_sampling_routine.resize(n_routines_supporting_format);
4727     shaderCollectionForSamplingFunctionVectorType::iterator jt = per_sampling_routine.begin();
4728 
4729     for (samplingFunctionsVectorType::const_iterator it = sampling_routines.begin(), end = sampling_routines.end();
4730          end != it; ++it)
4731     {
4732         if (TextureCubeMapArraySamplingTest::isSamplerSupportedByFunction(format.m_sampler_type, it->m_function))
4733         {
4734             jt->init(gl, format, it->m_function, test);
4735             ++jt;
4736         }
4737     }
4738 }
4739 
4740 /** Constructor
4741  *
4742  *  @param type           Type of shader
4743  *  @param is_supported   If configuration is supported
4744  *  @param primitive_type Type of primitive
4745  *  @param name           Name of sampling shader stage
4746  **/
4747 TextureCubeMapArraySamplingTest::shaderConfiguration::shaderConfiguration(shaderType type, glw::GLenum primitive_type,
4748                                                                           const glw::GLchar *name)
4749     : m_type(type)
4750     , m_primitive_type(primitive_type)
4751     , m_name(name)
4752 {
4753 }
4754 
4755 /** Constructor
4756  *
4757  **/
4758 TextureCubeMapArraySamplingTest::shaderDefinition::shaderDefinition()
4759     : m_gl(0)
4760     , m_shader_stage(0)
4761     , m_shader_object_id(m_invalid_shader_object_id)
4762 {
4763 }
4764 
4765 /** Destructor
4766  *
4767  **/
4768 TextureCubeMapArraySamplingTest::shaderDefinition::~shaderDefinition()
4769 {
4770     if (m_invalid_shader_object_id != m_shader_object_id)
4771     {
4772         if (0 != m_gl)
4773         {
4774             m_gl->deleteShader(m_shader_object_id);
4775 
4776             m_gl = 0;
4777         }
4778 
4779         m_shader_object_id = m_invalid_shader_object_id;
4780     }
4781 
4782     m_source.clear();
4783 }
4784 
4785 /** Attach shade to program
4786  *
4787  *  @parma program_object_id Progam id
4788  **/
4789 void TextureCubeMapArraySamplingTest::shaderDefinition::attach(glw::GLuint program_object_id) const
4790 {
4791     if (0 == m_gl)
4792     {
4793         throw tcu::InternalError("shaderDefinition not initialized", "", __FILE__, __LINE__);
4794     }
4795 
4796     m_gl->attachShader(program_object_id, m_shader_object_id);
4797 
4798     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glAttachShader() call failed.");
4799 }
4800 
4801 /** Compile shader
4802  *
4803  *  @returns true  When successful
4804  *           false When compilation failed
4805  **/
4806 bool TextureCubeMapArraySamplingTest::shaderDefinition::compile()
4807 {
4808     glw::GLint compile_status = GL_FALSE;
4809     const glw::GLchar *source = m_source.c_str();
4810 
4811     /* Set shaders source */
4812     m_gl->shaderSource(m_shader_object_id, 1, &source, NULL);
4813 
4814     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glShaderSource() call failed.");
4815 
4816     /* Try to compile the shader */
4817     m_gl->compileShader(m_shader_object_id);
4818 
4819     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glCompileShader() call failed.");
4820 
4821     /* Check if all shaders compiled successfully */
4822     m_gl->getShaderiv(m_shader_object_id, GL_COMPILE_STATUS, &compile_status);
4823 
4824     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glGetShaderiv() call failed.");
4825 
4826     if (compile_status == GL_FALSE)
4827     {
4828         return false;
4829     }
4830 
4831     return true;
4832 }
4833 
4834 /** Get shader id
4835  *
4836  *  @returns Shader id
4837  **/
4838 glw::GLuint TextureCubeMapArraySamplingTest::shaderDefinition::getShaderId() const
4839 {
4840     return m_shader_object_id;
4841 }
4842 
4843 /** Get source
4844  *
4845  *  @returns Code of shader
4846  **/
4847 const std::string &TextureCubeMapArraySamplingTest::shaderDefinition::getSource() const
4848 {
4849     return m_source;
4850 }
4851 
4852 /** Initialize shader informations
4853  *
4854  *  @param gl           GL functions
4855  *  @param shader_stage Stage of shader
4856  *  @param source       Source of shader
4857  **/
4858 void TextureCubeMapArraySamplingTest::shaderDefinition::init(const glw::Functions &gl, glw::GLenum shader_stage,
4859                                                              const std::string &source,
4860                                                              TextureCubeMapArraySamplingTest *test)
4861 {
4862     m_gl                           = &gl;
4863     m_shader_stage                 = shader_stage;
4864     const glw::GLchar *source_cstr = source.c_str();
4865     m_source                       = test->specializeShader(1, &source_cstr);
4866 
4867     if (m_invalid_shader_object_id == m_shader_object_id)
4868     {
4869         if (0 != m_gl)
4870         {
4871             m_shader_object_id = m_gl->createShader(m_shader_stage);
4872 
4873             GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shader");
4874 
4875             if (m_invalid_shader_object_id == m_shader_object_id)
4876             {
4877                 throw tcu::InternalError("glCreateShader returned invalid id", "", __FILE__, __LINE__);
4878             }
4879         }
4880     }
4881 }
4882 
4883 /** Initialize shader group
4884  *
4885  **/
4886 void TextureCubeMapArraySamplingTest::shaderGroup::init()
4887 {
4888     pass_through_fragment_shader               = 0;
4889     pass_through_tesselation_control_shader    = 0;
4890     pass_through_tesselation_evaluation_shader = 0;
4891     pass_through_vertex_shader                 = 0;
4892     sampling_compute_shader                    = 0;
4893     sampling_fragment_shader                   = 0;
4894     sampling_geometry_shader                   = 0;
4895     sampling_tesselation_control_shader        = 0;
4896     sampling_tesselation_evaluation_shader     = 0;
4897     sampling_vertex_shader                     = 0;
4898 }
4899 
4900 /** Constructor
4901  *
4902  **/
4903 TextureCubeMapArraySamplingTest::textureDefinition::textureDefinition()
4904     : m_gl(0)
4905     , m_texture_object_id(m_invalid_texture_object_id)
4906 {
4907 }
4908 
4909 /** Destructor
4910  *
4911  **/
4912 TextureCubeMapArraySamplingTest::textureDefinition::~textureDefinition()
4913 {
4914     if (m_invalid_texture_object_id != m_texture_object_id)
4915     {
4916         if (0 != m_gl)
4917         {
4918             m_gl->deleteTextures(1, &m_texture_object_id);
4919 
4920             m_gl = 0;
4921         }
4922 
4923         m_texture_object_id = m_invalid_texture_object_id;
4924     }
4925 }
4926 
4927 /** Bind texture
4928  *
4929  *  @param binding_point Where texture will be bound
4930  **/
4931 void TextureCubeMapArraySamplingTest::textureDefinition::bind(glw::GLenum binding_point) const
4932 {
4933     if (0 == m_gl)
4934     {
4935         throw tcu::InternalError("TextureDefinition not initialized", "", __FILE__, __LINE__);
4936     }
4937 
4938     m_gl->bindTexture(binding_point, m_texture_object_id);
4939     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to bind texture");
4940 }
4941 
4942 /** Get texture id
4943  *
4944  *  @returns Texture id
4945  **/
4946 glw::GLuint TextureCubeMapArraySamplingTest::textureDefinition::getTextureId() const
4947 {
4948     return m_texture_object_id;
4949 }
4950 
4951 /** Initialize texture information
4952  *
4953  *  @param gl         GL functions
4954  *  @param bind_image Address of glBindImageTexture procedure
4955  **/
4956 void TextureCubeMapArraySamplingTest::textureDefinition::init(const glw::Functions &gl)
4957 {
4958     m_gl = &gl;
4959 
4960     gl.genTextures(1, &m_texture_object_id);
4961     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to generate texture");
4962 }
4963 
4964 /** Set texture as image
4965  *
4966  *  @param image_unit      Index of image unit
4967  *  @param internal_format Format for image unit
4968  **/
4969 void TextureCubeMapArraySamplingTest::textureDefinition::setupImage(glw::GLuint image_unit, glw::GLenum internal_format)
4970 {
4971     if ((0 == m_gl) || (m_invalid_texture_object_id == m_texture_object_id))
4972     {
4973         throw tcu::InternalError("Not initialized textureDefinition", "", __FILE__, __LINE__);
4974     }
4975 
4976     m_gl->bindImageTexture(image_unit, m_texture_object_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, internal_format);
4977 
4978     GLU_EXPECT_NO_ERROR(m_gl->getError(), "glBindImageTexture");
4979 }
4980 
4981 /** Setup texture unit with this
4982  *
4983  *  @param texture_unit Index of texture unit
4984  *  @param sampler_name_p Name of sampler uniform
4985  *  @param program_id   Program id
4986  *  @param is_shadow    If depth comparison should be enabled
4987  **/
4988 void TextureCubeMapArraySamplingTest::textureDefinition::setupSampler(glw::GLuint texture_unit,
4989                                                                       const glw::GLchar *sampler_name_p,
4990                                                                       glw::GLuint program_id, bool is_shadow)
4991 {
4992     if ((0 == m_gl) || (m_invalid_texture_object_id == m_texture_object_id))
4993     {
4994         throw tcu::InternalError("Not initialized textureDefinition", "", __FILE__, __LINE__);
4995     }
4996 
4997     glw::GLint sampler_location = m_gl->getUniformLocation(program_id, sampler_name_p);
4998     if ((m_invalid_uniform_location == (glw::GLuint)sampler_location) || (GL_NO_ERROR != m_gl->getError()))
4999     {
5000         //throw tcu::InternalError("Failed to get sampler location", sampler_name_p, __FILE__, __LINE__);
5001         return;
5002     }
5003 
5004     m_gl->activeTexture(GL_TEXTURE0 + texture_unit);
5005     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to activate texture unit");
5006 
5007     m_gl->bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_texture_object_id);
5008     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to bind texture to GL_TEXTURE_CUBE_MAP_ARRAY_EXT");
5009 
5010     if (true == is_shadow)
5011     {
5012         m_gl->texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
5013         m_gl->texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
5014     }
5015 
5016     m_gl->uniform1i(sampler_location, texture_unit);
5017     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to set sampler uniform");
5018 }
5019 
5020 /** Constructor
5021  *
5022  **/
5023 TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::vertexArrayObjectDefinition()
5024     : m_gl(0)
5025     , m_vertex_array_object_id(m_invalid_vertex_array_object_id)
5026 {
5027 }
5028 
5029 /** Destructor
5030  *
5031  **/
5032 TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::~vertexArrayObjectDefinition()
5033 {
5034     if (m_invalid_vertex_array_object_id != m_vertex_array_object_id)
5035     {
5036         if (0 != m_gl)
5037         {
5038             m_gl->deleteVertexArrays(1, &m_vertex_array_object_id);
5039 
5040             m_gl = 0;
5041         }
5042 
5043         m_vertex_array_object_id = m_invalid_vertex_array_object_id;
5044     }
5045 }
5046 
5047 /** Initialize vertex array object
5048  *
5049  *  @param gl                GL functions
5050  *  @param format            Texture format
5051  *  @param sampling_function Type of sampling function
5052  *  @param buffers           Buffer collection
5053  *  @param program_id        Program id
5054  **/
5055 void TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::init(const glw::Functions &gl,
5056                                                                         const formatDefinition &format,
5057                                                                         const samplingFunction &sampling_function,
5058                                                                         const bufferCollection &buffers,
5059                                                                         glw::GLuint program_id)
5060 {
5061     m_gl = &gl;
5062 
5063     m_gl->genVertexArrays(1, &m_vertex_array_object_id);
5064     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to generate VAO.");
5065 
5066     m_gl->bindVertexArray(m_vertex_array_object_id);
5067     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to bind VAO.");
5068 
5069     attributeDefinition positionAttribute = {vertex_shader_position, type_vec4, Position, 0};
5070     const attributeDefinition *format_attributes;
5071     glw::GLuint n_format_attributes;
5072     const attributeDefinition *routine_attributes = 0;
5073     glw::GLuint n_routine_attributes              = 0;
5074 
5075     getAttributes(format.m_sampler_type, format_attributes, n_format_attributes);
5076     getAttributes(sampling_function, routine_attributes, n_routine_attributes);
5077 
5078     setupAttribute(positionAttribute, buffers, program_id);
5079 
5080     for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
5081     {
5082         setupAttribute(routine_attributes[i], buffers, program_id);
5083     }
5084 
5085     for (glw::GLuint i = 0; i < n_format_attributes; ++i)
5086     {
5087         setupAttribute(format_attributes[i], buffers, program_id);
5088     }
5089 }
5090 
5091 /** Setup vertex array object
5092  *
5093  *  @param attribute  Attribute information
5094  *  @param buffers    Buffer collection
5095  *  @param program_id Program id
5096  **/
5097 void TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::setupAttribute(const attributeDefinition &attribute,
5098                                                                                   const bufferCollection &buffers,
5099                                                                                   glw::GLuint program_id)
5100 {
5101     std::string attribute_name     = vertex_shader_input;
5102     const bufferDefinition *buffer = 0;
5103     glw::GLuint n_components       = 0;
5104     glw::GLenum type               = GL_FLOAT;
5105 
5106     attribute_name.append(attribute.name);
5107 
5108     switch (attribute.attribute_id)
5109     {
5110     case Position:
5111         n_components = 4;
5112         buffer       = &buffers.postion;
5113         break;
5114     case TextureCoordinates:
5115         n_components = 4;
5116         buffer       = &buffers.texture_coordinate;
5117         break;
5118     case TextureCoordinatesForGather:
5119         n_components = 4;
5120         buffer       = &buffers.texture_coordinate_for_gather;
5121         break;
5122     case Lod:
5123         n_components = 1;
5124         buffer       = &buffers.lod;
5125         break;
5126     case GradX:
5127         n_components = 4;
5128         buffer       = &buffers.grad_x;
5129         break;
5130     case GradY:
5131         n_components = 4;
5132         buffer       = &buffers.grad_y;
5133         break;
5134     case RefZ:
5135         n_components = 1;
5136         buffer       = &buffers.refZ;
5137         break;
5138     }
5139 
5140     /* Get attribute location */
5141     glw::GLint attribute_location = m_gl->getAttribLocation(program_id, attribute_name.c_str());
5142 
5143     if ((m_invalid_attribute_location == (glw::GLuint)attribute_location) || (GL_NO_ERROR != m_gl->getError()))
5144     {
5145         //throw tcu::InternalError("Failed to get location of attribute:", attribute_name.c_str(), __FILE__, __LINE__);
5146         return;
5147     }
5148 
5149     buffer->bind(GL_ARRAY_BUFFER);
5150 
5151     m_gl->enableVertexAttribArray(attribute_location);
5152     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to enable attribute");
5153 
5154     m_gl->vertexAttribPointer(attribute_location, n_components, type, GL_FALSE, 0 /* stride */, 0 /* offset */);
5155 
5156     GLU_EXPECT_NO_ERROR(m_gl->getError(), "Failed to setup vertex attribute arrays");
5157 }
5158 
5159 #if TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION
5160 /** Get file name for given face
5161  * Such pattern is used: texture_cube_map_array_sampling_test_w_WIDTH_h_HEIGHT_l_LEVEL_i_INDEX_f_FACE
5162  *
5163  *  @param width  Width of texture
5164  *  @param height Height of texture
5165  *  @param level  Mipmap level
5166  *  @param index  Index of element in array
5167  *  @param face   Cube map's face index
5168  *  @param name   File name
5169  **/
5170 void getTextureFileName(glw::GLuint width, glw::GLuint height, glw::GLuint level, glw::GLuint index, glw::GLuint face,
5171                         std::string &name)
5172 {
5173     std::stringstream file_name;
5174 
5175     file_name << TEXTURECUBEMAPARRAYSAMPLINGTEST_PATH_FOR_COMPRESSION;
5176 
5177     file_name << "texture_cube_map_array_sampling_test_"
5178               << "w_" << width << "_h_" << height << "_l_" << level << "_i_" << index << "_f_" << face;
5179 
5180     name = file_name.str();
5181 }
5182 
5183 /** Store whole cube map as TGA files. Each face is stored as separate image.
5184  *
5185  *  @param resolution Resolution of base level
5186  **/
5187 void prepareDumpForTextureCompression(const TextureCubeMapArraySamplingTest::resolutionDefinition &resolution)
5188 {
5189     glw::GLsizei texture_width  = resolution.m_width;
5190     glw::GLsizei texture_height = resolution.m_height;
5191 
5192     const glw::GLuint n_components    = 4;
5193     const glw::GLuint n_faces         = 6;
5194     const glw::GLint n_array_elements = resolution.m_depth / n_faces;
5195     const glw::GLint n_mipmap_levels  = getMipmapLevelCount(resolution.m_width, resolution.m_height);
5196 
5197     const unsigned char tga_id_length                = 0; // no id
5198     const unsigned char tga_color_map_type           = 0; // no color map
5199     const unsigned char tga_image_type               = 2; // rgb no compression
5200     const unsigned short tga_color_map_offset        = 0; // no color map
5201     const unsigned short tga_color_map_length        = 0; // no color map
5202     const unsigned char tga_color_map_bits_per_pixel = 0; // no color map
5203     const unsigned short tga_image_x                 = 0;
5204     const unsigned short tga_image_y                 = 0;
5205     const unsigned char tga_image_bits_per_pixel     = 32;
5206     const unsigned char tga_image_descriptor         = 0x8; // 8 per alpha
5207 
5208     for (glw::GLint mipmap_level = 0; mipmap_level < n_mipmap_levels; ++mipmap_level)
5209     {
5210         const unsigned short tga_image_width  = texture_width;
5211         const unsigned short tga_image_height = texture_height;
5212 
5213         for (glw::GLint array_index = 0; array_index < n_array_elements; ++array_index)
5214         {
5215             for (glw::GLint face = 0; face < n_faces; ++face)
5216             {
5217                 std::fstream file;
5218                 std::string file_name;
5219                 getTextureFileName(resolution.m_width, resolution.m_height, mipmap_level, array_index, face, file_name);
5220                 file_name.append(".tga");
5221 
5222                 file.open(file_name.c_str(), std::fstream::out | std::fstream::binary);
5223 
5224                 file.write((const char *)&tga_id_length, sizeof(tga_id_length));
5225                 file.write((const char *)&tga_color_map_type, sizeof(tga_color_map_type));
5226                 file.write((const char *)&tga_image_type, sizeof(tga_image_type));
5227                 file.write((const char *)&tga_color_map_offset, sizeof(tga_color_map_offset));
5228                 file.write((const char *)&tga_color_map_length, sizeof(tga_color_map_length));
5229                 file.write((const char *)&tga_color_map_bits_per_pixel, sizeof(tga_color_map_bits_per_pixel));
5230                 file.write((const char *)&tga_image_x, sizeof(tga_image_x));
5231                 file.write((const char *)&tga_image_y, sizeof(tga_image_y));
5232                 file.write((const char *)&tga_image_width, sizeof(tga_image_width));
5233                 file.write((const char *)&tga_image_height, sizeof(tga_image_height));
5234                 file.write((const char *)&tga_image_bits_per_pixel, sizeof(tga_image_bits_per_pixel));
5235                 file.write((const char *)&tga_image_descriptor, sizeof(tga_image_descriptor));
5236 
5237                 glw::GLubyte components[n_components];
5238 
5239                 getCompressedColorUByteComponents(face, array_index, mipmap_level, n_array_elements, n_mipmap_levels,
5240                                                   components);
5241 
5242                 for (glw::GLuint y = 0; y < texture_height; ++y)
5243                 {
5244                     for (glw::GLuint x = 0; x < texture_width; ++x)
5245                     {
5246                         for (glw::GLuint i = 0; i < n_components; ++i)
5247                         {
5248                             file.write((const char *)&components[i], sizeof(glw::GLubyte));
5249                         }
5250                     }
5251                 }
5252             }
5253         }
5254 
5255         texture_width  = de::max(1, texture_width / 2);
5256         texture_height = de::max(1, texture_height / 2);
5257     }
5258 }
5259 
5260 #endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION */
5261 
5262 } // namespace glcts
5263