• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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