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 "esextcGeometryShaderNonarrayInput.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "gluDefs.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuTestLog.hpp"
31
32 #include <algorithm>
33 #include <string>
34 #include <vector>
35
36 namespace glcts
37 {
38
39 /* Fragment shader code */
40 const char* GeometryShaderNonarrayInputCase::m_fs_code = "${VERSION}\n"
41 "\n"
42 "precision highp float;\n"
43 "\n"
44 "out vec4 color;\n"
45 "\n"
46 "void main()\n"
47 "{\n"
48 " color = vec4(0, 1, 0, 1);\n"
49 "}\n";
50
51 /* Geometry shader body parts */
52 const char* GeometryShaderNonarrayInputCase::m_gs_code_preamble = "${VERSION}\n"
53 "${GEOMETRY_SHADER_REQUIRE}\n"
54 "\n";
55
56 const char* GeometryShaderNonarrayInputCase::m_gs_code_body = "layout(points) in;\n"
57 "layout(triangle_strip, max_vertices=4) out;\n"
58 "\n"
59 "#ifndef USE_BLOCK\n"
60 " #define V1 v1[0]\n"
61 " #define V2 v2[0]\n"
62 " #define V3 v3[0]\n"
63 "\n"
64 " in vec4 v1[];\n"
65 " in vec4 v2[];\n"
66 " in vec4 v3[];\n"
67 " \n"
68 " #ifdef CORRUPT\n"
69 " #define V4 v4\n"
70 " in vec4 v4;\n"
71 " #else\n"
72 " #define V4 v4[0]\n"
73 " in vec4 v4[];\n"
74 " #endif\n"
75 "#else\n"
76 " in VS_GS\n"
77 " {\n"
78 " in vec4 v1;\n"
79 " in vec4 v2;\n"
80 " in vec4 v3;\n"
81 " in vec4 v4;\n"
82 " #ifdef CORRUPT\n"
83 " } interface_block;\n"
84 "\n"
85 " #define V1 interface_block.v1\n"
86 " #define V2 interface_block.v2\n"
87 " #define V3 interface_block.v3\n"
88 " #define V4 interface_block.v4\n"
89 " #else\n"
90 " } interface_block[];\n"
91 "\n"
92 " #define V1 interface_block[0].v1\n"
93 " #define V2 interface_block[0].v2\n"
94 " #define V3 interface_block[0].v3\n"
95 " #define V4 interface_block[0].v4\n"
96 " #endif\n"
97 "#endif\n"
98 "\n"
99 "void main()\n"
100 "{\n"
101 " gl_Position = V1;\n"
102 " EmitVertex();\n"
103 " gl_Position = V2;\n"
104 " EmitVertex();\n"
105 " gl_Position = V3;\n"
106 " EmitVertex();\n"
107 " gl_Position = V4;\n"
108 " EmitVertex();\n"
109 " EndPrimitive();\n"
110 "}\n";
111
112 /* Vertex shader body parts */
113 const char* GeometryShaderNonarrayInputCase::m_vs_code_preamble = "${VERSION}\n"
114 "\n";
115
116 const char* GeometryShaderNonarrayInputCase::m_vs_code_body = "#ifndef USE_BLOCK\n"
117 " #define V1 v1\n"
118 " #define V2 v2\n"
119 " #define V3 v3\n"
120 " #define V4 v4\n"
121 "\n"
122 " out vec4 v1;\n"
123 " out vec4 v2;\n"
124 " out vec4 v3;\n"
125 " out vec4 v4;\n"
126 "#else\n"
127 " ${SHADER_IO_BLOCKS_ENABLE}\n"
128 " #define V1 interface_block.v1\n"
129 " #define V2 interface_block.v2\n"
130 " #define V3 interface_block.v3\n"
131 " #define V4 interface_block.v4\n"
132 "\n"
133 " out VS_GS\n"
134 " {\n"
135 " vec4 v1;\n"
136 " vec4 v2;\n"
137 " vec4 v3;\n"
138 " vec4 v4;\n"
139 " } interface_block;\n"
140 "#endif\n"
141 "\n"
142 "void main()\n"
143 "{\n"
144 " V1 = vec4(-1, -1, 0, 1);\n"
145 " V2 = vec4(-1, 1, 0, 1);\n"
146 " V3 = vec4( 1, -1, 0, 1);\n"
147 " V4 = vec4( 1, 1, 0, 1);\n"
148 "}\n";
149
150 /* Definitions */
151 #define TEXTURE_HEIGHT (4)
152 #define TEXTURE_WIDTH (4)
153
154 /** Constructor
155 *
156 * @param context Test context
157 * @param name Test case's name
158 * @param description Test case's desricption
159 **/
GeometryShaderNonarrayInputCase(Context & context,const ExtParameters & extParams,const char * name,const char * description)160 GeometryShaderNonarrayInputCase::GeometryShaderNonarrayInputCase(Context& context, const ExtParameters& extParams,
161 const char* name, const char* description)
162 : TestCaseBase(context, extParams, name, description)
163 , m_fbo_id(0)
164 , m_fs(0)
165 , m_gs_invalid_non_ib(0)
166 , m_gs_invalid_ib(0)
167 , m_gs_valid_non_ib(0)
168 , m_gs_valid_ib(0)
169 , m_po_a_invalid(0)
170 , m_po_b_invalid(0)
171 , m_po_a_valid(0)
172 , m_po_b_valid(0)
173 , m_to_id(0)
174 , m_vao_id(0)
175 , m_vs_valid_ib(0)
176 , m_vs_valid_non_ib(0)
177 {
178 }
179
180 /** Executes the test.
181 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
182 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
183 * Note the function throws exception should an error occur!
184 **/
iterate(void)185 tcu::TestNode::IterateResult GeometryShaderNonarrayInputCase::iterate(void)
186 {
187 glw::GLint compile_status = GL_FALSE;
188 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
189 glw::GLint link_status = GL_FALSE;
190 unsigned int m = 0;
191 unsigned int n = 0;
192
193 /* Form the shaders */
194 const char* fs_parts[] = { m_fs_code };
195 const char* gs_invalid_non_ib_parts[] = { m_gs_code_preamble, "#define CORRUPT\n", m_gs_code_body };
196 const char* gs_invalid_ib_parts[] = { m_gs_code_preamble, "#define CORRUPT\n#define USE_BLOCK\n", m_gs_code_body };
197 const char* gs_valid_non_ib_parts[] = { m_gs_code_preamble, m_gs_code_body };
198 const char* gs_valid_ib_parts[] = { m_gs_code_preamble, "#define USE_BLOCK\n", m_gs_code_body };
199 const char* vs_valid_non_ib_parts[] = { m_vs_code_preamble, m_vs_code_body };
200 const char* vs_valid_ib_parts[] = { m_vs_code_preamble, "#define USE_BLOCK\n", m_vs_code_body };
201
202 /* This test should only run if EXT_geometry_shader is supported.
203 * Note that EXT_shader_io_blocks support is implied. */
204 if (!m_is_geometry_shader_extension_supported)
205 {
206 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
207 }
208
209 /* Create program objects */
210 m_po_a_invalid = gl.createProgram();
211 m_po_b_invalid = gl.createProgram();
212
213 /* Create shader objects */
214 m_fs = gl.createShader(GL_FRAGMENT_SHADER);
215 m_gs_invalid_non_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
216 m_gs_invalid_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
217 m_gs_valid_non_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
218 m_gs_valid_ib = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
219 m_vs_valid_non_ib = gl.createShader(GL_VERTEX_SHADER);
220 m_vs_valid_ib = gl.createShader(GL_VERTEX_SHADER);
221
222 shaderSourceSpecialized(m_fs, DE_LENGTH_OF_ARRAY(fs_parts), fs_parts);
223 shaderSourceSpecialized(m_gs_invalid_non_ib, DE_LENGTH_OF_ARRAY(gs_invalid_non_ib_parts), gs_invalid_non_ib_parts);
224 shaderSourceSpecialized(m_gs_invalid_ib, DE_LENGTH_OF_ARRAY(gs_invalid_ib_parts), gs_invalid_ib_parts);
225 shaderSourceSpecialized(m_gs_valid_non_ib, DE_LENGTH_OF_ARRAY(gs_valid_non_ib_parts), gs_valid_non_ib_parts);
226 shaderSourceSpecialized(m_gs_valid_ib, DE_LENGTH_OF_ARRAY(gs_valid_ib_parts), gs_valid_ib_parts);
227 shaderSourceSpecialized(m_vs_valid_non_ib, DE_LENGTH_OF_ARRAY(vs_valid_non_ib_parts), vs_valid_non_ib_parts);
228 shaderSourceSpecialized(m_vs_valid_ib, DE_LENGTH_OF_ARRAY(vs_valid_ib_parts), vs_valid_ib_parts);
229
230 /* Create and form invalid programs */
231 gl.attachShader(m_po_a_invalid, m_fs);
232 gl.attachShader(m_po_a_invalid, m_gs_invalid_non_ib);
233 gl.attachShader(m_po_a_invalid, m_vs_valid_non_ib);
234
235 gl.attachShader(m_po_b_invalid, m_fs);
236 gl.attachShader(m_po_b_invalid, m_gs_invalid_ib);
237 gl.attachShader(m_po_b_invalid, m_vs_valid_ib);
238
239 /* Try to compile the shaders. Do not check GL_COMPILE_STATUS - we expect a linking failure */
240 gl.compileShader(m_fs);
241 gl.compileShader(m_gs_invalid_non_ib);
242 gl.compileShader(m_gs_invalid_ib);
243 gl.compileShader(m_vs_valid_non_ib);
244 gl.compileShader(m_vs_valid_ib);
245
246 /* Try to link the programs */
247 gl.linkProgram(m_po_a_invalid);
248 gl.getProgramiv(m_po_a_invalid, GL_LINK_STATUS, &link_status);
249
250 if (link_status != GL_FALSE)
251 {
252 m_testCtx.getLog() << tcu::TestLog::Message
253 << "Program linked sucessfully although it shouldn't because geometry shaders are not "
254 "expected to support non-array input attributes."
255 << tcu::TestLog::EndMessage;
256
257 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
258 return STOP;
259 }
260
261 gl.linkProgram(m_po_b_invalid);
262 gl.getProgramiv(m_po_b_invalid, GL_LINK_STATUS, &link_status);
263
264 if (link_status != GL_FALSE)
265 {
266 m_testCtx.getLog() << tcu::TestLog::Message
267 << "Program linked sucessfully although it shouldn't because geometry shaders are not "
268 "expected to support non-array block input attributes."
269 << tcu::TestLog::EndMessage;
270
271 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
272 return STOP;
273 }
274
275 /* Release the programs before we continue */
276 gl.deleteProgram(m_po_a_invalid);
277 gl.deleteProgram(m_po_b_invalid);
278
279 m_po_a_invalid = 0;
280 m_po_b_invalid = 0;
281
282 /* Release the invalid geometry shaders */
283 gl.deleteShader(m_gs_invalid_non_ib);
284 gl.deleteShader(m_gs_invalid_ib);
285
286 m_gs_invalid_non_ib = 0;
287 m_gs_invalid_ib = 0;
288
289 /* Create and form valid programs */
290 m_po_a_valid = gl.createProgram();
291 m_po_b_valid = gl.createProgram();
292
293 gl.attachShader(m_po_a_valid, m_fs);
294 gl.attachShader(m_po_a_valid, m_gs_valid_non_ib);
295 gl.attachShader(m_po_a_valid, m_vs_valid_non_ib);
296
297 gl.attachShader(m_po_b_valid, m_fs);
298 gl.attachShader(m_po_b_valid, m_gs_valid_ib);
299 gl.attachShader(m_po_b_valid, m_vs_valid_ib);
300
301 gl.compileShader(m_gs_valid_non_ib);
302 gl.compileShader(m_gs_valid_ib);
303
304 gl.getShaderiv(m_gs_valid_non_ib, GL_COMPILE_STATUS, &compile_status);
305
306 if (compile_status != GL_TRUE)
307 {
308 std::string log = getCompilationInfoLog(m_gs_valid_non_ib);
309
310 m_testCtx.getLog() << tcu::TestLog::Message << "Valid geometry shader didn't compile. Error message: " << log
311 << tcu::TestLog::EndMessage;
312
313 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
314 return STOP;
315 }
316
317 gl.getShaderiv(m_gs_valid_ib, GL_COMPILE_STATUS, &compile_status);
318
319 if (compile_status != GL_TRUE)
320 {
321 std::string log = getCompilationInfoLog(m_gs_valid_ib);
322
323 m_testCtx.getLog() << tcu::TestLog::Message << "Valid geometry shader didn't compile. Error message: " << log
324 << tcu::TestLog::EndMessage;
325
326 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
327 return STOP;
328 }
329
330 gl.linkProgram(m_po_a_valid);
331 gl.getProgramiv(m_po_a_valid, GL_LINK_STATUS, &link_status);
332
333 if (link_status != GL_TRUE)
334 {
335 std::string log = getLinkingInfoLog(m_po_a_valid);
336
337 m_testCtx.getLog() << tcu::TestLog::Message
338 << "Program failed to link although it was expected to link successfully. Error message: "
339 << log << tcu::TestLog::EndMessage;
340
341 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
342 return STOP;
343 }
344
345 gl.linkProgram(m_po_b_valid);
346 gl.getProgramiv(m_po_b_valid, GL_LINK_STATUS, &link_status);
347
348 if (link_status != GL_TRUE)
349 {
350 std::string log = getLinkingInfoLog(m_po_b_valid);
351
352 m_testCtx.getLog() << tcu::TestLog::Message
353 << "Program failed to link although it was expected to link successfully. Error message: "
354 << log << tcu::TestLog::EndMessage;
355
356 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
357 return STOP;
358 }
359
360 /* Set up a FBO */
361 gl.genFramebuffers(1, &m_fbo_id);
362 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
363
364 gl.genTextures(1, &m_to_id);
365 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
366 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
367 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
368
369 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up a framebuffer object");
370
371 gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
372
373 /* Generate and bind a VAO */
374 gl.genVertexArrays(1, &m_vao_id);
375 gl.bindVertexArray(m_vao_id);
376
377 /* Set up clear color */
378 gl.clearColor(1.0f, 0, 0, 0);
379
380 /* Use both program objects and verify they work correctly */
381 for (m = 0; m < 2 /* programs */; ++m)
382 {
383 glw::GLuint program = (m == 0) ? m_po_a_valid : m_po_b_valid;
384 unsigned char result[TEXTURE_WIDTH * TEXTURE_HEIGHT * 4 /*components */];
385
386 /* Clear the color attachment before we continue */
387 gl.clear(GL_COLOR_BUFFER_BIT);
388
389 /* Render! */
390 gl.useProgram(program);
391 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
392
393 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
394
395 /* Read back the result */
396 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result);
397
398 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color attachment 0");
399
400 /* Verify the result data is correct */
401 for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
402 {
403 if (result[n * 4 + 0] != 0 || result[n * 4 + 1] != 255 || result[n * 4 + 2] != 0 ||
404 result[n * 4 + 3] != 255)
405 {
406 m_testCtx.getLog() << tcu::TestLog::Message
407 << "Pixel data isn't correct. All pixels should have green color. Pixel at: "
408 << "[" << n / 4 << ", " << n % 4 << "] "
409 << "has color: "
410 << "[" << result[n * 4 + 0] << ", " << result[n * 4 + 1] << ", " << result[n * 4 + 2]
411 << ", " << result[n * 4 + 3] << "]" << tcu::TestLog::EndMessage;
412
413 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
414 return STOP;
415 } /* if (result data is invalid) */
416 } /* for (all pixels) */
417 } /* for (all programs) */
418
419 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
420 return STOP;
421 }
422
423 /** Deinitializes GLES objects created during the test.
424 *
425 */
deinit(void)426 void GeometryShaderNonarrayInputCase::deinit(void)
427 {
428 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
429
430 /* Reset OpenGL ES state */
431 gl.useProgram(0);
432 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
433 gl.bindVertexArray(0);
434
435 if (m_po_a_valid != 0)
436 {
437 gl.deleteProgram(m_po_a_valid);
438 }
439
440 if (m_po_b_valid != 0)
441 {
442 gl.deleteProgram(m_po_b_valid);
443 }
444
445 if (m_fs != 0)
446 {
447 gl.deleteShader(m_fs);
448 }
449
450 if (m_gs_invalid_ib != 0)
451 {
452 gl.deleteShader(m_gs_invalid_ib);
453 }
454
455 if (m_gs_invalid_non_ib != 0)
456 {
457 gl.deleteShader(m_gs_invalid_non_ib);
458 }
459
460 if (m_gs_valid_ib != 0)
461 {
462 gl.deleteShader(m_gs_valid_ib);
463 }
464
465 if (m_gs_valid_non_ib != 0)
466 {
467 gl.deleteShader(m_gs_valid_non_ib);
468 }
469
470 if (m_vs_valid_ib != 0)
471 {
472 gl.deleteShader(m_vs_valid_ib);
473 }
474
475 if (m_vs_valid_non_ib != 0)
476 {
477 gl.deleteShader(m_vs_valid_non_ib);
478 }
479
480 if (m_to_id != 0)
481 {
482 gl.deleteTextures(1, &m_to_id);
483 }
484
485 if (m_fbo_id != 0)
486 {
487 gl.deleteFramebuffers(1, &m_fbo_id);
488 }
489
490 if (m_vao_id != 0)
491 {
492 gl.deleteVertexArrays(1, &m_vao_id);
493 }
494
495 /* Release base class */
496 TestCaseBase::deinit();
497 }
498
499 } // namespace glcts
500