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 "esextcGeometryShaderLayeredFramebuffer.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuTestLog.hpp"
31 #include <cstring>
32
33 namespace glcts
34 {
35 /** Constructor
36 *
37 * @param context Test context
38 * @param name Test case's name
39 * @param description Test case's desricption
40 **/
GeometryShaderLayeredFramebufferBlending(Context & context,const ExtParameters & extParams,const char * name,const char * description)41 GeometryShaderLayeredFramebufferBlending::GeometryShaderLayeredFramebufferBlending(Context &context,
42 const ExtParameters &extParams,
43 const char *name,
44 const char *description)
45 : TestCaseBase(context, extParams, name, description)
46 , m_fbo_id(0)
47 , m_fs_id(0)
48 , m_gs_id(0)
49 , m_po_id(0)
50 , m_read_fbo_id(0)
51 , m_to_id(0)
52 , m_vao_id(0)
53 , m_vs_id(0)
54 {
55 /* Left blank on purpose */
56 }
57
58 /** Deinitializes GLES objects created during the test. */
deinit(void)59 void GeometryShaderLayeredFramebufferBlending::deinit(void)
60 {
61 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
62
63 /* Clean up */
64 if (m_fbo_id != 0)
65 {
66 gl.deleteFramebuffers(1, &m_fbo_id);
67 }
68
69 if (m_fs_id != 0)
70 {
71 gl.deleteShader(m_fs_id);
72 }
73
74 if (m_gs_id != 0)
75 {
76 gl.deleteShader(m_gs_id);
77 }
78
79 if (m_po_id != 0)
80 {
81 gl.deleteProgram(m_po_id);
82 }
83
84 if (m_read_fbo_id != 0)
85 {
86 gl.deleteFramebuffers(1, &m_read_fbo_id);
87 }
88
89 if (m_to_id != 0)
90 {
91 gl.deleteTextures(1, &m_to_id);
92 }
93
94 if (m_vao_id != 0)
95 {
96 gl.deleteVertexArrays(1, &m_vao_id);
97 }
98
99 if (m_vs_id != 0)
100 {
101 gl.deleteShader(m_vs_id);
102 }
103
104 /* Release base class */
105 TestCaseBase::deinit();
106 }
107
108 /** Executes the test.
109 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
110 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
111 * Note the function throws exception should an error occur!
112 **/
iterate(void)113 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferBlending::iterate(void)
114 {
115 /* Test-wide constants */
116 #define N_TEXTURE_COMPONENTS (4)
117 #define TEXTURE_DEPTH (4)
118 #define TEXTURE_HEIGHT (4)
119 #define TEXTURE_WIDTH (4)
120
121 /* Fragment shader code */
122 const char *fs_code = "${VERSION}\n"
123 "\n"
124 "precision highp float;\n"
125 "\n"
126 "out vec4 result;\n"
127 "\n"
128 "void main()\n"
129 "{\n"
130 " result = vec4(0.2);\n"
131 "}\n";
132
133 /* Geometry shader code */
134 const char *gs_code = "${VERSION}\n"
135 "${GEOMETRY_SHADER_REQUIRE}\n"
136 "\n"
137 "layout(points) in;\n"
138 "layout(triangle_strip, max_vertices=64) out;\n"
139 "\n"
140 "void main()\n"
141 "{\n"
142 " for (int n = 0; n < 4; ++n)\n"
143 " {\n"
144 " gl_Layer = n;\n"
145 " gl_Position = vec4(1, 1, 0, 1);\n"
146 " EmitVertex();\n"
147 "\n"
148 " gl_Layer = n;\n"
149 " gl_Position = vec4(1, -1, 0, 1);\n"
150 " EmitVertex();\n"
151 "\n"
152 " gl_Layer = n;\n"
153 " gl_Position = vec4(-1, 1, 0, 1);\n"
154 " EmitVertex();\n"
155 "\n"
156 " gl_Layer = n;\n"
157 " gl_Position = vec4(-1, -1, 0, 1);\n"
158 " EmitVertex();\n"
159 "\n"
160 " EndPrimitive();\n"
161 " }\n"
162 "}\n";
163
164 /* General variables */
165 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
166 unsigned int n = 0;
167 unsigned int n_component = 0;
168 unsigned int n_layer = 0;
169 unsigned int n_slice = 0;
170 unsigned int x = 0;
171 unsigned int y = 0;
172
173 unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
174 unsigned char buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
175 unsigned char buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
176 unsigned char buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
177 unsigned char buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
178 unsigned char ref_buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
179 unsigned char ref_buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
180 unsigned char ref_buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
181 unsigned char ref_buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
182
183 if (!m_is_geometry_shader_extension_supported)
184 {
185 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
186 }
187
188 /* Set up shader objects */
189 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
190 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
191 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
192
193 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate shader objects");
194
195 /* Set up program objects */
196 m_po_id = gl.createProgram();
197
198 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
199 &m_boilerplate_vs_code))
200 {
201 TCU_FAIL("Could not build program object");
202 }
203
204 /* Prepare texture data we will use for each slice */
205 for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
206 {
207 unsigned char *slice_pixels_ptr[] = {
208 buffer_slice1 + n * N_TEXTURE_COMPONENTS, buffer_slice2 + n * N_TEXTURE_COMPONENTS,
209 buffer_slice3 + n * N_TEXTURE_COMPONENTS, buffer_slice4 + n * N_TEXTURE_COMPONENTS};
210
211 for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice)
212 {
213 slice_pixels_ptr[n_slice][0] = 0;
214 slice_pixels_ptr[n_slice][1] = (unsigned char)(n_slice * 255 / 4);
215 slice_pixels_ptr[n_slice][2] = (unsigned char)(n_slice * 255 / 8);
216 slice_pixels_ptr[n_slice][3] = (unsigned char)(n_slice * 255 / 12);
217 } /* for (all slices) */
218 } /* for (all pixels) */
219
220 /* Calculate reference texture data we will later use when verifying the rendered data */
221 for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
222 {
223 unsigned char *ref_slice_pixels_ptr[] = {
224 ref_buffer_slice1 + n * N_TEXTURE_COMPONENTS, ref_buffer_slice2 + n * N_TEXTURE_COMPONENTS,
225 ref_buffer_slice3 + n * N_TEXTURE_COMPONENTS, ref_buffer_slice4 + n * N_TEXTURE_COMPONENTS};
226
227 unsigned char *slice_pixels_ptr[] = {
228 buffer_slice1 + n * N_TEXTURE_COMPONENTS, buffer_slice2 + n * N_TEXTURE_COMPONENTS,
229 buffer_slice3 + n * N_TEXTURE_COMPONENTS, buffer_slice4 + n * N_TEXTURE_COMPONENTS};
230
231 for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice)
232 {
233 unsigned char *ref_slice_ptr = ref_slice_pixels_ptr[n_slice];
234 unsigned char *slice_ptr = slice_pixels_ptr[n_slice];
235 float slice_rgba[] = {
236 float(slice_ptr[0]) / 255.0f, /* convert to FP representation */
237 float(slice_ptr[1]) / 255.0f, /* convert to FP representation */
238 float(slice_ptr[2]) / 255.0f, /* convert to FP representation */
239 float(slice_ptr[3]) / 255.0f /* convert to FP representation */
240 };
241
242 for (n_component = 0; n_component < N_TEXTURE_COMPONENTS; ++n_component)
243 {
244 float temp_component = slice_rgba[n_component] /* dst_color */ * slice_rgba[n_component] /* dst_color */
245 + 0.8f /* 1-src_color */ * 0.2f /* src_color */;
246
247 /* Clamp if necessary */
248 if (temp_component < 0)
249 {
250 temp_component = 0.0f;
251 }
252 else if (temp_component > 1)
253 {
254 temp_component = 1.0f;
255 }
256
257 /* Convert back to GL_RGBA8 */
258 ref_slice_ptr[n_component] = (unsigned char)(temp_component * 255.0f);
259 } /* for (all components) */
260 } /* for (all slices) */
261 } /* for (all pixels) */
262
263 /* Set up texture object used for the test */
264 gl.genTextures(1, &m_to_id);
265 gl.bindTexture(GL_TEXTURE_3D, m_to_id);
266 gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
267 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
268 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice1);
269 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
270 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice2);
271 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
272 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice3);
273 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
274 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice4);
275
276 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object");
277
278 /* Set up framebuffer object used for the test */
279 gl.genFramebuffers(1, &m_fbo_id);
280 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
281
282 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */);
283
284 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer");
285
286 /* Generate and bind a vertex array object */
287 gl.genVertexArrays(1, &m_vao_id);
288 gl.bindVertexArray(m_vao_id);
289
290 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up vertex array object");
291
292 /* Set up blending */
293 gl.blendFunc(GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR);
294 gl.enable(GL_BLEND);
295
296 /* Render */
297 gl.useProgram(m_po_id);
298 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
299
300 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
301
302 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed");
303
304 /* Verify rendered data in the layers */
305 gl.genFramebuffers(1, &m_read_fbo_id);
306 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
307
308 for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
309 {
310 bool has_layer_failed = false;
311
312 const unsigned char *ref_buffer = (n_layer == 0) ? ref_buffer_slice1 :
313 (n_layer == 1) ? ref_buffer_slice2 :
314 (n_layer == 2) ? ref_buffer_slice3 :
315 ref_buffer_slice4;
316
317 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */, n_layer);
318 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
319
320 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixel data!");
321
322 for (y = 0; y < TEXTURE_HEIGHT; ++y)
323 {
324 const unsigned int pixel_size = N_TEXTURE_COMPONENTS;
325 const unsigned char *ref_row = ref_buffer + y * pixel_size;
326 const unsigned char *row = buffer + y * pixel_size;
327
328 for (x = 0; x < TEXTURE_WIDTH; ++x)
329 {
330 #define EPSILON (1)
331
332 const unsigned char *data = row + x * pixel_size;
333 const unsigned char *ref_data = ref_row + x * pixel_size;
334
335 if (de::abs((int)data[0] - (int)ref_data[0]) > EPSILON ||
336 de::abs((int)data[1] - (int)ref_data[1]) > EPSILON ||
337 de::abs((int)data[2] - (int)ref_data[2]) > EPSILON ||
338 de::abs((int)data[3] - (int)ref_data[3]) > EPSILON)
339 {
340 m_testCtx.getLog() << tcu::TestLog::Message << "(layer=" << n_layer << " x=" << x << " y=" << y
341 << ") "
342 << "Reference value is different than the rendered data (epsilon > " << EPSILON
343 << "): "
344 << "(" << (unsigned int)ref_data[0] << ", " << (unsigned int)ref_data[1] << ", "
345 << (unsigned int)ref_data[2] << ", " << (unsigned int)ref_data[3] << ") vs "
346 << "(" << (unsigned int)data[0] << ", " << (unsigned int)data[1] << ", "
347 << (unsigned int)data[2] << ", " << (unsigned int)data[3] << ")."
348 << tcu::TestLog::EndMessage;
349
350 has_layer_failed = true;
351 } /* if (regions are different) */
352
353 #undef EPSILON
354 } /* for (all pixels in a row) */
355 } /* for (all rows) */
356
357 if (has_layer_failed)
358 {
359 TCU_FAIL("Pixel data comparison failed");
360 }
361 } /* for (all layers) */
362
363 /* Done */
364 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
365 return STOP;
366
367 #undef N_TEXTURE_COMPONENTS
368 #undef TEXTURE_DEPTH
369 #undef TEXTURE_HEIGHT
370 #undef TEXTURE_WIDTH
371 }
372
373 /** Constructor
374 *
375 * @param context Test context
376 * @param name Test case's name
377 * @param description Test case's description
378 **/
GeometryShaderLayeredFramebufferClear(Context & context,const ExtParameters & extParams,const char * name,const char * description)379 GeometryShaderLayeredFramebufferClear::GeometryShaderLayeredFramebufferClear(Context &context,
380 const ExtParameters &extParams,
381 const char *name, const char *description)
382 : TestCaseBase(context, extParams, name, description)
383 , m_fbo_char_id(0)
384 , m_fbo_int_id(0)
385 , m_fbo_uint_id(0)
386 , m_read_fbo_id(0)
387 , m_to_rgba32i_id(0)
388 , m_to_rgba32ui_id(0)
389 , m_to_rgba8_id(0)
390 {
391 /* Left blank on purpose */
392 }
393
394 /** Executes the test.
395 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
396 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
397 * Note the function throws exception should an error occur!
398 **/
iterate(void)399 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferClear::iterate(void)
400 {
401 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
402
403 /* Test-wide definitions */
404 #define N_TEXTURE_COMPONENTS (4)
405 #define TEXTURE_DEPTH (4)
406 #define TEXTURE_HEIGHT (4)
407 #define TEXTURE_WIDTH (4)
408
409 /* Type definitions */
410 typedef enum
411 {
412 /* Always first */
413 CLEAR_FIRST = 0,
414
415 /* glClear() */
416 CLEAR_PLAIN = CLEAR_FIRST,
417 /* glClearBufferfv() */
418 CLEAR_BUFFERFV,
419 /* glClearBufferiv() */
420 CLEAR_BUFFERIV,
421 /* glClearBufferuiv() */
422 CLEAR_BUFFERUIV,
423
424 /* Always last */
425 CLEAR_COUNT
426 } _clear_type;
427
428 /* General variables */
429 const glw::GLenum fbo_draw_buffer = GL_COLOR_ATTACHMENT0;
430
431 int n = 0;
432 int n_layer = 0;
433 int x = 0;
434 int y = 0;
435
436 unsigned char buffer_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
437 int buffer_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
438 unsigned int buffer_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
439 unsigned char slice_1_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
440 int slice_1_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
441 unsigned int slice_1_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
442 unsigned char slice_2_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
443 int slice_2_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
444 unsigned int slice_2_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
445 unsigned char slice_3_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
446 int slice_3_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
447 unsigned int slice_3_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
448 unsigned char slice_4_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
449 int slice_4_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
450 unsigned int slice_4_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
451
452 /* Only carry on if geometry shaders are supported */
453 if (!m_is_geometry_shader_extension_supported)
454 {
455 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
456 }
457
458 /* Set up slice data */
459 memset(slice_1_data_char, 0, sizeof(slice_1_data_char));
460 memset(slice_1_data_int, 0, sizeof(slice_1_data_int));
461 memset(slice_1_data_uint, 0, sizeof(slice_1_data_uint));
462 memset(slice_2_data_char, 0, sizeof(slice_2_data_char));
463 memset(slice_2_data_int, 0, sizeof(slice_2_data_int));
464 memset(slice_2_data_uint, 0, sizeof(slice_2_data_uint));
465 memset(slice_3_data_char, 0, sizeof(slice_3_data_char));
466 memset(slice_3_data_int, 0, sizeof(slice_3_data_int));
467 memset(slice_3_data_uint, 0, sizeof(slice_3_data_uint));
468 memset(slice_4_data_char, 0, sizeof(slice_4_data_char));
469 memset(slice_4_data_int, 0, sizeof(slice_4_data_int));
470 memset(slice_4_data_uint, 0, sizeof(slice_4_data_uint));
471
472 for (n = 0; n < 4 /* width */ * 4 /* height */; ++n)
473 {
474 slice_1_data_char[4 * n + 0] = 255;
475 slice_1_data_int[4 * n + 0] = 255;
476 slice_1_data_uint[4 * n + 0] = 255;
477
478 slice_2_data_char[4 * n + 1] = 255;
479 slice_2_data_int[4 * n + 1] = 255;
480 slice_2_data_uint[4 * n + 1] = 255;
481
482 slice_3_data_char[4 * n + 2] = 255;
483 slice_3_data_int[4 * n + 2] = 255;
484 slice_3_data_uint[4 * n + 2] = 255;
485
486 slice_4_data_char[4 * n + 0] = 255;
487 slice_4_data_char[4 * n + 1] = 255;
488 slice_4_data_int[4 * n + 0] = 255;
489 slice_4_data_int[4 * n + 1] = 255;
490 slice_4_data_uint[4 * n + 0] = 255;
491 slice_4_data_uint[4 * n + 1] = 255;
492 } /* for (all pixels) */
493
494 /* Set up texture objects */
495 gl.genTextures(1, &m_to_rgba8_id);
496 gl.genTextures(1, &m_to_rgba32i_id);
497 gl.genTextures(1, &m_to_rgba32ui_id);
498
499 for (n = 0; n < 3 /* textures */; ++n)
500 {
501 void *to_data_1 = (n == 0) ? (void *)slice_1_data_char :
502 (n == 1) ? (void *)slice_1_data_int :
503 (void *)slice_1_data_uint;
504
505 void *to_data_2 = (n == 0) ? (void *)slice_2_data_char :
506 (n == 1) ? (void *)slice_2_data_int :
507 (void *)slice_2_data_uint;
508
509 void *to_data_3 = (n == 0) ? (void *)slice_3_data_char :
510 (n == 1) ? (void *)slice_3_data_int :
511 (void *)slice_3_data_uint;
512
513 void *to_data_4 = (n == 0) ? (void *)slice_4_data_char :
514 (n == 1) ? (void *)slice_4_data_int :
515 (void *)slice_4_data_uint;
516
517 glw::GLenum to_format = (n == 0) ? GL_RGBA : (n == 1) ? GL_RGBA_INTEGER : GL_RGBA_INTEGER;
518
519 glw::GLenum to_internalformat = (n == 0) ? GL_RGBA8 : (n == 1) ? GL_RGBA32I : GL_RGBA32UI;
520
521 glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id;
522
523 glw::GLenum to_type = (n == 0) ? GL_UNSIGNED_BYTE : (n == 1) ? GL_INT : GL_UNSIGNED_INT;
524
525 gl.bindTexture(GL_TEXTURE_3D, to_id);
526
527 gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, to_internalformat, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
528
529 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
530 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_1);
531 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
532 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_2);
533 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
534 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_3);
535 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
536 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_4);
537
538 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
539 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
540 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
541
542 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture object");
543 } /* for (all texture objects) */
544
545 /* Set up framebuffer object */
546 gl.genFramebuffers(1, &m_fbo_char_id);
547 gl.genFramebuffers(1, &m_fbo_int_id);
548 gl.genFramebuffers(1, &m_fbo_uint_id);
549 gl.genFramebuffers(1, &m_read_fbo_id);
550
551 for (n = 0; n < 3 /* framebuffers */; ++n)
552 {
553 glw::GLuint fbo_id = (n == 0) ? m_fbo_char_id : (n == 1) ? m_fbo_int_id : m_fbo_uint_id;
554
555 glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id;
556
557 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
558 gl.drawBuffers(1, &fbo_draw_buffer);
559 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */);
560
561 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
562 } /* for (all framebuffers) */
563
564 /* Try reading from the layered framebuffer. */
565 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_char_id);
566 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer_char);
567
568 /* Is the returned data an exact copy of what we've uploaded for layer zero? */
569 if (memcmp(buffer_char, slice_1_data_char, sizeof(slice_1_data_char)) != 0)
570 {
571 TCU_FAIL("Retrieved data is different from data uploaded for layer 0 of a layered framebuffer.");
572 }
573
574 /* Iterate through all clear calls supported */
575
576 for (int current_test = static_cast<int>(CLEAR_FIRST); current_test < static_cast<int>(CLEAR_COUNT); current_test++)
577 {
578 void *buffer = NULL;
579 const float clear_color_float[] = {0.25f, 0.5f, 1.0f, 32.0f / 255.0f};
580 const int clear_color_int[] = {64, 128, 255, 32};
581 glw::GLuint fbo_id = 0;
582 int pixel_size = 0;
583 void *slice_1_data = NULL;
584 void *slice_2_data = NULL;
585 void *slice_3_data = NULL;
586 void *slice_4_data = NULL;
587 glw::GLenum to_format = GL_NONE;
588 glw::GLuint to_id = 0;
589 glw::GLenum to_type = GL_NONE;
590
591 switch (static_cast<_clear_type>(current_test))
592 {
593 case CLEAR_BUFFERFV:
594 case CLEAR_PLAIN:
595 {
596 buffer = buffer_char;
597 fbo_id = m_fbo_char_id;
598 pixel_size = N_TEXTURE_COMPONENTS;
599 slice_1_data = slice_1_data_char;
600 slice_2_data = slice_2_data_char;
601 slice_3_data = slice_3_data_char;
602 slice_4_data = slice_4_data_char;
603 to_format = GL_RGBA;
604 to_id = m_to_rgba8_id;
605 to_type = GL_UNSIGNED_BYTE;
606
607 break;
608 }
609
610 case CLEAR_BUFFERIV:
611 {
612 buffer = (void *)buffer_int;
613 fbo_id = m_fbo_int_id;
614 pixel_size = N_TEXTURE_COMPONENTS * sizeof(int);
615 slice_1_data = slice_1_data_int;
616 slice_2_data = slice_2_data_int;
617 slice_3_data = slice_3_data_int;
618 slice_4_data = slice_4_data_int;
619 to_format = GL_RGBA_INTEGER;
620 to_id = m_to_rgba32i_id;
621 to_type = GL_INT;
622
623 break;
624 }
625
626 case CLEAR_BUFFERUIV:
627 {
628 buffer = (void *)buffer_uint;
629 fbo_id = m_fbo_uint_id;
630 pixel_size = N_TEXTURE_COMPONENTS * sizeof(unsigned int);
631 slice_1_data = slice_1_data_uint;
632 slice_2_data = slice_2_data_uint;
633 slice_3_data = slice_3_data_uint;
634 slice_4_data = slice_4_data_uint;
635 to_format = GL_RGBA_INTEGER;
636 to_id = m_to_rgba32ui_id;
637 to_type = GL_UNSIGNED_INT;
638
639 break;
640 }
641
642 default:
643 {
644 /* This location should never be reached */
645 TCU_FAIL("Execution flow failure");
646 }
647 } /* switch (current_test)*/
648
649 /* Restore layer data just in case */
650 gl.bindTexture(GL_TEXTURE_3D, to_id);
651 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
652 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_1_data);
653 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
654 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_2_data);
655 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
656 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_3_data);
657 gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
658 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_4_data);
659
660 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed.");
661
662 /* Issue requested clear call */
663 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
664
665 switch (current_test)
666 {
667 case CLEAR_PLAIN:
668 {
669 gl.clearColor(clear_color_float[0], clear_color_float[1], clear_color_float[2], clear_color_float[3]);
670 gl.clear(GL_COLOR_BUFFER_BIT);
671
672 break;
673 }
674
675 case CLEAR_BUFFERIV:
676 {
677 gl.clearBufferiv(GL_COLOR, 0 /* draw buffer index */, clear_color_int);
678
679 break;
680 }
681
682 case CLEAR_BUFFERUIV:
683 {
684 gl.clearBufferuiv(GL_COLOR, 0 /* draw buffer index */, (const glw::GLuint *)clear_color_int);
685
686 break;
687 }
688
689 case CLEAR_BUFFERFV:
690 {
691 gl.clearBufferfv(GL_COLOR, 0 /* draw buffer index */, clear_color_float);
692
693 break;
694 }
695
696 default:
697 {
698 /* This location should never be reached */
699 TCU_FAIL("Execution flow failure");
700 }
701 } /* switch (current_test) */
702
703 /* Make sure no error was generated */
704 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear call failed.");
705
706 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
707 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create read framebuffer object!");
708
709 /* Check the layer data after a clear call */
710 for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
711 {
712 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */, n_layer);
713 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, to_format, to_type, buffer);
714
715 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
716
717 /* If we requested an integer clear, the pixels we obtained should be reset to specific values.
718 * If we asked for a FP-based clear, consider an epsilon. */
719 for (y = 0; y < TEXTURE_HEIGHT; ++y)
720 {
721 const int row_size = TEXTURE_WIDTH * pixel_size;
722 unsigned char *row = (unsigned char *)buffer + y * row_size;
723
724 for (x = 0; x < TEXTURE_WIDTH; ++x)
725 {
726 if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV)
727 {
728 unsigned int *pixel = (unsigned int *)(row + x * pixel_size);
729 if (memcmp(pixel, clear_color_int, sizeof(clear_color_int)) != 0)
730 {
731 /* Test fails at this point */
732 m_testCtx.getLog()
733 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
734 << clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2]
735 << ", " << clear_color_int[3] << "] is different from the one retrieved ["
736 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
737 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
738
739 TCU_FAIL("Data comparison failure");
740 } /* if (memcmp(pixel, clear_color_int, sizeof(clear_color_int) ) != 0) */
741 } /* if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) */
742 else
743 {
744 #define EPSILON (1)
745
746 unsigned char *pixel = (unsigned char *)(row + x * pixel_size);
747
748 if (de::abs((int)pixel[0] - clear_color_int[0]) > EPSILON ||
749 de::abs((int)pixel[1] - clear_color_int[1]) > EPSILON ||
750 de::abs((int)pixel[2] - clear_color_int[2]) > EPSILON ||
751 de::abs((int)pixel[3] - clear_color_int[3]) > EPSILON)
752 {
753 /* Test fails at this point */
754 m_testCtx.getLog()
755 << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
756 << clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2]
757 << ", " << clear_color_int[3] << "] is different from the one retrieved ["
758 << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
759 << (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
760
761 TCU_FAIL("Data comparison failure");
762 } /* if (pixel component has exceeded an allowed epsilon) */
763
764 #undef EPSILON
765 }
766 } /* for (all pixels) */
767 } /* for (all rows) */
768 } /* for (all layers) */
769 } /* for (all clear call types) */
770
771 /* Done */
772 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
773 return STOP;
774
775 #undef TEXTURE_DEPTH
776 #undef TEXTURE_HEIGHT
777 #undef TEXTURE_WIDTH
778 }
779
780 /** Deinitializes GLES objects created during the test. */
deinit(void)781 void GeometryShaderLayeredFramebufferClear::deinit(void)
782 {
783 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
784
785 if (m_fbo_char_id != 0)
786 {
787 gl.deleteFramebuffers(1, &m_fbo_char_id);
788 }
789
790 if (m_fbo_int_id != 0)
791 {
792 gl.deleteFramebuffers(1, &m_fbo_int_id);
793 }
794
795 if (m_fbo_uint_id != 0)
796 {
797 gl.deleteFramebuffers(1, &m_fbo_uint_id);
798 }
799
800 if (m_to_rgba32i_id != 0)
801 {
802 gl.deleteTextures(1, &m_to_rgba32i_id);
803 }
804
805 if (m_to_rgba32ui_id != 0)
806 {
807 gl.deleteTextures(1, &m_to_rgba32ui_id);
808 }
809
810 if (m_to_rgba8_id != 0)
811 {
812 gl.deleteTextures(1, &m_to_rgba8_id);
813 }
814
815 if (m_read_fbo_id != 0)
816 {
817 gl.deleteFramebuffers(1, &m_read_fbo_id);
818 }
819
820 /* Release base class */
821 TestCaseBase::deinit();
822 }
823
824 /** Constructor
825 *
826 * @param context Test context
827 * @param name Test case's name
828 * @param description Test case's desricption
829 **/
GeometryShaderLayeredFramebufferDepth(Context & context,const ExtParameters & extParams,const char * name,const char * description)830 GeometryShaderLayeredFramebufferDepth::GeometryShaderLayeredFramebufferDepth(Context &context,
831 const ExtParameters &extParams,
832 const char *name, const char *description)
833 : TestCaseBase(context, extParams, name, description)
834 , m_fbo_id(0)
835 , m_fs_id(0)
836 , m_gs_id(0)
837 , m_po_id(0)
838 , m_read_fbo_id(0)
839 , m_to_a_id(0)
840 , m_to_b_id(0)
841 , m_vao_id(0)
842 , m_vs_id(0)
843 {
844 /* Left blank on purpose */
845 }
846
847 /** Deinitializes GLES objects created during the test. */
deinit(void)848 void GeometryShaderLayeredFramebufferDepth::deinit(void)
849 {
850 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
851
852 /* Clean up */
853 if (m_fbo_id != 0)
854 {
855 gl.deleteFramebuffers(1, &m_fbo_id);
856 }
857
858 if (m_fs_id != 0)
859 {
860 gl.deleteShader(m_fs_id);
861 }
862
863 if (m_gs_id != 0)
864 {
865 gl.deleteShader(m_gs_id);
866 }
867
868 if (m_po_id != 0)
869 {
870 gl.deleteProgram(m_po_id);
871 }
872
873 if (m_read_fbo_id != 0)
874 {
875 gl.deleteFramebuffers(1, &m_read_fbo_id);
876 }
877
878 if (m_to_a_id != 0)
879 {
880 gl.deleteTextures(1, &m_to_a_id);
881 }
882
883 if (m_to_b_id != 0)
884 {
885 gl.deleteTextures(1, &m_to_b_id);
886 }
887
888 if (m_vao_id != 0)
889 {
890 gl.deleteVertexArrays(1, &m_vao_id);
891 }
892
893 if (m_vs_id != 0)
894 {
895 gl.deleteShader(m_vs_id);
896 }
897
898 /* Release base class */
899 TestCaseBase::deinit();
900 }
901
902 /** Executes the test.
903 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
904 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
905 * Note the function throws exception should an error occur!
906 **/
iterate(void)907 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferDepth::iterate(void)
908 {
909 /* General variables */
910 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
911 unsigned int n = 0;
912 unsigned int x = 0;
913 unsigned int y = 0;
914
915 /* Test-wide definitions */
916 #define N_TEXTURE_COMPONENTS (4)
917 #define TEXTURE_DEPTH (4)
918 #define TEXTURE_HEIGHT (4)
919 #define TEXTURE_WIDTH (4)
920
921 /* Fragment shader code */
922 const char *fs_code = "${VERSION}\n"
923 "\n"
924 "precision highp float;\n"
925 "\n"
926 "out vec4 result;\n"
927 "\n"
928 "void main()\n"
929 "{\n"
930 " result = vec4(1.0);\n"
931 "}\n";
932
933 const char *gs_code = "${VERSION}\n"
934 "${GEOMETRY_SHADER_REQUIRE}\n"
935 "\n"
936 "layout(points) in;\n"
937 "layout(triangle_strip, max_vertices=64) out;\n"
938 "\n"
939 "void main()\n"
940 "{\n"
941 " for (int n = 0; n < 4; ++n)\n"
942 " {\n"
943 " float depth = -1.0 + float(n) * 0.5;\n"
944 "\n"
945 " gl_Layer = n;\n"
946 " gl_Position = vec4(1, 1, depth, 1);\n"
947 " EmitVertex();\n"
948 "\n"
949 " gl_Layer = n;\n"
950 " gl_Position = vec4(1, -1, depth, 1);\n"
951 " EmitVertex();\n"
952 "\n"
953 " gl_Layer = n;\n"
954 " gl_Position = vec4(-1, 1, depth, 1);\n"
955 " EmitVertex();\n"
956 "\n"
957 " gl_Layer = n;\n"
958 " gl_Position = vec4(-1, -1, depth, 1);\n"
959 " EmitVertex();\n"
960 "\n"
961 " EndPrimitive();\n"
962 " }\n"
963 "}\n";
964
965 /* This test should only run if EXT_geometry_shader is supported */
966 if (!m_is_geometry_shader_extension_supported)
967 {
968 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
969 }
970
971 /* Set up texture objects we will be using for the test */
972 gl.genTextures(1, &m_to_a_id);
973 gl.genTextures(1, &m_to_b_id);
974
975 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
976 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
977 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
978 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT,
979 TEXTURE_DEPTH);
980
981 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture objects");
982
983 /* Set up framebuffer object we will use for the test */
984 gl.genFramebuffers(1, &m_fbo_id);
985 gl.genFramebuffers(1, &m_read_fbo_id);
986
987 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
988
989 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
990 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_to_b_id, 0 /* level */);
991
992 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
993
994 if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
995 {
996 m_testCtx.getLog() << tcu::TestLog::Message
997 << "Draw framebuffer is incomplete: " << gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER)
998 << tcu::TestLog::EndMessage;
999
1000 TCU_FAIL("Draw framebuffer is incomplete.");
1001 }
1002
1003 /* Set up shader objects */
1004 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1005 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1006 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1007
1008 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize shader objects");
1009
1010 /* Set up program object */
1011 m_po_id = gl.createProgram();
1012
1013 if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
1014 &m_boilerplate_vs_code))
1015 {
1016 TCU_FAIL("Could not build program object");
1017 }
1018
1019 /* Set up vertex array object */
1020 gl.genVertexArrays(1, &m_vao_id);
1021 gl.bindVertexArray(m_vao_id);
1022
1023 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind vertex array object");
1024
1025 /* Clear the depth attachment before we continue */
1026 gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */);
1027 gl.clearDepthf(0.5f);
1028 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1029
1030 GLU_EXPECT_NO_ERROR(gl.getError(), "Depth buffer clear operation failed");
1031
1032 /* Render */
1033 gl.useProgram(m_po_id);
1034 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
1035
1036 gl.enable(GL_DEPTH_TEST);
1037 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1038
1039 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
1040
1041 /* Verify the output */
1042 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
1043
1044 for (n = 0; n < TEXTURE_DEPTH; ++n)
1045 {
1046 unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
1047 unsigned char ref_color[4];
1048
1049 /* Determine reference color */
1050 if (n < 2)
1051 {
1052 memset(ref_color, 0xFF, sizeof(ref_color));
1053 }
1054 else
1055 {
1056 memset(ref_color, 0, sizeof(ref_color));
1057 }
1058
1059 /* Read the rendered layer data */
1060 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
1061 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1062
1063 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1064
1065 /* Compare all pixels against the reference value */
1066 for (y = 0; y < TEXTURE_HEIGHT; ++y)
1067 {
1068 const unsigned int pixel_size = N_TEXTURE_COMPONENTS;
1069 const unsigned int row_width = TEXTURE_WIDTH * pixel_size;
1070 const unsigned char *row_data = buffer + y * row_width;
1071
1072 for (x = 0; x < TEXTURE_WIDTH; ++x)
1073 {
1074 const unsigned char *result = row_data + x * pixel_size;
1075
1076 if (memcmp(result, ref_color, sizeof(ref_color)) != 0)
1077 {
1078 m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") "
1079 << "Reference value is different than the rendered data: "
1080 << "(" << (unsigned int)ref_color[0] << ", " << (unsigned int)ref_color[1]
1081 << ", " << (unsigned int)ref_color[2] << ", " << (unsigned int)ref_color[3]
1082 << ") vs "
1083 << "(" << (unsigned int)result[0] << ", " << (unsigned int)result[1] << ", "
1084 << (unsigned int)result[2] << ", " << (unsigned int)result[3] << ")."
1085 << tcu::TestLog::EndMessage;
1086
1087 TCU_FAIL("Rendered data mismatch");
1088 } /* if (memcmp(row_data + x * pixel_size, ref_color, sizeof(ref_color) ) != 0)*/
1089 } /* for (all pixels in a row) */
1090 } /* for (all rows) */
1091 } /* for (all layers) */
1092
1093 /* Done */
1094 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1095 return STOP;
1096
1097 #undef N_TEXTURE_COMPONENTS
1098 #undef TEXTURE_DEPTH
1099 #undef TEXTURE_HEIGHT
1100 #undef TEXTURE_WIDTH
1101 }
1102
1103 /** Constructor
1104 *
1105 * @param context Test context
1106 * @param name Test case's name
1107 * @param description Test case's desricption
1108 **/
GeometryShaderLayeredFramebufferStencil(Context & context,const ExtParameters & extParams,const char * name,const char * description)1109 GeometryShaderLayeredFramebufferStencil::GeometryShaderLayeredFramebufferStencil(Context &context,
1110 const ExtParameters &extParams,
1111 const char *name,
1112 const char *description)
1113 : TestCaseBase(context, extParams, name, description)
1114 , m_fbo_id(0)
1115 , m_fs_id(0)
1116 , m_gs_id(0)
1117 , m_po_id(0)
1118 , m_to_a_id(0)
1119 , m_to_b_id(0)
1120 , m_vao_id(0)
1121 , m_vs_id(0)
1122 {
1123 /* Left blank on purpose */
1124 }
1125
1126 /** Deinitializes GLES objects created during the test. */
deinit(void)1127 void GeometryShaderLayeredFramebufferStencil::deinit(void)
1128 {
1129 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1130
1131 /* Clean up */
1132 if (m_fbo_id != 0)
1133 {
1134 gl.deleteFramebuffers(1, &m_fbo_id);
1135 }
1136
1137 if (m_fs_id != 0)
1138 {
1139 gl.deleteShader(m_fs_id);
1140 }
1141
1142 if (m_gs_id != 0)
1143 {
1144 gl.deleteShader(m_gs_id);
1145 }
1146
1147 if (m_po_id != 0)
1148 {
1149 gl.deleteProgram(m_po_id);
1150 }
1151
1152 if (m_to_a_id != 0)
1153 {
1154 gl.deleteTextures(1, &m_to_a_id);
1155 }
1156
1157 if (m_to_b_id != 0)
1158 {
1159 gl.deleteTextures(1, &m_to_b_id);
1160 }
1161
1162 if (m_vao_id != 0)
1163 {
1164 gl.deleteVertexArrays(1, &m_vao_id);
1165 }
1166
1167 if (m_vs_id != 0)
1168 {
1169 gl.deleteShader(m_vs_id);
1170 }
1171
1172 /* Release base class */
1173 TestCaseBase::deinit();
1174 }
1175
1176 /** Executes the test.
1177 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1178 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1179 * Note the function throws exception should an error occur!
1180 **/
iterate(void)1181 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferStencil::iterate(void)
1182 {
1183 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1184
1185 /* Test-wide definitions */
1186 #define N_TEXTURE_COMPONENTS (4)
1187 #define TEXTURE_DEPTH (4)
1188 #define TEXTURE_HEIGHT (4)
1189 #define TEXTURE_WIDTH (8)
1190
1191 /* Fragment shader code */
1192 const char *fs_code = "${VERSION}\n"
1193 "\n"
1194 "precision highp float;\n"
1195 "\n"
1196 "out vec4 result;\n"
1197 "\n"
1198 "void main()\n"
1199 "{\n"
1200 " result = vec4(1, 1, 1, 1);\n"
1201 "}\n";
1202
1203 /* Geometry shader code */
1204 const char *gs_code = "${VERSION}\n"
1205 "${GEOMETRY_SHADER_REQUIRE}\n"
1206 "\n"
1207 "precision highp float;\n"
1208 "\n"
1209 "layout (points) in;\n"
1210 "layout (triangle_strip, max_vertices = 16) out;\n"
1211 "\n"
1212 "void main()\n"
1213 "{\n"
1214 " for (int n = 0; n < 4; ++n)\n"
1215 " {\n"
1216 " gl_Position = vec4(1, -1, 0, 1);\n"
1217 " gl_Layer = n;\n"
1218 " EmitVertex();\n"
1219 "\n"
1220 " gl_Position = vec4(1, 1, 0, 1);\n"
1221 " gl_Layer = n;\n"
1222 " EmitVertex();\n"
1223 "\n"
1224 " gl_Position = vec4(-1, -1, 0, 1);\n"
1225 " gl_Layer = n;\n"
1226 " EmitVertex();\n"
1227 "\n"
1228 " gl_Position = vec4(-1, 1, 0, 1);\n"
1229 " gl_Layer = n;\n"
1230 " EmitVertex();\n"
1231 "\n"
1232 " EndPrimitive();\n"
1233 " }\n"
1234 "\n"
1235 "}\n";
1236
1237 /* General variables */
1238 int n = 0;
1239
1240 unsigned char slice_null_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 1 /* byte per texel */] = {0};
1241 unsigned char slice_1_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = {0};
1242 unsigned char slice_2_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = {0};
1243 unsigned char slice_3_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = {0};
1244 unsigned char slice_4_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */] = {0};
1245
1246 /* This test should only run if EXT_geometry_shader is supported */
1247 if (!m_is_geometry_shader_extension_supported)
1248 {
1249 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1250 }
1251
1252 /* Create shader & program objects */
1253 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1254 m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1255 m_po_id = gl.createProgram();
1256 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1257
1258 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader or program objects");
1259
1260 /* Build test program object */
1261 if (!buildProgram(m_po_id, m_fs_id, 1 /* parts */, &fs_code, m_gs_id, 1 /* parts */, &gs_code, m_vs_id,
1262 1 /* parts */, &m_boilerplate_vs_code))
1263 {
1264 TCU_FAIL("Could not build test program object");
1265 }
1266
1267 /* Generate and bind a vertex array object */
1268 gl.genVertexArrays(1, &m_vao_id);
1269 gl.bindVertexArray(m_vao_id);
1270
1271 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create & bind a vertex array object.");
1272
1273 /* Configure slice data */
1274 for (n = 0; n < TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */; ++n)
1275 {
1276 /* We are okay with depth data being filled with glitch, but need the stencil data to be
1277 * as per test spec. To keep code simple, we do not differentiate between floating-point and
1278 * stencil part.
1279 */
1280 slice_1_data[n] = 2;
1281 slice_2_data[n] = 1;
1282
1283 /* Slices 3 and 4 should be filled with 0s */
1284 slice_3_data[n] = 0;
1285 slice_4_data[n] = 0;
1286 } /* for (all pixels making up slices) */
1287
1288 /* Set up texture objects */
1289 gl.genTextures(1, &m_to_a_id);
1290 gl.genTextures(1, &m_to_b_id);
1291
1292 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
1293 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH,
1294 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1295
1296 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1297 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1298 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
1299 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1300 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
1301 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1302 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
1303 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1304
1305 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object A.");
1306
1307 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
1308 gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_DEPTH32F_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
1309 TEXTURE_DEPTH, 0 /* border */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
1310
1311 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1312 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1313 slice_1_data);
1314 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
1315 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1316 slice_2_data);
1317 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
1318 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1319 slice_3_data);
1320 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
1321 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1322 slice_4_data);
1323
1324 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object B.");
1325
1326 /* Set up depth tests */
1327 gl.disable(GL_DEPTH_TEST);
1328
1329 /* Set up stencil tests */
1330 gl.enable(GL_STENCIL_TEST);
1331 gl.stencilFunc(GL_LESS, 0, /* reference value */ 0xFFFFFFFF /* mask */);
1332
1333 /* Set up framebuffer objects */
1334 gl.genFramebuffers(1, &m_fbo_id);
1335 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1336
1337 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
1338 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_to_b_id, 0 /* level */);
1339
1340 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer.");
1341
1342 /* Issue the draw call. */
1343 gl.useProgram(m_po_id);
1344 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1345
1346 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed.");
1347
1348 /* Check the results */
1349 for (n = 0; n < 4 /* layers */; ++n)
1350 {
1351 glw::GLenum fbo_completeness = GL_NONE;
1352 int m = 0;
1353 unsigned char ref_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = {0};
1354 unsigned char result_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = {0};
1355 int x = 0;
1356 int y = 0;
1357
1358 /* Configure the read framebuffer */
1359 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
1360
1361 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
1362 gl.framebufferTexture(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0 /* texture */, 0 /* level */);
1363
1364 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer.");
1365
1366 /* Verify read framebuffer is considered complete */
1367 fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
1368
1369 if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
1370 {
1371 m_testCtx.getLog() << tcu::TestLog::Message << "Read FBO is incomplete: "
1372 << "[" << fbo_completeness << "]" << tcu::TestLog::EndMessage;
1373
1374 TCU_FAIL("Read FBO is incomplete.");
1375 }
1376
1377 /* Build reference data */
1378 for (m = 0; m < TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS; ++m)
1379 {
1380 if (n < 2)
1381 {
1382 ref_data[m] = 255;
1383 }
1384 else
1385 {
1386 ref_data[m] = 0;
1387 }
1388 } /* for (all reference pixels) */
1389
1390 /* Read the rendered data */
1391 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
1392
1393 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed");
1394
1395 for (y = 0; y < TEXTURE_HEIGHT; ++y)
1396 {
1397 int pixel_size = N_TEXTURE_COMPONENTS;
1398 int row_size = pixel_size * TEXTURE_WIDTH;
1399 unsigned char *ref_row = ref_data + y * row_size;
1400 unsigned char *result_row = result_data + y * row_size;
1401
1402 for (x = 0; x < TEXTURE_WIDTH; ++x)
1403 {
1404 if (memcmp(ref_row, result_row, pixel_size) != 0)
1405 {
1406 m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << "): Rendered data "
1407 << "(" << result_row[0] << ", " << result_row[1] << ", " << result_row[2] << ", "
1408 << result_row[3] << ")"
1409 << " is different from reference data "
1410 << "(" << ref_row[0] << ", " << ref_row[1] << ", " << ref_row[2] << ", "
1411 << ref_row[3] << ")" << tcu::TestLog::EndMessage;
1412
1413 TCU_FAIL("Data comparison failed");
1414 } /* if (memcmp(ref_row, result_row, pixel_size) != 0) */
1415
1416 ref_row += pixel_size;
1417 result_row += pixel_size;
1418 } /* for (all pixels in a row) */
1419 } /* for (all pixels) */
1420 } /* for (all layers) */
1421
1422 /* Done */
1423 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1424 return STOP;
1425
1426 #undef N_TEXTURE_COMPONENTS
1427 #undef TEXTURE_DEPTH
1428 #undef TEXTURE_HEIGHT
1429 #undef TEXTURE_WIDTH
1430 }
1431
1432 } // namespace glcts
1433