1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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 /**
25  * \file  gl4cSyncTests.cpp
26  * \brief Declares test classes for synchronization functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cIncompleteTextureAccessTests.hpp"
30 
31 #include "deSharedPtr.hpp"
32 
33 #include "gluContextInfo.hpp"
34 #include "gluDefs.hpp"
35 #include "gluPixelTransfer.hpp"
36 #include "gluStrUtil.hpp"
37 
38 #include "tcuFuzzyImageCompare.hpp"
39 #include "tcuImageCompare.hpp"
40 #include "tcuRenderTarget.hpp"
41 #include "tcuSurface.hpp"
42 #include "tcuTestLog.hpp"
43 
44 #include "glw.h"
45 #include "glwFunctions.hpp"
46 
47 namespace gl4cts
48 {
49 namespace IncompleteTextureAccess
50 {
51 /****************************************** Incomplete Texture Access Tests Group ***********************************************/
52 
53 /** @brief Incomplete Texture Access Tests Group constructor.
54  *
55  *  @param [in] context     OpenGL context.
56  */
Tests(deqp::Context & context)57 Tests::Tests(deqp::Context& context)
58 	: TestCaseGroup(context, "incomplete_texture_access", "Incomplete Texture Access Tests Suite")
59 {
60 }
61 
62 /** @brief Incomplete Texture Access Tests initializer. */
init()63 void Tests::init()
64 {
65 	addChild(new IncompleteTextureAccess::SamplerTest(m_context));
66 }
67 
68 /*************************************** Sampler Incomplete Texture Access Test Test *******************************************/
69 
70 /** @brief Sampler Incomplete Texture Access Test constructor.
71  *
72  *  @param [in] context     OpenGL context.
73  */
SamplerTest(deqp::Context & context)74 SamplerTest::SamplerTest(deqp::Context& context)
75 	: deqp::TestCase(context, "sampler", "Fetch using sampler test"), m_po(0), m_to(0), m_fbo(0), m_rbo(0), m_vao(0)
76 {
77 	/* Intentionally left blank. */
78 }
79 
80 /** @brief Iterate Incomplete Texture Access Test cases.
81  *
82  *  @return Iteration result.
83  */
iterate()84 tcu::TestNode::IterateResult SamplerTest::iterate()
85 {
86 	/* Get context setup. */
87 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
88 
89 	if (!is_at_least_gl_45)
90 	{
91 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
92 
93 		return STOP;
94 	}
95 
96 	/* Running tests. */
97 	bool is_ok	= true;
98 	bool is_error = false;
99 
100 	try
101 	{
102 		PrepareFramebuffer();
103 		PrepareVertexArrays();
104 
105 		for (glw::GLuint i = 0; i < s_configurations_count; ++i)
106 		{
107 			PrepareProgram(s_configurations[i]);
108 			PrepareTexture(s_configurations[i]);
109 
110 			Draw();
111 
112 			if (!Check(s_configurations[i]))
113 			{
114 				m_context.getTestContext().getLog()
115 					<< tcu::TestLog::Message << "Incomplete texture sampler access test failed with sampler "
116 					<< s_configurations[i].sampler_template << "." << tcu::TestLog::EndMessage;
117 
118 				is_ok = false;
119 			}
120 
121 			CleanCase();
122 		}
123 	}
124 	catch (...)
125 	{
126 		is_ok	= false;
127 		is_error = true;
128 	}
129 
130 	/* Cleanup. */
131 	CleanCase();
132 	CleanTest();
133 
134 	/* Result's setup. */
135 	if (is_ok)
136 	{
137 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
138 	}
139 	else
140 	{
141 		if (is_error)
142 		{
143 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
144 		}
145 		else
146 		{
147 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
148 		}
149 	}
150 
151 	return STOP;
152 }
153 
PrepareProgram(Configuration configuration)154 void SamplerTest::PrepareProgram(Configuration configuration)
155 {
156 	/* Shortcut for GL functionality */
157 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
158 
159 	struct Shader
160 	{
161 		glw::GLchar const* source[5];
162 		glw::GLsizei const count;
163 		glw::GLenum const  type;
164 		glw::GLuint		   id;
165 	} shader[] = { { { s_vertex_shader, NULL, NULL, NULL, NULL }, 1, GL_VERTEX_SHADER, 0 },
166 				   { { s_fragment_shader_head, configuration.sampler_template, s_fragment_shader_body,
167 					   configuration.fetch_template, s_fragment_shader_tail },
168 					 5,
169 					 GL_FRAGMENT_SHADER,
170 					 0 } };
171 
172 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
173 
174 	try
175 	{
176 		/* Create program. */
177 		m_po = gl.createProgram();
178 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
179 
180 		/* Shader compilation. */
181 
182 		for (glw::GLuint i = 0; i < shader_count; ++i)
183 		{
184 			{
185 				shader[i].id = gl.createShader(shader[i].type);
186 
187 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
188 
189 				gl.attachShader(m_po, shader[i].id);
190 
191 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
192 
193 				gl.shaderSource(shader[i].id, shader[i].count, shader[i].source, NULL);
194 
195 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
196 
197 				gl.compileShader(shader[i].id);
198 
199 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
200 
201 				glw::GLint status = GL_FALSE;
202 
203 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
204 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
205 
206 				if (GL_FALSE == status)
207 				{
208 					glw::GLint log_size = 0;
209 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
210 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
211 
212 					glw::GLchar* log_text = new glw::GLchar[log_size];
213 
214 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
215 
216 					m_context.getTestContext().getLog()
217 						<< tcu::TestLog::Message << "Shader compilation has failed.\n"
218 						<< "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
219 						<< "Shader compilation error log:\n"
220 						<< log_text << "\n"
221 						<< "Shader source code:\n"
222 						<< shader[i].source[0] << (shader[i].source[1] ? shader[i].source[1] : "")
223 						<< (shader[i].source[2] ? shader[i].source[2] : "")
224 						<< (shader[i].source[3] ? shader[i].source[3] : "")
225 						<< (shader[i].source[4] ? shader[i].source[4] : "") << "\n"
226 						<< tcu::TestLog::EndMessage;
227 
228 					delete[] log_text;
229 
230 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
231 
232 					throw 0;
233 				}
234 			}
235 		}
236 
237 		/* Link. */
238 		gl.linkProgram(m_po);
239 
240 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
241 
242 		glw::GLint status = GL_FALSE;
243 
244 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
245 
246 		if (GL_TRUE == status)
247 		{
248 			for (glw::GLuint i = 0; i < shader_count; ++i)
249 			{
250 				if (shader[i].id)
251 				{
252 					gl.detachShader(m_po, shader[i].id);
253 
254 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
255 				}
256 			}
257 		}
258 		else
259 		{
260 			glw::GLint log_size = 0;
261 
262 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
263 
264 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
265 
266 			glw::GLchar* log_text = new glw::GLchar[log_size];
267 
268 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
269 
270 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
271 												<< log_text << "\n"
272 												<< tcu::TestLog::EndMessage;
273 
274 			delete[] log_text;
275 
276 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
277 
278 			throw 0;
279 		}
280 	}
281 	catch (...)
282 	{
283 		if (m_po)
284 		{
285 			gl.deleteProgram(m_po);
286 
287 			m_po = 0;
288 		}
289 	}
290 
291 	for (glw::GLuint i = 0; i < shader_count; ++i)
292 	{
293 		if (0 != shader[i].id)
294 		{
295 			gl.deleteShader(shader[i].id);
296 
297 			shader[i].id = 0;
298 		}
299 	}
300 
301 	if (0 == m_po)
302 	{
303 		throw 0;
304 	}
305 	else
306 	{
307 		gl.useProgram(m_po);
308 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUsePrograms has failed");
309 	}
310 }
311 
PrepareTexture(Configuration configuration)312 void SamplerTest::PrepareTexture(Configuration configuration)
313 {
314 	/* Shortcut for GL functionality. */
315 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
316 
317 	if (m_to)
318 	{
319 		throw 0;
320 	}
321 
322 	gl.genTextures(1, &m_to);
323 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures has failed");
324 
325 	gl.bindTexture(configuration.texture_target, m_to);
326 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture has failed");
327 }
328 
PrepareFramebuffer()329 void SamplerTest::PrepareFramebuffer()
330 {
331 	/* Shortcut for GL functionality. */
332 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
333 
334 	/* Sanity checks. */
335 	if (m_fbo || m_rbo)
336 	{
337 		throw 0;
338 	}
339 
340 	/* Framebuffer creation. */
341 	gl.genFramebuffers(1, &m_fbo);
342 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers has failed");
343 
344 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
345 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer has failed");
346 
347 	gl.genRenderbuffers(1, &m_rbo);
348 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers has failed");
349 
350 	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
351 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer has failed");
352 
353 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1 /* x size */, 1 /* y size */);
354 	GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage has failed");
355 
356 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
357 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer has failed");
358 
359 	/* Sanity checks. */
360 	if (GL_FRAMEBUFFER_COMPLETE != gl.checkFramebufferStatus(GL_FRAMEBUFFER))
361 	{
362 		throw 0;
363 	}
364 }
365 
PrepareVertexArrays()366 void SamplerTest::PrepareVertexArrays()
367 {
368 	/* Shortcut for GL functionality. */
369 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
370 
371 	/* Sanity checks.*/
372 	if (m_vao)
373 	{
374 		throw 0;
375 	}
376 
377 	/* Empty vao creation. */
378 	gl.genVertexArrays(1, &m_vao);
379 	GLU_EXPECT_NO_ERROR(gl.getError(), "gGenVertexArrays has failed");
380 
381 	gl.bindVertexArray(m_vao);
382 	GLU_EXPECT_NO_ERROR(gl.getError(), "gBindVertexArrays has failed");
383 }
384 
Draw()385 void SamplerTest::Draw()
386 {
387 	/* Shortcut for GL functionality. */
388 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
389 
390 	/* Draw setup. */
391 	gl.activeTexture(GL_TEXTURE0);
392 	GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture has failed");
393 
394 	gl.uniform1i(gl.getUniformLocation(m_po, "texture_input"), 0);
395 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i has failed");
396 
397 	/* Draw. */
398 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
399 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays has failed");
400 }
401 
Check(Configuration configuration)402 bool SamplerTest::Check(Configuration configuration)
403 {
404 	/* Shortcut for GL functionality. */
405 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
406 
407 	/* Return storage. */
408 	glw::GLfloat result[4] = { 7.f, 7.f, 7.f, 7.f };
409 
410 	/* Fetch. */
411 	gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, result);
412 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels has failed");
413 
414 	/* Comparison. */
415 	for (glw::GLuint i = 0; i < 4 /* # components */; ++i)
416 	{
417 		if (de::abs(configuration.expected_result[i] - result[i]) > 0.0125 /* precision */)
418 		{
419 			/* Fail.*/
420 			return false;
421 		}
422 	}
423 
424 	/* Comparsion passed.*/
425 	return true;
426 }
427 
CleanCase()428 void SamplerTest::CleanCase()
429 {
430 	/* Shortcut for GL functionality. */
431 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
432 
433 	/* Program cleanup. */
434 	if (m_po)
435 	{
436 		gl.deleteProgram(m_po);
437 
438 		m_po = 0;
439 	}
440 
441 	/* Texture cleanup. */
442 	if (m_to)
443 	{
444 		gl.deleteTextures(1, &m_to);
445 
446 		m_to = 0;
447 	}
448 
449 	/* Errors cleanup. */
450 	while (gl.getError())
451 		;
452 }
453 
CleanTest()454 void SamplerTest::CleanTest()
455 {
456 	/* Shortcut for GL functionality. */
457 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
458 
459 	/* Framebuffer cleanup. */
460 	if (m_fbo)
461 	{
462 		gl.deleteFramebuffers(1, &m_fbo);
463 
464 		m_fbo = 0;
465 	}
466 
467 	/* Renderbuffer cleanup. */
468 	if (m_rbo)
469 	{
470 		gl.deleteRenderbuffers(1, &m_rbo);
471 
472 		m_rbo = 0;
473 	}
474 
475 	/* Vertex arrays cleanup. */
476 	if (m_vao)
477 	{
478 		gl.deleteVertexArrays(1, &m_vao);
479 
480 		m_vao = 0;
481 	}
482 
483 	/* Errors cleanup. */
484 	while (gl.getError())
485 		;
486 }
487 
488 const struct SamplerTest::Configuration SamplerTest::s_configurations[] = {
489 	/* regular floating point sampling */
490 	{ GL_TEXTURE_1D, "sampler1D", "texture(texture_input, 0.0)", { 0.f, 0.f, 0.f, 1.f } },
491 	{ GL_TEXTURE_2D, "sampler2D", "texture(texture_input, vec2(0.0))", { 0.f, 0.f, 0.f, 1.f } },
492 	{ GL_TEXTURE_3D, "sampler3D", "texture(texture_input, vec3(0.0))", { 0.f, 0.f, 0.f, 1.f } },
493 	{ GL_TEXTURE_CUBE_MAP, "samplerCube", "texture(texture_input, vec3(0.0))", { 0.f, 0.f, 0.f, 1.f } },
494 	{ GL_TEXTURE_RECTANGLE, "sampler2DRect", "texture(texture_input, vec2(0.0))", { 0.f, 0.f, 0.f, 1.f } },
495 	{ GL_TEXTURE_1D_ARRAY, "sampler1DArray", "texture(texture_input, vec2(0.0))", { 0.f, 0.f, 0.f, 1.f } },
496 	{ GL_TEXTURE_2D_ARRAY, "sampler2DArray", "texture(texture_input, vec3(0.0))", { 0.f, 0.f, 0.f, 1.f } },
497 	{ GL_TEXTURE_CUBE_MAP_ARRAY, "samplerCubeArray", "texture(texture_input, vec4(0.0))", { 0.f, 0.f, 0.f, 1.f } },
498 
499 	/* Shadow textures. */
500 	{ GL_TEXTURE_1D,
501 	  "sampler1DShadow",
502 	  "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)",
503 	  { 0.f, 0.f, 0.f, 0.f } },
504 	{ GL_TEXTURE_2D,
505 	  "sampler2DShadow",
506 	  "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)",
507 	  { 0.f, 0.f, 0.f, 0.f } },
508 	{ GL_TEXTURE_CUBE_MAP,
509 	  "samplerCubeShadow",
510 	  "vec4(texture(texture_input, vec4(0.0)), 0.0, 0.0, 0.0)",
511 	  { 0.f, 0.f, 0.f, 0.f } },
512 	{ GL_TEXTURE_RECTANGLE,
513 	  "sampler2DRectShadow",
514 	  "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)",
515 	  { 0.f, 0.f, 0.f, 0.f } },
516 	{ GL_TEXTURE_1D_ARRAY,
517 	  "sampler1DArrayShadow",
518 	  "vec4(texture(texture_input, vec3(0.0)), 0.0, 0.0, 0.0)",
519 	  { 0.f, 0.f, 0.f, 0.f } },
520 	{ GL_TEXTURE_2D_ARRAY,
521 	  "sampler2DArrayShadow",
522 	  "vec4(texture(texture_input, vec4(0.0)), 0.0, 0.0, 0.0)",
523 	  { 0.f, 0.f, 0.f, 0.f } },
524 	{ GL_TEXTURE_CUBE_MAP_ARRAY,
525 	  "samplerCubeArrayShadow",
526 	  "vec4(texture(texture_input, vec4(0.0), 1.0), 0.0, 0.0, 0.0)",
527 	  { 0.f, 0.f, 0.f, 0.f } }
528 };
529 
530 const glw::GLuint SamplerTest::s_configurations_count = sizeof(s_configurations) / sizeof(s_configurations[0]);
531 
532 const glw::GLchar* SamplerTest::s_vertex_shader = "#version 450\n"
533 												  "\n"
534 												  "void main()\n"
535 												  "{\n"
536 												  "    switch(gl_VertexID)\n"
537 												  "    {\n"
538 												  "        case 0:\n"
539 												  "            gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
540 												  "            break;\n"
541 												  "        case 1:\n"
542 												  "            gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
543 												  "            break;\n"
544 												  "        case 2:\n"
545 												  "            gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
546 												  "            break;\n"
547 												  "        case 3:\n"
548 												  "            gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
549 												  "            break;\n"
550 												  "    }\n"
551 												  "}\n";
552 
553 const glw::GLchar* SamplerTest::s_fragment_shader_head = "#version 450\n"
554 														 "\n"
555 														 "uniform ";
556 
557 const glw::GLchar* SamplerTest::s_fragment_shader_body = " texture_input;\n"
558 														 "out vec4 texture_output;\n"
559 														 "\n"
560 														 "void main()\n"
561 														 "{\n"
562 														 "    texture_output = ";
563 
564 const glw::GLchar* SamplerTest::s_fragment_shader_tail = ";\n"
565 														 "}\n";
566 
567 } /* IncompleteTextureAccess namespace */
568 } /* gl4cts namespace */
569