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 Memory object stress test
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsMemoryStressCase.hpp"
     25 #include "gluShaderProgram.hpp"
     26 #include "tcuTestLog.hpp"
     27 #include "tcuCommandLine.hpp"
     28 #include "deRandom.hpp"
     29 #include "deClock.h"
     30 #include "deString.h"
     31 
     32 #include "glw.h"
     33 
     34 #include <vector>
     35 #include <iostream>
     36 
     37 using std::vector;
     38 using tcu::TestLog;
     39 
     40 namespace deqp
     41 {
     42 namespace gls
     43 {
     44 
     45 static const char* glErrorToString (deUint32 error)
     46 {
     47 	switch (error)
     48 	{
     49 		case GL_OUT_OF_MEMORY:
     50 			return "GL_OUT_OF_MEMORY";
     51 			break;
     52 
     53 		case GL_INVALID_ENUM:
     54 			return "GL_INVALID_ENUM";
     55 			break;
     56 
     57 		case GL_INVALID_FRAMEBUFFER_OPERATION:
     58 			return "GL_INVALID_FRAMEBUFFER_OPERATION";
     59 			break;
     60 
     61 		case GL_INVALID_OPERATION:
     62 			return "GL_INVALID_OPERATION";
     63 			break;
     64 
     65 		case GL_INVALID_VALUE:
     66 			return "GL_INVALID_VALUE";
     67 			break;
     68 
     69 		case 0:
     70 			return "<none>";
     71 			break;
     72 
     73 		default:
     74 			// \todo [mika] Handle uknown errors?
     75 			DE_ASSERT(false);
     76 			return NULL;
     77 			break;
     78 	}
     79 }
     80 
     81 static const float s_quadCoords[] =
     82 {
     83 	-1.0f, -1.0f,
     84 	 1.0f, -1.0f,
     85 	 1.0f,  1.0f,
     86 	-1.0f,  1.0f
     87 };
     88 
     89 static const GLubyte s_quadIndices[] =
     90 {
     91 	0, 1, 2,
     92 	2, 3, 0
     93 };
     94 
     95 class TextureRenderer
     96 {
     97 public:
     98 			TextureRenderer		(tcu::TestLog& log, glu::RenderContext& renderContext);
     99 			~TextureRenderer	(void);
    100 	void	render				(deUint32 texture);
    101 
    102 private:
    103 	glu::ShaderProgram*	m_program;
    104 	glu::RenderContext&	m_renderCtx;
    105 
    106 	deUint32			m_coordBuffer;
    107 	deUint32			m_indexBuffer;
    108 	deUint32			m_vao;
    109 
    110 	static const char*	s_vertexShaderGLES2;
    111 	static const char*	s_fragmentShaderGLES2;
    112 
    113 	static const char*	s_vertexShaderGLES3;
    114 	static const char*	s_fragmentShaderGLES3;
    115 
    116 	static const char*	s_vertexShaderGL3;
    117 	static const char*	s_fragmentShaderGL3;
    118 };
    119 
    120 const char* TextureRenderer::s_vertexShaderGLES2 =
    121 "attribute mediump vec2 a_coord;\n"
    122 "varying mediump vec2 v_texCoord;\n"
    123 "void main (void)\n"
    124 "{\n"
    125 "\tv_texCoord = 0.5 * (a_coord + vec2(1.0));\n"
    126 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
    127 "}\n";
    128 
    129 const char* TextureRenderer::s_fragmentShaderGLES2 =
    130 "varying mediump vec2 v_texCoord;\n"
    131 "uniform sampler2D u_texture;\n"
    132 "void main (void)\n"
    133 "{\n"
    134 "\tgl_FragColor = texture2D(u_texture, v_texCoord);\n"
    135 "}\n";
    136 
    137 const char* TextureRenderer::s_vertexShaderGLES3 =
    138 "#version 300 es\n"
    139 "in mediump vec2 a_coord;\n"
    140 "out mediump vec2 v_texCoord;\n"
    141 "void main (void)\n"
    142 "{\n"
    143 "\tv_texCoord = 0.5 * (a_coord + vec2(1.0));\n"
    144 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
    145 "}\n";
    146 
    147 const char* TextureRenderer::s_fragmentShaderGLES3 =
    148 "#version 300 es\n"
    149 "in mediump vec2 v_texCoord;\n"
    150 "uniform sampler2D u_texture;\n"
    151 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
    152 "void main (void)\n"
    153 "{\n"
    154 "\tdEQP_FragColor = texture(u_texture, v_texCoord);\n"
    155 "}\n";
    156 
    157 const char* TextureRenderer::s_vertexShaderGL3 =
    158 "#version 330\n"
    159 "in mediump vec2 a_coord;\n"
    160 "out mediump vec2 v_texCoord;\n"
    161 "void main (void)\n"
    162 "{\n"
    163 "\tv_texCoord = 0.5 * (a_coord + vec2(1.0));\n"
    164 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
    165 "}\n";
    166 
    167 const char* TextureRenderer::s_fragmentShaderGL3 =
    168 "#version 330\n"
    169 "in mediump vec2 v_texCoord;\n"
    170 "uniform sampler2D u_texture;\n"
    171 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
    172 "void main (void)\n"
    173 "{\n"
    174 "\tdEQP_FragColor = texture(u_texture, v_texCoord);\n"
    175 "}\n";
    176 
    177 TextureRenderer::TextureRenderer (tcu::TestLog& log, glu::RenderContext& renderContext)
    178 	: m_program		(NULL)
    179 	, m_renderCtx	(renderContext)
    180 	, m_coordBuffer	(0)
    181 	, m_indexBuffer	(0)
    182 	, m_vao			(0)
    183 {
    184 	const glu::ContextType ctxType = renderContext.getType();
    185 
    186 	if (glu::isGLSLVersionSupported(ctxType, glu::GLSL_VERSION_300_ES))
    187 		m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(s_vertexShaderGLES3, s_fragmentShaderGLES3));
    188 	else if (glu::isGLSLVersionSupported(ctxType, glu::GLSL_VERSION_100_ES))
    189 		m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(s_vertexShaderGLES2, s_fragmentShaderGLES2));
    190 	else if (glu::isGLSLVersionSupported(ctxType, glu::GLSL_VERSION_330))
    191 		m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(s_vertexShaderGL3, s_fragmentShaderGL3));
    192 	else
    193 		DE_ASSERT(false);
    194 
    195 	if (ctxType.getProfile() == glu::PROFILE_CORE)
    196 		GLU_CHECK_CALL(glGenVertexArrays(1, &m_vao));
    197 
    198 	GLU_CHECK_CALL(glGenBuffers(1, &m_coordBuffer));
    199 	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_coordBuffer));
    200 	GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(s_quadCoords), s_quadCoords, GL_STATIC_DRAW));
    201 
    202 	GLU_CHECK_CALL(glGenBuffers(1, &m_indexBuffer));
    203 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer));
    204 	GLU_CHECK_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s_quadIndices), s_quadIndices, GL_STATIC_DRAW));
    205 
    206 	if (!m_program->isOk())
    207 	{
    208 		log << *m_program;
    209 		TCU_CHECK_MSG(m_program->isOk(), "Shader compilation failed");
    210 	}
    211 }
    212 
    213 TextureRenderer::~TextureRenderer (void)
    214 {
    215 	delete m_program;
    216 	glDeleteBuffers(1, &m_coordBuffer);
    217 	glDeleteBuffers(1, &m_indexBuffer);
    218 }
    219 
    220 void TextureRenderer::render (deUint32 texture)
    221 {
    222 	deUint32 coordLoc = -1;
    223 	deUint32 texLoc	= -1;
    224 
    225 	GLU_CHECK_CALL(glUseProgram(m_program->getProgram()));
    226 
    227 	coordLoc = glGetAttribLocation(m_program->getProgram(), "a_coord");
    228 	GLU_CHECK();
    229 	TCU_CHECK(coordLoc != (deUint32)-1);
    230 
    231 	if (m_vao != 0)
    232 		GLU_CHECK_CALL(glBindVertexArray(m_vao));
    233 
    234 	GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
    235 
    236 	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_coordBuffer));
    237 	GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL));
    238 
    239 	GLU_CHECK_CALL(glActiveTexture(GL_TEXTURE0));
    240 	GLU_CHECK_CALL(glBindTexture(GL_TEXTURE_2D, texture));
    241 
    242 	texLoc = glGetUniformLocation(m_program->getProgram(), "u_texture");
    243 	GLU_CHECK();
    244 	TCU_CHECK(texLoc != (deUint32)-1);
    245 
    246 	GLU_CHECK_CALL(glUniform1i(texLoc, 0));
    247 
    248 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer));
    249 	GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, NULL));
    250 
    251 	GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
    252 
    253 	if (m_vao != 0)
    254 		GLU_CHECK_CALL(glBindVertexArray(0));
    255 }
    256 
    257 class BufferRenderer
    258 {
    259 public:
    260 			BufferRenderer	(tcu::TestLog& log, glu::RenderContext& renderContext);
    261 			~BufferRenderer	(void);
    262 	void	render			(deUint32 buffer, int size);
    263 
    264 private:
    265 	glu::ShaderProgram*	m_program;
    266 	glu::RenderContext&	m_renderCtx;
    267 
    268 	deUint32			m_coordBuffer;
    269 	deUint32			m_indexBuffer;
    270 	deUint32			m_vao;
    271 
    272 	static const char*	s_vertexShaderGLES2;
    273 	static const char*	s_fragmentShaderGLES2;
    274 
    275 	static const char*	s_vertexShaderGLES3;
    276 	static const char*	s_fragmentShaderGLES3;
    277 
    278 	static const char*	s_vertexShaderGL3;
    279 	static const char*	s_fragmentShaderGL3;
    280 };
    281 
    282 const char* BufferRenderer::s_vertexShaderGLES2 =
    283 "attribute mediump vec2 a_coord;\n"
    284 "attribute mediump vec4 a_buffer;\n"
    285 "varying mediump vec4 v_buffer;\n"
    286 "void main (void)\n"
    287 "{\n"
    288 "\tv_buffer = a_buffer;\n"
    289 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
    290 "}\n";
    291 
    292 const char* BufferRenderer::s_fragmentShaderGLES2 =
    293 "varying mediump vec4 v_buffer;\n"
    294 "void main (void)\n"
    295 "{\n"
    296 "\tgl_FragColor = v_buffer;\n"
    297 "}\n";
    298 
    299 const char* BufferRenderer::s_vertexShaderGLES3 =
    300 "#version 300 es\n"
    301 "in mediump vec2 a_coord;\n"
    302 "in mediump vec4 a_buffer;\n"
    303 "out mediump vec4 v_buffer;\n"
    304 "void main (void)\n"
    305 "{\n"
    306 "\tv_buffer = a_buffer;\n"
    307 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
    308 "}\n";
    309 
    310 const char* BufferRenderer::s_fragmentShaderGLES3 =
    311 "#version 300 es\n"
    312 "in mediump vec4 v_buffer;\n"
    313 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
    314 "void main (void)\n"
    315 "{\n"
    316 "\tdEQP_FragColor = v_buffer;\n"
    317 "}\n";
    318 
    319 const char* BufferRenderer::s_vertexShaderGL3 =
    320 "#version 330\n"
    321 "in mediump vec2 a_coord;\n"
    322 "in mediump vec4 a_buffer;\n"
    323 "out mediump vec4 v_buffer;\n"
    324 "void main (void)\n"
    325 "{\n"
    326 "\tv_buffer = a_buffer;\n"
    327 "\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
    328 "}\n";
    329 
    330 const char* BufferRenderer::s_fragmentShaderGL3 =
    331 "#version 330\n"
    332 "in mediump vec4 v_buffer;\n"
    333 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
    334 "void main (void)\n"
    335 "{\n"
    336 "\tdEQP_FragColor = v_buffer;\n"
    337 "}\n";
    338 
    339 BufferRenderer::BufferRenderer (tcu::TestLog& log, glu::RenderContext& renderContext)
    340 	: m_program		(NULL)
    341 	, m_renderCtx	(renderContext)
    342 	, m_coordBuffer	(0)
    343 	, m_indexBuffer	(0)
    344 	, m_vao			(0)
    345 {
    346 	const glu::ContextType ctxType = renderContext.getType();
    347 
    348 	if (glu::isGLSLVersionSupported(ctxType, glu::GLSL_VERSION_300_ES))
    349 		m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(s_vertexShaderGLES3, s_fragmentShaderGLES3));
    350 	else if (glu::isGLSLVersionSupported(ctxType, glu::GLSL_VERSION_100_ES))
    351 		m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(s_vertexShaderGLES2, s_fragmentShaderGLES2));
    352 	else if (glu::isGLSLVersionSupported(ctxType, glu::GLSL_VERSION_330))
    353 		m_program = new glu::ShaderProgram(m_renderCtx, glu::makeVtxFragSources(s_vertexShaderGL3, s_fragmentShaderGL3));
    354 	else
    355 		DE_ASSERT(false);
    356 
    357 	if (ctxType.getProfile() == glu::PROFILE_CORE)
    358 		GLU_CHECK_CALL(glGenVertexArrays(1, &m_vao));
    359 
    360 	GLU_CHECK_CALL(glGenBuffers(1, &m_coordBuffer));
    361 	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_coordBuffer));
    362 	GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, sizeof(s_quadCoords), s_quadCoords, GL_STATIC_DRAW));
    363 
    364 	GLU_CHECK_CALL(glGenBuffers(1, &m_indexBuffer));
    365 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer));
    366 	GLU_CHECK_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(s_quadIndices), s_quadIndices, GL_STATIC_DRAW));
    367 
    368 	if (!m_program->isOk())
    369 	{
    370 		log << *m_program;
    371 		TCU_CHECK_MSG(m_program->isOk(), "Shader compilation failed");
    372 	}
    373 }
    374 
    375 BufferRenderer::~BufferRenderer (void)
    376 {
    377 	delete m_program;
    378 	glDeleteBuffers(1, &m_coordBuffer);
    379 	glDeleteBuffers(1, &m_indexBuffer);
    380 }
    381 
    382 void BufferRenderer::render (deUint32 buffer, int size)
    383 {
    384 	DE_UNREF(size);
    385 	DE_ASSERT((size_t)size >= sizeof(GLubyte) * 4 * 6);
    386 	GLU_CHECK_CALL(glUseProgram(m_program->getProgram()));
    387 
    388 	deUint32 bufferLoc = glGetAttribLocation(m_program->getProgram(), "a_buffer");
    389 	TCU_CHECK(bufferLoc != (deUint32)-1);
    390 
    391 	deUint32 coordLoc = glGetAttribLocation(m_program->getProgram(), "a_coord");
    392 	TCU_CHECK(coordLoc != (deUint32)-1);
    393 
    394 	if (m_vao != 0)
    395 		GLU_CHECK_CALL(glBindVertexArray(m_vao));
    396 
    397 	GLU_CHECK_CALL(glEnableVertexAttribArray(bufferLoc));
    398 	GLU_CHECK_CALL(glEnableVertexAttribArray(coordLoc));
    399 
    400 	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_coordBuffer));
    401 	GLU_CHECK_CALL(glVertexAttribPointer(coordLoc, 2, GL_FLOAT, GL_FALSE, 0, NULL));
    402 
    403 	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
    404 	GLU_CHECK_CALL(glVertexAttribPointer(bufferLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0));
    405 	GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
    406 
    407 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer));
    408 	GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, NULL));
    409 
    410 	GLU_CHECK_CALL(glDisableVertexAttribArray(bufferLoc));
    411 	GLU_CHECK_CALL(glDisableVertexAttribArray(coordLoc));
    412 
    413 	if (m_vao != 0)
    414 		GLU_CHECK_CALL(glBindVertexArray(0));
    415 }
    416 
    417 class MemObjectAllocator
    418 {
    419 public:
    420 	enum Result
    421 	{
    422 		RESULT_GOT_BAD_ALLOC = 0,
    423 		RESULT_GEN_TEXTURES_FAILED,
    424 		RESULT_GEN_BUFFERS_FAILED,
    425 		RESULT_BUFFER_DATA_FAILED,
    426 		RESULT_BUFFER_SUB_DATA_FAILED,
    427 		RESULT_TEXTURE_IMAGE_FAILED,
    428 		RESULT_TEXTURE_SUB_IMAGE_FAILED,
    429 		RESULT_BIND_TEXTURE_FAILED,
    430 		RESULT_BIND_BUFFER_FAILED,
    431 		RESULT_DELETE_TEXTURES_FAILED,
    432 		RESULT_DELETE_BUFFERS_FAILED,
    433 		RESULT_RENDER_FAILED,
    434 
    435 		RESULT_LAST
    436 	};
    437 
    438 						MemObjectAllocator	(tcu::TestLog& log, glu::RenderContext& renderContext, MemObjectType objectTypes, const MemObjectConfig& config, int seed);
    439 						~MemObjectAllocator	(void);
    440 	bool				allocUntilFailure	(void);
    441 	void				clearObjects		(void);
    442 	Result				getResult			(void) const { return m_result; }
    443 	deUint32			getGLError			(void) const { return m_glError; }
    444 	int					getObjectCount		(void) const { return m_objectCount; }
    445 	deUint32			getBytes			(void) const { return m_bytesRequired; }
    446 
    447 	static const char*	resultToString		(Result result);
    448 
    449 private:
    450 
    451 	void				allocateTexture		(de::Random& rnd);
    452 	void				allocateBuffer		(de::Random& rnd);
    453 
    454 	vector<deUint32>	m_buffers;
    455 	vector<deUint32>	m_textures;
    456 	int					m_seed;
    457 	int					m_objectCount;
    458 	deUint32			m_bytesRequired;
    459 	MemObjectType		m_objectTypes;
    460 	Result				m_result;
    461 	MemObjectConfig		m_config;
    462 	deUint32			m_glError;
    463 	vector<deUint8>		m_dummyData;
    464 	BufferRenderer		m_bufferRenderer;
    465 	TextureRenderer		m_textureRenderer;
    466 };
    467 
    468 MemObjectAllocator::MemObjectAllocator (tcu::TestLog& log, glu::RenderContext& renderContext, MemObjectType objectTypes, const MemObjectConfig& config, int seed)
    469 	: m_seed			(seed)
    470 	, m_objectCount		(0)
    471 	, m_bytesRequired	(0)
    472 	, m_objectTypes		(objectTypes)
    473 	, m_result			(RESULT_LAST)
    474 	, m_config			(config)
    475 	, m_glError			(0)
    476 	, m_bufferRenderer	(log, renderContext)
    477 	, m_textureRenderer	(log, renderContext)
    478 {
    479 	DE_UNREF(renderContext);
    480 
    481 	if (m_config.useDummyData)
    482 	{
    483 		int dummySize = deMax32(m_config.maxBufferSize, m_config.maxTextureSize*m_config.maxTextureSize*4);
    484 		m_dummyData = vector<deUint8>(dummySize);
    485 	}
    486 	else if (m_config.write)
    487 		m_dummyData = vector<deUint8>(128);
    488 }
    489 
    490 MemObjectAllocator::~MemObjectAllocator (void)
    491 {
    492 }
    493 
    494 bool MemObjectAllocator::allocUntilFailure (void)
    495 {
    496 	de::Random rnd(m_seed);
    497 	GLU_CHECK_MSG("Error in init");
    498 	try
    499 	{
    500 		const deUint64	timeoutUs	= 10000000; // 10s
    501 		deUint64		beginTimeUs	= deGetMicroseconds();
    502 		deUint64		currentTimeUs;
    503 
    504 		do
    505 		{
    506 			GLU_CHECK_MSG("Unkown Error");
    507 			switch (m_objectTypes)
    508 			{
    509 				case MEMOBJECTTYPE_TEXTURE:
    510 					allocateTexture(rnd);
    511 					break;
    512 
    513 				case MEMOBJECTTYPE_BUFFER:
    514 					allocateBuffer(rnd);
    515 					break;
    516 
    517 				default:
    518 				{
    519 					if (rnd.getBool())
    520 						allocateBuffer(rnd);
    521 					else
    522 						allocateTexture(rnd);
    523 					break;
    524 				}
    525 			}
    526 
    527 			if (m_result != RESULT_LAST)
    528 			{
    529 				glFinish();
    530 				return true;
    531 			}
    532 
    533 			currentTimeUs = deGetMicroseconds();
    534 		} while (currentTimeUs - beginTimeUs < timeoutUs);
    535 
    536 		// Timeout
    537 		if (currentTimeUs - beginTimeUs >= timeoutUs)
    538 			return false;
    539 		else
    540 			return true;
    541 	}
    542 	catch (const std::bad_alloc&)
    543 	{
    544 		m_result = RESULT_GOT_BAD_ALLOC;
    545 		return true;
    546 	}
    547 }
    548 
    549 void MemObjectAllocator::clearObjects (void)
    550 {
    551 	deUint32 error = 0;
    552 
    553 	if (!m_textures.empty())
    554 	{
    555 		glDeleteTextures((GLsizei)m_textures.size(), &(m_textures[0]));
    556 		error = glGetError();
    557 		if (error != 0)
    558 		{
    559 			m_result	= RESULT_DELETE_TEXTURES_FAILED;
    560 			m_glError	= error;
    561 		}
    562 
    563 		m_textures.clear();
    564 	}
    565 
    566 	if (!m_buffers.empty())
    567 	{
    568 		glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0]));
    569 		error = glGetError();
    570 		if (error != 0)
    571 		{
    572 			m_result	= RESULT_DELETE_BUFFERS_FAILED;
    573 			m_glError	= error;
    574 		}
    575 
    576 		m_buffers.clear();
    577 	}
    578 }
    579 
    580 void MemObjectAllocator::allocateTexture (de::Random& rnd)
    581 {
    582 	const int	vectorBlockSize = 128;
    583 	deUint32	tex		= 0;
    584 	deUint32	error	= 0;
    585 	int			width	= rnd.getInt(m_config.minTextureSize, m_config.maxTextureSize);
    586 	int			height	= rnd.getInt(m_config.minTextureSize, m_config.maxTextureSize);
    587 
    588 	glGenTextures(1, &tex);
    589 	error = glGetError();
    590 	if (error != 0)
    591 	{
    592 		m_result	= RESULT_GEN_TEXTURES_FAILED;
    593 		m_glError	= error;
    594 		return;
    595 	}
    596 
    597 	if (m_textures.size() % vectorBlockSize == 0)
    598 		m_textures.reserve(m_textures.size() + vectorBlockSize);
    599 
    600 	m_textures.push_back(tex);
    601 
    602 	glBindTexture(GL_TEXTURE_2D, tex);
    603 	error = glGetError();
    604 	if (error != 0)
    605 	{
    606 		m_result	= RESULT_BIND_TEXTURE_FAILED;
    607 		m_glError	= error;
    608 		return;
    609 	}
    610 
    611 	if (m_config.useDummyData)
    612 	{
    613 		DE_ASSERT((int)m_dummyData.size() >= width*height*4);
    614 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(m_dummyData[0]));
    615 	}
    616 	else
    617 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    618 
    619 	error = glGetError();
    620 	if (error != 0)
    621 	{
    622 		m_result	= RESULT_TEXTURE_IMAGE_FAILED;
    623 		m_glError	= error;
    624 		return;
    625 	}
    626 
    627 	if (m_config.write)
    628 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &(m_dummyData[0]));
    629 
    630 	error = glGetError();
    631 	if (error != 0)
    632 	{
    633 		m_result	= RESULT_TEXTURE_SUB_IMAGE_FAILED;
    634 		m_glError	= error;
    635 		return;
    636 	}
    637 
    638 	if (m_config.use)
    639 	{
    640 		try
    641 		{
    642 			m_textureRenderer.render(tex);
    643 		}
    644 		catch (const glu::Error& err)
    645 		{
    646 			m_result	= RESULT_RENDER_FAILED;
    647 			m_glError	= err.getError();
    648 			return;
    649 		}
    650 		catch (const glu::OutOfMemoryError&)
    651 		{
    652 			m_result	= RESULT_RENDER_FAILED;
    653 			m_glError	= GL_OUT_OF_MEMORY;
    654 			return;
    655 		}
    656 	}
    657 
    658 	glBindTexture(GL_TEXTURE_2D, 0);
    659 	error = glGetError();
    660 	if (error != 0)
    661 	{
    662 		m_result	= RESULT_BIND_TEXTURE_FAILED;
    663 		m_glError	= error;
    664 		return;
    665 	}
    666 
    667 	m_objectCount++;
    668 	m_bytesRequired += width*height*4;
    669 }
    670 
    671 void MemObjectAllocator::allocateBuffer (de::Random& rnd)
    672 {
    673 	const int	vectorBlockSize = 128;
    674 	deUint32	buffer			= 0;
    675 	deUint32	error			= 0;
    676 	int			size			= rnd.getInt(m_config.minBufferSize, m_config.maxBufferSize);
    677 
    678 	glGenBuffers(1, &buffer);
    679 	error = glGetError();
    680 	if (error != 0)
    681 	{
    682 		m_result	= RESULT_GEN_BUFFERS_FAILED;
    683 		m_glError	= error;
    684 		return;
    685 	}
    686 
    687 	glBindBuffer(GL_ARRAY_BUFFER, buffer);
    688 	error = glGetError();
    689 	if (error != 0)
    690 	{
    691 		m_result	= RESULT_BIND_BUFFER_FAILED;
    692 		m_glError	= error;
    693 		return;
    694 	}
    695 
    696 	if (m_buffers.size() % vectorBlockSize == 0)
    697 		m_buffers.reserve(m_buffers.size() + vectorBlockSize);
    698 
    699 	m_buffers.push_back(buffer);
    700 
    701 	if (m_config.useDummyData)
    702 	{
    703 		DE_ASSERT((int)m_dummyData.size() >= size);
    704 		glBufferData(GL_ARRAY_BUFFER, size, &(m_dummyData[0]), GL_DYNAMIC_DRAW);
    705 	}
    706 	else
    707 		glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
    708 
    709 	error = glGetError();
    710 	if (error != 0)
    711 	{
    712 		m_result	= RESULT_BUFFER_DATA_FAILED;
    713 		m_glError	= error;
    714 		return;
    715 	}
    716 
    717 	if (m_config.write)
    718 		glBufferSubData(GL_ARRAY_BUFFER, 0, 1, &(m_dummyData[0]));
    719 
    720 	error = glGetError();
    721 	if (error != 0)
    722 	{
    723 		m_result	= RESULT_BUFFER_SUB_DATA_FAILED;
    724 		m_glError	= error;
    725 		return;
    726 	}
    727 
    728 	if (m_config.use)
    729 	{
    730 		try
    731 		{
    732 			m_bufferRenderer.render(buffer, size);
    733 		}
    734 		catch (const glu::Error& err)
    735 		{
    736 			m_result	= RESULT_RENDER_FAILED;
    737 			m_glError	= err.getError();
    738 			return;
    739 		}
    740 		catch (const glu::OutOfMemoryError&)
    741 		{
    742 			m_result	= RESULT_RENDER_FAILED;
    743 			m_glError	= GL_OUT_OF_MEMORY;
    744 			return;
    745 		}
    746 	}
    747 
    748 	glBindBuffer(GL_ARRAY_BUFFER, 0);
    749 	error = glGetError();
    750 	if (error != 0)
    751 	{
    752 		m_result	= RESULT_BIND_BUFFER_FAILED;
    753 		m_glError	= error;
    754 		return;
    755 	}
    756 
    757 	m_objectCount++;
    758 	m_bytesRequired += size;
    759 }
    760 
    761 const char* MemObjectAllocator::resultToString (Result result)
    762 {
    763 	switch (result)
    764 	{
    765 		case RESULT_GOT_BAD_ALLOC:
    766 			return "Caught std::bad_alloc";
    767 			break;
    768 
    769 		case RESULT_GEN_TEXTURES_FAILED:
    770 			return "glGenTextures failed";
    771 			break;
    772 
    773 		case RESULT_GEN_BUFFERS_FAILED:
    774 			return "glGenBuffers failed";
    775 			break;
    776 
    777 		case RESULT_BUFFER_DATA_FAILED:
    778 			return "glBufferData failed";
    779 			break;
    780 
    781 		case RESULT_BUFFER_SUB_DATA_FAILED:
    782 			return "glBufferSubData failed";
    783 			break;
    784 
    785 		case RESULT_TEXTURE_IMAGE_FAILED:
    786 			return "glTexImage2D failed";
    787 			break;
    788 
    789 		case RESULT_TEXTURE_SUB_IMAGE_FAILED:
    790 			return "glTexSubImage2D failed";
    791 			break;
    792 
    793 		case RESULT_BIND_TEXTURE_FAILED:
    794 			return "glBindTexture failed";
    795 			break;
    796 
    797 		case RESULT_BIND_BUFFER_FAILED:
    798 			return "glBindBuffer failed";
    799 			break;
    800 
    801 		case RESULT_DELETE_TEXTURES_FAILED:
    802 			return "glDeleteTextures failed";
    803 			break;
    804 
    805 		case RESULT_DELETE_BUFFERS_FAILED:
    806 			return "glDeleteBuffers failed";
    807 			break;
    808 
    809 		case RESULT_RENDER_FAILED:
    810 			return "Rendering result failed";
    811 			break;
    812 
    813 		default:
    814 			DE_ASSERT(false);
    815 			return NULL;
    816 	}
    817 }
    818 
    819 MemoryStressCase::MemoryStressCase (tcu::TestContext& ctx, glu::RenderContext& renderContext, deUint32 objectTypes, int minTextureSize, int maxTextureSize, int minBufferSize, int maxBufferSize, bool write, bool use, bool useDummyData, bool clearAfterOOM, const char* name, const char* desc)
    820 	: tcu::TestCase					(ctx, name, desc)
    821 	, m_iteration					(0)
    822 	, m_iterationCount				(5)
    823 	, m_objectTypes					((MemObjectType)objectTypes)
    824 	, m_zeroAlloc					(false)
    825 	, m_clearAfterOOM				(clearAfterOOM)
    826 	, m_renderCtx					(renderContext)
    827 {
    828 	m_allocated.reserve(m_iterationCount);
    829 	m_config.maxTextureSize = maxTextureSize;
    830 	m_config.minTextureSize = minTextureSize;
    831 	m_config.maxBufferSize	= maxBufferSize;
    832 	m_config.minBufferSize	= minBufferSize;
    833 	m_config.useDummyData	= useDummyData;
    834 	m_config.write			= write;
    835 	m_config.use			= use;
    836 }
    837 
    838 MemoryStressCase::~MemoryStressCase (void)
    839 {
    840 }
    841 
    842 void MemoryStressCase::init (void)
    843 {
    844 	if (!m_testCtx.getCommandLine().isOutOfMemoryTestEnabled())
    845 	{
    846 		m_testCtx.getLog() << TestLog::Message << "Tests that exhaust memory are disabled, use --deqp-test-oom=enable command line option to enable." << TestLog::EndMessage;
    847 		throw tcu::NotSupportedError("OOM tests disabled");
    848 	}
    849 }
    850 
    851 void MemoryStressCase::deinit (void)
    852 {
    853 	TCU_CHECK(!m_zeroAlloc);
    854 }
    855 
    856 tcu::TestCase::IterateResult MemoryStressCase::iterate (void)
    857 {
    858 	bool			end		= false;
    859 	tcu::TestLog&	log		= m_testCtx.getLog();
    860 
    861 	MemObjectAllocator allocator(log, m_renderCtx, m_objectTypes, m_config, deStringHash(getName()));
    862 
    863 	if (!allocator.allocUntilFailure())
    864 	{
    865 		// Allocation timed out
    866 		allocator.clearObjects();
    867 
    868 		log << TestLog::Message << "Timeout. Couldn't exhaust memory in timelimit. Allocated " << allocator.getObjectCount() << " objects." << TestLog::EndMessage;
    869 
    870 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    871 		return STOP;
    872 	}
    873 
    874 	// Try to cancel rendering operations
    875 	if (m_clearAfterOOM)
    876 		GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT));
    877 
    878 	allocator.clearObjects();
    879 
    880 	m_allocated.push_back(allocator.getObjectCount());
    881 
    882 	if (m_iteration != 0  && allocator.getObjectCount() == 0)
    883 		m_zeroAlloc = true;
    884 
    885 	log << TestLog::Message << "Got error when allocation object count: " << allocator.getObjectCount() << " bytes: " << allocator.getBytes() << TestLog::EndMessage;
    886 
    887 	if ((allocator.getGLError() == 0) && (allocator.getResult() == MemObjectAllocator::RESULT_GOT_BAD_ALLOC))
    888 	{
    889 		log << TestLog::Message << "std::bad_alloc" << TestLog::EndMessage;
    890 		end = true;
    891 		m_testCtx.setTestResult(QP_TEST_RESULT_RESOURCE_ERROR, "Memory allocation failed");
    892 	}
    893 	else if (allocator.getGLError() != GL_OUT_OF_MEMORY)
    894 	{
    895 		log << TestLog::Message << "Invalid Error " << MemObjectAllocator::resultToString(allocator.getResult())
    896 			<< " GLError: " << glErrorToString(allocator.getGLError()) <<
    897 		TestLog::EndMessage;
    898 
    899 		end = true;
    900 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    901 	}
    902 
    903 	if ((m_iteration+1) == m_iterationCount)
    904 	{
    905 		int min = m_allocated[0];
    906 		int max = m_allocated[0];
    907 
    908 		float threshold = 50.0f;
    909 
    910 		for (int allocNdx = 0; allocNdx < (int)m_allocated.size(); allocNdx++)
    911 		{
    912 			min = deMin32(m_allocated[allocNdx], min);
    913 			max = deMax32(m_allocated[allocNdx], max);
    914 		}
    915 
    916 		if (min == 0 && max != 0)
    917 		{
    918 			log << TestLog::Message << "Allocation count zero" << TestLog::EndMessage;
    919 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    920 		}
    921 		else
    922 		{
    923 			const float change = (min - max) / ((float)(max));
    924 			if (change > threshold)
    925 			{
    926 				log << TestLog::Message << "Allocated objects max: " << max << ", min: " << min << ", difference: " << change << "% threshold: " << threshold << "%" << TestLog::EndMessage;
    927 				m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Allocation count variation");
    928 			}
    929 			else
    930 				m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    931 		}
    932 		end = true;
    933 	}
    934 
    935 	GLU_CHECK_CALL(glFinish());
    936 
    937 	m_iteration++;
    938 	if (end)
    939 		return STOP;
    940 	else
    941 		return CONTINUE;
    942 }
    943 
    944 } // gls
    945 } // deqp
    946