Home | History | Annotate | Download | only in common
      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
     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>
     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 
     83 	ResultData(deUint32 tId) : textureId(tId), bufferId(0)
     84 	{
     85 	}
     86 
     87 	ResultData(deUint32 tId, deUint32 bId) : textureId(tId), bufferId(bId)
     88 	{
     89 	}
     90 };
     91 
     92 template <typename DATA_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>
    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>
    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>
    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>
    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>
    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>
    191 ResultData create(const Functions& gl)
    192 {
    193 	(void)gl;
    194 	TCU_FAIL("Missing specialization implementation.");
    195 }
    196 
    197 template <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    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 <>
    294 ResultData create<GL_TEXTURE_1D, GL_DEPTH_COMPONENT16>(const Functions& gl)
    295 {
    296 	return createTexture1D<unsigned char>(gl, 1, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
    297 }
    298 
    299 template <>
    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 <>
    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 <>
    313 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32F>(const Functions& gl)
    314 {
    315 	return createTextureBuffer<float>(gl, GL_RGBA32F);
    316 }
    317 
    318 template <>
    319 ResultData create<GL_TEXTURE_BUFFER, GL_RGBA32I>(const Functions& gl)
    320 {
    321 	return createTextureBuffer<int>(gl, GL_RGBA32I);
    322 }
    323 
    324 template <>
    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 
    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 
    397 SpecifiedLocationCase::~SpecifiedLocationCase()
    398 {
    399 }
    400 
    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 
    548 NegativeLocationCase::NegativeLocationCase(deqp::Context& context) : deqp::TestCase(context, "invalid_cases", "")
    549 {
    550 }
    551 
    552 NegativeLocationCase::~NegativeLocationCase()
    553 {
    554 }
    555 
    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 
    593 LayoutLocationTests::LayoutLocationTests(Context& context) : TestCaseGroup(context, "layout_location", "")
    594 {
    595 }
    596 
    597 LayoutLocationTests::~LayoutLocationTests(void)
    598 {
    599 }
    600 
    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