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  esextcTextureCubeMapArrayImageOperations.cpp
26 * \brief texture_cube_map_array extension - Image Operations (Test 8)
27 */ /*-------------------------------------------------------------------*/
28
29#include "esextcTextureCubeMapArrayImageOperations.hpp"
30#include "gluContextInfo.hpp"
31#include "gluStrUtil.hpp"
32#include "glwEnums.hpp"
33#include "glwFunctions.hpp"
34#include "tcuTestLog.hpp"
35#include <cmath>
36#include <cstring>
37#include <vector>
38
39namespace glcts
40{
41
42/* Set constant values for tests */
43const glw::GLfloat TextureCubeMapArrayImageOpCompute::m_f_base  = 1.5f;
44const glw::GLint   TextureCubeMapArrayImageOpCompute::m_i_base  = -1;
45const glw::GLuint  TextureCubeMapArrayImageOpCompute::m_ui_base = 1;
46
47const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_components	= 4;
48const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_dimensions	= 3;
49const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_image_formats = 3;
50const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_resolutions   = 4;
51const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_storage_type  = 2;
52
53const char* TextureCubeMapArrayImageOpCompute::m_mutable_storage   = "MUTABLE";
54const char* TextureCubeMapArrayImageOpCompute::m_immutable_storage = "IMMUTABLE";
55
56/* Helper arrays for tests configuration */
57
58/* Different texture resolutions */
59const int m_resolutions[TextureCubeMapArrayImageOpCompute::m_n_resolutions]
60					   [TextureCubeMapArrayImageOpCompute::m_n_dimensions] = {
61						   /* Width , Height, Depth */
62						   { 16, 16, 12 },
63						   { 32, 32, 6 },
64						   { 4, 4, 18 },
65						   { 8, 8, 6 }
66					   };
67
68/** Check if buffers contains the same values
69 * @param a      buffer with data to compare
70 * @param b      buffer with data to compare
71 * @param length buffers length
72 * @return       true if both buffers are equal, otherwise false
73 */
74template <typename T>
75glw::GLboolean areBuffersEqual(const T* a, const T* b, glw::GLuint length)
76{
77	return (memcmp(a, b, length * sizeof(T))) ? false : true;
78}
79
80/** Check if buffers contains the same values (float type)
81 * @param a      buffer with data to compare
82 * @param b      buffer with data to compare
83 * @param length buffers length
84 * @return       true if both buffers are equal, otherwise false
85 */
86template <>
87glw::GLboolean areBuffersEqual(const glw::GLfloat* a, const glw::GLfloat* b, glw::GLuint length)
88{
89	for (glw::GLuint i = 0; i < length; ++i)
90	{
91		if (de::abs(a[i] - b[i]) > TestCaseBase::m_epsilon_float)
92		{
93			return false;
94		}
95	}
96	return true;
97}
98
99/** Fill buffer with test data
100 * @param data       buffer where values will be stored
101 * @param width      buffer/texture width
102 * @param height     buffer/texture height
103 * @param depth      buffer/texture depth
104 * @param components buffer/texture components number
105 * @param base       base value used to fill array
106 **/
107template <typename T>
108void fillData(T* data, glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLuint components, T base)
109{
110	for (glw::GLuint i = 0; i < depth; ++i)
111	{
112		for (glw::GLuint j = 0; j < width; ++j)
113		{
114			for (glw::GLuint k = 0; k < height; ++k)
115			{
116				for (glw::GLuint l = 0; l < components; ++l)
117				{
118					data[i * width * height * components + j * height * components + k * components + l] = base + (T)i;
119				}
120			}
121		}
122	}
123}
124
125/** Check if results are es expected and log error if not
126 * @param context      application context
127 * @param id           id of texture
128 * @param width        texture width
129 * @param height       texture height
130 * @param depth        texture depth
131 * @param components   number of components per texel
132 * @param format       texture data format
133 * @param type         texture data type
134 * @param storType     storageType
135 * @param expectedData buffer with expected data
136 * @return             return true if data read from the texture is the same as expected
137 */
138template <typename T>
139bool checkResults(Context& context, glw::GLuint copy_po_id, glw::GLuint id, glw::GLuint width, glw::GLuint height,
140				  glw::GLuint depth, glw::GLuint components, glw::GLenum format, glw::GLenum type,
141				  STORAGE_TYPE storType, T* expectedData)
142{
143	/* Get GL entry points */
144	const glw::Functions& gl = context.getRenderContext().getFunctions();
145
146	/* prepare buffers for result data */
147	std::vector<T> resultData(width * height * components);
148
149	glw::GLint  old_program = 0;
150	glw::GLuint uint_tex_id = 0;
151
152	/* Floating point textures are not renderable, so we will need to copy their bits to a temporary unsigned integer texture */
153	if (type == GL_FLOAT)
154	{
155		/* Generate a new texture name */
156		gl.genTextures(1, &uint_tex_id);
157		GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating temporary texture object!");
158
159		/* Allocate unsigned integer storage */
160		gl.bindTexture(GL_TEXTURE_2D, uint_tex_id);
161		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding temporary texture object!");
162		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, width, height);
163		GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating temporary texture object!");
164
165		/* Set the filter mode */
166		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
167		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
168		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
169		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
170
171		/* Attach it to the framebuffer */
172		gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, uint_tex_id, 0);
173		GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to frame buffer");
174
175		/* And bind it to an image unit for writing */
176		gl.bindImageTexture(1, uint_tex_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
177		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding integer texture for copy destination");
178
179		/* Finally, bind the copy compute shader */
180		gl.getIntegerv(GL_CURRENT_PROGRAM, &old_program);
181		GLU_EXPECT_NO_ERROR(gl.getError(), "Error querying old program!");
182		gl.useProgram(copy_po_id);
183		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
184	}
185
186	bool result = true;
187
188	for (glw::GLuint i = 0; i < depth; ++i)
189	{
190		/* Floating point textures are not renderable */
191		if (type == GL_FLOAT)
192		{
193			/* Use a compute shader to store the float bits as unsigned integers */
194			gl.bindImageTexture(0, id, 0, GL_FALSE, i, GL_READ_ONLY, GL_RGBA32F);
195			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding floating point texture for copy source");
196			gl.dispatchCompute(width, height, 1);
197			GLU_EXPECT_NO_ERROR(gl.getError(), "Error dispatching float-to-integer compute shader");
198
199			/* Read data as unsigned ints */
200			gl.readPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &resultData[0]);
201			GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels from frame buffer!");
202		}
203		else
204		{
205			/* Attach proper 2D texture to frame buffer and read pixels */
206			gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, id, 0, i);
207			GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to frame buffer");
208
209			/* Read data */
210			gl.readPixels(0, 0, width, height, format, type, &resultData[0]);
211			GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels from frame buffer!");
212		}
213
214		/* Prepare correct pointer for expected data layer */
215		T* pointer = &expectedData[0] + (i * width * height * components);
216
217		/* If compared data are not equal log error and return false */
218		if (!areBuffersEqual<T>(&resultData[0], pointer, width * height * components))
219		{
220			context.getTestContext().getLog()
221				<< tcu::TestLog::Message << "Wrong value in result texture for "
222				<< ((type == GL_FLOAT) ? "imageCubeArray" : ((type == GL_INT) ? "iimageCubeArray" : "uimageCubeArray"))
223				<< " for resolution[w,h,d] = [" << width << "," << height << "," << depth << "] for layer[" << i
224				<< "] and " << ((storType == ST_MUTABLE) ? TextureCubeMapArrayImageOpCompute::m_mutable_storage :
225														   TextureCubeMapArrayImageOpCompute::m_immutable_storage)
226				<< " storage!" << tcu::TestLog::EndMessage;
227			result = false;
228			break;
229		}
230	}
231
232	/* Clean up the floating point stuff */
233	if (type == GL_FLOAT)
234	{
235		/* Restore the program */
236		gl.useProgram(old_program);
237		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
238
239		/* Delete the temporary texture */
240		gl.deleteTextures(1, &uint_tex_id);
241		GLU_EXPECT_NO_ERROR(gl.getError(), "Error deleting temporary texture!");
242	}
243
244	return result;
245}
246
247/** Configure texture object
248 * @param context        application context
249 * @param id             pointer where texture id will be stored
250 * @param width          texture width
251 * @param height         texture height
252 * @param depth          texture depth
253 * @param storType       storageType
254 * @param internalFormat texture internal format
255 * @param format         texture data format
256 * @param type           texture data type
257 * @param data           initialization data for texture
258 */
259template <typename T>
260void configureTexture(glcts::Context& context, glw::GLuint* id, glw::GLuint width, glw::GLuint height,
261					  glw::GLuint depth, STORAGE_TYPE storType, glw::GLenum internalFormat, glw::GLenum format,
262					  glw::GLenum type, const T* data)
263{
264	/* Get GL entry points */
265	const glw::Functions& gl = context.getRenderContext().getFunctions();
266
267	/* Generate texture object */
268	gl.activeTexture(GL_TEXTURE0);
269	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active texture unit!");
270
271	gl.genTextures(1, id);
272	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
273
274	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, *id);
275	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
276
277	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
278	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
279	gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
280	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
281
282	/* used glTexImage3D() method if texture should be MUTABLE */
283	if (storType == ST_MUTABLE)
284	{
285		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
286		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
287		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
288		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
289
290		gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalFormat, width, height, depth, 0, format, type, data);
291		GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store");
292	}
293	/* used glTexStorage3D() method if texture should be IMMUTABLE */
294	else
295	{
296		gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, internalFormat, width, height, depth);
297		GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store");
298
299		gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 0, width, height, depth, format, type, data);
300		GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data");
301	}
302}
303
304/** Constructor
305 *
306 *  @param context       Test context
307 *  @param name          Test case's name
308 *  @param description   Test case's description
309 **/
310TextureCubeMapArrayImageOpCompute::TextureCubeMapArrayImageOpCompute(Context& context, const ExtParameters& extParams,
311																	 const char* name, const char* description,
312																	 SHADER_TO_CHECK shaderToCheck)
313	: TestCaseBase(context, extParams, name, description)
314	, m_shader_to_check(shaderToCheck)
315	, m_cs_id(0)
316	, m_fbo_id(0)
317	, m_fs_id(0)
318	, m_gs_id(0)
319	, m_po_id(0)
320	, m_tc_id(0)
321	, m_te_id(0)
322	, m_vao_id(0)
323	, m_vs_id(0)
324	, m_copy_po_id(0)
325	, m_copy_cs_id(0)
326	, m_iimage_read_to_id(0)
327	, m_iimage_write_to_id(0)
328	, m_image_read_to_id(0)
329	, m_image_write_to_id(0)
330	, m_uimage_read_to_id(0)
331	, m_uimage_write_to_id(0)
332{
333	/* Nothing to be done here */
334}
335
336/** Initialize test case */
337void TextureCubeMapArrayImageOpCompute::initTest(void)
338{
339	/* Get GL entry points */
340	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
341
342	/* Check if texture_cube_map_array extension is supported */
343	if (!m_is_texture_cube_map_array_supported)
344	{
345		throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
346	}
347	if (!m_is_geometry_shader_extension_supported && m_shader_to_check == STC_GEOMETRY_SHADER)
348	{
349		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
350	}
351	if (!m_is_tessellation_shader_supported && (m_shader_to_check == STC_TESSELLATION_CONTROL_SHADER ||
352												m_shader_to_check == STC_TESSELLATION_EVALUATION_SHADER))
353	{
354		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
355	}
356
357	/* Generate and bind VAO */
358	gl.genVertexArrays(1, &m_vao_id);
359	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
360
361	gl.bindVertexArray(m_vao_id);
362	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
363
364	/* Generate and bind framebuffer */
365	gl.genFramebuffers(1, &m_fbo_id);
366	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating frame buffer object!");
367
368	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
369	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding frame buffer object!");
370
371	/* Create the floating point copy program */
372	m_copy_po_id			   = gl.createProgram();
373	m_copy_cs_id			   = gl.createShader(GL_COMPUTE_SHADER);
374	const char* copy_cs_source = getFloatingPointCopyShaderSource();
375	buildProgram(m_copy_po_id, m_copy_cs_id, 1, &copy_cs_source);
376
377	/* Create program */
378	m_po_id = gl.createProgram();
379	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
380
381	configureProgram();
382}
383
384/** Deinitialize test case */
385void TextureCubeMapArrayImageOpCompute::deinit(void)
386{
387	/* Get GL entry points */
388	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
389
390	/* Reset GLES configuration */
391	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
392	gl.useProgram(0);
393	gl.bindVertexArray(0);
394
395	/* Delete GLES objects */
396	if (m_po_id != 0)
397	{
398		gl.deleteProgram(m_po_id);
399		m_po_id = 0;
400	}
401	if (m_cs_id != 0)
402	{
403		gl.deleteShader(m_cs_id);
404		m_cs_id = 0;
405	}
406	if (m_fs_id != 0)
407	{
408		gl.deleteShader(m_fs_id);
409		m_fs_id = 0;
410	}
411	if (m_gs_id != 0)
412	{
413		gl.deleteShader(m_gs_id);
414		m_gs_id = 0;
415	}
416	if (m_tc_id != 0)
417	{
418		gl.deleteShader(m_tc_id);
419		m_tc_id = 0;
420	}
421	if (m_te_id != 0)
422	{
423		gl.deleteShader(m_te_id);
424		m_te_id = 0;
425	}
426	if (m_vs_id != 0)
427	{
428		gl.deleteShader(m_vs_id);
429		m_vs_id = 0;
430	}
431	if (m_copy_cs_id != 0)
432	{
433		gl.deleteShader(m_copy_cs_id);
434		m_copy_cs_id = 0;
435	}
436	if (m_copy_po_id != 0)
437	{
438		gl.deleteProgram(m_copy_po_id);
439		m_copy_po_id = 0;
440	}
441	if (m_fbo_id != 0)
442	{
443		gl.deleteFramebuffers(1, &m_fbo_id);
444		m_fbo_id = 0;
445	}
446	if (m_vao_id != 0)
447	{
448		gl.deleteVertexArrays(1, &m_vao_id);
449		m_vao_id = 0;
450	}
451
452	removeTextures();
453
454	/* Deinitialize base class */
455	TestCaseBase::deinit();
456}
457
458/** Delete texture objects */
459void TextureCubeMapArrayImageOpCompute::removeTextures()
460{
461	/* Get GL entry points */
462	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
463
464	gl.activeTexture(GL_TEXTURE0);
465	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
466
467	/* Delete texture objects */
468	if (m_iimage_read_to_id != 0)
469	{
470		gl.deleteTextures(1, &m_iimage_read_to_id);
471		m_iimage_read_to_id = 0;
472	}
473
474	if (m_iimage_write_to_id != 0)
475	{
476		gl.deleteTextures(1, &m_iimage_write_to_id);
477		m_iimage_write_to_id = 0;
478	}
479
480	if (m_image_read_to_id != 0)
481	{
482		gl.deleteTextures(1, &m_image_read_to_id);
483		m_image_read_to_id = 0;
484	}
485
486	if (m_image_write_to_id != 0)
487	{
488		gl.deleteTextures(1, &m_image_write_to_id);
489		m_image_write_to_id = 0;
490	}
491
492	if (m_uimage_read_to_id != 0)
493	{
494		gl.deleteTextures(1, &m_uimage_read_to_id);
495		m_uimage_read_to_id = 0;
496	}
497
498	if (m_uimage_write_to_id != 0)
499	{
500		gl.deleteTextures(1, &m_uimage_write_to_id);
501		m_uimage_write_to_id = 0;
502	}
503}
504
505/** Executes the test.
506 *
507 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
508 *
509 *  Note the function throws exception should an error occur!
510 *
511 *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
512 **/
513tcu::TestCase::IterateResult TextureCubeMapArrayImageOpCompute::iterate()
514{
515	initTest();
516
517	/* Get GL entry points */
518	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
519
520	gl.useProgram(m_po_id);
521	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
522
523	bool test_passed = true;
524
525	std::vector<glw::GLfloat> floatData;
526	std::vector<glw::GLfloat> floatClean;
527	std::vector<glw::GLint>   intData;
528	std::vector<glw::GLint>   intClean;
529	std::vector<glw::GLuint>  uIntData;
530	std::vector<glw::GLuint>  uIntClean;
531
532	/* Execute test throught all resolutions, storage types, and image types */
533	for (glw::GLuint res_index = 0; res_index < m_n_resolutions; ++res_index)
534	{
535		glw::GLuint width  = m_resolutions[res_index][DL_WIDTH];
536		glw::GLuint height = m_resolutions[res_index][DL_HEIGHT];
537		glw::GLuint depth  = m_resolutions[res_index][DL_DEPTH];
538
539		/* Allocate memory buffers for data */
540		floatData.resize(width * height * depth * m_n_components);
541		floatClean.resize(width * height * depth * m_n_components);
542		intData.resize(width * height * depth * m_n_components);
543		intClean.resize(width * height * depth * m_n_components);
544		uIntData.resize(width * height * depth * m_n_components);
545		uIntClean.resize(width * height * depth * m_n_components);
546
547		memset(&floatClean[0], 0, width * height * depth * m_n_components * sizeof(glw::GLfloat));
548		memset(&intClean[0], 0, width * height * depth * m_n_components * sizeof(glw::GLint));
549		memset(&uIntClean[0], 0, width * height * depth * m_n_components * sizeof(glw::GLuint));
550
551		/* Fill buffers with expected data*/
552		fillData<glw::GLfloat>(&floatData[0], width, height, depth, m_n_components, m_f_base);
553		fillData<glw::GLint>(&intData[0], width, height, depth, m_n_components, m_i_base);
554		fillData<glw::GLuint>(&uIntData[0], width, height, depth, m_n_components, m_ui_base);
555
556		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
557		{
558
559			/**
560			 * Mutable textures cannot be bound as image textures on ES, but can be on
561			 * desktop GL.
562			 * */
563
564			/* Work on mutable texture storage */
565
566			/* Generate texture objects */
567			configureTexture<glw::GLfloat>(m_context, &m_image_read_to_id, width, height, depth, ST_MUTABLE, GL_RGBA32F,
568										   GL_RGBA, GL_FLOAT, &floatData[0]);
569			configureTexture<glw::GLfloat>(m_context, &m_image_write_to_id, width, height, depth, ST_MUTABLE,
570										   GL_RGBA32F, GL_RGBA, GL_FLOAT, &floatClean[0]);
571
572			configureTexture<glw::GLint>(m_context, &m_iimage_read_to_id, width, height, depth, ST_MUTABLE, GL_RGBA32I,
573										 GL_RGBA_INTEGER, GL_INT, &intData[0]);
574			configureTexture<glw::GLint>(m_context, &m_iimage_write_to_id, width, height, depth, ST_MUTABLE, GL_RGBA32I,
575										 GL_RGBA_INTEGER, GL_INT, &intClean[0]);
576
577			configureTexture<glw::GLuint>(m_context, &m_uimage_read_to_id, width, height, depth, ST_MUTABLE,
578										  GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &uIntData[0]);
579			configureTexture<glw::GLuint>(m_context, &m_uimage_write_to_id, width, height, depth, ST_MUTABLE,
580										  GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &uIntClean[0]);
581
582			/* Bind texture objects to image units */
583			gl.bindImageTexture(IF_IMAGE, m_image_read_to_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32F);
584			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
585			gl.bindImageTexture(IF_IIMAGE, m_iimage_read_to_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32I);
586			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
587			gl.bindImageTexture(IF_UIMAGE, m_uimage_read_to_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32UI);
588			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
589			gl.bindImageTexture(IF_IMAGE + m_n_image_formats, m_image_write_to_id, 0, GL_TRUE, 0, GL_WRITE_ONLY,
590								GL_RGBA32F);
591			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
592			gl.bindImageTexture(IF_IIMAGE + m_n_image_formats, m_iimage_write_to_id, 0, GL_TRUE, 0, GL_WRITE_ONLY,
593								GL_RGBA32I);
594			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
595			gl.bindImageTexture(IF_UIMAGE + m_n_image_formats, m_uimage_write_to_id, 0, GL_TRUE, 0, GL_WRITE_ONLY,
596								GL_RGBA32UI);
597			GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
598
599			/* Call shaders */
600			runShaders(width, height, depth);
601
602			/* Check results */
603			if (!checkResults<glw::GLfloat>(m_context, m_copy_po_id, m_image_write_to_id, width, height, depth,
604											m_n_components, GL_RGBA, GL_FLOAT, ST_MUTABLE, &floatData[0]))
605			{
606				test_passed = false;
607			}
608
609			if (!checkResults<glw::GLint>(m_context, m_copy_po_id, m_iimage_write_to_id, width, height, depth,
610										  m_n_components, GL_RGBA_INTEGER, GL_INT, ST_MUTABLE, &intData[0]))
611			{
612				test_passed = false;
613			}
614
615			if (!checkResults<glw::GLuint>(m_context, m_copy_po_id, m_uimage_write_to_id, width, height, depth,
616										   m_n_components, GL_RGBA_INTEGER, GL_UNSIGNED_INT, ST_MUTABLE, &uIntData[0]))
617			{
618				test_passed = false;
619			}
620
621			/* Delete textures */
622			removeTextures();
623		}
624
625		/* Work on immutable texture storage */
626
627		/* Generate texture objects */
628		configureTexture<glw::GLfloat>(m_context, &m_image_read_to_id, width, height, depth, ST_IMMUTABLE, GL_RGBA32F,
629									   GL_RGBA, GL_FLOAT, &floatData[0]);
630		configureTexture<glw::GLfloat>(m_context, &m_image_write_to_id, width, height, depth, ST_IMMUTABLE, GL_RGBA32F,
631									   GL_RGBA, GL_FLOAT, &floatClean[0]);
632
633		configureTexture<glw::GLint>(m_context, &m_iimage_read_to_id, width, height, depth, ST_IMMUTABLE, GL_RGBA32I,
634									 GL_RGBA_INTEGER, GL_INT, &intData[0]);
635		configureTexture<glw::GLint>(m_context, &m_iimage_write_to_id, width, height, depth, ST_IMMUTABLE, GL_RGBA32I,
636									 GL_RGBA_INTEGER, GL_INT, &intClean[0]);
637
638		configureTexture<glw::GLuint>(m_context, &m_uimage_read_to_id, width, height, depth, ST_IMMUTABLE, GL_RGBA32UI,
639									  GL_RGBA_INTEGER, GL_UNSIGNED_INT, &uIntData[0]);
640		configureTexture<glw::GLuint>(m_context, &m_uimage_write_to_id, width, height, depth, ST_IMMUTABLE, GL_RGBA32UI,
641									  GL_RGBA_INTEGER, GL_UNSIGNED_INT, &uIntClean[0]);
642
643		/* Bind texture objects to image units */
644		gl.bindImageTexture(IF_IMAGE, m_image_read_to_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32F);
645		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
646		gl.bindImageTexture(IF_IIMAGE, m_iimage_read_to_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32I);
647		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
648		gl.bindImageTexture(IF_UIMAGE, m_uimage_read_to_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32UI);
649		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
650		gl.bindImageTexture(IF_IMAGE + m_n_image_formats, m_image_write_to_id, 0, GL_TRUE, 0, GL_WRITE_ONLY,
651							GL_RGBA32F);
652		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
653		gl.bindImageTexture(IF_IIMAGE + m_n_image_formats, m_iimage_write_to_id, 0, GL_TRUE, 0, GL_WRITE_ONLY,
654							GL_RGBA32I);
655		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
656		gl.bindImageTexture(IF_UIMAGE + m_n_image_formats, m_uimage_write_to_id, 0, GL_TRUE, 0, GL_WRITE_ONLY,
657							GL_RGBA32UI);
658		GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
659
660		/* Call shaders */
661		runShaders(width, height, depth);
662
663		/* Check results */
664		if (!checkResults<glw::GLfloat>(m_context, m_copy_po_id, m_image_write_to_id, width, height, depth,
665										m_n_components, GL_RGBA, GL_FLOAT, ST_IMMUTABLE, &floatData[0]))
666		{
667			test_passed = false;
668		}
669
670		if (!checkResults<glw::GLint>(m_context, m_copy_po_id, m_iimage_write_to_id, width, height, depth,
671									  m_n_components, GL_RGBA_INTEGER, GL_INT, ST_IMMUTABLE, &intData[0]))
672		{
673			test_passed = false;
674		}
675
676		if (!checkResults<glw::GLuint>(m_context, m_copy_po_id, m_uimage_write_to_id, width, height, depth,
677									   m_n_components, GL_RGBA_INTEGER, GL_UNSIGNED_INT, ST_IMMUTABLE, &uIntData[0]))
678		{
679			test_passed = false;
680		}
681
682		/* Delete textures */
683		removeTextures();
684	}
685
686	if (test_passed)
687		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
688	else
689		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
690
691	return STOP;
692}
693
694/** Run shaders - call glDispatchCompute for compuate shaders and glDrawArrays for other types of shaders */
695void TextureCubeMapArrayImageOpCompute::runShaders(glw::GLuint width, glw::GLuint height, glw::GLuint depth)
696{
697	/* Get GL entry points */
698	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
699
700	switch (m_shader_to_check)
701	{
702	/* Call compute shader */
703	case STC_COMPUTE_SHADER:
704	{
705		gl.dispatchCompute(width, height, depth);
706		GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
707		gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
708		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
709
710		break;
711	}
712	/* Run programs for VERTEX/FRAGMENT/GEOMETRY shader */
713	case STC_VERTEX_SHADER:
714	case STC_FRAGMENT_SHADER:
715	case STC_GEOMETRY_SHADER:
716	{
717		glw::GLint dimensions_location = gl.getUniformLocation(m_po_id, "dimensions");
718		GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting uniform location!");
719
720		if (dimensions_location == -1)
721		{
722			TCU_FAIL("Invalid location returned for active uniform!");
723		}
724
725		gl.uniform3i(dimensions_location, width, height, depth);
726		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for uniform variable!");
727
728		gl.drawArrays(GL_POINTS, 0, 1);
729		GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
730		gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
731		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
732
733		break;
734	}
735	case STC_TESSELLATION_CONTROL_SHADER:
736	case STC_TESSELLATION_EVALUATION_SHADER:
737	{
738		glw::GLint dimensions_location = gl.getUniformLocation(m_po_id, "dimensions");
739		GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting uniform location!");
740
741		if (dimensions_location == -1)
742		{
743			TCU_FAIL("Invalid location returned for active uniform!");
744		}
745
746		gl.uniform3i(dimensions_location, width, height, depth);
747		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for uniform variable!");
748
749		gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
750		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting patch parameter!");
751
752		gl.drawArrays(m_glExtTokens.PATCHES, 0, 1);
753		GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
754		gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
755		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
756
757		gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
758		GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting patch parameter!");
759
760		break;
761	}
762	}
763}
764
765/** Configure program object with proper shaders depending on m_shader_to_check value */
766void TextureCubeMapArrayImageOpCompute::configureProgram(void)
767{
768	/* Get GL entry points */
769	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
770
771	switch (m_shader_to_check)
772	{
773	case STC_COMPUTE_SHADER:
774	{
775		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
776		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
777
778		const char* csCode = getComputeShaderCode();
779
780		/* Images are required for compute shader */
781		if (!buildProgram(m_po_id, m_cs_id, 1 /* part */, &csCode))
782		{
783			TCU_FAIL("Could not create a program from valid compute shader code!");
784		}
785		break;
786	}
787	case STC_VERTEX_SHADER:
788	{
789		m_vs_id = gl.createShader(GL_VERTEX_SHADER);
790		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
791		m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
792		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
793
794		const char* vsCode = getVertexShaderCode();
795		const char* fsCode = getFragmentShaderCodeBoilerPlate();
796
797		/* Execute test only if images are supported by vertex shader */
798		if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_vs_id, 1 /* part */, &vsCode))
799		{
800			throw tcu::NotSupportedError(
801				"imageCubeArray/iimageCubeArray/uimageCubeArray are not supported by Vertex Shader", "", __FILE__,
802				__LINE__);
803		}
804		break;
805	}
806	case STC_FRAGMENT_SHADER:
807	{
808		m_vs_id = gl.createShader(GL_VERTEX_SHADER);
809		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
810		m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
811		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
812
813		const char* vsCode = getVertexShaderCodeBoilerPlate();
814		const char* fsCode = getFragmentShaderCode();
815
816		/* Execute test only if images are supported by fragment shader */
817		if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_vs_id, 1 /* part */, &vsCode))
818		{
819			throw tcu::NotSupportedError(
820				"imageCubeArray/iimageCubeArray/uimageCubeArray are not supported by Fragment Shader", "", __FILE__,
821				__LINE__);
822		}
823		break;
824	}
825	case STC_GEOMETRY_SHADER:
826	{
827		m_vs_id = gl.createShader(GL_VERTEX_SHADER);
828		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
829		m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
830		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
831		m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
832		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
833
834		const char* vsCode = getVertexShaderCodeBoilerPlate();
835		const char* gsCode = getGeometryShaderCode();
836		const char* fsCode = getFragmentShaderCodeBoilerPlate();
837
838		/* Execute test only if images are supported by geometry shader */
839		if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_gs_id, 1 /* part */, &gsCode, m_vs_id,
840						  1 /* part */, &vsCode))
841		{
842			throw tcu::NotSupportedError(
843				"imageCubeArray/iimageCubeArray/uimageCubeArray are not supported by Geometry Shader", "", __FILE__,
844				__LINE__);
845		}
846		break;
847	}
848	case STC_TESSELLATION_CONTROL_SHADER:
849	{
850		m_vs_id = gl.createShader(GL_VERTEX_SHADER);
851		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
852		m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
853		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
854		m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
855		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
856		m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
857		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
858
859		const char* vsCode  = getVertexShaderCodeBoilerPlate();
860		const char* tcsCode = getTessControlShaderCode();
861		const char* tesCode = getTessEvaluationShaderCodeBoilerPlate();
862		const char* fsCode  = getFragmentShaderCodeBoilerPlate();
863
864		/* Execute test only if images are supported by tessellation control shader */
865		if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_tc_id, 1 /* part */, &tcsCode, m_te_id,
866						  1 /* part */, &tesCode, m_vs_id, 1 /* part */, &vsCode))
867		{
868			throw tcu::NotSupportedError(
869				"imageCubeArray/iimageCubeArray/uimageCubeArray are not supported by Tessellation Control Shader", "",
870				__FILE__, __LINE__);
871		}
872		break;
873	}
874	case STC_TESSELLATION_EVALUATION_SHADER:
875	{
876		m_vs_id = gl.createShader(GL_VERTEX_SHADER);
877		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
878		m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
879		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
880		m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
881		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
882		m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
883		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object!");
884
885		const char* vsCode  = getVertexShaderCodeBoilerPlate();
886		const char* tcsCode = getTessControlShaderCodeBoilerPlate();
887		const char* tesCode = getTessEvaluationShaderCode();
888		const char* fsCode  = getFragmentShaderCodeBoilerPlate();
889
890		/* Execute test only if images are supported by tessellation evaluation shader */
891		if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_tc_id, 1 /* part */, &tcsCode, m_te_id,
892						  1 /* part */, &tesCode, m_vs_id, 1 /* part */, &vsCode))
893		{
894			throw tcu::NotSupportedError(
895				"imageCubeArray/iimageCubeArray/uimageCubeArray are not supported by Tessellation Evaluation Shader",
896				"", __FILE__, __LINE__);
897		}
898		break;
899	}
900	default:
901		break;
902	}
903}
904
905/** Returns code for Compute Shader
906 *  @return pointer to literal with Compute Shader code
907 **/
908const char* TextureCubeMapArrayImageOpCompute::getComputeShaderCode()
909{
910	static const char* computeShaderCode =
911		"${VERSION}\n"
912		"\n"
913		"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
914		"\n"
915		"precision highp float;\n"
916		"\n"
917		"layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
918		"\n"
919		"layout (rgba32f,  binding = 0) highp uniform readonly imageCubeArray  imageRead;\n"
920		"layout (rgba32i,  binding = 1) highp uniform readonly iimageCubeArray iimageRead;\n"
921		"layout (rgba32ui, binding = 2) highp uniform readonly uimageCubeArray uimageRead;\n"
922		"layout (rgba32f,  binding = 3) highp uniform writeonly imageCubeArray  imageWrite;\n"
923		"layout (rgba32i,  binding = 4) highp uniform writeonly iimageCubeArray iimageWrite;\n"
924		"layout (rgba32ui, binding = 5) highp uniform writeonly uimageCubeArray uimageWrite;\n"
925		"\n"
926		"void main(void)\n"
927		"{\n"
928		"    ivec3 position = ivec3(gl_GlobalInvocationID.xyz);\n"
929		"    imageStore(imageWrite,  position, imageLoad(imageRead,  position));\n"
930		"    imageStore(iimageWrite, position, imageLoad(iimageRead, position));\n"
931		"    imageStore(uimageWrite, position, imageLoad(uimageRead, position));\n"
932		"}\n";
933
934	return computeShaderCode;
935}
936
937/** Returns code for Vertex Shader
938 * @return pointer to literal with Vertex Shader code
939 **/
940const char* TextureCubeMapArrayImageOpCompute::getVertexShaderCode(void)
941{
942
943	static const char* vertexShaderCode =
944		"${VERSION}\n"
945		"\n"
946		"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
947		"\n"
948		"precision highp float;\n"
949		"\n"
950		"layout (rgba32f,  binding = 0) highp uniform readonly imageCubeArray  imageRead;\n"
951		"layout (rgba32i,  binding = 1) highp uniform readonly iimageCubeArray iimageRead;\n"
952		"layout (rgba32ui, binding = 2) highp uniform readonly uimageCubeArray uimageRead;\n"
953		"layout (rgba32f,  binding = 3) highp uniform writeonly imageCubeArray  imageWrite;\n"
954		"layout (rgba32i,  binding = 4) highp uniform writeonly iimageCubeArray iimageWrite;\n"
955		"layout (rgba32ui, binding = 5) highp uniform writeonly uimageCubeArray uimageWrite;\n"
956		"\n"
957		"uniform ivec3 dimensions;\n"
958		"\n"
959		"void main()\n"
960		"{\n"
961		"\n"
962		"    gl_PointSize = 1.0f;\n"
963		"    for(int w = 0; w < dimensions[0]; ++w)\n" /* width */
964		"    {\n"
965		"        for(int h = 0; h < dimensions[1]; ++h)\n" /* height */
966		"        {\n"
967		"            for(int d = 0; d < dimensions[2]; ++d)\n" /* depth */
968		"            {\n"
969		"                ivec3  position  = ivec3(w,h,d);\n"
970		"                imageStore(imageWrite,  position, imageLoad(imageRead,  position));\n"
971		"                imageStore(iimageWrite, position, imageLoad(iimageRead, position));\n"
972		"                imageStore(uimageWrite, position, imageLoad(uimageRead, position));\n"
973		"            }\n"
974		"        }\n"
975		"    }\n"
976		"\n"
977		"}\n";
978
979	return vertexShaderCode;
980}
981
982/** Returns code for Boiler Plate Vertex Shader
983 * @return pointer to literal with Boiler Plate Vertex Shader code
984 **/
985const char* TextureCubeMapArrayImageOpCompute::getVertexShaderCodeBoilerPlate(void)
986{
987	static const char* vertexShaderBoilerPlateCode = "${VERSION}\n"
988													 "\n"
989													 "precision highp float;\n"
990													 "\n"
991													 "void main()\n"
992													 "{\n"
993													 "    gl_Position = vec4(0, 0, 0, 1.0f);\n"
994													 "    gl_PointSize = 1.0f;\n"
995													 "}\n";
996
997	return vertexShaderBoilerPlateCode;
998}
999
1000/** Returns code for Fragment Shader
1001 *  @return pointer to literal with Fragment Shader code
1002 **/
1003const char* TextureCubeMapArrayImageOpCompute::getFragmentShaderCode(void)
1004{
1005	static const char* fragmentShaderCode =
1006		"${VERSION}\n"
1007		"\n"
1008		"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
1009		"\n"
1010		"precision highp float;\n"
1011		"\n"
1012		"layout (rgba32f,  binding = 0) highp uniform readonly imageCubeArray  imageRead;\n"
1013		"layout (rgba32i,  binding = 1) highp uniform readonly iimageCubeArray iimageRead;\n"
1014		"layout (rgba32ui, binding = 2) highp uniform readonly uimageCubeArray uimageRead;\n"
1015		"layout (rgba32f,  binding = 3) highp uniform writeonly imageCubeArray  imageWrite;\n"
1016		"layout (rgba32i,  binding = 4) highp uniform writeonly iimageCubeArray iimageWrite;\n"
1017		"layout (rgba32ui, binding = 5) highp uniform writeonly uimageCubeArray uimageWrite;\n"
1018		"\n"
1019		"uniform ivec3 dimensions;\n"
1020		"\n"
1021		"void main()\n"
1022		"{\n"
1023		"\n"
1024		"    for(int w = 0; w < dimensions[0]; ++w)\n" /* width */
1025		"    {\n"
1026		"        for(int h = 0; h < dimensions[1]; ++h)\n" /* height */
1027		"        {\n"
1028		"            for(int d = 0; d < dimensions[2]; ++d)\n" /* depth */
1029		"            {\n"
1030		"                ivec3  position  = ivec3(w,h,d);\n"
1031		"                imageStore(imageWrite,  position, imageLoad(imageRead,  position));\n"
1032		"                imageStore(iimageWrite, position, imageLoad(iimageRead, position));\n"
1033		"                imageStore(uimageWrite, position, imageLoad(uimageRead, position));\n"
1034		"            }"
1035		"        }"
1036		"    }"
1037		"\n"
1038		"}\n";
1039
1040	return fragmentShaderCode;
1041}
1042
1043/** Returns code for Boiler Plate Fragment Shader
1044 *  @return pointer to literal with Boiler Plate Fragment Shader code
1045 **/
1046const char* TextureCubeMapArrayImageOpCompute::getFragmentShaderCodeBoilerPlate(void)
1047{
1048	static const char* fragmentShaderBoilerPlateCode = "${VERSION}\n"
1049													   "\n"
1050													   "precision highp float;\n"
1051													   "\n"
1052													   "void main()\n"
1053													   "{\n"
1054													   "}\n";
1055
1056	return fragmentShaderBoilerPlateCode;
1057}
1058
1059/** Returns code for Geometry Shader
1060 * @return pointer to literal with Geometry Shader code
1061 **/
1062const char* TextureCubeMapArrayImageOpCompute::getGeometryShaderCode(void)
1063{
1064	static const char* geometryShaderCode =
1065		"${VERSION}\n"
1066		"\n"
1067		"${GEOMETRY_SHADER_ENABLE}\n"
1068		"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
1069		"\n"
1070		"precision highp float;\n"
1071		"\n"
1072		"layout (rgba32f,  binding = 0) highp uniform readonly imageCubeArray  imageRead;\n"
1073		"layout (rgba32i,  binding = 1) highp uniform readonly iimageCubeArray iimageRead;\n"
1074		"layout (rgba32ui, binding = 2) highp uniform readonly uimageCubeArray uimageRead;\n"
1075		"layout (rgba32f,  binding = 3) highp uniform writeonly imageCubeArray  imageWrite;\n"
1076		"layout (rgba32i,  binding = 4) highp uniform writeonly iimageCubeArray iimageWrite;\n"
1077		"layout (rgba32ui, binding = 5) highp uniform writeonly uimageCubeArray uimageWrite;\n"
1078		"\n"
1079		"uniform ivec3 dimensions;\n"
1080		"\n"
1081		"layout(points) in;\n"
1082		"layout(points, max_vertices=1) out;\n"
1083		"\n"
1084		"void main()\n"
1085		"{\n"
1086		"\n"
1087		"    for(int w = 0; w < dimensions[0]; ++w)\n" /* width */
1088		"    {\n"
1089		"        for(int h = 0; h < dimensions[1]; ++h)\n" /* height */
1090		"        {\n"
1091		"            for(int d = 0; d < dimensions[2]; ++d)\n" /* depth */
1092		"            {\n"
1093		"                ivec3  position  = ivec3(w,h,d);\n"
1094		"                imageStore(imageWrite,  position, imageLoad(imageRead,  position));\n"
1095		"                imageStore(iimageWrite, position, imageLoad(iimageRead, position));\n"
1096		"                imageStore(uimageWrite, position, imageLoad(uimageRead, position));\n"
1097		"            }\n"
1098		"        }\n"
1099		"    }\n"
1100		"\n"
1101		"}\n";
1102
1103	return geometryShaderCode;
1104}
1105
1106/** Returns code for Tessellation Control Shader
1107 *  @return pointer to literal with Tessellation Control Shader code
1108 **/
1109const char* TextureCubeMapArrayImageOpCompute::getTessControlShaderCode(void)
1110{
1111	static const char* tessellationControlShaderCode =
1112		"${VERSION}\n"
1113		"\n"
1114		"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
1115		"${TESSELLATION_SHADER_ENABLE}\n"
1116		"\n"
1117		"precision highp float;\n"
1118		"\n"
1119		"layout (rgba32f,  binding = 0) highp uniform readonly imageCubeArray  imageRead;\n"
1120		"layout (rgba32i,  binding = 1) highp uniform readonly iimageCubeArray iimageRead;\n"
1121		"layout (rgba32ui, binding = 2) highp uniform readonly uimageCubeArray uimageRead;\n"
1122		"layout (rgba32f,  binding = 3) highp uniform writeonly imageCubeArray  imageWrite;\n"
1123		"layout (rgba32i,  binding = 4) highp uniform writeonly iimageCubeArray iimageWrite;\n"
1124		"layout (rgba32ui, binding = 5) highp uniform writeonly uimageCubeArray uimageWrite;\n"
1125		"\n"
1126		"uniform ivec3 dimensions;\n"
1127		"\n"
1128		"layout (vertices = 1) out;\n"
1129		"\n"
1130		"void main()\n"
1131		"{\n"
1132		"\n"
1133		"    gl_TessLevelInner[0] = 1.0;\n"
1134		"    gl_TessLevelInner[1] = 1.0;\n"
1135		"    gl_TessLevelOuter[0] = 1.0;\n"
1136		"    gl_TessLevelOuter[1] = 1.0;\n"
1137		"    gl_TessLevelOuter[2] = 1.0;\n"
1138		"    gl_TessLevelOuter[3] = 1.0;\n"
1139		"\n"
1140		"    for(int w = 0; w < dimensions[0]; ++w)\n" /* width */
1141		"    {\n"
1142		"        for(int h = 0; h < dimensions[1]; ++h)\n" /* height */
1143		"        {\n"
1144		"            for(int d = 0; d < dimensions[2]; ++d)\n" /* depth */
1145		"            {\n"
1146		"                ivec3  position  = ivec3(w,h,d);\n"
1147		"                imageStore(imageWrite,  position, imageLoad(imageRead,  position.xyz));\n"
1148		"                imageStore(iimageWrite, position, imageLoad(iimageRead, position.xyz));\n"
1149		"                imageStore(uimageWrite, position, imageLoad(uimageRead, position.xyz));\n"
1150		"            }\n"
1151		"        }\n"
1152		"    }\n"
1153		"\n"
1154		"}\n";
1155
1156	return tessellationControlShaderCode;
1157}
1158
1159/** Returns code for Boiler Plate Tessellation Control Shader
1160 *  @return pointer to literal with Boiler Plate Tessellation Control Shader code
1161 **/
1162const char* TextureCubeMapArrayImageOpCompute::getTessControlShaderCodeBoilerPlate(void)
1163{
1164	static const char* tessControlShaderBoilerPlateCode = "${VERSION}\n"
1165														  "\n"
1166														  "${TESSELLATION_SHADER_ENABLE}\n"
1167														  "\n"
1168														  "precision highp float;\n"
1169														  "\n"
1170														  "layout (vertices = 1) out;\n"
1171														  "\n"
1172														  "void main()\n"
1173														  "{\n"
1174														  "    gl_TessLevelInner[0] = 1.0;\n"
1175														  "    gl_TessLevelInner[1] = 1.0;\n"
1176														  "    gl_TessLevelOuter[0] = 1.0;\n"
1177														  "    gl_TessLevelOuter[1] = 1.0;\n"
1178														  "    gl_TessLevelOuter[2] = 1.0;\n"
1179														  "    gl_TessLevelOuter[3] = 1.0;\n"
1180														  "}\n";
1181
1182	return tessControlShaderBoilerPlateCode;
1183}
1184
1185/** Returns code for Tessellation Evaluation Shader
1186 *  @return pointer to literal with Tessellation Evaluation Shader code
1187 **/
1188const char* TextureCubeMapArrayImageOpCompute::getTessEvaluationShaderCode(void)
1189{
1190	static const char* tessellationEvaluationShaderCode =
1191		"${VERSION}\n"
1192		"\n"
1193		"${TESSELLATION_SHADER_ENABLE}\n"
1194		"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
1195		"\n"
1196		"precision highp float;\n"
1197		"\n"
1198		"layout (rgba32f,  binding = 0) highp uniform readonly imageCubeArray  imageRead;\n"
1199		"layout (rgba32i,  binding = 1) highp uniform readonly iimageCubeArray iimageRead;\n"
1200		"layout (rgba32ui, binding = 2) highp uniform readonly uimageCubeArray uimageRead;\n"
1201		"layout (rgba32f,  binding = 3) highp uniform writeonly imageCubeArray  imageWrite;\n"
1202		"layout (rgba32i,  binding = 4) highp uniform writeonly iimageCubeArray iimageWrite;\n"
1203		"layout (rgba32ui, binding = 5) highp uniform writeonly uimageCubeArray uimageWrite;\n"
1204		"\n"
1205		"uniform ivec3 dimensions;\n"
1206		"\n"
1207		"layout(isolines, point_mode) in;"
1208		"\n"
1209		"void main()\n"
1210		"{\n"
1211		"\n"
1212		"    for(int w = 0; w < dimensions[0]; ++w)\n" /* width */
1213		"    {\n"
1214		"        for(int h = 0; h < dimensions[1]; ++h)\n" /* height */
1215		"        {\n"
1216		"            for(int d = 0; d < dimensions[2]; ++d)\n" /* depth */
1217		"            {\n"
1218		"                ivec3  position  = ivec3(w,h,d);\n"
1219		"                imageStore(imageWrite,  position, imageLoad(imageRead,  position));\n"
1220		"                imageStore(iimageWrite, position, imageLoad(iimageRead, position));\n"
1221		"                imageStore(uimageWrite, position, imageLoad(uimageRead, position));\n"
1222		"            }\n"
1223		"        }\n"
1224		"    }\n"
1225		"\n"
1226		"}\n";
1227
1228	return tessellationEvaluationShaderCode;
1229}
1230
1231/** Returns code for Boiler Plate Tessellation Evaluation Shader
1232 *  @return pointer to literal with Boiler Plate Tessellation Evaluation Shader code
1233 **/
1234const char* TextureCubeMapArrayImageOpCompute::getTessEvaluationShaderCodeBoilerPlate(void)
1235{
1236	static const char* tessellationEvaluationShaderBoilerPlateCode = "${VERSION}\n"
1237																	 "\n"
1238																	 "${TESSELLATION_SHADER_ENABLE}\n"
1239																	 "\n"
1240																	 "precision highp float;\n"
1241																	 "\n"
1242																	 "layout(isolines, point_mode) in;"
1243																	 "\n"
1244																	 "void main()\n"
1245																	 "{\n"
1246																	 "}\n";
1247
1248	return tessellationEvaluationShaderBoilerPlateCode;
1249}
1250
1251const char* TextureCubeMapArrayImageOpCompute::getFloatingPointCopyShaderSource(void)
1252{
1253	static const char* floatingPointCopyShaderCode =
1254		"${VERSION}\n"
1255		"\n"
1256		"layout (local_size_x=1) in;\n"
1257		"\n"
1258		"layout(binding=0, rgba32f) uniform highp readonly image2D src;\n"
1259		"layout(binding=1, rgba32ui) uniform highp writeonly uimage2D dst;\n"
1260		"\n"
1261		"void main()\n"
1262		"{\n"
1263		"ivec2 coord = ivec2(gl_WorkGroupID.xy);\n"
1264		"imageStore(dst, coord, floatBitsToUint(imageLoad(src, coord)));\n"
1265		"}\n";
1266
1267	return floatingPointCopyShaderCode;
1268}
1269
1270} /* glcts */
1271