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
41namespace glcts
42{
43/** Constructor.
44 *
45 *  @param context     Rendering context
46 *  @param name        Test name
47 *  @param description Test description
48 */
49ShaderTextureImageSamplesTestBase::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 **/
82bool 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;
159end:
160	return result;
161}
162
163/** Deinitializes all GL objects that may have been created during test execution. */
164void 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 **/
196void 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 **/
226void 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 **/
564void 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 **/
590ShaderTextureImageSampleFunctionalTest::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 **/
602void 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 */
625tcu::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 **/
652ShaderTextureImageSamplesGLSLExtensionEnableTest::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 */
666tcu::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 **/
695ShaderTextureImageSamplesGLSLExtensionRequireTest::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 */
709tcu::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 */
735ShaderTextureImageSamplesTests::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. */
743void 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