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