• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2018 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  * \file glcLayoutLocationTests.cpp
20  * \brief
21  */ /*-------------------------------------------------------------------*/
22 #include "glcLayoutLocationTests.hpp"
23 
24 #include "tcuRenderTarget.hpp"
25 #include "tcuStringTemplate.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuTexture.hpp"
29 #include "tcuTextureUtil.hpp"
30 
31 #include "deStringUtil.hpp"
32 
33 #include "glwDefs.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 
37 #include "gluDrawUtil.hpp"
38 #include "gluPixelTransfer.hpp"
39 #include "gluShaderProgram.hpp"
40 #include "gluTexture.hpp"
41 #include "gluTextureUtil.hpp"
42 
43 using namespace glw;
44 
45 namespace glcts
46 {
47 
48 static const GLuint WIDTH  = 2;
49 static const GLuint HEIGHT = 2;
50 
51 // Helper function used to set texture parameters
setTexParameters(const Functions & gl,GLenum target,bool depthTexture)52 void setTexParameters(const Functions& gl, GLenum target, bool depthTexture)
53 {
54 	gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
55 	gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
56 
57 	if (depthTexture)
58 	{
59 		gl.texParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
60 		gl.texParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
61 	}
62 }
63 
64 // Helper function used to create texture data
65 template <typename DATA_TYPE>
generateData(std::size_t width,std::size_t height,std::size_t components)66 std::vector<DATA_TYPE> generateData(std::size_t width, std::size_t height, std::size_t components)
67 {
68 	DE_ASSERT((components == 1) || (components == 4));
69 	std::size_t			   size = width * height * components;
70 	std::vector<DATA_TYPE> data(size, 0);
71 	for (std::size_t i = 0; i < size; i += components)
72 		data[i]		   = static_cast<DATA_TYPE>(255);
73 	return data;
74 }
75 
76 // Structure used to return id of created object it had to be defined to support
77 // GL_TEXTURE_BUFFER cases which require creation of both texture and buffer
78 struct ResultData
79 {
80 	deUint32 textureId; // id of created texture
81 	deUint32 bufferId;  // used only by GL_TEXTURE_BUFFER
82 
ResultDataglcts::ResultData83 	ResultData(deUint32 tId) : textureId(tId), bufferId(0)
84 	{
85 	}
86 
ResultDataglcts::ResultData87 	ResultData(deUint32 tId, deUint32 bId) : textureId(tId), bufferId(bId)
88 	{
89 	}
90 };
91 
92 template <typename DATA_TYPE>
createTexture1D(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)93 ResultData createTexture1D(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format,
94 						   GLenum type)
95 {
96 	std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, 1, components);
97 
98 	deUint32 id;
99 	gl.genTextures(1, &id);
100 	gl.bindTexture(GL_TEXTURE_1D, id);
101 	gl.texImage1D(GL_TEXTURE_1D, 0, internalFormat, WIDTH, 0, format, type, &data[0]);
102 	setTexParameters(gl, GL_TEXTURE_1D, components == 1);
103 	return id;
104 }
105 
106 template <typename DATA_TYPE>
createTexture2D(const Functions & gl,std::size_t components,GLenum target,GLenum internalFormat,GLenum format,GLenum type)107 ResultData createTexture2D(const Functions& gl, std::size_t components, GLenum target, GLenum internalFormat,
108 						   GLenum format, GLenum type)
109 {
110 	std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
111 
112 	deUint32 id;
113 	gl.genTextures(1, &id);
114 	gl.bindTexture(target, id);
115 	gl.texStorage2D(target, 1, internalFormat, WIDTH, HEIGHT);
116 	gl.texSubImage2D(target, 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]);
117 	setTexParameters(gl, target, components == 1);
118 	return id;
119 }
120 
121 template <typename DATA_TYPE>
createTexture3D(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)122 ResultData createTexture3D(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format,
123 						   GLenum type)
124 {
125 	std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
126 
127 	deUint32 id;
128 	gl.genTextures(1, &id);
129 	gl.bindTexture(GL_TEXTURE_3D, id);
130 	gl.texStorage3D(GL_TEXTURE_3D, 1, internalFormat, WIDTH, HEIGHT, 1);
131 	gl.texSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]);
132 	setTexParameters(gl, GL_TEXTURE_3D, components == 1);
133 	return id;
134 }
135 
136 template <typename DATA_TYPE>
createCubeMap(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)137 ResultData createCubeMap(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format, GLenum type)
138 {
139 	std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
140 
141 	deUint32 id;
142 	gl.genTextures(1, &id);
143 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, id);
144 	GLenum faces[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
145 					   GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
146 	gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalFormat, WIDTH, HEIGHT);
147 	for (int i = 0; i < 6; ++i)
148 		gl.texSubImage2D(faces[i], 0, 0, 0, WIDTH, HEIGHT, format, type, &data[0]);
149 	setTexParameters(gl, GL_TEXTURE_CUBE_MAP, components == 1);
150 	return id;
151 }
152 
153 template <typename DATA_TYPE>
createTexture2DArray(const Functions & gl,std::size_t components,GLenum internalFormat,GLenum format,GLenum type)154 ResultData createTexture2DArray(const Functions& gl, std::size_t components, GLenum internalFormat, GLenum format,
155 								GLenum type)
156 {
157 	std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, components);
158 
159 	deUint32 id;
160 	gl.genTextures(1, &id);
161 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, id);
162 	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalFormat, WIDTH, HEIGHT, 1);
163 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, WIDTH, HEIGHT, 1, format, type, &data[0]);
164 	setTexParameters(gl, GL_TEXTURE_2D_ARRAY, components == 1);
165 	return id;
166 }
167 
168 template <typename DATA_TYPE>
createTextureBuffer(const Functions & gl,GLenum internalFormat)169 ResultData createTextureBuffer(const Functions& gl, GLenum internalFormat)
170 {
171 	std::vector<DATA_TYPE> data = generateData<DATA_TYPE>(WIDTH, HEIGHT, 4);
172 
173 	deUint32 bufferId;
174 	gl.genBuffers(1, &bufferId);
175 	gl.bindBuffer(GL_TEXTURE_BUFFER, bufferId);
176 	gl.bufferData(GL_TEXTURE_BUFFER, WIDTH * HEIGHT * 4 * sizeof(DATA_TYPE), &data[0], GL_STATIC_DRAW);
177 
178 	deUint32 textureId;
179 	gl.genTextures(1, &textureId);
180 	gl.bindTexture(GL_TEXTURE_BUFFER, textureId);
181 	gl.texBuffer(GL_TEXTURE_BUFFER, internalFormat, bufferId);
182 	return ResultData(textureId, bufferId);
183 }
184 
185 // create function was implemented for convinience. Specializations of this
186 // template simplify definition of test data by reducting the number of
187 // attributes which were moved to create fn implementation. This aproach
188 // also simplyfies texture creation in the test as create takes just a single
189 // parameter for all test cases.
190 template <GLenum, GLenum>
create(const Functions & gl)191 ResultData create(const Functions& gl)
192 {
193 	(void)gl;
194 	TCU_FAIL("Missing specialization implementation.");
195 }
196 
197 template <>
create(const Functions & gl)198 ResultData create<GL_TEXTURE_2D, GL_RGBA8>(const Functions& gl)
199 {
200 	return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_2D, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
201 }
202 
203 template <>
create(const Functions & gl)204 ResultData create<GL_TEXTURE_3D, GL_RGBA8>(const Functions& gl)
205 {
206 	return createTexture3D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
207 }
208 
209 template <>
create(const Functions & gl)210 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>(const Functions& gl)
211 {
212 	return createCubeMap<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
213 }
214 
215 template <>
create(const Functions & gl)216 ResultData create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>(const Functions& gl)
217 {
218 	return createCubeMap<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
219 }
220 
221 template <>
create(const Functions & gl)222 ResultData create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>(const Functions& gl)
223 {
224 	return createTexture2D<short>(gl, 1, GL_TEXTURE_2D, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
225 }
226 
227 template <>
create(const Functions & gl)228 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>(const Functions& gl)
229 {
230 	return createTexture2DArray<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
231 }
232 
233 template <>
create(const Functions & gl)234 ResultData create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions& gl)
235 {
236 	return createTexture2DArray<short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
237 }
238 
239 template <>
create(const Functions & gl)240 ResultData create<GL_TEXTURE_2D, GL_RGBA32I>(const Functions& gl)
241 {
242 	return createTexture2D<int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
243 }
244 
245 template <>
create(const Functions & gl)246 ResultData create<GL_TEXTURE_3D, GL_RGBA32I>(const Functions& gl)
247 {
248 	return createTexture3D<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
249 }
250 
251 template <>
create(const Functions & gl)252 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>(const Functions& gl)
253 {
254 	return createCubeMap<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
255 }
256 
257 template <>
create(const Functions & gl)258 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>(const Functions& gl)
259 {
260 	return createTexture2DArray<int>(gl, 4, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT);
261 }
262 
263 template <>
create(const Functions & gl)264 ResultData create<GL_TEXTURE_2D, GL_RGBA32UI>(const Functions& gl)
265 {
266 	return createTexture2D<unsigned int>(gl, 4, GL_TEXTURE_2D, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
267 }
268 
269 template <>
create(const Functions & gl)270 ResultData create<GL_TEXTURE_3D, GL_RGBA32UI>(const Functions& gl)
271 {
272 	return createTexture3D<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
273 }
274 
275 template <>
create(const Functions & gl)276 ResultData create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>(const Functions& gl)
277 {
278 	return createCubeMap<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
279 }
280 
281 template <>
create(const Functions & gl)282 ResultData create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>(const Functions& gl)
283 {
284 	return createTexture2DArray<unsigned int>(gl, 4, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
285 }
286 
287 template <>
create(const Functions & gl)288 ResultData create<GL_TEXTURE_1D, GL_RGBA8>(const Functions& gl)
289 {
290 	return createTexture1D<unsigned char>(gl, 4, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
291 }
292 
293 template <>
create(const Functions & gl)294 ResultData create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>(const Functions& gl)
295 {
296 	return createTexture1D<unsigned short>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
297 }
298 
299 template <>
create(const Functions & gl)300 ResultData create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>(const Functions& gl)
301 {
302 	return createTexture2D<unsigned char>(gl, 4, GL_TEXTURE_1D_ARRAY, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
303 }
304 
305 template <>
create(const Functions & gl)306 ResultData create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>(const Functions& gl)
307 {
308 	return createTexture2D<short>(gl, 1, GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT,
309 								  GL_UNSIGNED_SHORT);
310 }
311 
312 template <>
create(const Functions & gl)313 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32F>(const Functions& gl)
314 {
315 	return createTextureBuffer<float>(gl, GL_RGBA32F);
316 }
317 
318 template <>
create(const Functions & gl)319 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32I>(const Functions& gl)
320 {
321 	return createTextureBuffer<int>(gl, GL_RGBA32I);
322 }
323 
324 template <>
create(const Functions & gl)325 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32UI>(const Functions& gl)
326 {
327 	return createTextureBuffer<unsigned int>(gl, GL_RGBA32UI);
328 }
329 
330 // Structure used to define all test case data
331 struct SamplerCaseData
332 {
333 	typedef ResultData (*CreateFnPtr)(const Functions& gl);
334 
335 	CreateFnPtr	create;						// pointer to function that will create texture
336 	const char*	name;						// test case name
337 	const char*	opaqueType;					// sampler or image
338 	const char*	outAssignment;				// operation that determines fragment color
339 	const int	num_frag_image_uniforms;	// the number of required fragment image uniform
340 };
341 
342 class SpecifiedLocationCase : public deqp::TestCase
343 {
344 public:
345 	SpecifiedLocationCase(deqp::Context& context, const SamplerCaseData& data);
346 	virtual ~SpecifiedLocationCase();
347 
348 	tcu::TestNode::IterateResult iterate();
349 
350 private:
351 	ResultData (*m_createFn)(const Functions& gl);
352 	std::map<std::string, std::string> m_specializationMap;
353 
354 	bool		m_isImageCase;
355 	GLenum		m_imageFormat;
356 	std::string	m_imageFormatQualifier;
357 	int			m_num_frag_image_uniform;
358 };
359 
SpecifiedLocationCase(deqp::Context & context,const SamplerCaseData & data)360 SpecifiedLocationCase::SpecifiedLocationCase(deqp::Context& context, const SamplerCaseData& data)
361 	: deqp::TestCase(context, data.name, ""), m_createFn(data.create)
362 {
363 	std::string type(data.opaqueType);
364 	m_specializationMap["OPAQUE_TYPE"]	= type;
365 	m_specializationMap["OUT_ASSIGNMENT"] = data.outAssignment;
366 
367 	m_isImageCase = (type.find("sampler") == std::string::npos);
368 	if (m_isImageCase)
369 	{
370 		m_specializationMap["OPAQUE_TYPE_NAME"] = "image";
371 		m_specializationMap["ACCESS"]			= "readonly";
372 
373 		if (type.find("iimage") != std::string::npos)
374 		{
375 			m_imageFormatQualifier = "rgba32i";
376 			m_imageFormat		   = GL_RGBA32I;
377 		}
378 		else if (type.find("uimage") != std::string::npos)
379 		{
380 			m_imageFormatQualifier = "rgba32ui";
381 			m_imageFormat		   = GL_RGBA32UI;
382 		}
383 		else
384 		{
385 			m_imageFormatQualifier = "rgba8";
386 			m_imageFormat		   = GL_RGBA8;
387 		}
388 	}
389 	else
390 	{
391 		m_specializationMap["OPAQUE_TYPE_NAME"] = "sampler";
392 		m_specializationMap["ACCESS"]			= "";
393 	}
394 	m_num_frag_image_uniform = data.num_frag_image_uniforms;
395 }
396 
~SpecifiedLocationCase()397 SpecifiedLocationCase::~SpecifiedLocationCase()
398 {
399 }
400 
iterate(void)401 tcu::TestNode::IterateResult SpecifiedLocationCase::iterate(void)
402 {
403 	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
404 	static const float	positions[]   = { -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0 };
405 
406 	static const char* vsTemplate = "${VERSION}\n"
407 									"precision highp float;\n"
408 									"layout(location=0) in highp vec2 inPosition;\n"
409 									"layout(location=0) out highp vec2 coords;\n"
410 									"void main(void)\n"
411 									"{\n"
412 									"  coords = vec2(max(0.0, inPosition.x), max(0.0, inPosition.y));\n"
413 									"  gl_Position = vec4(inPosition, 0.0, 1.0);\n"
414 									"}\n";
415 
416 	static const char* fsTemplate =
417 		"${VERSION}\n"
418 		"precision highp float;\n"
419 		"layout(location=0) in vec2 coords;\n"
420 		"layout(location=0) out vec4 fragColor;\n"
421 		"layout(${OPAQUE_TYPE_QUALIFIERS}) ${ACCESS} uniform highp ${OPAQUE_TYPE} ${OPAQUE_TYPE_NAME};\n"
422 		"void main(void)\n"
423 		"{\n"
424 		"  fragColor = ${OUT_ASSIGNMENT};\n"
425 		"}\n";
426 
427 	glu::RenderContext& renderContext = m_context.getRenderContext();
428 	glu::ContextType	contextType   = renderContext.getType();
429 	glu::GLSLVersion	glslVersion   = glu::getContextTypeGLSLVersion(contextType);
430 	const Functions&	gl			  = renderContext.getFunctions();
431 	bool				contextTypeES = glu::isContextTypeES(contextType);
432 	bool				contextES32	  = glu::contextSupports(contextType, glu::ApiType::es(3, 2));
433 	if (contextTypeES && !contextES32 && !m_context.getContextInfo().isExtensionSupported("GL_ANDROID_extension_pack_es31a"))
434 		if (m_context.getContextInfo().getInt(GL_MAX_FRAGMENT_IMAGE_UNIFORMS) < m_num_frag_image_uniform)
435 			throw tcu::NotSupportedError("The number of required fragment image uniform is larger than GL_MAX_FRAGMENT_IMAGE_UNIFORMS");
436 
437 	const int expectedLocation = 2;
438 	const int definedBinding   = 1;
439 
440 	std::ostringstream layoutSpecification;
441 	layoutSpecification << "location=" << expectedLocation;
442 	if (m_isImageCase)
443 	{
444 		if (contextTypeES)
445 			layoutSpecification << ", binding=" << definedBinding;
446 		layoutSpecification << ", " << m_imageFormatQualifier;
447 	}
448 
449 	m_specializationMap["VERSION"]				  = glu::getGLSLVersionDeclaration(glslVersion);
450 	m_specializationMap["OPAQUE_TYPE_QUALIFIERS"] = layoutSpecification.str();
451 
452 	std::string		   vs = tcu::StringTemplate(vsTemplate).specialize(m_specializationMap);
453 	std::string		   fs = tcu::StringTemplate(fsTemplate).specialize(m_specializationMap);
454 	glu::ShaderProgram program(gl, glu::makeVtxFragSources(vs.c_str(), fs.c_str()));
455 
456 	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
457 	if (!program.isOk())
458 	{
459 		m_testCtx.getLog() << program << tcu::TestLog::Message << "Creation of program failed."
460 						   << tcu::TestLog::EndMessage;
461 		return STOP;
462 	}
463 
464 	deUint32 programId = program.getProgram();
465 	int		 location  = gl.getUniformLocation(programId, m_specializationMap["OPAQUE_TYPE_NAME"].c_str());
466 	if (location != expectedLocation)
467 	{
468 		m_testCtx.getLog() << tcu::TestLog::Message << "Expected uniform to be at location " << expectedLocation
469 						   << ", not at " << location << "." << tcu::TestLog::EndMessage;
470 		return STOP;
471 	}
472 
473 	gl.useProgram(programId);
474 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
475 
476 	// Prepare texture/buffer
477 	gl.activeTexture(GL_TEXTURE1);
478 	ResultData resultData = (*m_createFn)(gl);
479 	GLU_EXPECT_NO_ERROR(gl.getError(), "GL object creation failed.");
480 
481 	if (m_isImageCase)
482 	{
483 		gl.bindImageTexture(definedBinding, resultData.textureId, 0, GL_TRUE, 0, GL_READ_ONLY, m_imageFormat);
484 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture");
485 	}
486 
487 	// in ES image uniforms cannot be updated
488 	// through any of the glUniform* commands
489 	if (!(contextTypeES && m_isImageCase))
490 	{
491 		gl.uniform1i(expectedLocation, definedBinding);
492 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
493 	}
494 
495 	// Create FBO with RBO
496 	deUint32 rboId;
497 	deUint32 fboId;
498 	gl.genRenderbuffers(1, &rboId);
499 	gl.bindRenderbuffer(GL_RENDERBUFFER, rboId);
500 	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, WIDTH, HEIGHT);
501 	gl.genFramebuffers(1, &fboId);
502 	gl.bindFramebuffer(GL_FRAMEBUFFER, fboId);
503 	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboId);
504 
505 	// Render
506 	gl.viewport(0, 0, WIDTH, HEIGHT);
507 	const glu::VertexArrayBinding vertexArrays[] = { glu::va::Float("inPosition", 2, 4, 0, positions) };
508 	glu::draw(renderContext, programId, DE_LENGTH_OF_ARRAY(vertexArrays), vertexArrays,
509 			  glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices));
510 
511 	// Grab surface
512 	tcu::Surface resultFrame(WIDTH, HEIGHT);
513 	glu::readPixels(renderContext, 0, 0, resultFrame.getAccess());
514 
515 	// Verify color of just first pixel
516 	const tcu::RGBA expectedColor(255, 0, 0, 0);
517 	tcu::RGBA		pixel = resultFrame.getPixel(0, 0);
518 	if (pixel != expectedColor)
519 	{
520 		m_testCtx.getLog() << tcu::TestLog::Message << "Incorrect color was generated, expected: ["
521 						   << expectedColor.getRed() << ", " << expectedColor.getGreen() << ", "
522 						   << expectedColor.getBlue() << ", " << expectedColor.getAlpha() << "], got ["
523 						   << pixel.getRed() << ", " << pixel.getGreen() << ", " << pixel.getBlue() << ", "
524 						   << pixel.getAlpha() << "]" << tcu::TestLog::EndMessage;
525 	}
526 	else
527 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
528 
529 	// Cleanup
530 	if (resultData.bufferId)
531 		gl.deleteBuffers(1, &resultData.bufferId);
532 	gl.deleteFramebuffers(1, &fboId);
533 	gl.deleteRenderbuffers(1, &rboId);
534 	gl.deleteTextures(1, &resultData.textureId);
535 
536 	return STOP;
537 }
538 
539 class NegativeLocationCase : public deqp::TestCase
540 {
541 public:
542 	NegativeLocationCase(deqp::Context& context);
543 	virtual ~NegativeLocationCase();
544 
545 	tcu::TestNode::IterateResult iterate();
546 };
547 
NegativeLocationCase(deqp::Context & context)548 NegativeLocationCase::NegativeLocationCase(deqp::Context& context) : deqp::TestCase(context, "invalid_cases", "")
549 {
550 }
551 
~NegativeLocationCase()552 NegativeLocationCase::~NegativeLocationCase()
553 {
554 }
555 
iterate()556 tcu::TestNode::IterateResult NegativeLocationCase::iterate()
557 {
558 	glu::RenderContext& renderContext = m_context.getRenderContext();
559 	glu::ContextType	contextType   = renderContext.getType();
560 	glu::GLSLVersion	glslVersion   = glu::getContextTypeGLSLVersion(contextType);
561 	const Functions&	gl			  = renderContext.getFunctions();
562 
563 	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
564 
565 	static const char* csTemplate = "${VERSION}\n"
566 									"layout(location=2, binding=0) uniform atomic_uint u_atomic;\n"
567 									"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
568 									"layout(binding=0) buffer Output {\n  uint value;\n} sb_out;\n\n"
569 									"void main (void) {\n"
570 									"  sb_out.value = atomicCounterIncrement(u_atomic);\n"
571 									"}";
572 
573 	std::map<std::string, std::string> specializationMap;
574 	specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion);
575 	std::string cs				 = tcu::StringTemplate(csTemplate).specialize(specializationMap);
576 
577 	m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
578 
579 	glu::ProgramSources sourcesCompute;
580 	sourcesCompute.sources[glu::SHADERTYPE_COMPUTE].push_back(cs);
581 	glu::ShaderProgram program(gl, sourcesCompute);
582 	if (program.isOk())
583 	{
584 		m_testCtx.getLog() << program << tcu::TestLog::Message
585 						   << "layout(location = N) is not allowed for atomic counters" << tcu::TestLog::EndMessage;
586 		return STOP;
587 	}
588 
589 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
590 	return STOP;
591 }
592 
LayoutLocationTests(Context & context)593 LayoutLocationTests::LayoutLocationTests(Context& context) : TestCaseGroup(context, "layout_location", "")
594 {
595 }
596 
~LayoutLocationTests(void)597 LayoutLocationTests::~LayoutLocationTests(void)
598 {
599 }
600 
init(void)601 void LayoutLocationTests::init(void)
602 {
603 	const SamplerCaseData commonArguments[] =
604 	{
605 		{ &create<GL_TEXTURE_2D, GL_RGBA8>,						"sampler_2d",				"sampler2D",			"texture(sampler, coords)",											0 },
606 		{ &create<GL_TEXTURE_3D, GL_RGBA8>,						"sampler_3d",				"sampler3D",			"texture(sampler, vec3(coords, 0.0))",								0 },
607 		{ &create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>,				"sampler_cube",				"samplerCube",			"texture(sampler, vec3(coords, 0.0))",								0 },
608 		{ &create<GL_TEXTURE_CUBE_MAP, GL_DEPTH_COMPONENT16>,	"sampler_cube_shadow",		"samplerCubeShadow",	"vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)",	0 },
609 		{ &create<GL_TEXTURE_2D, GL_DEPTH_COMPONENT16>,			"sampler_2d_shadow",		"sampler2DShadow",		"vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)",			0 },
610 		{ &create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>,				"sampler_2d_array",			"sampler2DArray",		"texture(sampler, vec3(coords, 0.0))",								0 },
611 		{ &create<GL_TEXTURE_2D_ARRAY, GL_DEPTH_COMPONENT16>,	"sampler_2d_array_shadow",	"sampler2DArrayShadow",	"vec4(texture(sampler, vec4(coords, 0.0, 0.0)), 0.0, 0.0, 0.0)",	0 },
612 		{ &create<GL_TEXTURE_2D, GL_RGBA32I>,					"isampler_2d",				"isampler2D",			"vec4(texture(sampler, coords))/255.0",								0 },
613 		{ &create<GL_TEXTURE_3D, GL_RGBA32I>,					"isampler_3d",				"isampler3D",			"vec4(texture(sampler, vec3(coords, 0.0)))/255.0",					0 },
614 		{ &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>,				"isampler_cube",			"isamplerCube",			"vec4(texture(sampler, vec3(coords, 0.0)))/255.0",					0 },
615 		{ &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>,				"isampler_2d_array",		"isampler2DArray",		"vec4(texture(sampler, vec3(coords, 0.0)))/255.0",					0 },
616 		{ &create<GL_TEXTURE_2D, GL_RGBA32UI>,					"usampler_2d",				"usampler2D",			"vec4(texture(sampler, coords))/255.0",								0 },
617 		{ &create<GL_TEXTURE_3D, GL_RGBA32UI>,					"usampler_3d",				"usampler3D",			"vec4(texture(sampler, vec3(coords, 0.0)))/255.0",					0 },
618 		{ &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>,			"usampler_cube",			"usamplerCube",			"vec4(texture(sampler, vec3(coords, 0.0)))/255.0",					0 },
619 		{ &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>,			"usampler_2d_array",		"usampler2DArray",		"vec4(texture(sampler, vec3(coords, 0.0)))/255.0",					0 },
620 
621 		{ &create<GL_TEXTURE_2D, GL_RGBA8>,						"image_2d",					"image2D",				"imageLoad(image, ivec2(0, 0))",									1 },
622 		{ &create<GL_TEXTURE_2D, GL_RGBA32I>,					"iimage_2d",				"iimage2D",				"vec4(imageLoad(image, ivec2(0, 0)))/255.0",						1 },
623 		{ &create<GL_TEXTURE_2D, GL_RGBA32UI>,					"uimage_2d",				"uimage2D",				"vec4(imageLoad(image, ivec2(0, 0)))/255.0",						1 },
624 		{ &create<GL_TEXTURE_3D, GL_RGBA8>,						"image_3d",					"image3D",				"imageLoad(image, ivec3(0, 0, 0))",									1 },
625 		{ &create<GL_TEXTURE_3D, GL_RGBA32I>,					"iimage_3d",				"iimage3D",				"vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",						1 },
626 		{ &create<GL_TEXTURE_3D, GL_RGBA32UI>,					"uimage_3d",				"uimage3D",				"vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",						1 },
627 		{ &create<GL_TEXTURE_CUBE_MAP, GL_RGBA8>,				"image_cube",				"imageCube",			"imageLoad(image, ivec3(0, 0, 0))",									1 },
628 		{ &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32I>,				"iimage_cube",				"iimageCube",			"vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",						1 },
629 		{ &create<GL_TEXTURE_CUBE_MAP, GL_RGBA32UI>,			"uimage_cube",				"uimageCube",			"vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",						1 },
630 		{ &create<GL_TEXTURE_2D_ARRAY, GL_RGBA8>,				"image_2d_array",			"image2DArray",			"imageLoad(image, ivec3(0, 0, 0))",									1 },
631 		{ &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32I>,				"iimage_2d_array",			"iimage2DArray",		"vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",						1 },
632 		{ &create<GL_TEXTURE_2D_ARRAY, GL_RGBA32UI>,			"uimage_2d_array",			"uimage2DArray",		"vec4(imageLoad(image, ivec3(0, 0, 0)))/255.0",						1 },
633 	};
634 
635 	// Additional array containing entries for core gl
636 	const SamplerCaseData coreArguments[] =
637 	{
638 		{ &create<GL_TEXTURE_BUFFER, GL_RGBA32F>,				"sampler_buffer",			"samplerBuffer",		"texelFetch(sampler, 1)",											0 },
639 		{ &create<GL_TEXTURE_BUFFER, GL_RGBA32I>,				"isampler_buffer",			"isamplerBuffer",		"vec4(texelFetch(sampler, 1))/255.0",								0 },
640 		{ &create<GL_TEXTURE_BUFFER, GL_RGBA32UI>,				"usampler_buffer",			"usamplerBuffer",		"vec4(texelFetch(sampler, 1))/255.0",								0 },
641 		{ &create<GL_TEXTURE_1D, GL_RGBA8>,						"sampler_1d",				"sampler1D",			"texture(sampler, coords.x)",										0 },
642 		{ &create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>,			"sampler_1d_shadow",		"sampler1DShadow",		"vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)",			0 },
643 		{ &create<GL_TEXTURE_1D_ARRAY, GL_RGBA8>,				"sampler_1d_array",			"sampler1DArray",		"texture(sampler, coords, 0.0)",									0 },
644 		{ &create<GL_TEXTURE_1D_ARRAY, GL_DEPTH_COMPONENT16>,	"sampler_1d_array_shadow",	"sampler1DArrayShadow",	"vec4(texture(sampler, vec3(coords, 0.0)), 0.0, 0.0, 0.0)",			0 },
645 	};
646 
647 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(commonArguments); ++i)
648 		addChild(new SpecifiedLocationCase(m_context, commonArguments[i]));
649 
650 	glu::RenderContext& renderContext = m_context.getRenderContext();
651 	glu::ContextType	contextType   = renderContext.getType();
652 	if (!glu::isContextTypeES(contextType))
653 	{
654 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(coreArguments); ++i)
655 			addChild(new SpecifiedLocationCase(m_context, coreArguments[i]));
656 	}
657 
658 	addChild(new NegativeLocationCase(m_context));
659 }
660 
661 } // glcts
662