Home | History | Annotate | Download | only in glshared
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL (ES) Module
      3  * -----------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      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 Texture buffer test case
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsTextureBufferCase.hpp"
     25 
     26 #include "tcuFormatUtil.hpp"
     27 #include "tcuImageCompare.hpp"
     28 #include "tcuRenderTarget.hpp"
     29 #include "tcuStringTemplate.hpp"
     30 #include "tcuSurface.hpp"
     31 #include "tcuTestLog.hpp"
     32 #include "tcuTextureUtil.hpp"
     33 
     34 #include "rrRenderer.hpp"
     35 #include "rrShaders.hpp"
     36 
     37 #include "gluObjectWrapper.hpp"
     38 #include "gluPixelTransfer.hpp"
     39 #include "gluShaderProgram.hpp"
     40 #include "gluShaderUtil.hpp"
     41 #include "gluStrUtil.hpp"
     42 #include "gluTexture.hpp"
     43 
     44 #include "glwEnums.hpp"
     45 #include "glwFunctions.hpp"
     46 
     47 #include "deRandom.hpp"
     48 #include "deStringUtil.hpp"
     49 #include "deUniquePtr.hpp"
     50 
     51 #include "deMemory.h"
     52 #include "deString.h"
     53 #include "deMath.h"
     54 
     55 #include <sstream>
     56 #include <string>
     57 #include <vector>
     58 
     59 using tcu::TestLog;
     60 
     61 using std::map;
     62 using std::string;
     63 using std::vector;
     64 
     65 using namespace deqp::gls::TextureBufferCaseUtil;
     66 
     67 namespace deqp
     68 {
     69 namespace gls
     70 {
     71 namespace
     72 {
     73 
     74 enum
     75 {
     76 	MAX_VIEWPORT_WIDTH	= 256,
     77 	MAX_VIEWPORT_HEIGHT	= 256,
     78 	MIN_VIEWPORT_WIDTH	= 64,
     79 	MIN_VIEWPORT_HEIGHT	= 64,
     80 };
     81 
     82 deUint8 extend2BitsToByte (deUint8 bits)
     83 {
     84 	deUint8 x = 0;
     85 
     86 	DE_ASSERT((bits & (~0x03u)) == 0);
     87 
     88 	x |= bits << 6;
     89 	x |= bits << 4;
     90 	x |= bits << 2;
     91 	x |= bits;
     92 
     93 	return x;
     94 }
     95 
     96 void genRandomCoords (de::Random rng, vector<deUint8>& coords, size_t offset, size_t size)
     97 {
     98 	const deUint8 bits		= 2;
     99 	const deUint8 bitMask	= deUint8((0x1u << bits) - 1);
    100 
    101 	coords.resize(size);
    102 
    103 	for (int i = 0; i < (int)size; i++)
    104 	{
    105 		const deUint8 xBits = deUint8(rng.getUint32() & bitMask);
    106 		coords[i] = extend2BitsToByte(xBits);
    107 	}
    108 
    109 	// Fill indices with nice quad
    110 	{
    111 		const deUint8 indices[] =
    112 		{
    113 			extend2BitsToByte(0x0u),
    114 			extend2BitsToByte(0x1u),
    115 			extend2BitsToByte(0x2u),
    116 			extend2BitsToByte(0x3u)
    117 		};
    118 
    119 		for (int i = 0; i < DE_LENGTH_OF_ARRAY(indices); i++)
    120 		{
    121 			const deUint8	index	= indices[i];
    122 			const size_t	posX	= (size_t(index) * 2) + 0;
    123 			const size_t	posY	= (size_t(index) * 2) + 1;
    124 
    125 			if (posX >= offset && posX < offset+size)
    126 				coords[posX - offset] = ((i % 2) == 0 ? extend2BitsToByte(0x0u) : extend2BitsToByte(0x3u));
    127 
    128 			if (posY >= offset && posY < offset+size)
    129 				coords[posY - offset] = ((i / 2) == 1 ? extend2BitsToByte(0x3u) : extend2BitsToByte(0x0u));
    130 		}
    131 	}
    132 
    133 	// Fill beginning of buffer
    134 	{
    135 		const deUint8 indices[] =
    136 		{
    137 			extend2BitsToByte(0x0u),
    138 			extend2BitsToByte(0x3u),
    139 			extend2BitsToByte(0x1u),
    140 
    141 			extend2BitsToByte(0x1u),
    142 			extend2BitsToByte(0x2u),
    143 			extend2BitsToByte(0x0u),
    144 
    145 			extend2BitsToByte(0x0u),
    146 			extend2BitsToByte(0x2u),
    147 			extend2BitsToByte(0x1u),
    148 
    149 			extend2BitsToByte(0x1u),
    150 			extend2BitsToByte(0x3u),
    151 			extend2BitsToByte(0x0u)
    152 		};
    153 
    154 		for (int i = (int)offset; i < DE_LENGTH_OF_ARRAY(indices) && i < (int)(offset + size); i++)
    155 			coords[i-offset] = indices[i];
    156 	}
    157 }
    158 
    159 class CoordVertexShader : public rr::VertexShader
    160 {
    161 public:
    162 	CoordVertexShader (void)
    163 		: rr::VertexShader(1, 1)
    164 	{
    165 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    166 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    167 	}
    168 
    169 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
    170 	{
    171 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
    172 		{
    173 			rr::VertexPacket* const		packet		= packets[packetNdx];
    174 			tcu::Vec4					position;
    175 
    176 			readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
    177 
    178 			packet->outputs[0]	= tcu::Vec4(1.0f);
    179 			packet->position	= tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
    180 		}
    181 	}
    182 };
    183 
    184 class TextureVertexShader : public rr::VertexShader
    185 {
    186 public:
    187 	TextureVertexShader (const tcu::ConstPixelBufferAccess& texture)
    188 		: rr::VertexShader	(1, 1)
    189 		, m_texture			(texture)
    190 	{
    191 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    192 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    193 	}
    194 
    195 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
    196 	{
    197 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
    198 		{
    199 			rr::VertexPacket* const		packet		= packets[packetNdx];
    200 			tcu::Vec4					position;
    201 			tcu::Vec4					texelValue;
    202 
    203 			readVertexAttrib(position, inputs[0], packet->instanceNdx, packet->vertexNdx);
    204 
    205 			texelValue	= tcu::Vec4(m_texture.getPixel(de::clamp<int>((deRoundFloatToInt32(position.x() * 4) + 4) * (deRoundFloatToInt32(position.y() * 4) + 4), 0, m_texture.getWidth()-1), 0));
    206 
    207 			packet->outputs[0]	= texelValue;
    208 			packet->position	= tcu::Vec4(2.0f * (position.x() - 0.5f), 2.0f * (position.y() - 0.5f), 0.0f, 1.0f);
    209 		}
    210 	}
    211 
    212 private:
    213 	const tcu::ConstPixelBufferAccess& m_texture;
    214 };
    215 
    216 class CoordFragmentShader : public rr::FragmentShader
    217 {
    218 public:
    219 	CoordFragmentShader (void)
    220 		: rr::FragmentShader (1, 1)
    221 	{
    222 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    223 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    224 	}
    225 
    226 
    227 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    228 	{
    229 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
    230 		{
    231 			rr::FragmentPacket&	packet		= packets[packetNdx];
    232 
    233 			const tcu::Vec4		vtxColor0	= rr::readVarying<float>(packet, context, 0, 0);
    234 			const tcu::Vec4		vtxColor1	= rr::readVarying<float>(packet, context, 0, 1);
    235 			const tcu::Vec4		vtxColor2	= rr::readVarying<float>(packet, context, 0, 2);
    236 			const tcu::Vec4		vtxColor3	= rr::readVarying<float>(packet, context, 0, 3);
    237 
    238 			const tcu::Vec4		color0		= vtxColor0;
    239 			const tcu::Vec4		color1		= vtxColor1;
    240 			const tcu::Vec4		color2		= vtxColor2;
    241 			const tcu::Vec4		color3		= vtxColor3;
    242 
    243 			rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
    244 			rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
    245 			rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
    246 			rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
    247 		}
    248 	}
    249 };
    250 
    251 class TextureFragmentShader : public rr::FragmentShader
    252 {
    253 public:
    254 	TextureFragmentShader (const tcu::ConstPixelBufferAccess& texture)
    255 		: rr::FragmentShader	(1, 1)
    256 		, m_texture				(texture)
    257 	{
    258 		m_inputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    259 		m_outputs[0].type	= rr::GENERICVECTYPE_FLOAT;
    260 	}
    261 
    262 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
    263 	{
    264 		for (int packetNdx = 0; packetNdx < numPackets; packetNdx++)
    265 		{
    266 			rr::FragmentPacket&	packet		= packets[packetNdx];
    267 
    268 			const tcu::IVec2	position	= packet.position;
    269 
    270 			const tcu::IVec2	position0	= packet.position + tcu::IVec2(0, 0);
    271 			const tcu::IVec2	position1	= packet.position + tcu::IVec2(1, 0);
    272 			const tcu::IVec2	position2	= packet.position + tcu::IVec2(0, 1);
    273 			const tcu::IVec2	position3	= packet.position + tcu::IVec2(1, 1);
    274 
    275 			const tcu::Vec4		texColor0	= m_texture.getPixel(de::clamp((position0.x() * position0.y()), 0, m_texture.getWidth()-1), 0);
    276 			const tcu::Vec4		texColor1	= m_texture.getPixel(de::clamp((position1.x() * position1.y()), 0, m_texture.getWidth()-1), 0);
    277 			const tcu::Vec4		texColor2	= m_texture.getPixel(de::clamp((position2.x() * position2.y()), 0, m_texture.getWidth()-1), 0);
    278 			const tcu::Vec4		texColor3	= m_texture.getPixel(de::clamp((position3.x() * position3.y()), 0, m_texture.getWidth()-1), 0);
    279 
    280 			const tcu::Vec4		vtxColor0	= rr::readVarying<float>(packet, context, 0, 0);
    281 			const tcu::Vec4		vtxColor1	= rr::readVarying<float>(packet, context, 0, 1);
    282 			const tcu::Vec4		vtxColor2	= rr::readVarying<float>(packet, context, 0, 2);
    283 			const tcu::Vec4		vtxColor3	= rr::readVarying<float>(packet, context, 0, 3);
    284 
    285 			const tcu::Vec4		color0		= 0.5f * (vtxColor0 + texColor0);
    286 			const tcu::Vec4		color1		= 0.5f * (vtxColor1 + texColor1);
    287 			const tcu::Vec4		color2		= 0.5f * (vtxColor2 + texColor2);
    288 			const tcu::Vec4		color3		= 0.5f * (vtxColor3 + texColor3);
    289 
    290 			rr::writeFragmentOutput(context, packetNdx, 0, 0, tcu::Vec4(color0.x() * color0.w(), color0.y() * color0.w(), color0.z() * color0.w(), 1.0f));
    291 			rr::writeFragmentOutput(context, packetNdx, 1, 0, tcu::Vec4(color1.x() * color1.w(), color1.y() * color1.w(), color1.z() * color1.w(), 1.0f));
    292 			rr::writeFragmentOutput(context, packetNdx, 2, 0, tcu::Vec4(color2.x() * color2.w(), color2.y() * color2.w(), color2.z() * color2.w(), 1.0f));
    293 			rr::writeFragmentOutput(context, packetNdx, 3, 0, tcu::Vec4(color3.x() * color3.w(), color3.y() * color3.w(), color3.z() * color3.w(), 1.0f));
    294 		}
    295 	}
    296 
    297 private:
    298 	const tcu::ConstPixelBufferAccess& m_texture;
    299 };
    300 
    301 string generateVertexShaderTemplate (RenderBits renderBits)
    302 {
    303 	std::ostringstream stream;
    304 
    305 	stream <<
    306 		"${VERSION_HEADER}\n";
    307 
    308 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
    309 		stream << "${TEXTURE_BUFFER_EXT}";
    310 
    311 	stream <<
    312 		"${VTX_INPUT} layout(location = 0) ${HIGHP} vec2 i_coord;\n"
    313 		"${VTX_OUTPUT} ${HIGHP} vec4 v_color;\n";
    314 
    315 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
    316 	{
    317 		stream <<
    318 			"uniform ${HIGHP} samplerBuffer u_vtxSampler;\n";
    319 	}
    320 
    321 	stream <<
    322 		"\n"
    323 		"void main (void)\n"
    324 		"{\n";
    325 
    326 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
    327 		stream << "\tv_color = texelFetch(u_vtxSampler, clamp((int(round(i_coord.x * 4.0)) + 4) * (int(round(i_coord.y * 4.0)) + 4), 0, textureSize(u_vtxSampler)-1));\n";
    328 	else
    329 		stream << "\tv_color = vec4(1.0);\n";
    330 
    331 	stream <<
    332 		"\tgl_Position = vec4(2.0 * (i_coord - vec2(0.5)), 0.0, 1.0);\n"
    333 		"}\n";
    334 
    335 	return stream.str();
    336 }
    337 
    338 string generateFragmentShaderTemplate (RenderBits renderBits)
    339 {
    340 	std::ostringstream stream;
    341 
    342 	stream <<
    343 		"${VERSION_HEADER}\n";
    344 
    345 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
    346 		stream << "${TEXTURE_BUFFER_EXT}";
    347 
    348 	stream <<
    349 		"${FRAG_OUTPUT} layout(location = 0) ${HIGHP} vec4 dEQP_FragColor;\n"
    350 		"${FRAG_INPUT} ${HIGHP} vec4 v_color;\n";
    351 
    352 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
    353 		stream << "uniform ${HIGHP} samplerBuffer u_fragSampler;\n";
    354 
    355 	stream <<
    356 		"\n"
    357 		"void main (void)\n"
    358 		"{\n";
    359 
    360 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
    361 		stream << "\t${HIGHP} vec4 color = 0.5 * (v_color + texelFetch(u_fragSampler, clamp(int(gl_FragCoord.x) * int(gl_FragCoord.y), 0, textureSize(u_fragSampler)-1)));\n";
    362 	else
    363 		stream << "\t${HIGHP} vec4 color = v_color;\n";
    364 
    365 	stream <<
    366 		"\tdEQP_FragColor = vec4(color.xyz * color.w, 1.0);\n"
    367 		"}\n";
    368 
    369 	return stream.str();
    370 }
    371 
    372 string specializeShader (const string& shaderTemplateString, glu::GLSLVersion glslVersion)
    373 {
    374 	const tcu::StringTemplate	shaderTemplate(shaderTemplateString);
    375 	map<string, string>			parameters;
    376 
    377 	parameters["VERSION_HEADER"]		= glu::getGLSLVersionDeclaration(glslVersion);
    378 	parameters["VTX_OUTPUT"]			= "out";
    379 	parameters["VTX_INPUT"]				= "in";
    380 	parameters["FRAG_INPUT"]			= "in";
    381 	parameters["FRAG_OUTPUT"]			= "out";
    382 	parameters["HIGHP"]					= (glslVersion == glu::GLSL_VERSION_330 ? "" : "highp");
    383 	parameters["TEXTURE_BUFFER_EXT"]	= (glslVersion == glu::GLSL_VERSION_330 ? "" : "#extension GL_EXT_texture_buffer : enable\n");
    384 
    385 	return shaderTemplate.specialize(parameters);
    386 }
    387 
    388 glu::ShaderProgram* createRenderProgram (glu::RenderContext&	renderContext,
    389 										 RenderBits				renderBits)
    390 {
    391 	const string				vertexShaderTemplate	= generateVertexShaderTemplate(renderBits);
    392 	const string				fragmentShaderTemplate	= generateFragmentShaderTemplate(renderBits);
    393 
    394 	const glu::GLSLVersion		glslVersion				= glu::getContextTypeGLSLVersion(renderContext.getType());
    395 
    396 	const string				vertexShaderSource		= specializeShader(vertexShaderTemplate, glslVersion);
    397 	const string				fragmentShaderSource	= specializeShader(fragmentShaderTemplate, glslVersion);
    398 
    399 	glu::ShaderProgram* const	program					= new glu::ShaderProgram(renderContext, glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
    400 
    401 	return program;
    402 }
    403 
    404 void logModifications (TestLog& log, ModifyBits modifyBits)
    405 {
    406 	tcu::ScopedLogSection section(log, "Modify Operations", "Modify Operations");
    407 
    408 	const struct
    409 	{
    410 		ModifyBits	bit;
    411 		const char*	str;
    412 	} bitInfos[] =
    413 	{
    414 		{ MODIFYBITS_BUFFERDATA,			"Recreate buffer data with glBufferData()."			},
    415 		{ MODIFYBITS_BUFFERSUBDATA,			"Modify texture buffer with glBufferSubData()."		},
    416 		{ MODIFYBITS_MAPBUFFER_WRITE,		"Map buffer write-only and rewrite data."			},
    417 		{ MODIFYBITS_MAPBUFFER_READWRITE,	"Map buffer readw-write check and rewrite data."	}
    418 	};
    419 
    420 	DE_ASSERT(modifyBits != 0);
    421 
    422 	for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
    423 	{
    424 		if (modifyBits & bitInfos[infoNdx].bit)
    425 			log << TestLog::Message << bitInfos[infoNdx].str << TestLog::EndMessage;
    426 	}
    427 }
    428 
    429 void modifyBufferData (TestLog&				log,
    430 					   de::Random&			rng,
    431 					   glu::TextureBuffer&	texture)
    432 {
    433 	vector<deUint8> data;
    434 
    435 	genRandomCoords(rng, data, 0, texture.getBufferSize());
    436 
    437 	log << TestLog::Message << "BufferData, Size: " << data.size() << TestLog::EndMessage;
    438 
    439 	texture.bufferData(&(data[0]), data.size());
    440 	texture.upload();
    441 }
    442 
    443 void modifyBufferSubData (TestLog&				log,
    444 						  de::Random&			rng,
    445 						  const glw::Functions&	gl,
    446 						  glu::TextureBuffer&	texture)
    447 {
    448 	const size_t				minSize		= 4*16;
    449 	const size_t				size		= de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
    450 	const size_t				minOffset	= texture.getOffset();
    451 	const size_t				offset		= minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
    452 	vector<deUint8>				data;
    453 
    454 	genRandomCoords(rng, data, offset, size);
    455 
    456 	log << TestLog::Message << "BufferSubData, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
    457 
    458 	gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
    459 	gl.bufferSubData(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)data.size(), &(data[0]));
    460 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    461 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glBufferSubData()");
    462 
    463 	deMemcpy(texture.getRefBuffer() + offset, &(data[0]), int(data.size()));
    464 }
    465 
    466 void modifyMapWrite (TestLog&				log,
    467 					 de::Random&			rng,
    468 					 const glw::Functions&	gl,
    469 					 glu::TextureBuffer&	texture)
    470 {
    471 	const size_t				minSize		= 4*16;
    472 	const size_t				size		= de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
    473 	const size_t				minOffset	= texture.getOffset();
    474 	const size_t				offset		= minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
    475 	vector<deUint8>				data;
    476 
    477 	genRandomCoords(rng, data, offset, size);
    478 
    479 	log << TestLog::Message << "glMapBufferRange, Write Only, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
    480 
    481 	gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
    482 	{
    483 		deUint8* ptr = (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT);
    484 
    485 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
    486 		TCU_CHECK(ptr);
    487 
    488 		for (int i = 0; i < (int)data.size(); i++)
    489 			ptr[i] = data[i];
    490 
    491 		TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
    492 	}
    493 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    494 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
    495 
    496 	deMemcpy(texture.getRefBuffer()+offset, &(data[0]), int(data.size()));
    497 }
    498 
    499 void modifyMapReadWrite (TestLog&				log,
    500 						 tcu::ResultCollector&	resultCollector,
    501 						 de::Random&			rng,
    502 						 const glw::Functions&	gl,
    503 						 glu::TextureBuffer&	texture)
    504 {
    505 	const size_t				minSize		= 4*16;
    506 	const size_t				size		= de::max<size_t>(minSize, size_t((texture.getSize() != 0 ? texture.getSize() : texture.getBufferSize()) * (0.7 + 0.3 * rng.getFloat())));
    507 	const size_t				minOffset	= texture.getOffset();
    508 	const size_t				offset		= minOffset + (rng.getUint32() % (texture.getBufferSize() - (size + minOffset)));
    509 	vector<deUint8>				data;
    510 
    511 	genRandomCoords(rng, data, offset, size);
    512 
    513 	log << TestLog::Message << "glMapBufferRange, Read Write, Offset: " << offset << ", Size: " << size << TestLog::EndMessage;
    514 
    515 	gl.bindBuffer(GL_TEXTURE_BUFFER, texture.getGLBuffer());
    516 	{
    517 		size_t			invalidBytes	= 0;
    518 		deUint8* const	ptr				= (deUint8*)gl.mapBufferRange(GL_TEXTURE_BUFFER, (glw::GLsizei)offset, (glw::GLsizei)size, GL_MAP_WRITE_BIT|GL_MAP_READ_BIT);
    519 
    520 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
    521 		TCU_CHECK(ptr);
    522 
    523 		for (int i = 0; i < (int)data.size(); i++)
    524 		{
    525 			if (ptr[i] != texture.getRefBuffer()[offset+i])
    526 			{
    527 				if (invalidBytes < 24)
    528 					log << TestLog::Message << "Invalid byte in mapped buffer. " << tcu::Format::Hex<2>(data[i]).toString() << " at " << i << ", expected " << tcu::Format::Hex<2>(texture.getRefBuffer()[i]).toString() << TestLog::EndMessage;
    529 
    530 				invalidBytes++;
    531 			}
    532 
    533 			ptr[i] = data[i];
    534 		}
    535 
    536 		TCU_CHECK(gl.unmapBuffer(GL_TEXTURE_BUFFER));
    537 
    538 		if (invalidBytes > 0)
    539 		{
    540 			log << TestLog::Message << "Total of " << invalidBytes << " invalid bytes." << TestLog::EndMessage;
    541 			resultCollector.fail("Invalid data in mapped buffer");
    542 		}
    543 	}
    544 
    545 	gl.bindBuffer(GL_TEXTURE_BUFFER, 0);
    546 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update data with glMapBufferRange()");
    547 
    548 	for (int i = 0; i < (int)data.size(); i++)
    549 		texture.getRefBuffer()[offset+i] = data[i];
    550 }
    551 
    552 void modify (TestLog&						log,
    553 			 tcu::ResultCollector&			resultCollector,
    554 			 glu::RenderContext&			renderContext,
    555 			 ModifyBits						modifyBits,
    556 			 de::Random&					rng,
    557 			 glu::TextureBuffer&			texture)
    558 {
    559 	const tcu::ScopedLogSection modifySection(log, "Modifying Texture buffer", "Modifying Texture Buffer");
    560 
    561 	logModifications(log, modifyBits);
    562 
    563 	if (modifyBits & MODIFYBITS_BUFFERDATA)
    564 		modifyBufferData(log, rng, texture);
    565 
    566 	if (modifyBits & MODIFYBITS_BUFFERSUBDATA)
    567 		modifyBufferSubData(log, rng, renderContext.getFunctions(), texture);
    568 
    569 	if (modifyBits & MODIFYBITS_MAPBUFFER_WRITE)
    570 		modifyMapWrite(log, rng, renderContext.getFunctions(), texture);
    571 
    572 	if (modifyBits & MODIFYBITS_MAPBUFFER_READWRITE)
    573 		modifyMapReadWrite(log, resultCollector, rng, renderContext.getFunctions(), texture);
    574 }
    575 
    576 void renderGL (glu::RenderContext&		renderContext,
    577 			   RenderBits				renderBits,
    578 			   deUint32					coordSeed,
    579 			   int						triangleCount,
    580 			   glu::ShaderProgram&		program,
    581 			   glu::TextureBuffer&		texture)
    582 {
    583 	const glw::Functions&	gl			= renderContext.getFunctions();
    584 	const glu::VertexArray	vao			(renderContext);
    585 	const glu::Buffer		coordBuffer	(renderContext);
    586 
    587 	gl.useProgram(program.getProgram());
    588 	gl.bindVertexArray(*vao);
    589 
    590 	gl.enableVertexAttribArray(0);
    591 
    592 	if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
    593 	{
    594 		gl.bindBuffer(GL_ARRAY_BUFFER, texture.getGLBuffer());
    595 		gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
    596 	}
    597 	else
    598 	{
    599 		de::Random		rng(coordSeed);
    600 		vector<deUint8> coords;
    601 
    602 		genRandomCoords(rng, coords, 0, 256*2);
    603 
    604 		gl.bindBuffer(GL_ARRAY_BUFFER, *coordBuffer);
    605 		gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)coords.size(), &(coords[0]), GL_STREAM_DRAW);
    606 		gl.vertexAttribPointer(0, 2, GL_UNSIGNED_BYTE, true, 0, DE_NULL);
    607 	}
    608 
    609 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
    610 	{
    611 		const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_vtxSampler");
    612 
    613 		gl.activeTexture(GL_TEXTURE0);
    614 		gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
    615 		gl.uniform1i(location, 0);
    616 	}
    617 
    618 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
    619 	{
    620 		const deInt32 location = gl.getUniformLocation(program.getProgram(), "u_fragSampler");
    621 
    622 		gl.activeTexture(GL_TEXTURE1);
    623 		gl.bindTexture(GL_TEXTURE_BUFFER, texture.getGLTexture());
    624 		gl.uniform1i(location, 1);
    625 		gl.activeTexture(GL_TEXTURE0);
    626 	}
    627 
    628 	if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
    629 	{
    630 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, texture.getGLBuffer());
    631 		gl.drawElements(GL_TRIANGLES, triangleCount * 3, GL_UNSIGNED_BYTE, DE_NULL);
    632 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    633 	}
    634 	else
    635 		gl.drawArrays(GL_TRIANGLES, 0, triangleCount * 3);
    636 
    637 	if (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE)
    638 	{
    639 		gl.activeTexture(GL_TEXTURE1);
    640 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
    641 	}
    642 
    643 	if (renderBits & RENDERBITS_AS_VERTEX_TEXTURE)
    644 	{
    645 		gl.activeTexture(GL_TEXTURE0);
    646 		gl.bindTexture(GL_TEXTURE_BUFFER, 0);
    647 	}
    648 
    649 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    650 	gl.disableVertexAttribArray(0);
    651 
    652 	gl.bindVertexArray(0);
    653 	gl.useProgram(0);
    654 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
    655 }
    656 
    657 void renderReference (RenderBits					renderBits,
    658 					  deUint32						coordSeed,
    659 					  int							triangleCount,
    660 					  glu::TextureBuffer&			texture,
    661 					  const tcu::PixelBufferAccess&	target)
    662 {
    663 	const CoordVertexShader			coordVertexShader;
    664 	const TextureVertexShader		textureVertexShader		(texture.getRefTexture());
    665 	const rr::VertexShader* const	vertexShader			= (renderBits & RENDERBITS_AS_VERTEX_TEXTURE ? static_cast<const rr::VertexShader*>(&textureVertexShader) : &coordVertexShader);
    666 
    667 	const CoordFragmentShader		coordFragmmentShader;
    668 	const TextureFragmentShader		textureFragmentShader	(texture.getRefTexture());
    669 	const rr::FragmentShader* const	fragmentShader			= (renderBits & RENDERBITS_AS_FRAGMENT_TEXTURE ? static_cast<const rr::FragmentShader*>(&textureFragmentShader) : &coordFragmmentShader);
    670 
    671 	const rr::Renderer				renderer;
    672 	const rr::RenderState			renderState(rr::ViewportState(rr::WindowRectangle(0, 0, target.getWidth(), target.getHeight())));
    673 	const rr::RenderTarget			renderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(target));
    674 
    675 	const rr::Program				program(vertexShader, fragmentShader);
    676 
    677 	rr::VertexAttrib				vertexAttribs[1];
    678 	vector<deUint8>					coords;
    679 
    680 	if (renderBits & RENDERBITS_AS_VERTEX_ARRAY)
    681 	{
    682 		vertexAttribs[0].type			= rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
    683 		vertexAttribs[0].size			= 2;
    684 		vertexAttribs[0].pointer		= texture.getRefBuffer();
    685 	}
    686 	else
    687 	{
    688 		de::Random rng(coordSeed);
    689 
    690 		genRandomCoords(rng, coords, 0, 256*2);
    691 
    692 		vertexAttribs[0].type			= rr::VERTEXATTRIBTYPE_NONPURE_UNORM8;
    693 		vertexAttribs[0].size			= 2;
    694 		vertexAttribs[0].pointer		= &(coords[0]);
    695 	}
    696 
    697 	if (renderBits & RENDERBITS_AS_INDEX_ARRAY)
    698 	{
    699 		const rr::PrimitiveList	primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, rr::DrawIndices((const void*)texture.getRefBuffer(), rr::INDEXTYPE_UINT8));
    700 		const rr::DrawCommand	cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
    701 
    702 		renderer.draw(cmd);
    703 	}
    704 	else
    705 	{
    706 		const rr::PrimitiveList	primitives(rr::PRIMITIVETYPE_TRIANGLES, triangleCount * 3, 0);
    707 		const rr::DrawCommand	cmd(renderState, renderTarget, program, 1, vertexAttribs, primitives);
    708 
    709 		renderer.draw(cmd);
    710 	}
    711 }
    712 
    713 void logRendering (TestLog& log, RenderBits renderBits)
    714 {
    715 	const struct
    716 	{
    717 		RenderBits	bit;
    718 		const char*	str;
    719 	} bitInfos[] =
    720 	{
    721 		{ RENDERBITS_AS_VERTEX_ARRAY,		"vertex array"		},
    722 		{ RENDERBITS_AS_INDEX_ARRAY,		"index array"		},
    723 		{ RENDERBITS_AS_VERTEX_TEXTURE,		"vertex texture"	},
    724 		{ RENDERBITS_AS_FRAGMENT_TEXTURE,	"fragment texture"	}
    725 	};
    726 
    727 	std::ostringstream	stream;
    728 	vector<const char*> usedAs;
    729 
    730 	DE_ASSERT(renderBits != 0);
    731 
    732 	for (int infoNdx = 0; infoNdx < DE_LENGTH_OF_ARRAY(bitInfos); infoNdx++)
    733 	{
    734 		if (renderBits & bitInfos[infoNdx].bit)
    735 			usedAs.push_back(bitInfos[infoNdx].str);
    736 	}
    737 
    738 	stream << "Render using texture buffer as ";
    739 
    740 	for (int asNdx = 0; asNdx < (int)usedAs.size(); asNdx++)
    741 	{
    742 		if (asNdx+1 == (int)usedAs.size() && (int)usedAs.size() > 1)
    743 			stream << " and ";
    744 		else if (asNdx > 0)
    745 			stream << ", ";
    746 
    747 		stream << usedAs[asNdx];
    748 	}
    749 
    750 	stream << ".";
    751 
    752 	log << TestLog::Message << stream.str() << TestLog::EndMessage;
    753 }
    754 
    755 void render (TestLog&						log,
    756 			 glu::RenderContext&			renderContext,
    757 			 RenderBits						renderBits,
    758 			 de::Random&					rng,
    759 			 glu::ShaderProgram&			program,
    760 			 glu::TextureBuffer&			texture,
    761 			 const tcu::PixelBufferAccess&	target)
    762 {
    763 	const tcu::ScopedLogSection	renderSection	(log, "Render Texture buffer", "Render Texture Buffer");
    764 	const int					triangleCount	= 8;
    765 	const deUint32				coordSeed		= rng.getUint32();
    766 
    767 	logRendering(log, renderBits);
    768 
    769 	renderGL(renderContext, renderBits, coordSeed, triangleCount, program, texture);
    770 	renderReference(renderBits, coordSeed, triangleCount, texture, target);
    771 }
    772 
    773 void verifyScreen (TestLog&								log,
    774 				   tcu::ResultCollector&				resultCollector,
    775 				   glu::RenderContext&					renderContext,
    776 				   const tcu::ConstPixelBufferAccess&	referenceTarget)
    777 {
    778 	const tcu::ScopedLogSection	verifySection	(log, "Verify screen contents", "Verify screen contents");
    779 	tcu::Surface				screen			(referenceTarget.getWidth(), referenceTarget.getHeight());
    780 
    781 	glu::readPixels(renderContext, 0, 0, screen.getAccess());
    782 
    783 	if (!tcu::fuzzyCompare(log, "Result of rendering", "Result of rendering", referenceTarget, screen.getAccess(), 0.05f, tcu::COMPARE_LOG_RESULT))
    784 		resultCollector.fail("Rendering failed");
    785 }
    786 
    787 void logImplementationInfo (TestLog& log, glu::RenderContext& renderContext)
    788 {
    789 	const tcu::ScopedLogSection		section	(log, "Implementation Values", "Implementation Values");
    790 	de::UniquePtr<glu::ContextInfo>	info	(glu::ContextInfo::create(renderContext));
    791 	const glw::Functions&			gl		= renderContext.getFunctions();
    792 
    793 	if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE)))
    794 	{
    795 		deInt32 maxTextureSize;
    796 
    797 		gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
    798 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE)");
    799 
    800 		log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE : " <<  maxTextureSize << TestLog::EndMessage;
    801 	}
    802 	else if (glu::contextSupports(renderContext.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer"))
    803 	{
    804 		{
    805 			deInt32 maxTextureSize;
    806 
    807 			gl.getIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureSize);
    808 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE_EXT)");
    809 
    810 			log << TestLog::Message << "GL_MAX_TEXTURE_BUFFER_SIZE_EXT : " <<  maxTextureSize << TestLog::EndMessage;
    811 		}
    812 
    813 		{
    814 			deInt32 textureBufferAlignment;
    815 
    816 			gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &textureBufferAlignment);
    817 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT)");
    818 
    819 			log << TestLog::Message << "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT : " <<  textureBufferAlignment << TestLog::EndMessage;
    820 		}
    821 	}
    822 	else
    823 		DE_ASSERT(DE_FALSE);
    824 }
    825 
    826 void logTextureInfo (TestLog&	log,
    827 					 deUint32	format,
    828 					 size_t		bufferSize,
    829 					 size_t		offset,
    830 					 size_t		size)
    831 {
    832 	const tcu::ScopedLogSection	section(log, "Texture Info", "Texture Info");
    833 
    834 	log << TestLog::Message << "Texture format : " << glu::getPixelFormatStr(format) << TestLog::EndMessage;
    835 	log << TestLog::Message << "Buffer size : " << bufferSize << TestLog::EndMessage;
    836 
    837 	if (offset != 0 || size != 0)
    838 	{
    839 		log << TestLog::Message << "Buffer range offset: " << offset << TestLog::EndMessage;
    840 		log << TestLog::Message << "Buffer range size: " << size << TestLog::EndMessage;
    841 	}
    842 }
    843 
    844 void runTests (tcu::TestContext&	testCtx,
    845 			   glu::RenderContext&	renderContext,
    846 			   de::Random&			rng,
    847 			   deUint32				format,
    848 			   size_t				bufferSize,
    849 			   size_t				offset,
    850 			   size_t				size,
    851 			   RenderBits			preRender,
    852 			   glu::ShaderProgram*	preRenderProgram,
    853 			   ModifyBits			modifyType,
    854 			   RenderBits			postRender,
    855 			   glu::ShaderProgram*	postRenderProgram)
    856 {
    857 	const tcu::RenderTarget	renderTarget	(renderContext.getRenderTarget());
    858 	const glw::Functions&	gl				= renderContext.getFunctions();
    859 
    860 	const int				width			= de::min<int>(renderTarget.getWidth(), MAX_VIEWPORT_WIDTH);
    861 	const int				height			= de::min<int>(renderTarget.getHeight(), MAX_VIEWPORT_HEIGHT);
    862 	const tcu::Vec4			clearColor		(0.25f, 0.5f, 0.75f, 1.0f);
    863 
    864 	TestLog&				log				= testCtx.getLog();
    865 	tcu::ResultCollector	resultCollector	(log);
    866 
    867 	logImplementationInfo(log, renderContext);
    868 	logTextureInfo(log, format, bufferSize, offset, size);
    869 
    870 	{
    871 		tcu::Surface			referenceTarget	(width, height);
    872 		vector<deUint8>			bufferData;
    873 
    874 		genRandomCoords(rng, bufferData, 0, bufferSize);
    875 
    876 		for (deUint8 i = 0; i < 4; i++)
    877 		{
    878 			const deUint8 val = extend2BitsToByte(i);
    879 
    880 			if (val >= offset && val < offset + size)
    881 			{
    882 				bufferData[val*2 + 0] = (i / 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
    883 				bufferData[val*2 + 1] = (i % 2 == 0 ? extend2BitsToByte(0x2u) : extend2BitsToByte(0x01u));
    884 			}
    885 		}
    886 
    887 		{
    888 			glu::TextureBuffer texture (renderContext, format, bufferSize, offset, size, &(bufferData[0]));
    889 
    890 			TCU_CHECK_MSG(width >= MIN_VIEWPORT_WIDTH || height >= MIN_VIEWPORT_HEIGHT, "Too small viewport");
    891 
    892 			DE_ASSERT(preRender == 0 || preRenderProgram);
    893 			DE_ASSERT(postRender == 0 || postRenderProgram);
    894 
    895 			gl.viewport(0, 0, width, height);
    896 			gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
    897 			gl.clear(GL_COLOR_BUFFER_BIT);
    898 			GLU_EXPECT_NO_ERROR(gl.getError(), "Screen setup failed");
    899 
    900 			tcu::clear(referenceTarget.getAccess(), clearColor);
    901 
    902 			texture.upload();
    903 
    904 			if (preRender != 0)
    905 				render(log, renderContext, preRender, rng, *preRenderProgram, texture, referenceTarget.getAccess());
    906 
    907 			if (modifyType != 0)
    908 				modify(log, resultCollector, renderContext, modifyType, rng, texture);
    909 
    910 			if (postRender != 0)
    911 				render(log, renderContext, postRender, rng, *postRenderProgram, texture, referenceTarget.getAccess());
    912 		}
    913 
    914 		verifyScreen(log, resultCollector, renderContext, referenceTarget.getAccess());
    915 
    916 		resultCollector.setTestContextResult(testCtx);
    917 	}
    918 }
    919 
    920 } // anonymous
    921 
    922 TextureBufferCase::TextureBufferCase (tcu::TestContext&		testCtx,
    923 									  glu::RenderContext&	renderCtx,
    924 									  deUint32				format,
    925 									  size_t				bufferSize,
    926 									  size_t				offset,
    927 									  size_t				size,
    928 									  RenderBits			preRender,
    929 									  ModifyBits			modify,
    930 									  RenderBits			postRender,
    931 									  const char*			name,
    932 									  const char*			description)
    933 	: tcu::TestCase				(testCtx, name, description)
    934 	, m_renderCtx				(renderCtx)
    935 	, m_format					(format)
    936 	, m_bufferSize				(bufferSize)
    937 	, m_offset					(offset)
    938 	, m_size					(size)
    939 
    940 	, m_preRender				(preRender)
    941 	, m_modify					(modify)
    942 	, m_postRender				(postRender)
    943 
    944 	, m_preRenderProgram		(DE_NULL)
    945 	, m_postRenderProgram		(DE_NULL)
    946 {
    947 }
    948 
    949 TextureBufferCase::~TextureBufferCase (void)
    950 {
    951 	TextureBufferCase::deinit();
    952 }
    953 
    954 void TextureBufferCase::init (void)
    955 {
    956 	de::UniquePtr<glu::ContextInfo> info (glu::ContextInfo::create(m_renderCtx));
    957 
    958 	if (!glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 3, glu::PROFILE_CORE))
    959 		&& !(glu::contextSupports(m_renderCtx.getType(), glu::ApiType(3, 1, glu::PROFILE_ES)) && info->isExtensionSupported("GL_EXT_texture_buffer")))
    960 		throw tcu::NotSupportedError("Texture buffers not supported", "", __FILE__, __LINE__);
    961 
    962 	if (m_preRender != 0)
    963 	{
    964 		TestLog&					log			= m_testCtx.getLog();
    965 		const char* const			sectionName	= (m_postRender != 0 ? "Primary render program" : "Render program");
    966 		const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
    967 
    968 		m_preRenderProgram = createRenderProgram(m_renderCtx, m_preRender);
    969 		m_testCtx.getLog() << (*m_preRenderProgram);
    970 
    971 		TCU_CHECK(m_preRenderProgram->isOk());
    972 	}
    973 
    974 	if (m_postRender != 0)
    975 	{
    976 		// Reusing program
    977 		if (m_preRender == m_postRender)
    978 		{
    979 			m_postRenderProgram = m_preRenderProgram;
    980 		}
    981 		else
    982 		{
    983 			TestLog&					log			= m_testCtx.getLog();
    984 			const char* const			sectionName	= (m_preRender!= 0 ? "Secondary render program" : "Render program");
    985 			const tcu::ScopedLogSection	section		(log, sectionName, sectionName);
    986 
    987 			m_postRenderProgram = createRenderProgram(m_renderCtx, m_postRender);
    988 			m_testCtx.getLog() << (*m_postRenderProgram);
    989 
    990 			TCU_CHECK(m_postRenderProgram->isOk());
    991 		}
    992 	}
    993 }
    994 
    995 void TextureBufferCase::deinit (void)
    996 {
    997 	if (m_preRenderProgram == m_postRenderProgram)
    998 		m_postRenderProgram = DE_NULL;
    999 
   1000 	delete m_preRenderProgram;
   1001 	m_preRenderProgram = DE_NULL;
   1002 
   1003 	delete m_postRenderProgram;
   1004 	m_postRenderProgram = DE_NULL;
   1005 }
   1006 
   1007 tcu::TestCase::IterateResult TextureBufferCase::iterate (void)
   1008 {
   1009 	de::Random	rng		(deInt32Hash(deStringHash(getName())));
   1010 	size_t		offset;
   1011 
   1012 	if (m_offset != 0)
   1013 	{
   1014 		const glw::Functions&	gl			= m_renderCtx.getFunctions();
   1015 		deInt32					alignment	= 0;
   1016 
   1017 		gl.getIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT, &alignment);
   1018 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)");
   1019 
   1020 		offset = m_offset * alignment;
   1021 	}
   1022 	else
   1023 		offset = 0;
   1024 
   1025 	runTests(m_testCtx, m_renderCtx, rng, m_format, m_bufferSize, offset, m_size, m_preRender, m_preRenderProgram, m_modify, m_postRender, m_postRenderProgram);
   1026 
   1027 	return STOP;
   1028 }
   1029 
   1030 } // gls
   1031 } // deqp
   1032