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 #include "esextcTextureCubeMapArrayColorDepthAttachments.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30
31 namespace glcts
32 {
33 /* Shader parts */
34 const glw::GLchar *const TextureCubeMapArrayColorDepthAttachmentsTest::m_fragment_shader_code =
35 "${VERSION}\n"
36 "/* FS */\n"
37 "\n"
38 "precision highp float;\n"
39 "\n"
40 "in flat int fs_in_color;\n"
41 "\n"
42 "layout(location = 0) out int fs_out_color;\n"
43 "\n"
44 "void main()\n"
45 "{\n"
46 " fs_out_color = fs_in_color;\n"
47 "}\n"
48 "\n";
49
50 const glw::GLchar *const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_preamble =
51 "${VERSION}\n"
52 "/* Layered GS */\n"
53 "\n"
54 "${GEOMETRY_SHADER_REQUIRE}\n"
55 "\n"
56 "precision highp float;\n"
57 "\n"
58 "layout(points) in;\n"
59 "layout(triangle_strip, max_vertices=4) out;\n"
60 "\n";
61
62 const glw::GLchar *const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_layered =
63 "in flat int vs_out_layer[];\n"
64 "\n"
65 "out flat int fs_in_color;\n"
66 "\n"
67 "void main()\n"
68 "{\n"
69 " int layer = vs_out_layer[0];\n";
70
71 const glw::GLchar *const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_non_layered =
72 "uniform int uni_layer;\n"
73 "\n"
74 "out flat int fs_in_color;\n"
75 "\n"
76 "void main()\n"
77 "{\n"
78 " int layer = uni_layer;\n";
79
80 const glw::GLchar *const TextureCubeMapArrayColorDepthAttachmentsTest::m_geometry_shader_code_body =
81 ";\n"
82 " \n"
83 " // Left-Bottom\n"
84 " gl_Position = vec4(-1.0, -1.0, depth, 1);\n"
85 " gl_Layer = layer;\n"
86 " fs_in_color = layer;\n"
87 " EmitVertex();\n"
88 " \n"
89 " // Left-Top\n"
90 " gl_Position = vec4(-1.0, 1.0, depth, 1);\n"
91 " gl_Layer = layer;\n"
92 " fs_in_color = layer;\n"
93 " EmitVertex();\n"
94 " \n"
95 " // Right-Bottom\n"
96 " gl_Position = vec4( 1.0, -1.0, depth, 1);\n"
97 " gl_Layer = layer;\n"
98 " fs_in_color = layer;\n"
99 " EmitVertex();\n"
100 " \n"
101 " // Right-Top\n"
102 " gl_Position = vec4( 1.0, 1.0, depth, 1);\n"
103 " gl_Layer = layer;\n"
104 " fs_in_color = layer;\n"
105 " EmitVertex();\n"
106 " EndPrimitive();\n"
107 "}\n"
108 "\n";
109
110 const glw::GLchar *const TextureCubeMapArrayColorDepthAttachmentsTest::m_vertex_shader_code =
111 "${VERSION}\n"
112 "/* VS */\n"
113 "\n"
114 "precision highp float;\n"
115 "\n"
116 "flat out int vs_out_layer;\n"
117 "\n"
118 "void main()\n"
119 "{\n"
120 " gl_PointSize = 1.0f;\n"
121 " vs_out_layer = gl_VertexID;\n"
122 "}\n"
123 "\n";
124
125 /* Static constants */
126 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_color_internal_format = GL_R32I;
127 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_color_format = GL_RED_INTEGER;
128 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_color_type = GL_INT;
129 const glw::GLenum TextureCubeMapArrayColorDepthAttachmentsTest::m_depth_format = GL_DEPTH_COMPONENT;
130
131 /** Verifies all texels in user-provided data buffer are equal to user-specified vector value.
132 *
133 * @tparam T Type of image components
134 * @tparam N_Components Number of image components
135 *
136 * @param image_width Width of image
137 * @param image_height Height of image
138 * @param components Amount of components per texel
139 * @param image Image data
140 *
141 * @return true if all texels are found valid, false otherwise.
142 **/
143 template <typename T, unsigned int N_Components>
verifyImage(glw::GLuint image_width,glw::GLuint image_height,const T * components,const T * image)144 bool verifyImage(glw::GLuint image_width, glw::GLuint image_height, const T *components, const T *image)
145 {
146 const glw::GLuint line_size = image_width * N_Components;
147
148 for (glw::GLuint y = 0; y < image_height; ++y)
149 {
150 const glw::GLuint line_offset = y * line_size;
151
152 for (glw::GLuint x = 0; x < image_width; ++x)
153 {
154 const glw::GLuint pixel_offset = line_offset + x * N_Components;
155
156 for (glw::GLuint component = 0; component < N_Components; ++component)
157 {
158 if (image[pixel_offset + component] != components[component])
159 {
160 return false;
161 }
162 } /* for (all components) */
163 } /* for (all columns) */
164 } /* for (all rows) */
165
166 return true;
167 }
168
169 /** Constructor
170 *
171 * @param size Size of texture
172 * @param n_cubemaps Number of cube-maps in array
173 **/
_texture_size(glw::GLuint size,glw::GLuint n_cubemaps)174 TextureCubeMapArrayColorDepthAttachmentsTest::_texture_size::_texture_size(glw::GLuint size, glw::GLuint n_cubemaps)
175 : m_size(size)
176 , m_n_cubemaps(n_cubemaps)
177 {
178 /* Nothing to be done here */
179 }
180
181 /** Constructor
182 *
183 * @param context Test context
184 * @param name Test case's name
185 * @param description Test case's description
186 **/
TextureCubeMapArrayColorDepthAttachmentsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)187 TextureCubeMapArrayColorDepthAttachmentsTest::TextureCubeMapArrayColorDepthAttachmentsTest(
188 Context &context, const ExtParameters &extParams, const char *name, const char *description)
189 : TestCaseBase(context, extParams, name, description)
190 , m_vao_id(0)
191 , m_color_texture_id(0)
192 , m_depth_texture_id(0)
193 , m_fragment_shader_id(0)
194 , m_framebuffer_object_id(0)
195 , m_layered_geometry_shader_id(0)
196 , m_layered_program_id(0)
197 , m_non_layered_geometry_shader_id(0)
198 , m_non_layered_program_id(0)
199 , m_non_layered_program_id_uni_layer_uniform_location(0)
200 , m_vertex_shader_id(0)
201 , m_depth_internal_format(0)
202 , m_depth_type(0)
203 , m_n_invalid_color_checks(0)
204 , m_n_invalid_depth_checks(0)
205 {
206 /* Define tested resolutions */
207 m_resolutions.push_back(_texture_size(8, 8));
208 m_resolutions.push_back(_texture_size(64, 3));
209 m_resolutions.push_back(_texture_size(117, 1));
210 m_resolutions.push_back(_texture_size(256, 1));
211 m_resolutions.push_back(_texture_size(173, 3));
212 }
213
214 /** Attaches an user-specified texture object to zeroth color attachment OR depth attachment of
215 * test-maintained FBO in a layered manner.
216 *
217 * @param texture_id Texture object's ID.
218 * @param should_use_as_color_attachment true to attach the texture object to GL_COLOR_ATTACHMENT0 of
219 * the test-maintained FBO; false to use GL_DEPTH_ATTACHMENT
220 * binding point.
221 **/
configureLayeredFramebufferAttachment(glw::GLuint texture_id,bool should_use_as_color_attachment)222 void TextureCubeMapArrayColorDepthAttachmentsTest::configureLayeredFramebufferAttachment(
223 glw::GLuint texture_id, bool should_use_as_color_attachment)
224 {
225 glw::GLenum attachment = GL_NONE;
226 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
227
228 /* Determine which attachment should be used */
229 if (true == should_use_as_color_attachment)
230 {
231 attachment = GL_COLOR_ATTACHMENT0;
232 }
233 else
234 {
235 attachment = GL_DEPTH_ATTACHMENT;
236 }
237
238 /* Re-bind the draw framebuffer, just in case. */
239 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_object_id);
240 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
241
242 /* Update the FBO's attachment */
243 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
244 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureEXT() call failed.");
245 }
246
247 /** Attaches an user-specified texture object to zeroth color attachment OR depth attachment of
248 * test-maintained FBO in a non-layered manner.
249 *
250 * @param texture_id Texture object's ID.
251 * @param n_layer Layer of the texture to attach.
252 * @param should_use_as_color_attachment true to attach the texture object to GL_COLOR_ATTACHMENT0 of
253 * the test-maintained FBO; false to use GL_DEPTH_ATTACHMENT
254 * binding point.
255 * @param should_update_draw_framebuffer true to bind the test-maintained FBO to GL_DRAW_FRAMEBUFFER
256 * binding point first, false to use GL_READ_FRAMEBUFFER binding
257 * point.
258 **/
configureNonLayeredFramebufferAttachment(glw::GLuint texture_id,glw::GLuint n_layer,bool should_use_as_color_attachment,bool should_update_draw_framebuffer)259 void TextureCubeMapArrayColorDepthAttachmentsTest::configureNonLayeredFramebufferAttachment(
260 glw::GLuint texture_id, glw::GLuint n_layer, bool should_use_as_color_attachment,
261 bool should_update_draw_framebuffer)
262 {
263 glw::GLenum attachment_type = GL_NONE;
264 glw::GLenum framebuffer_target = GL_NONE;
265 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
266
267 /* Determine which attachment should be used */
268 if (true == should_use_as_color_attachment)
269 {
270 attachment_type = GL_COLOR_ATTACHMENT0;
271 }
272 else
273 {
274 attachment_type = GL_DEPTH_ATTACHMENT;
275 }
276
277 /* Determine which framebuffer target should be used */
278 if (true == should_update_draw_framebuffer)
279 {
280 framebuffer_target = GL_DRAW_FRAMEBUFFER;
281 }
282 else
283 {
284 framebuffer_target = GL_READ_FRAMEBUFFER;
285 }
286
287 /* Re-bind the framebuffer, just in case. */
288 gl.bindFramebuffer(framebuffer_target, m_framebuffer_object_id);
289 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
290
291 /* Use the specified texture layer as attachment */
292 gl.framebufferTextureLayer(framebuffer_target, attachment_type, texture_id, 0 /* level */, n_layer);
293 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed.");
294 }
295
296 /* Deinitializes GLES objects created during the test. */
deinit()297 void TextureCubeMapArrayColorDepthAttachmentsTest::deinit()
298 {
299 /* Deinitialize base class */
300 TestCaseBase::deinit();
301
302 if (true != m_is_texture_cube_map_array_supported)
303 {
304 return;
305 }
306 if (true != m_is_geometry_shader_extension_supported)
307 {
308 return;
309 }
310
311 /* GL functions */
312 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
313
314 /* Release texture objects */
315 releaseAndDetachTextureObject(m_color_texture_id, true /* is_color_attachment */);
316 releaseAndDetachTextureObject(m_depth_texture_id, false /* is_color_attachment */);
317
318 /* Restore default state */
319 gl.useProgram(0);
320 gl.bindVertexArray(0);
321
322 /* Delete all remaining ES objects the test may have created. */
323 if (0 != m_fragment_shader_id)
324 {
325 gl.deleteShader(m_fragment_shader_id);
326
327 m_fragment_shader_id = 0;
328 }
329
330 if (0 != m_framebuffer_object_id)
331 {
332 gl.deleteFramebuffers(1, &m_framebuffer_object_id);
333
334 m_framebuffer_object_id = 0;
335 }
336
337 if (0 != m_layered_geometry_shader_id)
338 {
339 gl.deleteShader(m_layered_geometry_shader_id);
340
341 m_layered_geometry_shader_id = 0;
342 }
343
344 if (0 != m_layered_program_id)
345 {
346 gl.deleteProgram(m_layered_program_id);
347
348 m_layered_program_id = 0;
349 }
350
351 if (0 != m_non_layered_geometry_shader_id)
352 {
353 gl.deleteShader(m_non_layered_geometry_shader_id);
354
355 m_non_layered_geometry_shader_id = 0;
356 }
357
358 if (0 != m_non_layered_program_id)
359 {
360 gl.deleteProgram(m_non_layered_program_id);
361
362 m_non_layered_program_id = 0;
363 }
364
365 if (0 != m_vertex_shader_id)
366 {
367 gl.deleteShader(m_vertex_shader_id);
368
369 m_vertex_shader_id = 0;
370 }
371
372 if (m_vao_id != 0)
373 {
374 gl.deleteVertexArrays(1, &m_vao_id);
375
376 m_vao_id = 0;
377 }
378 }
379
380 /* Determines depth internalformat that can be used for a draw framebuffer.
381 * The result is stored in m_depth_internal_format and m_depth_type.
382 **/
determineSupportedDepthFormat()383 void TextureCubeMapArrayColorDepthAttachmentsTest::determineSupportedDepthFormat()
384 {
385 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
386
387 /* Start with 16-bit depth internalformat */
388 m_depth_internal_format = GL_DEPTH_COMPONENT16;
389 m_depth_type = GL_UNSIGNED_SHORT;
390
391 while (true)
392 {
393 /* Create color and depth texture objectss */
394 generateAndConfigureTextureObjects(8, /* texture_width */
395 1, /* n_cubemaps */
396 false); /* should_generate_mutable_textures */
397
398 /* Set framebuffer attachments up */
399 configureNonLayeredFramebufferAttachment(m_color_texture_id, 0 /* layer */, true /* is_color_attachment */,
400 true /* should_update_draw_framebuffer */);
401 configureNonLayeredFramebufferAttachment(m_depth_texture_id, 0 /* layer */, false /* is_color_attachment */,
402 true /* should_update_draw_framebuffer */);
403
404 /* Check framebuffer status */
405 const glw::GLenum framebuffer_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
406
407 if (GL_FRAMEBUFFER_COMPLETE == framebuffer_status)
408 {
409 return;
410 }
411
412 /* Current format does not work too well, try another one */
413 switch (m_depth_internal_format)
414 {
415 case GL_DEPTH_COMPONENT16:
416 {
417 m_depth_internal_format = GL_DEPTH_COMPONENT24;
418 m_depth_type = GL_UNSIGNED_INT;
419
420 break;
421 }
422
423 case GL_DEPTH_COMPONENT24:
424 {
425 m_depth_internal_format = GL_DEPTH_COMPONENT32F;
426 m_depth_type = GL_FLOAT;
427
428 break;
429 }
430
431 case GL_DEPTH_COMPONENT32F:
432 {
433 throw tcu::NotSupportedError("Implementation does not support any known depth format");
434 }
435
436 default:
437 {
438 TCU_FAIL("Unrecognized depth internalformat");
439 }
440 } /* switch (m_depth_internal_format) */
441 } /* while (true) */
442 }
443
444 /** Execute a draw call that renders (texture_size.m_n_cubemaps * 6) points.
445 * First, the viewport is configured to match the texture resolution and
446 * both color & depth buffers are cleared.
447 *
448 * @param texture_size Render-target resolution.
449 *
450 **/
draw(const _texture_size & texture_size)451 void TextureCubeMapArrayColorDepthAttachmentsTest::draw(const _texture_size &texture_size)
452 {
453 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
454
455 /* Set up the viewport */
456 gl.viewport(0, /* x */
457 0, /* y */
458 texture_size.m_size, texture_size.m_size);
459 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
460
461 /* Clear color & depth buffers */
462 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
463 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
464
465 gl.drawArrays(GL_POINTS, 0 /* first */, texture_size.m_n_cubemaps * 6 /* layer-faces per cube-map */);
466 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
467 }
468
469 /** Releases existing color & depth cube-map texture array objects, generates new
470 * ones and configures them as per user-specified properties.
471 *
472 * @param texture_width Size to use for each layer-face's width and height.
473 * @param n_cubemaps Number of cube-maps to initialize for the cube-map texture arrays.
474 * @param should_generate_mutable_textures true if the texture should be initialized as mutable, false otherwise.
475 **/
generateAndConfigureTextureObjects(glw::GLuint texture_width,glw::GLuint n_cubemaps,bool should_generate_mutable_textures)476 void TextureCubeMapArrayColorDepthAttachmentsTest::generateAndConfigureTextureObjects(
477 glw::GLuint texture_width, glw::GLuint n_cubemaps, bool should_generate_mutable_textures)
478 {
479 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
480
481 /* Release any texture objects that may have already been initialized */
482 releaseAndDetachTextureObject(m_color_texture_id, true /* is_color_attachment */);
483 releaseAndDetachTextureObject(m_depth_texture_id, false /* is_color_attachment */);
484
485 /* Generate texture objects */
486 gl.genTextures(1, &m_color_texture_id);
487 gl.genTextures(1, &m_depth_texture_id);
488
489 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed");
490
491 /* Configure new textures' storage */
492 if (true == should_generate_mutable_textures)
493 {
494 prepareMutableTextureObject(m_color_texture_id, texture_width, n_cubemaps,
495 true /* should_take_color_texture_properties */);
496 prepareMutableTextureObject(m_depth_texture_id, texture_width, n_cubemaps,
497 false /* should_take_color_texture_properties */);
498 }
499 else
500 {
501 prepareImmutableTextureObject(m_color_texture_id, texture_width, n_cubemaps,
502 true /* should_take_color_texture_properties */);
503 prepareImmutableTextureObject(m_depth_texture_id, texture_width, n_cubemaps,
504 false /* should_take_color_texture_properties */);
505 }
506 }
507
508 /* Initializes all ES objects needed to run the test */
initTest()509 void TextureCubeMapArrayColorDepthAttachmentsTest::initTest()
510 {
511 const glw::GLchar *depth_calculation_code = DE_NULL;
512 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
513
514 /* Check if EXT_texture_cube_map_array extension is supported */
515 if (true != m_is_texture_cube_map_array_supported)
516 {
517 throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED);
518 }
519
520 /* This test should only run if EXT_geometry_shader is supported */
521 if (true != m_is_geometry_shader_extension_supported)
522 {
523 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED);
524 }
525
526 /* Generate and bind VAO */
527 gl.genVertexArrays(1, &m_vao_id);
528 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
529
530 gl.bindVertexArray(m_vao_id);
531 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
532
533 /* Create a framebuffer object */
534 gl.genFramebuffers(1, &m_framebuffer_object_id);
535 GLU_EXPECT_NO_ERROR(gl.getError(), "genFramebuffers");
536
537 /* Determine which depth format can be used as a depth attachment without
538 * making the FBO incomplete */
539 determineSupportedDepthFormat();
540
541 /* Decide which code snippet to use for depth value calculation */
542 switch (m_depth_internal_format)
543 {
544 case GL_DEPTH_COMPONENT16:
545 {
546 depth_calculation_code = "-1.0 + float(2 * layer) / float(0xffff)";
547
548 break;
549 }
550
551 case GL_DEPTH_COMPONENT24:
552 {
553 depth_calculation_code = "-1.0 + float(2 * layer) / float(0xffffff)";
554
555 break;
556 }
557
558 case GL_DEPTH_COMPONENT32F:
559 {
560 depth_calculation_code = "-1.0 + float(2 * layer) / 256.0";
561
562 break;
563 }
564
565 default:
566 {
567 TCU_FAIL("Unrecognized depth internal format");
568 }
569 } /* switch (m_depth_internal_format) */
570
571 /* Create shader objects */
572 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
573 m_layered_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
574 m_non_layered_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
575 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
576
577 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
578
579 /* Create program objects */
580 m_layered_program_id = gl.createProgram();
581 m_non_layered_program_id = gl.createProgram();
582
583 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed");
584
585 /* Build up an array of snippets making up bodies of two geometry shaders
586 * we'll be using for the test.
587 */
588 const glw::GLchar *const layered_geometry_shader_parts[] = {
589 m_geometry_shader_code_preamble, m_geometry_shader_code_layered, " float depth = ", depth_calculation_code,
590 m_geometry_shader_code_body};
591
592 const glw::GLchar *const non_layered_geometry_shader_parts[] = {
593 m_geometry_shader_code_preamble, m_geometry_shader_code_non_layered,
594 " float depth = ", depth_calculation_code, m_geometry_shader_code_body};
595
596 const glw::GLuint n_layered_geometry_shader_parts =
597 sizeof(layered_geometry_shader_parts) / sizeof(layered_geometry_shader_parts[0]);
598 const glw::GLuint n_non_layered_geometry_shader_parts =
599 sizeof(non_layered_geometry_shader_parts) / sizeof(non_layered_geometry_shader_parts[0]);
600
601 /* Build both programs */
602 if (!buildProgram(m_layered_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code,
603 m_layered_geometry_shader_id, n_layered_geometry_shader_parts, layered_geometry_shader_parts,
604 m_vertex_shader_id, 1, &m_vertex_shader_code))
605 {
606 TCU_FAIL("Could not build layered-case program object");
607 }
608
609 if (!buildProgram(m_non_layered_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code,
610 m_non_layered_geometry_shader_id, n_non_layered_geometry_shader_parts,
611 non_layered_geometry_shader_parts, m_vertex_shader_id, 1, &m_vertex_shader_code))
612 {
613 TCU_FAIL("Could not build non-layered-case program object");
614 }
615
616 /* Get location of "uni_layer" uniform */
617 m_non_layered_program_id_uni_layer_uniform_location = gl.getUniformLocation(m_non_layered_program_id, "uni_layer");
618
619 if ((-1 == m_non_layered_program_id_uni_layer_uniform_location) || (GL_NO_ERROR != gl.getError()))
620 {
621 TCU_FAIL("Could not retrieve location of uni_layer uniform for non-layered program");
622 }
623 }
624
625 /** Executes the test.
626 *
627 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
628 * Note the function throws exception should an error occur!
629 *
630 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
631 **/
iterate()632 tcu::TestCase::IterateResult TextureCubeMapArrayColorDepthAttachmentsTest::iterate()
633 {
634 /* GL functions */
635 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
636
637 /* Initialize all ES objects needed to run the test */
638 initTest();
639
640 /* Setup clear values */
641 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */);
642 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
643
644 gl.clearDepthf(1.0f /* d */);
645 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearDepthf() call failed.");
646
647 /* Enable depth test */
648 gl.enable(GL_DEPTH_TEST);
649 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed");
650
651 /* Execute tests for each resolution */
652 for (_texture_size_vector::iterator texture_size_iterator = m_resolutions.begin(),
653 end_iterator = m_resolutions.end();
654 end_iterator != texture_size_iterator; ++texture_size_iterator)
655 {
656 testNonLayeredRendering(*texture_size_iterator, false);
657 testNonLayeredRendering(*texture_size_iterator, true);
658 testLayeredRendering(*texture_size_iterator, false);
659 testLayeredRendering(*texture_size_iterator, true);
660 }
661
662 /* Test passes if there were no errors */
663 if ((0 != m_n_invalid_color_checks) || (0 != m_n_invalid_depth_checks))
664 {
665 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
666 }
667 else
668 {
669 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
670 }
671
672 /* Done */
673 return STOP;
674 }
675
676 /** Takes a texture ID, binds it to GL_TEXTURE_CUBE_MAP_ARRAY texture target and
677 * initializes an immutable texture storage of @param texture_size x @param texture_size
678 * x (@param n_elements * 6) resolution.
679 *
680 * @param texture_id ID to use for the initialization.
681 * @param texture_size Width & height to use for each layer-face.
682 * @param n_cubemaps Amount of cube-maps to initialize.
683 * @param should_take_color_texture_properties true if m_color_internal_format, m_color_format,
684 * m_color_type should be used for texture storage
685 * initialization, false to use relevant m_depth_*
686 * fields.
687 **/
prepareImmutableTextureObject(glw::GLuint texture_id,glw::GLuint texture_size,glw::GLuint n_cubemaps,bool should_take_color_texture_properties)688 void TextureCubeMapArrayColorDepthAttachmentsTest::prepareImmutableTextureObject(
689 glw::GLuint texture_id, glw::GLuint texture_size, glw::GLuint n_cubemaps, bool should_take_color_texture_properties)
690 {
691 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
692 glw::GLenum internal_format = GL_NONE;
693
694 /* Set internal_format accordingly to requested texture type */
695 if (true == should_take_color_texture_properties)
696 {
697 internal_format = m_color_internal_format;
698 }
699 else
700 {
701 internal_format = m_depth_internal_format;
702 }
703
704 /* Bind the texture object to GL_TEXTURE_CUBE_MAP_ARRAY texture target. */
705 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texture_id);
706 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
707
708 /* Initialize immutable texture storage as per description */
709 gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, /* n_mipmap_levels */
710 internal_format, texture_size, texture_size, n_cubemaps * 6 /* layer-faces per cube-map */);
711
712 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed.");
713 }
714
715 /** Takes a texture ID, binds it to GL_TEXTURE_CUBE_MAP_ARRAY texture target and
716 * initializes a mutable texture storage of @param texture_size x @param texture_size
717 * x (@param n_elements * 6) resolution. Finally,the function sets GL_TEXTURE_MAX_LEVEL
718 * of the texture object to 0.
719 *
720 * @param texture_id ID to use for the initialization.
721 * @param texture_size Width & height to use for each layer-face.
722 * @param n_cubemaps Amount of cube-maps to initialize.
723 * @param should_take_color_texture_properties true if m_color_internal_format, m_color_format,
724 * m_color_type should be used for texture storage
725 * initialization, false to use relevant m_depth_*
726 * fields.
727 **/
prepareMutableTextureObject(glw::GLuint texture_id,glw::GLuint texture_size,glw::GLuint n_cubemaps,bool should_take_color_texture_properties)728 void TextureCubeMapArrayColorDepthAttachmentsTest::prepareMutableTextureObject(
729 glw::GLuint texture_id, glw::GLuint texture_size, glw::GLuint n_cubemaps, bool should_take_color_texture_properties)
730 {
731 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
732 glw::GLenum format = GL_NONE;
733 glw::GLenum internal_format = GL_NONE;
734 glw::GLenum type = GL_NONE;
735
736 /* Set internal_format, format and type accordingly to requested texture type */
737 if (true == should_take_color_texture_properties)
738 {
739 internal_format = m_color_internal_format;
740 format = m_color_format;
741 type = m_color_type;
742 }
743 else
744 {
745 internal_format = m_depth_internal_format;
746 format = m_depth_format;
747 type = m_depth_type;
748 }
749
750 /* Bind the texture object to GL_TEXTURE_CUBE_MAP_ARRAY texture target. */
751 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texture_id);
752 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
753
754 /* Initialize mutable texture storage as per description */
755 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0 /* mipmap_level */, internal_format, texture_size, texture_size,
756 n_cubemaps * 6 /* layer-faces per cube-map */, 0 /* border */, format, type,
757 DE_NULL); /* initial data */
758 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D() call failed");
759
760 /* Update GL_TEXTURE_MAX_LEVEL so that the texture is considered complete */
761 gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, 0 /* param */);
762
763 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call failed");
764 }
765
766 /** Releases a texture object and detaches it from test-maintained draw framebuffer.
767 *
768 * @param texture_id Id of the texture object;
769 * @param is_color_attachment true if the texture object described by id @param texture_id
770 * is current draw framebuffer's color attachment, false if it's
771 * a depth attachment.
772 **/
releaseAndDetachTextureObject(glw::GLuint texture_id,bool is_color_attachment)773 void TextureCubeMapArrayColorDepthAttachmentsTest::releaseAndDetachTextureObject(glw::GLuint texture_id,
774 bool is_color_attachment)
775 {
776 glw::GLenum attachment = GL_NONE;
777 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
778
779 if (true == is_color_attachment)
780 {
781 attachment = GL_COLOR_ATTACHMENT0;
782 }
783 else
784 {
785 attachment = GL_DEPTH_ATTACHMENT;
786 }
787
788 /* Update draw framewbuffer binding just in case. */
789 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_object_id);
790 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
791
792 /* Clean framebuffer's attachment */
793 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, /* texture */
794 0); /* level */
795 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
796
797 /* Unbind the texture object from GL_TEXTURE_CUBE_MAP_ARRAY binding point */
798 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
799 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
800
801 /* Finally delete the texture object */
802 gl.deleteTextures(1, &texture_id);
803 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
804 }
805
806 /** Verifies layered rendering works correctly.
807 *
808 * @param texture_size Resolution of texture;
809 * @param should_use_mutable_textures true if mutable textures should be used for the test,
810 * false to use immutable textures.
811 **/
testLayeredRendering(const _texture_size & texture_size,bool should_use_mutable_textures)812 void TextureCubeMapArrayColorDepthAttachmentsTest::testLayeredRendering(const _texture_size &texture_size,
813 bool should_use_mutable_textures)
814 {
815 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
816
817 /* Generate texture objects for the test */
818 generateAndConfigureTextureObjects(texture_size.m_size, texture_size.m_n_cubemaps, should_use_mutable_textures);
819
820 /* Setup layered framebuffer */
821 configureLayeredFramebufferAttachment(m_color_texture_id, true /* should_use_as_color_attachment */);
822 configureLayeredFramebufferAttachment(m_depth_texture_id, false /* should_use_as_color_attachment */);
823
824 /* Activate the program object that performs layered rendering */
825 gl.useProgram(m_layered_program_id);
826
827 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
828
829 /* Issue the draw call. */
830 draw(texture_size);
831
832 /* Restore default framebuffer attachments */
833 configureLayeredFramebufferAttachment(0 /* texture_id */, true /* should_use_as_color_attachment */);
834 configureLayeredFramebufferAttachment(0 /* texture_id */, false /* should_use_as_color_attachment */);
835
836 /* Restore draw framebuffer binding */
837 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
838
839 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
840
841 /* Time to verify the results - update read framebuffer binding first. */
842 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer_object_id);
843
844 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
845
846 /* Iterate through all layer-faces */
847 for (glw::GLuint n_layer_face = 0; n_layer_face < texture_size.m_n_cubemaps * 6 /* layer-faces per cube-map */;
848 ++n_layer_face)
849 {
850 /* Configure read framebuffer attachments to point to the layer of our current interest */
851 configureNonLayeredFramebufferAttachment(m_color_texture_id, n_layer_face,
852 true, /* should_use_as_color_attachment */
853 false); /* should_update_draw_framebuffer */
854 configureNonLayeredFramebufferAttachment(m_depth_texture_id, n_layer_face,
855 false, /* should_use_as_color_attachment */
856 false); /* should_update_draw_framebuffer */
857
858 /* Verify contents of color and depth attachments */
859 bool is_color_data_ok = verifyColorData(texture_size, n_layer_face);
860 bool is_depth_data_ok = false;
861
862 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
863 {
864 switch (m_depth_internal_format)
865 {
866 case GL_DEPTH_COMPONENT16:
867 {
868 is_depth_data_ok = verifyDepth16Data(texture_size, n_layer_face);
869
870 break;
871 }
872
873 case GL_DEPTH_COMPONENT24:
874 {
875 is_depth_data_ok = verifyDepth24Data(texture_size, n_layer_face);
876
877 break;
878 }
879
880 case GL_DEPTH_COMPONENT32F:
881 {
882 is_depth_data_ok = verifyDepth32FData(texture_size, n_layer_face);
883
884 break;
885 }
886
887 default:
888 {
889 TCU_FAIL("Unrecognized depth internalformat");
890 }
891 } /* switch (m_depth_internal_format) */
892 }
893 else
894 {
895 is_depth_data_ok = true;
896 }
897
898 /* Any errors? Increment relevant counters */
899 if (false == is_color_data_ok)
900 {
901 m_n_invalid_color_checks++;
902 }
903
904 if (false == is_depth_data_ok)
905 {
906 m_n_invalid_depth_checks++;
907 }
908 } /* for (all layer-faces) */
909 }
910
911 /** Verifies layered rendering works correctly.
912 *
913 * @param texture_size Resolution of texture
914 * @param should_use_mutable_texture true if an immutable texture should be used for
915 * the invocation; false if mutable.
916 **/
testNonLayeredRendering(const _texture_size & texture_size,bool should_use_mutable_texture)917 void TextureCubeMapArrayColorDepthAttachmentsTest::testNonLayeredRendering(const _texture_size &texture_size,
918 bool should_use_mutable_texture)
919 {
920 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
921
922 /* Activate a program object that renders in a non-layered fashion */
923 gl.useProgram(m_non_layered_program_id);
924
925 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
926
927 /* Create relevant textures */
928 generateAndConfigureTextureObjects(texture_size.m_size, texture_size.m_n_cubemaps, should_use_mutable_texture);
929
930 /* Iterate over all layer-faces */
931 for (glw::GLuint n_layer_face = 0; n_layer_face < texture_size.m_n_cubemaps * 6 /* layer-faces per cube-map */;
932 ++n_layer_face)
933 {
934 /* Set up non-layered framebuffer attachments */
935 configureNonLayeredFramebufferAttachment(m_color_texture_id, n_layer_face, true /* is_color_attachment */);
936 configureNonLayeredFramebufferAttachment(m_depth_texture_id, n_layer_face, false /* is_color_attachment */);
937
938 /* Update value assigned to "uni_layer" uniform */
939 gl.uniform1i(m_non_layered_program_id_uni_layer_uniform_location, n_layer_face);
940 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
941
942 /* Execute a draw call */
943 draw(texture_size);
944
945 /* Restore default framebuffer attachments */
946 configureNonLayeredFramebufferAttachment(0 /* texture_id */, 0 /* n_layer */,
947 true /* should_use_as_color_attachment */);
948 configureNonLayeredFramebufferAttachment(0 /* texture_id */, 0 /* n_layer */,
949 false /* should_use_as_color_attachment */);
950
951 /* Remove draw framebuffer binding */
952 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
953 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
954
955 /* Verify the results. First, make sure the read framebuffer binding is configured
956 * accordingly.
957 */
958 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_framebuffer_object_id);
959 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
960
961 /* Configure read framebuffer attachments to point to the layer of our current interest */
962 configureNonLayeredFramebufferAttachment(m_color_texture_id, n_layer_face,
963 true, /* should_use_as_color_attachment */
964 false); /* should_update_draw_framebuffer */
965 configureNonLayeredFramebufferAttachment(m_depth_texture_id, n_layer_face,
966 false, /* should_use_as_color_attachment */
967 false); /* should_update_draw_framebuffer */
968
969 /* Verify contents of color and depth attachments */
970 bool is_color_data_ok = verifyColorData(texture_size, n_layer_face);
971 bool is_depth_data_ok = false;
972
973 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
974 {
975 switch (m_depth_internal_format)
976 {
977 case GL_DEPTH_COMPONENT16:
978 {
979 is_depth_data_ok = verifyDepth16Data(texture_size, n_layer_face);
980
981 break;
982 }
983
984 case GL_DEPTH_COMPONENT24:
985 {
986 is_depth_data_ok = verifyDepth24Data(texture_size, n_layer_face);
987
988 break;
989 }
990
991 case GL_DEPTH_COMPONENT32F:
992 {
993 is_depth_data_ok = verifyDepth32FData(texture_size, n_layer_face);
994
995 break;
996 }
997
998 default:
999 {
1000 TCU_FAIL("Unrecognized depth internalformat");
1001 }
1002 } /* switch (m_depth_internal_format) */
1003 }
1004 else
1005 {
1006 is_depth_data_ok = true;
1007 }
1008
1009 /* Any errors? Increment relevant counters */
1010 if (false == is_color_data_ok)
1011 {
1012 m_n_invalid_color_checks++;
1013 }
1014
1015 if (false == is_depth_data_ok)
1016 {
1017 m_n_invalid_depth_checks++;
1018 }
1019 } /* for (all layer-faces) */
1020 }
1021
1022 /** Reads read buffer's color data and verifies its correctness.
1023 *
1024 * @param texture_size Texture size
1025 * @param n_layer Index of the layer to verify.
1026 *
1027 * @return true if the retrieved data was found correct, false otherwise.
1028 **/
verifyColorData(const _texture_size & texture_size,glw::GLuint n_layer)1029 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyColorData(const _texture_size &texture_size,
1030 glw::GLuint n_layer)
1031 {
1032 /* Allocate buffer for the data we will retrieve from the implementation */
1033 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1034 bool result = false;
1035 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size * 4;
1036 glw::GLuint *result_data = new glw::GLuint[result_data_size];
1037
1038 DE_ASSERT(result_data != NULL);
1039
1040 /* Read the data */
1041 gl.readPixels(0, /* x */
1042 0, /* y */
1043 texture_size.m_size, texture_size.m_size, GL_RGBA_INTEGER, m_color_type, result_data);
1044 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1045
1046 glw::GLuint expected[4] = {n_layer, 0, 0, 1};
1047
1048 /* Verify image, expected value is layer index */
1049 result = verifyImage<glw::GLuint, 4>(texture_size.m_size, texture_size.m_size, expected, result_data);
1050
1051 /* Release the buffer */
1052 if (result_data != NULL)
1053 {
1054 delete[] result_data;
1055
1056 result_data = NULL;
1057 }
1058
1059 return result;
1060 }
1061
1062 /** Reads read buffer's depth data (assuming it's of 16-bit resolution)
1063 * and verifies its correctness.
1064 *
1065 * @param texture_size Texture size
1066 * @param n_layer Index of the layer to verify.
1067 *
1068 * @return true if the retrieved data was found correct, false otherwise.
1069 **/
verifyDepth16Data(const _texture_size & texture_size,glw::GLuint n_layer)1070 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyDepth16Data(const _texture_size &texture_size,
1071 glw::GLuint n_layer)
1072 {
1073 /* Allocate buffer for the data we will retrieve from the implementation */
1074 glw::GLushort expected_value = (glw::GLushort)n_layer;
1075 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1076 bool result = false;
1077 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size;
1078 glw::GLushort *result_data = new glw::GLushort[result_data_size];
1079
1080 DE_ASSERT(result_data != NULL);
1081
1082 gl.pixelStorei(GL_PACK_ALIGNMENT, 2);
1083
1084 /* Read the data */
1085 gl.readPixels(0, /* x */
1086 0, /* y */
1087 texture_size.m_size, texture_size.m_size, m_depth_format, m_depth_type, result_data);
1088 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1089
1090 /* Verify image, expected value is layer index */
1091 result = verifyImage<glw::GLushort, 1>(texture_size.m_size, texture_size.m_size, &expected_value, result_data);
1092
1093 /* Release the buffer */
1094 if (result_data != NULL)
1095 {
1096 delete[] result_data;
1097
1098 result_data = NULL;
1099 }
1100
1101 gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
1102
1103 return result;
1104 }
1105
1106 /** Reads read buffer's depth data (assuming it's of 24-bit resolution)
1107 * and verifies its correctness.
1108 *
1109 * @param texture_size Texture size
1110 * @param n_layer Index of the layer to verify.
1111 *
1112 * @return true if the retrieved data was found correct, false otherwise.
1113 **/
verifyDepth24Data(const _texture_size & texture_size,glw::GLuint n_layer)1114 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyDepth24Data(const _texture_size &texture_size,
1115 glw::GLuint n_layer)
1116 {
1117 /* Allocate buffer for the data we will retrieve from the implementation */
1118 glw::GLuint expected_value = n_layer << 8;
1119 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1120 bool result = false;
1121 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size;
1122 glw::GLuint *result_data = new glw::GLuint[result_data_size];
1123
1124 DE_ASSERT(result_data != NULL);
1125
1126 /* Read the data */
1127 gl.readPixels(0, /* x */
1128 0, /* y */
1129 texture_size.m_size, texture_size.m_size, m_depth_format, m_depth_type, result_data);
1130 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1131
1132 /* Verify image, expected value is layer index */
1133 result = verifyImage<glw::GLuint, 1>(texture_size.m_size, texture_size.m_size, &expected_value, result_data);
1134
1135 /* Release the buffer */
1136 if (result_data != NULL)
1137 {
1138 delete[] result_data;
1139
1140 result_data = NULL;
1141 }
1142
1143 return result;
1144 }
1145
1146 /** Reads read buffer's depth data (assuming it's of 32-bit FP resolution)
1147 * and verifies its correctness.
1148 *
1149 * @param texture_size Texture size
1150 * @param n_layer Index of the layer to verify.
1151 *
1152 * @return true if the retrieved data was found correct, false otherwise.
1153 **/
verifyDepth32FData(const _texture_size & texture_size,glw::GLuint n_layer)1154 bool TextureCubeMapArrayColorDepthAttachmentsTest::verifyDepth32FData(const _texture_size &texture_size,
1155 glw::GLuint n_layer)
1156 {
1157 /* Allocate buffer for the data we will retrieve from the implementation */
1158 glw::GLfloat expected_value = (glw::GLfloat)n_layer / 256.0f;
1159 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1160 bool result = false;
1161 const glw::GLuint result_data_size = texture_size.m_size * texture_size.m_size;
1162 glw::GLfloat *result_data = new glw::GLfloat[result_data_size];
1163
1164 DE_ASSERT(result_data != NULL);
1165
1166 /* Read the data */
1167 gl.readPixels(0, /* x */
1168 0, /* y */
1169 texture_size.m_size, texture_size.m_size, m_depth_format, m_depth_type, result_data);
1170 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1171
1172 /* Verify image, expected value is layer index */
1173 result = verifyImage<glw::GLfloat, 1>(texture_size.m_size, texture_size.m_size, &expected_value, result_data);
1174
1175 /* Release the buffer */
1176 if (result_data != NULL)
1177 {
1178 delete[] result_data;
1179
1180 result_data = NULL;
1181 }
1182
1183 return result;
1184 }
1185
1186 } // namespace glcts
1187