Home | History | Annotate | Download | only in texture_buffer
      1 /*-------------------------------------------------------------------------
      2  * OpenGL Conformance Test Suite
      3  * -----------------------------
      4  *
      5  * Copyright (c) 2014-2016 The Khronos Group Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  */ /*!
     20  * \file
     21  * \brief
     22  */ /*-------------------------------------------------------------------*/
     23 
     24 /*!
     25  * \file  esextcTextureBufferOperations.cpp
     26  * \brief Texture Buffer Operations (Test 1)
     27  */ /*-------------------------------------------------------------------*/
     28 
     29 #include "esextcTextureBufferOperations.hpp"
     30 #include "gluContextInfo.hpp"
     31 #include "gluDefs.hpp"
     32 #include "glwEnums.hpp"
     33 #include "glwFunctions.hpp"
     34 #include "tcuTestLog.hpp"
     35 #include <cstring>
     36 #include <iostream>
     37 #include <vector>
     38 
     39 namespace glcts
     40 {
     41 
     42 const glw::GLuint TextureBufferOperations::m_n_vector_components = 4;
     43 
     44 /** Constructor
     45  *
     46  *  @param context     Test context
     47  *  @param name        Test case's name
     48  *  @param description Test case's description
     49  **/
     50 TextureBufferOperations::TextureBufferOperations(Context& context, const ExtParameters& extParams, const char* name,
     51 												 const char* description)
     52 	: TestCaseBase(context, extParams, name, description)
     53 	, m_n_vectors_in_buffer_texture(0)
     54 	, m_tb_bo_id(0)
     55 	, m_texbuff_id(0)
     56 	, m_cs_id(0)
     57 	, m_po_cs_id(0)
     58 	, m_ssbo_bo_id(0)
     59 	, m_fbo_id(0)
     60 	, m_fs_id(0)
     61 	, m_po_vs_fs_id(0)
     62 	, m_to_id(0)
     63 	, m_vao_id(0)
     64 	, m_vbo_id(0)
     65 	, m_vbo_indicies_id(0)
     66 	, m_vs_id(0)
     67 	, m_vertex_location(-1)
     68 	, m_index_location(-1)
     69 {
     70 	/* Nothing to be done here */
     71 }
     72 
     73 /** Initializes GLES objects used during the test.
     74  *
     75  */
     76 void TextureBufferOperations::initTest(void)
     77 {
     78 	/* Check if texture buffer extension is supported */
     79 	if (!m_is_texture_buffer_supported)
     80 	{
     81 		throw tcu::NotSupportedError(TEXTURE_BUFFER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
     82 	}
     83 
     84 	/* Get GL entry points */
     85 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
     86 
     87 	gl.getIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &m_n_vectors_in_buffer_texture);
     88 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting GL_MAX_COMPUTE_WORK_GROUP_SIZE parameter value!");
     89 
     90 	/* Create buffer object*/
     91 	gl.genBuffers(1, &m_tb_bo_id);
     92 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
     93 
     94 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, m_tb_bo_id);
     95 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object !");
     96 
     97 	gl.bufferData(m_glExtTokens.TEXTURE_BUFFER,
     98 				  m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), 0, GL_DYNAMIC_DRAW);
     99 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating data store for buffer object!");
    100 
    101 	/* Create texture buffer */
    102 	gl.genTextures(1, &m_texbuff_id);
    103 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
    104 
    105 	gl.activeTexture(GL_TEXTURE0);
    106 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active texture unit!");
    107 
    108 	gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, m_texbuff_id);
    109 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
    110 
    111 	gl.texBuffer(m_glExtTokens.TEXTURE_BUFFER, GL_RGBA32I, m_tb_bo_id);
    112 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object to texture buffer!");
    113 
    114 	/* Initialize texture buffer object */
    115 	initializeBufferObjectData();
    116 
    117 	/* Initialize first phase */
    118 	initFirstPhase();
    119 
    120 	/* Initialize second phase */
    121 	initSecondPhase();
    122 }
    123 
    124 void TextureBufferOperations::initFirstPhase(void)
    125 {
    126 	/* Get GL entry points */
    127 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    128 
    129 	/* Create program object */
    130 	m_po_cs_id = gl.createProgram();
    131 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
    132 
    133 	m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
    134 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating shader object!");
    135 
    136 	std::string csSource = getComputeShaderCode();
    137 	const char* csCode   = csSource.c_str();
    138 
    139 	if (!buildProgram(m_po_cs_id, m_cs_id, 1, &csCode))
    140 	{
    141 		TCU_FAIL("Could not create a program from valid compute shader code!");
    142 	}
    143 
    144 	/* Create Shader Storage Buffer Object */
    145 	gl.genBuffers(1, &m_ssbo_bo_id);
    146 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
    147 	gl.bindBuffer(GL_ARRAY_BUFFER, m_ssbo_bo_id);
    148 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding  buffer object!");
    149 	gl.bufferData(GL_ARRAY_BUFFER, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), 0,
    150 				  GL_DYNAMIC_DRAW);
    151 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating data store for buffer object!");
    152 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    153 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding  buffer object!");
    154 }
    155 
    156 /** Returns Compute shader Code
    157  *
    158  * @return pointer to literal with Compute Shader Code
    159  */
    160 std::string TextureBufferOperations::getComputeShaderCode() const
    161 {
    162 	std::stringstream strstream;
    163 
    164 	strstream << "${VERSION}\n"
    165 				 "\n"
    166 				 "${TEXTURE_BUFFER_REQUIRE}\n"
    167 				 "\n"
    168 				 "precision highp float;\n"
    169 				 "\n"
    170 				 "layout(rgba32i, binding = 0) uniform readonly highp iimageBuffer image_buffer;\n"
    171 				 "\n"
    172 				 "buffer ComputeSSBO\n"
    173 				 "{\n"
    174 				 "    ivec4 value[];\n"
    175 				 "} computeSSBO;\n"
    176 				 "\n"
    177 				 "layout (local_size_x = "
    178 			  << m_n_vectors_in_buffer_texture << " ) in;\n"
    179 												  "\n"
    180 												  "void main(void)\n"
    181 												  "{\n"
    182 												  "    int index = int(gl_LocalInvocationID.x);\n"
    183 												  "    computeSSBO.value[index] = imageLoad( image_buffer, index);\n"
    184 												  "}\n";
    185 
    186 	return strstream.str();
    187 }
    188 
    189 void TextureBufferOperations::initSecondPhase(void)
    190 {
    191 	/* Get GL entry points */
    192 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    193 
    194 	/* Create vertex array object */
    195 	gl.genVertexArrays(1, &m_vao_id);
    196 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
    197 
    198 	/* Create framebuffer object */
    199 	gl.genFramebuffers(1, &m_fbo_id);
    200 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing framebuffer object!");
    201 
    202 	/* Prepare texture object */
    203 	gl.genTextures(1, &m_to_id);
    204 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing texture buffer!");
    205 
    206 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
    207 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
    208 
    209 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32I, m_n_vectors_in_buffer_texture /* width */, 1 /* height */);
    210 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's texel data!");
    211 
    212 	/* Set GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER parameters values to GL_NEAREST*/
    213 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    214 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for GL_TEXTURE_MAG_FILTER parameter!");
    215 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    216 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for GL_TEXTURE_MIN_FILTER parameter!");
    217 
    218 	gl.bindTexture(GL_TEXTURE_2D, 0);
    219 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
    220 
    221 	/* Create program object */
    222 	m_po_vs_fs_id = gl.createProgram();
    223 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
    224 
    225 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
    226 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
    227 
    228 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
    229 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
    230 
    231 	std::string fsSource = getFragmentShaderCode();
    232 	std::string vsSource = getVertexShaderCode();
    233 
    234 	const char* fsCode = fsSource.c_str();
    235 	const char* vsCode = vsSource.c_str();
    236 
    237 	if (!buildProgram(m_po_vs_fs_id, m_fs_id, 1, &fsCode, m_vs_id, 1, &vsCode))
    238 	{
    239 		TCU_FAIL("Could not create a program from valid vertex/fragment shader source!");
    240 	}
    241 
    242 	/* Full screen quad */
    243 	glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
    244 								1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
    245 
    246 	/* Generate buffer object */
    247 	gl.genBuffers(1, &m_vbo_id);
    248 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
    249 	/* Bind buffer object */
    250 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
    251 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
    252 	/* Set data for buffer object */
    253 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    254 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting data for buffer object!");
    255 
    256 	/* Indicies */
    257 	glw::GLfloat indicies[] = { 0.f, 0.f, static_cast<glw::GLfloat>(m_n_vectors_in_buffer_texture) * 1.f,
    258 								static_cast<glw::GLfloat>(m_n_vectors_in_buffer_texture) * 1.f };
    259 
    260 	/* Generate buffer object */
    261 	gl.genBuffers(1, &m_vbo_indicies_id);
    262 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
    263 	/* Bind buffer object */
    264 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_indicies_id);
    265 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
    266 	/* Set data for buffer object */
    267 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);
    268 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error seting data for buffer object!");
    269 
    270 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    271 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
    272 }
    273 
    274 /** Returns Fragment Shader Code
    275  *
    276  * @return pointer to literal with Fragment Shader Code
    277  */
    278 std::string TextureBufferOperations::getFragmentShaderCode() const
    279 {
    280 	std::stringstream strstream;
    281 
    282 	strstream << "${VERSION}\n"
    283 				 "\n"
    284 				 "${TEXTURE_BUFFER_REQUIRE}\n"
    285 				 "\n"
    286 				 "precision highp float;\n"
    287 				 "\n"
    288 				 "in float fs_index;\n"
    289 				 "\n"
    290 				 "layout(location = 0) out ivec4 color;\n"
    291 				 "\n"
    292 				 "uniform highp isamplerBuffer sampler_buffer;\n"
    293 				 "\n"
    294 				 "void main(void)\n"
    295 				 "{\n"
    296 				 "    color = texelFetch( sampler_buffer, int(fs_index) );\n "
    297 				 "}\n";
    298 
    299 	return strstream.str();
    300 }
    301 
    302 /** Returns Vertex Shader Code
    303  *
    304  * @return pointer to literal with Vertex Shader Code
    305  */
    306 std::string TextureBufferOperations::getVertexShaderCode() const
    307 {
    308 	std::stringstream strstream;
    309 
    310 	strstream << "${VERSION}\n"
    311 				 "\n"
    312 				 "${TEXTURE_BUFFER_REQUIRE}\n"
    313 				 "\n"
    314 				 "precision highp float;\n"
    315 				 "\n"
    316 				 "in vec4 vs_position;\n"
    317 				 "in float  vs_index;\n"
    318 				 "\n"
    319 				 "out float fs_index;\n"
    320 				 "\n"
    321 				 "void main(void)\n"
    322 				 "{\n"
    323 				 "    gl_Position = vs_position;\n"
    324 				 "    fs_index    = vs_index;\n"
    325 				 "}\n";
    326 
    327 	return strstream.str();
    328 }
    329 
    330 /** Executes the test.
    331  *
    332  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    333  *
    334  *  Note the function throws exception should an error occur!
    335  *
    336  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    337  **/
    338 tcu::TestNode::IterateResult TextureBufferOperations::iterate(void)
    339 {
    340 	/* Initialize */
    341 	initTest();
    342 
    343 	/* Get GL entry points */
    344 	glw::GLboolean test_result = true;
    345 
    346 	/* Prepare expected data */
    347 	std::vector<glw::GLint> reference(m_n_vectors_in_buffer_texture * m_n_vector_components);
    348 	fillBufferWithData(&reference[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
    349 
    350 	std::vector<glw::GLint> result(m_n_vectors_in_buffer_texture * m_n_vector_components);
    351 
    352 	iterateFirstPhase(&result[0], static_cast<glw::GLuint>(m_n_vectors_in_buffer_texture * m_n_vector_components *
    353 														   sizeof(glw::GLint)));
    354 	if (!verifyResults(&reference[0], &result[0], static_cast<glw::GLuint>(m_n_vectors_in_buffer_texture *
    355 																		   m_n_vector_components * sizeof(glw::GLint)),
    356 					   "1st Phase Compute Shader\n"))
    357 	{
    358 		test_result = false;
    359 	}
    360 
    361 	iterateSecondPhase(&result[0]);
    362 	if (!verifyResults(&reference[0], &result[0], static_cast<glw::GLuint>(m_n_vectors_in_buffer_texture *
    363 																		   m_n_vector_components * sizeof(glw::GLint)),
    364 					   "2st Phase Vertex + Fragment Shader\n"))
    365 	{
    366 		test_result = false;
    367 	}
    368 
    369 	if (test_result)
    370 	{
    371 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    372 	}
    373 	else
    374 	{
    375 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    376 	}
    377 
    378 	return STOP;
    379 }
    380 
    381 void TextureBufferOperations::iterateFirstPhase(glw::GLint* result, glw::GLuint size)
    382 {
    383 	/* Get GL entry points */
    384 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    385 
    386 	gl.bindBuffer(GL_ARRAY_BUFFER, m_ssbo_bo_id);
    387 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding  buffer object!");
    388 
    389 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo_bo_id);
    390 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
    391 
    392 	gl.useProgram(m_po_cs_id);
    393 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program!");
    394 
    395 	gl.bindImageTexture(0, m_texbuff_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32I);
    396 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture to image unit!");
    397 
    398 	gl.dispatchCompute(1, 1, 1);
    399 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
    400 
    401 	gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
    402 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
    403 
    404 	/* Get result data */
    405 	glw::GLint* result_mapped = (glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, size, GL_MAP_READ_BIT);
    406 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space!");
    407 
    408 	memcpy(result, result_mapped, size);
    409 
    410 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
    411 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping buffer object's data store from client's address space!");
    412 
    413 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    414 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
    415 	gl.useProgram(0);
    416 }
    417 
    418 void TextureBufferOperations::iterateSecondPhase(glw::GLint* result)
    419 {
    420 	/* Get GL entry points */
    421 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    422 
    423 	gl.bindVertexArray(m_vao_id);
    424 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    425 
    426 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
    427 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!");
    428 
    429 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
    430 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
    431 
    432 	/* Attach output texture to framebuffer */
    433 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0);
    434 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to framebuffer's color attachment");
    435 
    436 	/* Check framebuffer status */
    437 	checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
    438 
    439 	/* Configure view port */
    440 	gl.viewport(0, 0, m_n_vectors_in_buffer_texture, 1);
    441 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting viewport!");
    442 
    443 	/* Use program */
    444 	gl.useProgram(m_po_vs_fs_id);
    445 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error using program object!");
    446 
    447 	glw::GLint sampler_location = gl.getUniformLocation(m_po_vs_fs_id, "sampler_buffer");
    448 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
    449 	if (sampler_location == -1)
    450 	{
    451 		TCU_FAIL("Could not get uniform location");
    452 	}
    453 
    454 	gl.uniform1i(sampler_location, 0);
    455 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding sampler with texture unit!");
    456 
    457 	/* Configure vertex position attribute */
    458 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
    459 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
    460 
    461 	m_vertex_location = gl.getAttribLocation(m_po_vs_fs_id, "vs_position");
    462 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
    463 	if (m_vertex_location == -1)
    464 	{
    465 		TCU_FAIL("Could not get uniform location");
    466 	}
    467 
    468 	gl.vertexAttribPointer(m_vertex_location, 4, GL_FLOAT, GL_FALSE, 0, 0);
    469 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
    470 
    471 	gl.enableVertexAttribArray(m_vertex_location);
    472 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
    473 
    474 	/* Configure index attribute */
    475 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_indicies_id);
    476 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
    477 
    478 	m_index_location = gl.getAttribLocation(m_po_vs_fs_id, "vs_index");
    479 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
    480 	if (m_index_location == -1)
    481 	{
    482 		TCU_FAIL("Could not get uniform location");
    483 	}
    484 
    485 	gl.vertexAttribPointer(m_index_location, 1, GL_FLOAT, GL_FALSE, 0, 0);
    486 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
    487 
    488 	gl.enableVertexAttribArray(m_index_location);
    489 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
    490 
    491 	/* Clear texture */
    492 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
    493 	gl.clear(GL_COLOR_BUFFER_BIT);
    494 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer");
    495 
    496 	/* Render */
    497 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    498 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
    499 
    500 	/* Read result data */
    501 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
    502 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object !");
    503 
    504 	gl.readPixels(0, 0, m_n_vectors_in_buffer_texture, 1, GL_RGBA_INTEGER, GL_INT, result);
    505 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels !");
    506 
    507 	gl.bindVertexArray(0);
    508 	gl.bindTexture(GL_TEXTURE_2D, 0);
    509 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    510 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
    511 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    512 	gl.disableVertexAttribArray(m_vertex_location);
    513 	gl.disableVertexAttribArray(m_index_location);
    514 	gl.useProgram(0);
    515 
    516 	m_vertex_location = -1;
    517 	m_index_location  = -1;
    518 }
    519 
    520 /** Check if result data is the same as reference data - log error if not
    521  *
    522  * @param  reference pointer to buffer with reference data
    523  * @param  result    pointer to buffer with result data
    524  * @param  size      size of buffers
    525  * @param  message   pointer to literal with message (informing about test phase)
    526  *
    527  * @return           returns true if reference data equals result data, otherwise log error and return false
    528  */
    529 glw::GLboolean TextureBufferOperations::verifyResults(glw::GLint* reference, glw::GLint* result, glw::GLuint size,
    530 													  const char* message)
    531 {
    532 	/* Log error if expected and result data is not equal */
    533 	if (memcmp(reference, result, size))
    534 	{
    535 		std::stringstream referenceData;
    536 		std::stringstream resultData;
    537 
    538 		referenceData << "[";
    539 		resultData << "[";
    540 
    541 		glw::GLuint n_entries = static_cast<glw::GLuint>(size / sizeof(glw::GLint));
    542 
    543 		for (glw::GLuint i = 0; i < n_entries; ++i)
    544 		{
    545 			referenceData << reference[i] << ",";
    546 			resultData << result[i] << ",";
    547 		}
    548 
    549 		referenceData << "]";
    550 		resultData << "]";
    551 
    552 		m_testCtx.getLog() << tcu::TestLog::Message << message
    553 						   << "Result buffer contains different data than reference buffer\n"
    554 						   << "Reference Buffer: " << referenceData.str() << "\n"
    555 						   << "Result Buffer: " << resultData.str() << "\n"
    556 						   << tcu::TestLog::EndMessage;
    557 		return false;
    558 	}
    559 
    560 	return true;
    561 }
    562 
    563 /** Fill buffer with test data
    564  *
    565  * @param buffer      pointer to buffer
    566  * @param bufferLenth buffer length
    567  */
    568 void TextureBufferOperations::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
    569 {
    570 	for (glw::GLuint i = 0; i < bufferLength; ++i)
    571 	{
    572 		buffer[i] = (glw::GLint)i;
    573 	}
    574 }
    575 
    576 /** Check Framebuffer Status - throw exception if status is different than GL_FRAMEBUFFER_COMPLETE
    577  *
    578  * @param framebuffer  - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
    579  *
    580  */
    581 void TextureBufferOperations::checkFramebufferStatus(glw::GLenum framebuffer)
    582 {
    583 	/* Get GL entry points */
    584 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    585 
    586 	/* Check framebuffer status */
    587 	glw::GLenum framebufferStatus = gl.checkFramebufferStatus(framebuffer);
    588 
    589 	if (GL_FRAMEBUFFER_COMPLETE != framebufferStatus)
    590 	{
    591 		switch (framebufferStatus)
    592 		{
    593 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
    594 		{
    595 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
    596 		}
    597 
    598 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
    599 		{
    600 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
    601 		}
    602 
    603 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
    604 		{
    605 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
    606 		}
    607 
    608 		case GL_FRAMEBUFFER_UNSUPPORTED:
    609 		{
    610 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_UNSUPPORTED");
    611 		}
    612 
    613 		default:
    614 		{
    615 			TCU_FAIL("Framebuffer incomplete, status not recognized");
    616 		}
    617 		};
    618 	} /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
    619 }
    620 
    621 /** Deinitializes GLES objects created during the test.
    622  *
    623  */
    624 void TextureBufferOperations::deinit(void)
    625 {
    626 	/* Get GLES entry points */
    627 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    628 
    629 	/* Reset GLES state */
    630 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, 0);
    631 	gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, 0);
    632 
    633 	/* Delete GLES objects */
    634 	if (0 != m_texbuff_id)
    635 	{
    636 		gl.deleteTextures(1, &m_texbuff_id);
    637 		m_texbuff_id = 0;
    638 	}
    639 
    640 	if (0 != m_tb_bo_id)
    641 	{
    642 		gl.deleteBuffers(1, &m_tb_bo_id);
    643 		m_tb_bo_id = 0;
    644 	}
    645 
    646 	deinitFirstPhase();
    647 	deinitSecondPhase();
    648 
    649 	/* Deinitialize base class */
    650 	TestCaseBase::deinit();
    651 }
    652 
    653 void TextureBufferOperations::deinitFirstPhase(void)
    654 {
    655 	/* Get GLES entry points */
    656 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    657 
    658 	/* Reset GLES state */
    659 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    660 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
    661 	gl.useProgram(0);
    662 
    663 	/* Delete GLES objects */
    664 	if (0 != m_po_cs_id)
    665 	{
    666 		gl.deleteProgram(m_po_cs_id);
    667 		m_po_cs_id = 0;
    668 	}
    669 
    670 	if (0 != m_cs_id)
    671 	{
    672 		gl.deleteShader(m_cs_id);
    673 		m_cs_id = 0;
    674 	}
    675 
    676 	if (0 != m_ssbo_bo_id)
    677 	{
    678 		gl.deleteBuffers(1, &m_ssbo_bo_id);
    679 		m_ssbo_bo_id = 0;
    680 	}
    681 }
    682 
    683 void TextureBufferOperations::deinitSecondPhase(void)
    684 {
    685 	/* Get GLES entry points */
    686 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    687 
    688 	/* Reset GLES state */
    689 	gl.bindVertexArray(0);
    690 	gl.bindTexture(GL_TEXTURE_2D, 0);
    691 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    692 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
    693 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    694 
    695 	if (m_vertex_location != -1)
    696 	{
    697 		gl.disableVertexAttribArray(m_vertex_location);
    698 		m_vertex_location = -1;
    699 	}
    700 
    701 	if (m_index_location != -1)
    702 	{
    703 		gl.disableVertexAttribArray(m_index_location);
    704 		m_index_location = -1;
    705 	}
    706 
    707 	gl.useProgram(0);
    708 
    709 	/* Delete GLES objects */
    710 	if (0 != m_po_vs_fs_id)
    711 	{
    712 		gl.deleteProgram(m_po_vs_fs_id);
    713 		m_po_vs_fs_id = 0;
    714 	}
    715 
    716 	if (0 != m_fs_id)
    717 	{
    718 		gl.deleteShader(m_fs_id);
    719 		m_fs_id = 0;
    720 	}
    721 
    722 	if (0 != m_vs_id)
    723 	{
    724 		gl.deleteShader(m_vs_id);
    725 		m_vs_id = 0;
    726 	}
    727 
    728 	if (0 != m_fbo_id)
    729 	{
    730 		gl.deleteFramebuffers(1, &m_fbo_id);
    731 		m_fbo_id = 0;
    732 	}
    733 
    734 	if (0 != m_to_id)
    735 	{
    736 		gl.deleteTextures(1, &m_to_id);
    737 		m_to_id = 0;
    738 	}
    739 
    740 	if (0 != m_vao_id)
    741 	{
    742 		gl.deleteVertexArrays(1, &m_vao_id);
    743 		m_vao_id = 0;
    744 	}
    745 
    746 	if (0 != m_vbo_id)
    747 	{
    748 		gl.deleteBuffers(1, &m_vbo_id);
    749 		m_vbo_id = 0;
    750 	}
    751 
    752 	if (0 != m_vbo_indicies_id)
    753 	{
    754 		gl.deleteBuffers(1, &m_vbo_indicies_id);
    755 		m_vbo_indicies_id = 0;
    756 	}
    757 }
    758 
    759 /** Constructor for Test Case 1
    760  *
    761  *  @param context     Test context
    762  *  @param name        Test case's name
    763  *  @param description Test case's description
    764  **/
    765 TextureBufferOperationsViaBufferObjectLoad::TextureBufferOperationsViaBufferObjectLoad(Context&				context,
    766 																					   const ExtParameters& extParams,
    767 																					   const char*			name,
    768 																					   const char*			description)
    769 	: TextureBufferOperations(context, extParams, name, description)
    770 {
    771 }
    772 
    773 /** Initialize texture buffer object with test data using glBufferSubData()
    774  *
    775  **/
    776 void TextureBufferOperationsViaBufferObjectLoad::initializeBufferObjectData(void)
    777 {
    778 	/* Get GL entry points */
    779 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    780 
    781 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
    782 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
    783 
    784 	gl.bufferSubData(m_glExtTokens.TEXTURE_BUFFER, 0,
    785 					 m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), &data[0]);
    786 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting buffer object data!");
    787 }
    788 
    789 /** Constructor for Test Case 2
    790  *
    791  *  @param context     Test context
    792  *  @param name        Test case's name
    793  *  @param description Test case's description
    794  **/
    795 TextureBufferOperationsViaCPUWrites::TextureBufferOperationsViaCPUWrites(Context&			  context,
    796 																		 const ExtParameters& extParams,
    797 																		 const char* name, const char* description)
    798 	: TextureBufferOperations(context, extParams, name, description)
    799 {
    800 }
    801 
    802 /** Initialize texture buffer object with test data using CPU Write
    803  *
    804  **/
    805 void TextureBufferOperationsViaCPUWrites::initializeBufferObjectData(void)
    806 {
    807 	/* Get GL entry points */
    808 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    809 
    810 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
    811 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
    812 
    813 	glw::GLint* tempBuffer = (glw::GLint*)gl.mapBufferRange(
    814 		m_glExtTokens.TEXTURE_BUFFER, 0, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint),
    815 		GL_MAP_WRITE_BIT);
    816 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space!");
    817 
    818 	for (glw::GLuint i = 0; i < data.size(); ++i)
    819 	{
    820 		tempBuffer[i] = data[i];
    821 	}
    822 
    823 	gl.unmapBuffer(m_glExtTokens.TEXTURE_BUFFER);
    824 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error ummapping buffer object's data store from client's address space!");
    825 }
    826 
    827 /** Constructor for Test Case 3
    828  *
    829  *  @param context     Test context
    830  *  @param name        Test case's name
    831  *  @param description Test case's description
    832  **/
    833 TextureBufferOperationsViaFrambufferReadBack::TextureBufferOperationsViaFrambufferReadBack(
    834 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
    835 	: TextureBufferOperations(context, extParams, name, description)
    836 	, m_fb_fbo_id(0)
    837 	, m_fb_fs_id(0)
    838 	, m_fb_po_id(0)
    839 	, m_fb_to_id(0)
    840 	, m_fb_vao_id(0)
    841 	, m_fb_vbo_id(0)
    842 	, m_fb_vs_id(0)
    843 	, m_position_location(-1)
    844 {
    845 }
    846 
    847 /** Initialize texture buffer object with test data using framebuffer readbacks to pixel buffer object
    848  *
    849  **/
    850 void TextureBufferOperationsViaFrambufferReadBack::initializeBufferObjectData()
    851 {
    852 	/* Get GL entry points */
    853 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    854 
    855 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
    856 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
    857 
    858 	/* Configure vertex array object */
    859 	gl.genVertexArrays(1, &m_fb_vao_id);
    860 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
    861 
    862 	gl.bindVertexArray(m_fb_vao_id);
    863 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
    864 
    865 	/* Prepare framebuffer object */
    866 	gl.genFramebuffers(1, &m_fb_fbo_id);
    867 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing framebuffer object!");
    868 
    869 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb_fbo_id);
    870 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!");
    871 
    872 	/* Prepare texture object */
    873 	gl.genTextures(1, &m_fb_to_id);
    874 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
    875 
    876 	gl.bindTexture(GL_TEXTURE_2D, m_fb_to_id);
    877 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
    878 
    879 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32I, m_n_vectors_in_buffer_texture /* width */, 1 /* height */);
    880 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store!");
    881 
    882 	/* Attach texture to framebuffer */
    883 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fb_to_id, 0);
    884 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to framebuffer's color attachment!");
    885 
    886 	/* Check framebuffer status */
    887 	checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
    888 
    889 	/* Configure view port */
    890 	gl.viewport(0, 0, m_n_vectors_in_buffer_texture, 1);
    891 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting viewport!");
    892 
    893 	/* Create program object */
    894 	m_fb_po_id = gl.createProgram();
    895 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
    896 
    897 	m_fb_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
    898 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
    899 
    900 	m_fb_vs_id = gl.createShader(GL_VERTEX_SHADER);
    901 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
    902 
    903 	std::string fsSource = getFBFragmentShaderCode();
    904 	std::string vsSource = getFBVertexShaderCode();
    905 
    906 	const char* fsCode = fsSource.c_str();
    907 	const char* vsCode = vsSource.c_str();
    908 
    909 	if (!buildProgram(m_fb_po_id, m_fb_fs_id, 1, &fsCode, m_fb_vs_id, 1, &vsCode))
    910 	{
    911 		TCU_FAIL("Could not create a program from valid vertex/fragment shader code!");
    912 	}
    913 
    914 	/* Full screen quad */
    915 	glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
    916 								1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
    917 
    918 	/* Generate buffer object */
    919 	gl.genBuffers(1, &m_fb_vbo_id);
    920 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
    921 
    922 	/* Bind buffer object */
    923 	gl.bindBuffer(GL_ARRAY_BUFFER, m_fb_vbo_id);
    924 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
    925 
    926 	/* Set data for buffer object */
    927 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    928 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting data for buffer object!");
    929 
    930 	gl.useProgram(m_fb_po_id);
    931 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
    932 
    933 	m_position_location = gl.getAttribLocation(m_fb_po_id, "inPosition");
    934 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
    935 	if (m_position_location == -1)
    936 	{
    937 		TCU_FAIL("Could not get uniform location");
    938 	}
    939 
    940 	gl.vertexAttribPointer(m_position_location, 4, GL_FLOAT, GL_FALSE, 0, 0);
    941 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
    942 
    943 	gl.enableVertexAttribArray(m_position_location);
    944 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
    945 
    946 	/* Clear texture */
    947 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
    948 	gl.clear(GL_COLOR_BUFFER_BIT);
    949 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer");
    950 
    951 	/* Render */
    952 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
    953 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
    954 
    955 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fb_fbo_id);
    956 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding frame buffer object!");
    957 
    958 	/* Bind buffer object to pixel pack buffer */
    959 	gl.bindBuffer(GL_PIXEL_PACK_BUFFER, m_tb_bo_id);
    960 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object !");
    961 
    962 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
    963 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_UNPACK_ALIGNMENT parameter to 1");
    964 
    965 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
    966 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_PACK_ALIGNMENT parameter to 1");
    967 
    968 	/* Fill buffer object with data from framebuffer object's color attachment */
    969 	gl.readPixels(0, 0, m_n_vectors_in_buffer_texture, 1, GL_RGBA_INTEGER, GL_INT, 0);
    970 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels !");
    971 
    972 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
    973 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_UNPACK_ALIGNMENT parameter to default value");
    974 
    975 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
    976 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_PACK_ALIGNMENT parameter to default value");
    977 
    978 	gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
    979 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
    980 
    981 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, m_tb_bo_id);
    982 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
    983 
    984 	gl.bindVertexArray(0);
    985 	gl.bindTexture(GL_TEXTURE_2D, 0);
    986 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    987 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
    988 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
    989 
    990 	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
    991 		gl.disableVertexAttribArray(m_position_location);
    992 
    993 	gl.useProgram(0);
    994 
    995 	m_position_location = -1;
    996 }
    997 
    998 /** Returns Fragment Shader Code
    999  *
   1000  * @return pointer to literal with Fragment Shader Code
   1001  */
   1002 std::string TextureBufferOperationsViaFrambufferReadBack::getFBFragmentShaderCode() const
   1003 {
   1004 	std::stringstream strstream;
   1005 
   1006 	strstream << "${VERSION}\n"
   1007 				 "\n"
   1008 				 "precision highp float;\n"
   1009 				 "\n"
   1010 				 "out ivec4 color;\n"
   1011 				 "\n"
   1012 				 "void main(void)\n"
   1013 				 "{\n"
   1014 				 "    color = ivec4(0, 1, 0, 1);\n"
   1015 				 "}\n";
   1016 
   1017 	return strstream.str();
   1018 }
   1019 
   1020 /** Returns Vertex Shader Code
   1021  *
   1022  * @return pointer to literal with Vertex Shader Code
   1023  */
   1024 std::string TextureBufferOperationsViaFrambufferReadBack::getFBVertexShaderCode() const
   1025 {
   1026 	std::stringstream strstream;
   1027 
   1028 	strstream << "${VERSION}\n"
   1029 				 "\n"
   1030 				 "precision highp float;\n"
   1031 				 "\n"
   1032 				 "in vec4 inPosition;\n"
   1033 				 "\n"
   1034 				 "void main(void)\n"
   1035 				 "{\n"
   1036 				 "    gl_Position = inPosition;\n"
   1037 				 "}\n";
   1038 
   1039 	return strstream.str();
   1040 }
   1041 
   1042 /** Fills buffer with test data
   1043  *
   1044  * @param buffer      pointer to buffer
   1045  * @param bufferLenth buffer length
   1046  */
   1047 void TextureBufferOperationsViaFrambufferReadBack::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
   1048 {
   1049 	for (glw::GLuint i = 0; i < bufferLength; ++i)
   1050 	{
   1051 		buffer[i] = (glw::GLint)(i % 2); /* Reference color is 0, 1, 0, 1 */
   1052 	}
   1053 }
   1054 
   1055 /** Deinitializes GLES objects created during the test.
   1056  *
   1057  */
   1058 void TextureBufferOperationsViaFrambufferReadBack::deinit(void)
   1059 {
   1060 	/* Get GL entry points */
   1061 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1062 
   1063 	/* Reset GLES state */
   1064 	gl.bindVertexArray(0);
   1065 	gl.bindTexture(GL_TEXTURE_2D, 0);
   1066 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
   1067 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
   1068 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1069 
   1070 	if (m_position_location != -1)
   1071 	{
   1072 		gl.disableVertexAttribArray(m_position_location);
   1073 		m_position_location = -1;
   1074 	}
   1075 
   1076 	gl.useProgram(0);
   1077 
   1078 	/* Delete GLES objects */
   1079 	if (0 != m_fb_po_id)
   1080 	{
   1081 		gl.deleteProgram(m_fb_po_id);
   1082 		m_fb_po_id = 0;
   1083 	}
   1084 
   1085 	if (0 != m_fb_fs_id)
   1086 	{
   1087 		gl.deleteShader(m_fb_fs_id);
   1088 		m_fb_fs_id = 0;
   1089 	}
   1090 
   1091 	if (0 != m_fb_vs_id)
   1092 	{
   1093 		gl.deleteShader(m_fb_vs_id);
   1094 		m_fb_vs_id = 0;
   1095 	}
   1096 
   1097 	if (0 != m_fb_fbo_id)
   1098 	{
   1099 		gl.deleteFramebuffers(1, &m_fb_fbo_id);
   1100 		m_fb_fbo_id = 0;
   1101 	}
   1102 
   1103 	if (0 != m_fb_to_id)
   1104 	{
   1105 		gl.deleteTextures(1, &m_fb_to_id);
   1106 		m_fb_to_id = 0;
   1107 	}
   1108 
   1109 	if (0 != m_fb_vbo_id)
   1110 	{
   1111 		gl.deleteBuffers(1, &m_fb_vbo_id);
   1112 		m_fb_vbo_id = 0;
   1113 	}
   1114 
   1115 	if (0 != m_fb_vao_id)
   1116 	{
   1117 		gl.deleteVertexArrays(1, &m_fb_vao_id);
   1118 		m_fb_vao_id = 0;
   1119 	}
   1120 
   1121 	/* Deinitialize base class */
   1122 	TextureBufferOperations::deinit();
   1123 }
   1124 
   1125 /** Constructor for Test Case 4
   1126  *
   1127  *  @param context     Test context
   1128  *  @param name        Test case's name
   1129  *  @param description Test case's description
   1130  **/
   1131 TextureBufferOperationsViaTransformFeedback::TextureBufferOperationsViaTransformFeedback(Context&			  context,
   1132 																						 const ExtParameters& extParams,
   1133 																						 const char*		  name,
   1134 																						 const char* description)
   1135 	: TextureBufferOperations(context, extParams, name, description)
   1136 	, m_tf_fs_id(0)
   1137 	, m_tf_po_id(0)
   1138 	, m_tf_vao_id(0)
   1139 	, m_tf_vbo_id(0)
   1140 	, m_tf_vs_id(0)
   1141 	, m_position_location(-1)
   1142 {
   1143 }
   1144 
   1145 /** Initialize buffer object with test data using transform feedback
   1146  *
   1147  **/
   1148 void TextureBufferOperationsViaTransformFeedback::initializeBufferObjectData()
   1149 {
   1150 	/* Get GL entry points */
   1151 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1152 
   1153 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
   1154 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
   1155 
   1156 	/* Configure vertex array object */
   1157 	gl.genVertexArrays(1, &m_tf_vao_id);
   1158 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
   1159 
   1160 	gl.bindVertexArray(m_tf_vao_id);
   1161 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
   1162 
   1163 	/* Configure buffer object*/
   1164 	gl.genBuffers(1, &m_tf_vbo_id);
   1165 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex buffer object!");
   1166 
   1167 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tf_vbo_id);
   1168 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex buffer object!");
   1169 
   1170 	gl.bufferData(GL_ARRAY_BUFFER, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), &data[0],
   1171 				  GL_DYNAMIC_DRAW);
   1172 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating buffer object's data store!");
   1173 
   1174 	m_tf_po_id = gl.createProgram();
   1175 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
   1176 
   1177 	/* Setup transform feedback varyings */
   1178 	const char* varyings[] = { "outPosition" };
   1179 	gl.transformFeedbackVaryings(m_tf_po_id, 1, varyings, GL_SEPARATE_ATTRIBS);
   1180 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error specifying transform feedback varyings!");
   1181 
   1182 	m_tf_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   1183 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
   1184 
   1185 	m_tf_vs_id = gl.createShader(GL_VERTEX_SHADER);
   1186 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
   1187 
   1188 	std::string fsSource = getTFFragmentShaderCode();
   1189 	std::string vsSource = getTFVertexShaderCode();
   1190 
   1191 	const char* fsCode = fsSource.c_str();
   1192 	const char* vsCode = vsSource.c_str();
   1193 
   1194 	if (!buildProgram(m_tf_po_id, m_tf_fs_id, 1, &fsCode, m_tf_vs_id, 1, &vsCode))
   1195 	{
   1196 		TCU_FAIL("Could not create a program from valid vertex/fragment shader code!");
   1197 	}
   1198 
   1199 	gl.useProgram(m_tf_po_id);
   1200 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
   1201 
   1202 	m_position_location = gl.getAttribLocation(m_tf_po_id, "inPosition");
   1203 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting attrib location!");
   1204 
   1205 	gl.vertexAttribIPointer(m_position_location, m_n_vector_components, GL_INT, 0, 0);
   1206 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting vertex attrib pointer!");
   1207 
   1208 	gl.enableVertexAttribArray(m_position_location);
   1209 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error enabling vertex attrib array!");
   1210 
   1211 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tb_bo_id);
   1212 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object to transform feedback binding point!");
   1213 
   1214 	gl.beginTransformFeedback(GL_POINTS);
   1215 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error starting transform feedback!");
   1216 
   1217 	/* Render */
   1218 	gl.drawArrays(GL_POINTS, 0, m_n_vectors_in_buffer_texture);
   1219 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error during rendering!");
   1220 
   1221 	gl.endTransformFeedback();
   1222 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error ending transform feedback!");
   1223 
   1224 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
   1225 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1226 	gl.bindVertexArray(0);
   1227 
   1228 	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
   1229 		gl.disableVertexAttribArray(m_position_location);
   1230 
   1231 	gl.useProgram(0);
   1232 
   1233 	m_position_location = -1;
   1234 }
   1235 
   1236 /** Returns Fragment shader Code
   1237  *
   1238  * @return pointer to literal with Fragment Shader Code
   1239  */
   1240 std::string TextureBufferOperationsViaTransformFeedback::getTFFragmentShaderCode() const
   1241 {
   1242 	std::stringstream strstream;
   1243 
   1244 	strstream << "${VERSION}\n"
   1245 				 "\n"
   1246 				 "${TEXTURE_BUFFER_REQUIRE}\n"
   1247 				 "\n"
   1248 				 "in flat ivec4 outPosition;\n"
   1249 				 "\n"
   1250 				 "precision highp float;\n"
   1251 				 "\n"
   1252 				 "void main(void)\n"
   1253 				 "{\n"
   1254 				 "}\n";
   1255 
   1256 	return strstream.str();
   1257 }
   1258 
   1259 /** Returns Vertex Shader Code
   1260  *
   1261  * @return pointer to literal with Vertex Shader Code
   1262  */
   1263 std::string TextureBufferOperationsViaTransformFeedback::getTFVertexShaderCode() const
   1264 {
   1265 	std::stringstream strstream;
   1266 
   1267 	strstream << "${VERSION}\n"
   1268 				 "\n"
   1269 				 "${TEXTURE_BUFFER_REQUIRE}\n"
   1270 				 "\n"
   1271 				 "precision highp float;\n"
   1272 				 "\n"
   1273 				 "in ivec4 inPosition;\n"
   1274 				 "\n"
   1275 				 "flat out ivec4 outPosition;\n"
   1276 				 "\n"
   1277 				 "void main(void)\n"
   1278 				 "{\n"
   1279 				 "    gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
   1280 				 "    outPosition = inPosition;\n"
   1281 				 "}\n";
   1282 
   1283 	return strstream.str();
   1284 }
   1285 
   1286 /** Deinitializes GLES objects created during the test. */
   1287 void TextureBufferOperationsViaTransformFeedback::deinit(void)
   1288 {
   1289 	/* Get GL entry points */
   1290 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1291 
   1292 	/* Reset GLES state */
   1293 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
   1294 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
   1295 	gl.bindVertexArray(0);
   1296 
   1297 	if (m_position_location != -1)
   1298 	{
   1299 		gl.disableVertexAttribArray(m_position_location);
   1300 		m_position_location = -1;
   1301 	}
   1302 
   1303 	gl.useProgram(0);
   1304 
   1305 	/* Delete GLES objects */
   1306 	if (0 != m_tf_po_id)
   1307 	{
   1308 		gl.deleteProgram(m_tf_po_id);
   1309 		m_tf_po_id = 0;
   1310 	}
   1311 
   1312 	if (0 != m_tf_vs_id)
   1313 	{
   1314 		gl.deleteShader(m_tf_vs_id);
   1315 		m_tf_vs_id = 0;
   1316 	}
   1317 
   1318 	if (0 != m_tf_fs_id)
   1319 	{
   1320 		gl.deleteShader(m_tf_fs_id);
   1321 		m_tf_fs_id = 0;
   1322 	}
   1323 
   1324 	if (0 != m_tf_vbo_id)
   1325 	{
   1326 		gl.deleteBuffers(1, &m_tf_vbo_id);
   1327 		m_tf_vbo_id = 0;
   1328 	}
   1329 
   1330 	if (0 != m_tf_vao_id)
   1331 	{
   1332 		gl.deleteVertexArrays(1, &m_tf_vao_id);
   1333 		m_tf_vao_id = 0;
   1334 	}
   1335 
   1336 	/* Deinitialize base class */
   1337 	TextureBufferOperations::deinit();
   1338 }
   1339 
   1340 const glw::GLuint TextureBufferOperationsViaImageStore::m_image_unit = 0;
   1341 
   1342 /** Constructor for Test Case 5
   1343  *
   1344  *  @param context     Test context
   1345  *  @param name        Test case's name
   1346  *  @param description Test case's description
   1347  **/
   1348 TextureBufferOperationsViaImageStore::TextureBufferOperationsViaImageStore(Context&				context,
   1349 																		   const ExtParameters& extParams,
   1350 																		   const char* name, const char* description)
   1351 	: TextureBufferOperations(context, extParams, name, description), m_is_cs_id(0), m_is_po_id(0)
   1352 {
   1353 }
   1354 
   1355 /** Initialize buffer object with test data using image store
   1356  *
   1357  **/
   1358 void TextureBufferOperationsViaImageStore::initializeBufferObjectData()
   1359 {
   1360 	/* Get Gl entry points */
   1361 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1362 
   1363 	/* Configure program object */
   1364 	m_is_po_id = gl.createProgram();
   1365 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
   1366 
   1367 	m_is_cs_id = gl.createShader(GL_COMPUTE_SHADER);
   1368 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
   1369 
   1370 	std::string csSource = getISComputeShaderCode();
   1371 	const char* csCode   = csSource.c_str();
   1372 
   1373 	if (!buildProgram(m_is_po_id, m_is_cs_id, 1, &csCode))
   1374 	{
   1375 		TCU_FAIL("Could not create a program from valid compute shader source!");
   1376 	}
   1377 
   1378 	gl.useProgram(m_is_po_id);
   1379 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
   1380 
   1381 	gl.bindImageTexture(m_image_unit, m_texbuff_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I);
   1382 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
   1383 
   1384 	gl.dispatchCompute(1, 1, 1);
   1385 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
   1386 
   1387 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
   1388 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
   1389 
   1390 	gl.useProgram(0);
   1391 }
   1392 
   1393 /** Returns Compute Shader Code
   1394  *
   1395  * @return pointer to literal with Compute Shader Code
   1396  */
   1397 std::string TextureBufferOperationsViaImageStore::getISComputeShaderCode() const
   1398 {
   1399 	std::stringstream strstream;
   1400 
   1401 	strstream << "${VERSION}\n"
   1402 				 "\n"
   1403 				 "${TEXTURE_BUFFER_REQUIRE}\n"
   1404 				 "\n"
   1405 				 "precision highp float;\n"
   1406 				 "\n"
   1407 				 "layout(rgba32i, binding = 0) uniform writeonly highp iimageBuffer image_buffer;\n"
   1408 				 "\n"
   1409 				 "layout (local_size_x = "
   1410 			  << m_n_vectors_in_buffer_texture
   1411 			  << " ) in;\n"
   1412 				 "\n"
   1413 				 "void main(void)\n"
   1414 				 "{\n"
   1415 				 "    imageStore(image_buffer, int(gl_LocalInvocationID.x), ivec4(gl_LocalInvocationID.x) );\n"
   1416 				 "}\n";
   1417 
   1418 	return strstream.str();
   1419 }
   1420 
   1421 /** Fill buffer with test data
   1422  *
   1423  * @param buffer      pointer to buffer
   1424  * @param bufferLenth buffer length
   1425  */
   1426 void TextureBufferOperationsViaImageStore::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
   1427 {
   1428 	for (glw::GLuint i = 0; i < bufferLength; ++i)
   1429 	{
   1430 		buffer[i] = (glw::GLint)(i / m_n_vector_components);
   1431 	}
   1432 }
   1433 
   1434 /** Deinitializes GLES objects created during the test. */
   1435 void TextureBufferOperationsViaImageStore::deinit(void)
   1436 {
   1437 	/* Get Gl entry points */
   1438 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1439 
   1440 	/* Reset GLES state */
   1441 	gl.useProgram(0);
   1442 
   1443 	/* Delete GLES objects */
   1444 	if (0 != m_is_po_id)
   1445 	{
   1446 		gl.deleteProgram(m_is_po_id);
   1447 		m_is_po_id = 0;
   1448 	}
   1449 
   1450 	if (0 != m_is_cs_id)
   1451 	{
   1452 		gl.deleteShader(m_is_cs_id);
   1453 		m_is_cs_id = 0;
   1454 	}
   1455 
   1456 	/* Deinitalize base class */
   1457 	TextureBufferOperations::deinit();
   1458 }
   1459 
   1460 /** Constructor for Test Case 6
   1461  *
   1462  *  @param context     Test context
   1463  *  @param name        Test case's name
   1464  *  @param description Test case's description
   1465  **/
   1466 TextureBufferOperationsViaSSBOWrites::TextureBufferOperationsViaSSBOWrites(Context&				context,
   1467 																		   const ExtParameters& extParams,
   1468 																		   const char* name, const char* description)
   1469 	: TextureBufferOperations(context, extParams, name, description), m_ssbo_cs_id(0), m_ssbo_po_id(0)
   1470 {
   1471 }
   1472 
   1473 /** Initialize buffer object with test data using ssbo writes
   1474  *
   1475  **/
   1476 void TextureBufferOperationsViaSSBOWrites::initializeBufferObjectData()
   1477 {
   1478 	/* Get Gl entry points */
   1479 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1480 
   1481 	/* Configure program object */
   1482 	m_ssbo_po_id = gl.createProgram();
   1483 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
   1484 
   1485 	m_ssbo_cs_id = gl.createShader(GL_COMPUTE_SHADER);
   1486 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
   1487 
   1488 	std::string csSource = getSSBOComputeShaderCode();
   1489 	const char* csCode   = csSource.c_str();
   1490 
   1491 	if (!buildProgram(m_ssbo_po_id, m_ssbo_cs_id, 1, &csCode))
   1492 	{
   1493 		TCU_FAIL("Could not create a program from valid compute shader source!");
   1494 	}
   1495 
   1496 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_tb_bo_id);
   1497 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
   1498 
   1499 	gl.useProgram(m_ssbo_po_id);
   1500 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
   1501 
   1502 	gl.dispatchCompute(1, 1, 1);
   1503 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
   1504 
   1505 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
   1506 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
   1507 
   1508 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
   1509 	gl.useProgram(0);
   1510 }
   1511 
   1512 /** Returns Compute Shader Code
   1513  *
   1514  * @return pointer to literal with Compute Shader Code
   1515  */
   1516 std::string TextureBufferOperationsViaSSBOWrites::getSSBOComputeShaderCode() const
   1517 {
   1518 	std::stringstream strstream;
   1519 
   1520 	strstream << "${VERSION}\n"
   1521 				 "\n"
   1522 				 "${TEXTURE_BUFFER_REQUIRE}\n"
   1523 				 "\n"
   1524 				 "precision highp float;\n"
   1525 				 "\n"
   1526 				 "buffer ComputeSSBO\n"
   1527 				 "{\n"
   1528 				 "    ivec4 value[];\n"
   1529 				 "} computeSSBO;\n"
   1530 				 "\n"
   1531 				 "layout (local_size_x = "
   1532 			  << m_n_vectors_in_buffer_texture
   1533 			  << " ) in;\n"
   1534 				 "\n"
   1535 				 "void main(void)\n"
   1536 				 "{\n"
   1537 				 "    computeSSBO.value[gl_LocalInvocationID.x] = ivec4(gl_LocalInvocationID.x);\n"
   1538 				 "}\n";
   1539 
   1540 	return strstream.str();
   1541 }
   1542 
   1543 /** Fill buffer with test data
   1544  *
   1545  * @param buffer      pointer to buffer
   1546  * @param bufferLenth buffer length
   1547  */
   1548 void TextureBufferOperationsViaSSBOWrites::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
   1549 {
   1550 	for (glw::GLuint i = 0; i < bufferLength; ++i)
   1551 	{
   1552 		buffer[i] = (glw::GLint)(i / m_n_vector_components);
   1553 	}
   1554 }
   1555 
   1556 /** Deinitializes GLES objects created during the test. */
   1557 void TextureBufferOperationsViaSSBOWrites::deinit(void)
   1558 {
   1559 	/* Get Gl entry points */
   1560 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1561 
   1562 	/* Reset GLES state */
   1563 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
   1564 	gl.useProgram(0);
   1565 
   1566 	/* Delete GLES objects */
   1567 	if (0 != m_ssbo_po_id)
   1568 	{
   1569 		gl.deleteProgram(m_ssbo_po_id);
   1570 		m_ssbo_po_id = 0;
   1571 	}
   1572 
   1573 	if (0 != m_ssbo_cs_id)
   1574 	{
   1575 		gl.deleteShader(m_ssbo_cs_id);
   1576 		m_ssbo_cs_id = 0;
   1577 	}
   1578 
   1579 	/* Deinitalize base class */
   1580 	TextureBufferOperations::deinit();
   1581 }
   1582 
   1583 } // namespace glcts
   1584