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