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