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