Home | History | Annotate | Download | only in texture_cube_map_array
      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 
     39 namespace glcts
     40 {
     41 
     42 /* Set constant values for tests */
     43 const glw::GLfloat TextureCubeMapArrayImageOpCompute::m_f_base  = 1.5f;
     44 const glw::GLint   TextureCubeMapArrayImageOpCompute::m_i_base  = -1;
     45 const glw::GLuint  TextureCubeMapArrayImageOpCompute::m_ui_base = 1;
     46 
     47 const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_components	= 4;
     48 const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_dimensions	= 3;
     49 const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_image_formats = 3;
     50 const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_resolutions   = 4;
     51 const glw::GLuint TextureCubeMapArrayImageOpCompute::m_n_storage_type  = 2;
     52 
     53 const char* TextureCubeMapArrayImageOpCompute::m_mutable_storage   = "MUTABLE";
     54 const char* TextureCubeMapArrayImageOpCompute::m_immutable_storage = "IMMUTABLE";
     55 
     56 /* Helper arrays for tests configuration */
     57 
     58 /* Different texture resolutions */
     59 const 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  */
     74 template <typename T>
     75 glw::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  */
     86 template <>
     87 glw::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  **/
    107 template <typename T>
    108 void 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  */
    138 template <typename T>
    139 bool 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  */
    259 template <typename T>
    260 void 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  **/
    310 TextureCubeMapArrayImageOpCompute::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 */
    337 void 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 */
    385 void 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 */
    459 void 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  **/
    513 tcu::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 */
    695 void 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 */
    766 void 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  **/
    908 const 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  **/
    940 const 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  **/
    985 const 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  **/
   1003 const 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  **/
   1046 const 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  **/
   1062 const 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  **/
   1109 const 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  **/
   1162 const 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  **/
   1188 const 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  **/
   1234 const 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 
   1251 const 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