• 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 /**
25  */ /*!
26  * \file  gl4cShaderTextureImageSamplesTests.cpp
27  * \brief Implements conformance tests for GL_ARB_shader_texture_image_samples functionality
28  */ /*-------------------------------------------------------------------*/
29 
30 #include "gl4cShaderTextureImageSamplesTests.hpp"
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuTestLog.hpp"
37 
38 #include <string>
39 #include <vector>
40 
41 namespace glcts
42 {
43 /** Constructor.
44  *
45  *  @param context     Rendering context
46  *  @param name        Test name
47  *  @param description Test description
48  */
ShaderTextureImageSamplesTestBase(deqp::Context & context,const char * name,const char * description)49 ShaderTextureImageSamplesTestBase::ShaderTextureImageSamplesTestBase(deqp::Context& context, const char* name,
50 																	 const char* description)
51 	: deqp::TestCase(context, name, description)
52 	, m_internalformat_n_samples_count(0)
53 	, m_internalformat_n_samples_data(DE_NULL)
54 	, m_bo_id(0)
55 	, m_cs_id(0)
56 	, m_po_id(0)
57 	, m_to_id(0)
58 	, m_to_depth(3)
59 	, m_to_height(4)
60 	, m_to_width(8)
61 {
62 	/* Left blank intentionally */
63 }
64 
65 /** Compiles a compute shader and optionally attaches it to a program object, which the
66  *  method can then try to link.
67  *
68  *  Shader object ID will be stored in m_cs_id.
69  *  Program object ID will be stored in m_po_id.
70  *
71  *  @param cs_body        Source code of the compute shader to use for compilation.
72  *  @param should_link_po true if the method should also attempt to link the program object.
73  *  @param should_succeed true if the compilation and linking (depending on @param should_link_po)
74  *                        processes should succeed, false otherwise. If GL implementation
75  *                        is found not to accept a valid compute shader, the method will
76  *                        throw a TestError exception.
77  *
78  *   Upon failure, the method *does not* delete the program & shader objects.
79  *
80  *  @return true if the compilation / linking process was successful, false otherwise.
81  **/
buildComputeProgram(const char * cs_body,bool should_link_po,bool should_succeed)82 bool ShaderTextureImageSamplesTestBase::buildComputeProgram(const char* cs_body, bool should_link_po,
83 															bool should_succeed)
84 {
85 	bool result = false;
86 
87 	/* Deinitialize any program / shader objects that may have already been initialized
88 	 * for this test instance.
89 	 */
90 	deinitProgramAndShaderObjects();
91 
92 	/* Create the objects */
93 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
94 
95 	m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
96 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
97 
98 	m_po_id = gl.createProgram();
99 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
100 
101 	/* Set up the shader object */
102 	gl.shaderSource(m_cs_id, 1,			/* count */
103 					&cs_body, DE_NULL); /* length */
104 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
105 
106 	/* Compile the shader object */
107 	glw::GLint compile_status = GL_FALSE;
108 
109 	gl.compileShader(m_cs_id);
110 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
111 
112 	gl.getShaderiv(m_cs_id, GL_COMPILE_STATUS, &compile_status);
113 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
114 
115 	if (compile_status != GL_TRUE)
116 	{
117 		if (should_succeed)
118 		{
119 			TCU_FAIL("Shader compilation failed.");
120 		}
121 
122 		goto end;
123 	}
124 	else
125 	{
126 		if (!should_succeed)
127 		{
128 			TCU_FAIL("Shader compilation has succeeded, even though it should not have.");
129 		}
130 	}
131 
132 	if (should_link_po)
133 	{
134 		/* Prepare the program object for linking */
135 		gl.attachShader(m_po_id, m_cs_id);
136 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
137 
138 		/* Link the program object */
139 		glw::GLint link_status = GL_FALSE;
140 
141 		gl.linkProgram(m_po_id);
142 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
143 
144 		gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
145 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
146 
147 		if (link_status != GL_TRUE)
148 		{
149 			if (should_succeed)
150 			{
151 				TCU_FAIL("Program linking failed.");
152 			}
153 
154 			goto end;
155 		}
156 	}
157 
158 	result = true;
159 end:
160 	return result;
161 }
162 
163 /** Deinitializes all GL objects that may have been created during test execution. */
deinit()164 void ShaderTextureImageSamplesTestBase::deinit()
165 {
166 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
167 
168 	deinitProgramAndShaderObjects();
169 
170 	if (m_bo_id != 0)
171 	{
172 		gl.deleteBuffers(1, &m_bo_id);
173 
174 		m_bo_id = 0;
175 	}
176 
177 	if (m_internalformat_n_samples_data != DE_NULL)
178 	{
179 		delete[] m_internalformat_n_samples_data;
180 
181 		m_internalformat_n_samples_data = DE_NULL;
182 	}
183 
184 	if (m_to_id != 0)
185 	{
186 		gl.deleteTextures(1, &m_to_id);
187 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
188 
189 		m_to_id = 0;
190 	}
191 }
192 
193 /** Deinitializes program & shader objects that may have been created
194  *  during test execution.
195  **/
deinitProgramAndShaderObjects()196 void ShaderTextureImageSamplesTestBase::deinitProgramAndShaderObjects()
197 {
198 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
199 
200 	if (m_cs_id != 0)
201 	{
202 		gl.deleteShader(m_cs_id);
203 
204 		m_cs_id = 0;
205 	}
206 
207 	if (m_po_id != 0)
208 	{
209 		gl.deleteProgram(m_po_id);
210 
211 		m_po_id = 0;
212 	}
213 }
214 
215 /** Executes the functional test as described in CTS_ARB_shader_texture_image_samples.
216  *
217  *  This method throws a TestError exception if OpenGL implementation reports any
218  *  error OR the "samples" value reported by OpenGL is found to be incorrect.
219  *
220  *  @param sampler_type Tells which sampler type should be used for the test. Note that
221  *                      even though sampler type enum values are named after texture samplers,
222  *                      the actual ES SL types used during the test will depend on whether
223  *                      the caller requested images or textures to be used (see @param test_type)
224  *  @param test_type    Tells whether the test should verify image or texture samplers.
225  **/
executeFunctionalTest(const _sampler_type & sampler_type,const _test_type & test_type)226 void ShaderTextureImageSamplesTestBase::executeFunctionalTest(const _sampler_type& sampler_type,
227 															  const _test_type&	test_type)
228 {
229 	std::string cs_body;
230 	const char* cs_template_code = "#version 430\n"
231 								   "\n"
232 								   "#extension GL_ARB_shader_texture_image_samples : require\n"
233 								   "\n"
234 								   "layout(local_size_x = 1) in;\n"
235 								   "\n"
236 								   "buffer Result\n"
237 								   "{\n"
238 								   "    int samples;\n"
239 								   "};\n"
240 								   "\n"
241 								   "SAMPLER_TYPE data;\n"
242 								   "\n"
243 								   "void main()\n"
244 								   "{\n"
245 								   "    samples = SAMPLES_MODIFIER\n"
246 								   "}\n";
247 
248 	/* Any program or shader objects lying around at this point? If so, release them
249 	 * before we proceed.
250 	 */
251 	deinitProgramAndShaderObjects();
252 
253 	/* Construct the shader body */
254 	const std::string samples_modifier_token		  = "SAMPLES_MODIFIER";
255 	size_t			  samples_modifier_token_location = std::string::npos;
256 	std::string		  samples_modifier_token_value;
257 	std::string		  sampler_type_string;
258 	const std::string sampler_type_token		  = "SAMPLER_TYPE";
259 	size_t			  sampler_type_token_location = std::string::npos;
260 	std::string		  sampler_type_token_value;
261 
262 	switch (test_type)
263 	{
264 	case TEST_TYPE_IMAGE:
265 	{
266 		samples_modifier_token_value = "imageSamples(data);\n";
267 
268 		switch (sampler_type)
269 		{
270 		case SAMPLER_TYPE_ISAMPLER2DMS:
271 		{
272 			sampler_type_string		 = "iimage2DMS";
273 			sampler_type_token_value = "layout(rgba8i) uniform iimage2DMS";
274 
275 			break;
276 		}
277 
278 		case SAMPLER_TYPE_ISAMPLER2DMSARRAY:
279 		{
280 			sampler_type_string		 = "iimage2DMSArray";
281 			sampler_type_token_value = "layout(rgba8i) uniform iimage2DMSArray";
282 
283 			break;
284 		}
285 
286 		case SAMPLER_TYPE_SAMPLER2DMS:
287 		{
288 			sampler_type_string		 = "image2DMS";
289 			sampler_type_token_value = "layout(rgba8) uniform image2DMS";
290 
291 			break;
292 		}
293 
294 		case SAMPLER_TYPE_SAMPLER2DMSARRAY:
295 		{
296 			sampler_type_string		 = "image2DMSArray";
297 			sampler_type_token_value = "layout(rgba8) uniform image2DMSArray";
298 
299 			break;
300 		}
301 
302 		case SAMPLER_TYPE_USAMPLER2DMS:
303 		{
304 			sampler_type_string		 = "uimage2DMS";
305 			sampler_type_token_value = "layout(rgba8ui) uniform uimage2DMS";
306 
307 			break;
308 		}
309 
310 		case SAMPLER_TYPE_USAMPLER2DMSARRAY:
311 		{
312 			sampler_type_string		 = "uimage2DMSArray";
313 			sampler_type_token_value = "layout(rgba8ui) uniform uimage2DMSArray";
314 
315 			break;
316 		}
317 
318 		default:
319 		{
320 			TCU_FAIL("Unrecognized sampler type");
321 		}
322 		} /* switch (sampler_type) */
323 
324 		break;
325 	} /* case TEST_TYPE_IMAGE: */
326 
327 	case TEST_TYPE_TEXTURE:
328 	{
329 		samples_modifier_token_value = "textureSamples(data);\n";
330 
331 		switch (sampler_type)
332 		{
333 		case SAMPLER_TYPE_ISAMPLER2DMS:
334 		{
335 			sampler_type_string		 = "isampler2DMS";
336 			sampler_type_token_value = "uniform isampler2DMS";
337 
338 			break;
339 		}
340 
341 		case SAMPLER_TYPE_ISAMPLER2DMSARRAY:
342 		{
343 			sampler_type_string		 = "isampler2DMSArray";
344 			sampler_type_token_value = "uniform isampler2DMSArray";
345 
346 			break;
347 		}
348 
349 		case SAMPLER_TYPE_SAMPLER2DMS:
350 		{
351 			sampler_type_string		 = "sampler2DMS";
352 			sampler_type_token_value = "uniform sampler2DMS";
353 
354 			break;
355 		}
356 
357 		case SAMPLER_TYPE_SAMPLER2DMSARRAY:
358 		{
359 			sampler_type_string		 = "sampler2DMSArray";
360 			sampler_type_token_value = "uniform sampler2DMSArray";
361 
362 			break;
363 		}
364 
365 		case SAMPLER_TYPE_USAMPLER2DMS:
366 		{
367 			sampler_type_string		 = "usampler2DMS";
368 			sampler_type_token_value = "uniform usampler2DMS";
369 
370 			break;
371 		}
372 
373 		case SAMPLER_TYPE_USAMPLER2DMSARRAY:
374 		{
375 			sampler_type_string		 = "usampler2DMSArray";
376 			sampler_type_token_value = "uniform usampler2DMSArray";
377 
378 			break;
379 		}
380 
381 		default:
382 		{
383 			TCU_FAIL("Unrecognized sampler type");
384 		}
385 		} /* switch (sampler_type) */
386 
387 		break;
388 	} /* case TEST_TYPE_TEXTURE: */
389 
390 	default:
391 	{
392 		TCU_FAIL("Unrecognized test type");
393 	}
394 	} /* switch (test_type) */
395 
396 	cs_body = cs_template_code;
397 
398 	while ((samples_modifier_token_location = cs_body.find(samples_modifier_token)) != std::string::npos)
399 	{
400 		cs_body.replace(samples_modifier_token_location, samples_modifier_token.length(), samples_modifier_token_value);
401 	}
402 
403 	while ((sampler_type_token_location = cs_body.find(sampler_type_token)) != std::string::npos)
404 	{
405 		cs_body.replace(sampler_type_token_location, sampler_type_token.length(), sampler_type_token_value);
406 	}
407 
408 	/* Build the compute program */
409 	if (!buildComputeProgram(cs_body.c_str(), true, /* should_link_po */
410 							 true))					/* should_succeed */
411 	{
412 		TCU_FAIL("Could not link a test program");
413 	}
414 
415 	/* Set up SSBO */
416 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
417 
418 	gl.shaderStorageBlockBinding(m_po_id, 0, /* storageBlockIndex */
419 								 0);		 /* storageBlockBinding */
420 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderStorageBlockBinding() call failed.");
421 
422 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, /* index */
423 					  m_bo_id);
424 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
425 
426 	/* Determine what numbers of samples we can use for GL_RGBA8, GL_RGBA8I
427 	 * or GL_RGBA8UI internalformats. Specific choice depends on the sampler type
428 	 * requested bty the caller.
429 	 */
430 	glw::GLenum texture_internalformat = GL_NONE;
431 	glw::GLenum texture_target		   = GL_NONE;
432 
433 	if (sampler_type == SAMPLER_TYPE_ISAMPLER2DMS || sampler_type == SAMPLER_TYPE_ISAMPLER2DMSARRAY)
434 	{
435 		texture_internalformat = GL_RGBA8I;
436 	}
437 	else if (sampler_type == SAMPLER_TYPE_SAMPLER2DMS || sampler_type == SAMPLER_TYPE_SAMPLER2DMSARRAY)
438 	{
439 		texture_internalformat = GL_RGBA8;
440 	}
441 	else
442 	{
443 		texture_internalformat = GL_RGBA8UI;
444 	}
445 
446 	if (sampler_type == SAMPLER_TYPE_ISAMPLER2DMS || sampler_type == SAMPLER_TYPE_SAMPLER2DMS ||
447 		sampler_type == SAMPLER_TYPE_USAMPLER2DMS)
448 	{
449 		texture_target = GL_TEXTURE_2D_MULTISAMPLE;
450 	}
451 	else
452 	{
453 		texture_target = GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
454 	}
455 
456 	gl.getInternalformativ(texture_target, texture_internalformat, GL_NUM_SAMPLE_COUNTS, 1, /* bufSize */
457 						   &m_internalformat_n_samples_count);
458 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() call failed.");
459 
460 	if (m_internalformat_n_samples_count < 1)
461 	{
462 		TCU_FAIL("Invalid value returned by glGetInternalformativ() for a GL_NUM_SAMPLE_COUNTS query");
463 	}
464 
465 	m_internalformat_n_samples_data = new glw::GLint[m_internalformat_n_samples_count];
466 
467 	gl.getInternalformativ(texture_target, texture_internalformat, GL_SAMPLES, m_internalformat_n_samples_count,
468 						   m_internalformat_n_samples_data);
469 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInternalformativ() call failed.");
470 
471 	/* Iterate over all sample counts. For each iteration, set up texture storage,
472 	 * run one work-item which will store the value retrieved by one of the two new
473 	 * ES SL functions into the buffer object. Once that happens, map the buffer
474 	 * object storage contents into process space and validate the value */
475 	for (int n_value = 0; n_value < m_internalformat_n_samples_count; ++n_value)
476 	{
477 		if (test_type == TEST_TYPE_IMAGE)
478 		{
479 			/* Shader images do not necessarily support all sample counts. */
480 			int max_image_samples;
481 
482 			gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
483 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_IMAGE_SAMPLES) call failed.");
484 
485 			if (m_internalformat_n_samples_data[n_value] > max_image_samples)
486 				continue;
487 		}
488 
489 		gl.genTextures(1, &m_to_id);
490 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
491 
492 		gl.bindTexture(texture_target, m_to_id);
493 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
494 
495 		if (texture_target == GL_TEXTURE_2D_MULTISAMPLE)
496 		{
497 			gl.texStorage2DMultisample(texture_target, m_internalformat_n_samples_data[n_value], texture_internalformat,
498 									   m_to_width, m_to_height, GL_FALSE); /* fixedsamplelocations */
499 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2DMultisample() call failed");
500 		}
501 		else
502 		{
503 			DE_ASSERT(texture_target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY);
504 
505 			gl.texStorage3DMultisample(texture_target, m_internalformat_n_samples_data[n_value], texture_internalformat,
506 									   m_to_width, m_to_height, m_to_depth, GL_TRUE); /* fixedsamplelocations */
507 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3DMultisample() call failed");
508 		}
509 
510 		/* If we're running the "image" test, bind the texture to zeroth image unit */
511 		if (test_type == TEST_TYPE_IMAGE)
512 		{
513 			gl.bindImageTexture(0,			/* unit */
514 								m_to_id, 0, /* level */
515 								GL_FALSE,   /* layered */
516 								0,			/* lyer */
517 								GL_READ_ONLY, texture_internalformat);
518 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
519 		}
520 
521 		/* Dispatch a compute request */
522 		gl.useProgram(m_po_id);
523 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
524 
525 		gl.dispatchCompute(1,  /* num_groups_x */
526 						   1,  /* num_groups_y */
527 						   1); /* num_groups_z */
528 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute() call failed.");
529 
530 		gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
531 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMemoryBarrier() call failed.");
532 
533 		/* Map the buffer object storage into process space */
534 		const void* bo_ptr		   = gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
535 		glw::GLint  expected_value = 0;
536 
537 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed");
538 
539 		expected_value = m_internalformat_n_samples_data[n_value];
540 
541 		if (*(int*)bo_ptr != expected_value)
542 		{
543 			m_testCtx.getLog() << tcu::TestLog::Message << "Value reported for the " << sampler_type_string << " test ["
544 							   << *(int*)bo_ptr << "] "
545 												   " is different from the expected one ["
546 							   << expected_value << "]." << tcu::TestLog::EndMessage;
547 
548 			TCU_FAIL("Invalid value reported by ES SL function");
549 		}
550 
551 		/* Safe to unmap the BO at this point */
552 		gl.unmapBuffer(GL_ARRAY_BUFFER);
553 
554 		gl.deleteTextures(1, &m_to_id);
555 		m_to_id = 0;
556 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures() call failed.");
557 	} /* for (all "n samples" values) */
558 }
559 
560 /** Initializes all GL objects required to run the test. Also throws a
561  *  NotSupportedError exception if GL_ARB_shader_texture_image_samples is not
562  *  reported as a supported extension.
563  **/
init()564 void ShaderTextureImageSamplesTestBase::init()
565 {
566 	/* Make sure GL_ARB_shader_texture_image_samples is supported before continuing */
567 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_shader_texture_image_samples"))
568 	{
569 		throw tcu::NotSupportedError("GL_ARB_shader_texture_image_samples extension is not supported.");
570 	}
571 
572 	/* Allocate BO storage to hold the result int value */
573 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
574 
575 	gl.genBuffers(1, &m_bo_id);
576 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
577 
578 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
579 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
580 
581 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(int), DE_NULL, /* data */
582 				  GL_STATIC_DRAW);						 /* usage */
583 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
584 }
585 
586 /** Constructor.
587  *
588  *  @param context Rendering context handle.
589  **/
ShaderTextureImageSampleFunctionalTest(deqp::Context & context,const char * test_name)590 ShaderTextureImageSampleFunctionalTest::ShaderTextureImageSampleFunctionalTest(deqp::Context& context,
591 																			   const char*	test_name)
592 	: ShaderTextureImageSamplesTestBase(context, test_name, "Verifies that the new ES SL functions (imageSamples() and "
593 															"textureSamples() ) work as per spec for all supported "
594 															"numbers of samples + texture target combinations.")
595 {
596 	type_to_test = test_name[0] == 'i' ? TEST_TYPE_IMAGE : TEST_TYPE_TEXTURE;
597 }
598 
599 /** Initializes all GL objects required to run the test.  Also throws a
600  *  NotSupportedError exception if testing images and GL_MAX_IMAGE_SAMPLES = 0.
601  **/
init()602 void ShaderTextureImageSampleFunctionalTest::init()
603 {
604 	ShaderTextureImageSamplesTestBase::init();
605 
606 	if (type_to_test == TEST_TYPE_IMAGE)
607 	{
608 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
609 
610 		glw::GLint max_image_samples;
611 		gl.getIntegerv(GL_MAX_IMAGE_SAMPLES, &max_image_samples);
612 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
613 
614 		if (max_image_samples == 0)
615 		{
616 			throw tcu::NotSupportedError("GL_MAX_IMAGE_SAMPLES == 0");
617 		}
618 	}
619 }
620 
621 /** Executes test iteration.
622  *
623  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
624  */
iterate()625 tcu::TestNode::IterateResult ShaderTextureImageSampleFunctionalTest::iterate()
626 {
627 	for (unsigned int n_sampler_type = 0; n_sampler_type < SAMPLER_TYPE_COUNT; ++n_sampler_type)
628 	{
629 		_sampler_type sampler_type = (_sampler_type)n_sampler_type;
630 
631 		for (unsigned int n_test_type = 0; n_test_type < TEST_TYPE_COUNT; ++n_test_type)
632 		{
633 			_test_type test_type = (_test_type)n_test_type;
634 
635 			if (test_type == type_to_test)
636 			{
637 				executeFunctionalTest(sampler_type, test_type);
638 			}
639 		} /* for (all test types) */
640 	}	 /* for (all sampler types) */
641 
642 	/* Test case passed */
643 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
644 
645 	return STOP;
646 }
647 
648 /** Constructor.
649  *
650  *  @param context Rendering context handle.
651  **/
ShaderTextureImageSamplesGLSLExtensionEnableTest(deqp::Context & context)652 ShaderTextureImageSamplesGLSLExtensionEnableTest::ShaderTextureImageSamplesGLSLExtensionEnableTest(
653 	deqp::Context& context)
654 	: ShaderTextureImageSamplesTestBase(
655 		  context, "glsl_extension_enable",
656 		  "Verifies a shader with \"#extension GL_ARB_shader_texture_image_samples : enable\" "
657 		  "line defines a corresponding pre-processor macro.")
658 {
659 	/* Left blank on purpose */
660 }
661 
662 /** Executes test iteration.
663  *
664  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
665  */
iterate()666 tcu::TestNode::IterateResult ShaderTextureImageSamplesGLSLExtensionEnableTest::iterate()
667 {
668 	const char* cs_body = "#version 440\n"
669 						  "\n"
670 						  "#extension GL_ARB_shader_texture_image_samples : enable\n"
671 						  "\n"
672 						  "void main()\n"
673 						  "{\n"
674 						  "#ifndef GL_ARB_shader_texture_image_samples\n"
675 						  "    force_compilation_error\n"
676 						  "#endif\n"
677 						  "}\n";
678 
679 	if (!buildComputeProgram(cs_body, false, /* should_link_po */
680 							 true))			 /* should_succeed */
681 	{
682 		TCU_FAIL("GL_ARB_shader_image_load_store preprocessor #define is not set to the value of 1");
683 	}
684 
685 	/* Test case passed */
686 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
687 
688 	return STOP;
689 }
690 
691 /** Constructor.
692  *
693  *  @param context Rendering context handle.
694  **/
ShaderTextureImageSamplesGLSLExtensionRequireTest(deqp::Context & context)695 ShaderTextureImageSamplesGLSLExtensionRequireTest::ShaderTextureImageSamplesGLSLExtensionRequireTest(
696 	deqp::Context& context)
697 	: ShaderTextureImageSamplesTestBase(
698 		  context, "glsl_extension_require",
699 		  "Verifies a shader with \"#extension GL_ARB_shader_texture_image_samples : require\" "
700 		  "line compiles without error.")
701 {
702 	/* Left blank on purpose */
703 }
704 
705 /** Executes test iteration.
706  *
707  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
708  */
iterate()709 tcu::TestNode::IterateResult ShaderTextureImageSamplesGLSLExtensionRequireTest::iterate()
710 {
711 	const char* cs_body = "#version 440\n"
712 						  "\n"
713 						  "#extension GL_ARB_shader_texture_image_samples : require\n"
714 						  "\n"
715 						  "void main()\n"
716 						  "{\n"
717 						  "}\n";
718 
719 	if (!buildComputeProgram(cs_body, false, /* should_link_po */
720 							 true))			 /* should_succeed */
721 	{
722 		TCU_FAIL("A valid compute program has failed to build");
723 	}
724 
725 	/* Test case passed */
726 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
727 
728 	return STOP;
729 }
730 
731 /** Constructor.
732  *
733  *  @param context Rendering context.
734  */
ShaderTextureImageSamplesTests(deqp::Context & context)735 ShaderTextureImageSamplesTests::ShaderTextureImageSamplesTests(deqp::Context& context)
736 	: TestCaseGroup(context, "shader_texture_image_samples_tests",
737 					"Contains conformance tests that verify GL implementation's support "
738 					"for GL_ARB_shader_texture_image_samples extension.")
739 {
740 }
741 
742 /** Initializes the test group contents. */
init()743 void ShaderTextureImageSamplesTests::init()
744 {
745 	addChild(new ShaderTextureImageSampleFunctionalTest(m_context, "image_functional_test"));
746 	addChild(new ShaderTextureImageSampleFunctionalTest(m_context, "texture_functional_test"));
747 	addChild(new ShaderTextureImageSamplesGLSLExtensionEnableTest(m_context));
748 	addChild(new ShaderTextureImageSamplesGLSLExtensionRequireTest(m_context));
749 }
750 
751 } /* glcts namespace */
752