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