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  **/
TextureBufferOperations(Context & context,const ExtParameters & extParams,const char * name,const char * description)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  */
initTest(void)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 
initFirstPhase(void)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  */
getComputeShaderCode() const160 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 
initSecondPhase(void)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  */
getFragmentShaderCode() const278 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  */
getVertexShaderCode() const306 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  **/
iterate(void)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 
iterateFirstPhase(glw::GLint * result,glw::GLuint size)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 
iterateSecondPhase(glw::GLint * result)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  */
verifyResults(glw::GLint * reference,glw::GLint * result,glw::GLuint size,const char * message)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  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)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  */
checkFramebufferStatus(glw::GLenum framebuffer)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  */
deinit(void)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 
deinitFirstPhase(void)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 
deinitSecondPhase(void)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  **/
TextureBufferOperationsViaBufferObjectLoad(Context & context,const ExtParameters & extParams,const char * name,const char * description)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  **/
initializeBufferObjectData(void)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  **/
TextureBufferOperationsViaCPUWrites(Context & context,const ExtParameters & extParams,const char * name,const char * description)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  **/
initializeBufferObjectData(void)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  **/
TextureBufferOperationsViaFrambufferReadBack(Context & context,const ExtParameters & extParams,const char * name,const char * description)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  **/
initializeBufferObjectData()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  */
getFBFragmentShaderCode() const1002 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  */
getFBVertexShaderCode() const1024 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  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)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  */
deinit(void)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  **/
TextureBufferOperationsViaTransformFeedback(Context & context,const ExtParameters & extParams,const char * name,const char * description)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  **/
initializeBufferObjectData()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 	gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1234 
1235 	m_position_location = -1;
1236 }
1237 
1238 /** Returns Fragment shader Code
1239  *
1240  * @return pointer to literal with Fragment Shader Code
1241  */
getTFFragmentShaderCode() const1242 std::string TextureBufferOperationsViaTransformFeedback::getTFFragmentShaderCode() const
1243 {
1244 	std::stringstream strstream;
1245 
1246 	strstream << "${VERSION}\n"
1247 				 "\n"
1248 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1249 				 "\n"
1250 				 "in flat ivec4 outPosition;\n"
1251 				 "\n"
1252 				 "precision highp float;\n"
1253 				 "\n"
1254 				 "void main(void)\n"
1255 				 "{\n"
1256 				 "}\n";
1257 
1258 	return strstream.str();
1259 }
1260 
1261 /** Returns Vertex Shader Code
1262  *
1263  * @return pointer to literal with Vertex Shader Code
1264  */
getTFVertexShaderCode() const1265 std::string TextureBufferOperationsViaTransformFeedback::getTFVertexShaderCode() const
1266 {
1267 	std::stringstream strstream;
1268 
1269 	strstream << "${VERSION}\n"
1270 				 "\n"
1271 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1272 				 "\n"
1273 				 "precision highp float;\n"
1274 				 "\n"
1275 				 "in ivec4 inPosition;\n"
1276 				 "\n"
1277 				 "flat out ivec4 outPosition;\n"
1278 				 "\n"
1279 				 "void main(void)\n"
1280 				 "{\n"
1281 				 "    gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
1282 				 "    outPosition = inPosition;\n"
1283 				 "}\n";
1284 
1285 	return strstream.str();
1286 }
1287 
1288 /** Deinitializes GLES objects created during the test. */
deinit(void)1289 void TextureBufferOperationsViaTransformFeedback::deinit(void)
1290 {
1291 	/* Get GL entry points */
1292 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1293 
1294 	/* Reset GLES state */
1295 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
1296 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1297 	gl.bindVertexArray(0);
1298 
1299 	if (m_position_location != -1)
1300 	{
1301 		gl.disableVertexAttribArray(m_position_location);
1302 		m_position_location = -1;
1303 	}
1304 
1305 	gl.useProgram(0);
1306 
1307 	/* Delete GLES objects */
1308 	if (0 != m_tf_po_id)
1309 	{
1310 		gl.deleteProgram(m_tf_po_id);
1311 		m_tf_po_id = 0;
1312 	}
1313 
1314 	if (0 != m_tf_vs_id)
1315 	{
1316 		gl.deleteShader(m_tf_vs_id);
1317 		m_tf_vs_id = 0;
1318 	}
1319 
1320 	if (0 != m_tf_fs_id)
1321 	{
1322 		gl.deleteShader(m_tf_fs_id);
1323 		m_tf_fs_id = 0;
1324 	}
1325 
1326 	if (0 != m_tf_vbo_id)
1327 	{
1328 		gl.deleteBuffers(1, &m_tf_vbo_id);
1329 		m_tf_vbo_id = 0;
1330 	}
1331 
1332 	if (0 != m_tf_vao_id)
1333 	{
1334 		gl.deleteVertexArrays(1, &m_tf_vao_id);
1335 		m_tf_vao_id = 0;
1336 	}
1337 
1338 	/* Deinitialize base class */
1339 	TextureBufferOperations::deinit();
1340 }
1341 
1342 const glw::GLuint TextureBufferOperationsViaImageStore::m_image_unit = 0;
1343 
1344 /** Constructor for Test Case 5
1345  *
1346  *  @param context     Test context
1347  *  @param name        Test case's name
1348  *  @param description Test case's description
1349  **/
TextureBufferOperationsViaImageStore(Context & context,const ExtParameters & extParams,const char * name,const char * description)1350 TextureBufferOperationsViaImageStore::TextureBufferOperationsViaImageStore(Context&				context,
1351 																		   const ExtParameters& extParams,
1352 																		   const char* name, const char* description)
1353 	: TextureBufferOperations(context, extParams, name, description), m_is_cs_id(0), m_is_po_id(0)
1354 {
1355 }
1356 
1357 /** Initialize buffer object with test data using image store
1358  *
1359  **/
initializeBufferObjectData()1360 void TextureBufferOperationsViaImageStore::initializeBufferObjectData()
1361 {
1362 	/* Get Gl entry points */
1363 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1364 
1365 	/* Configure program object */
1366 	m_is_po_id = gl.createProgram();
1367 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
1368 
1369 	m_is_cs_id = gl.createShader(GL_COMPUTE_SHADER);
1370 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
1371 
1372 	std::string csSource = getISComputeShaderCode();
1373 	const char* csCode   = csSource.c_str();
1374 
1375 	if (!buildProgram(m_is_po_id, m_is_cs_id, 1, &csCode))
1376 	{
1377 		TCU_FAIL("Could not create a program from valid compute shader source!");
1378 	}
1379 
1380 	gl.useProgram(m_is_po_id);
1381 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
1382 
1383 	gl.bindImageTexture(m_image_unit, m_texbuff_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I);
1384 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
1385 
1386 	gl.dispatchCompute(1, 1, 1);
1387 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
1388 
1389 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1390 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
1391 
1392 	gl.useProgram(0);
1393 }
1394 
1395 /** Returns Compute Shader Code
1396  *
1397  * @return pointer to literal with Compute Shader Code
1398  */
getISComputeShaderCode() const1399 std::string TextureBufferOperationsViaImageStore::getISComputeShaderCode() const
1400 {
1401 	std::stringstream strstream;
1402 
1403 	strstream << "${VERSION}\n"
1404 				 "\n"
1405 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1406 				 "\n"
1407 				 "precision highp float;\n"
1408 				 "\n"
1409 				 "layout(rgba32i, binding = 0) uniform writeonly highp iimageBuffer image_buffer;\n"
1410 				 "\n"
1411 				 "layout (local_size_x = "
1412 			  << m_n_vectors_in_buffer_texture
1413 			  << " ) in;\n"
1414 				 "\n"
1415 				 "void main(void)\n"
1416 				 "{\n"
1417 				 "    imageStore(image_buffer, int(gl_LocalInvocationID.x), ivec4(gl_LocalInvocationID.x) );\n"
1418 				 "}\n";
1419 
1420 	return strstream.str();
1421 }
1422 
1423 /** Fill buffer with test data
1424  *
1425  * @param buffer      pointer to buffer
1426  * @param bufferLenth buffer length
1427  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)1428 void TextureBufferOperationsViaImageStore::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
1429 {
1430 	for (glw::GLuint i = 0; i < bufferLength; ++i)
1431 	{
1432 		buffer[i] = (glw::GLint)(i / m_n_vector_components);
1433 	}
1434 }
1435 
1436 /** Deinitializes GLES objects created during the test. */
deinit(void)1437 void TextureBufferOperationsViaImageStore::deinit(void)
1438 {
1439 	/* Get Gl entry points */
1440 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1441 
1442 	/* Reset GLES state */
1443 	gl.useProgram(0);
1444 
1445 	/* Delete GLES objects */
1446 	if (0 != m_is_po_id)
1447 	{
1448 		gl.deleteProgram(m_is_po_id);
1449 		m_is_po_id = 0;
1450 	}
1451 
1452 	if (0 != m_is_cs_id)
1453 	{
1454 		gl.deleteShader(m_is_cs_id);
1455 		m_is_cs_id = 0;
1456 	}
1457 
1458 	/* Deinitalize base class */
1459 	TextureBufferOperations::deinit();
1460 }
1461 
1462 /** Constructor for Test Case 6
1463  *
1464  *  @param context     Test context
1465  *  @param name        Test case's name
1466  *  @param description Test case's description
1467  **/
TextureBufferOperationsViaSSBOWrites(Context & context,const ExtParameters & extParams,const char * name,const char * description)1468 TextureBufferOperationsViaSSBOWrites::TextureBufferOperationsViaSSBOWrites(Context&				context,
1469 																		   const ExtParameters& extParams,
1470 																		   const char* name, const char* description)
1471 	: TextureBufferOperations(context, extParams, name, description), m_ssbo_cs_id(0), m_ssbo_po_id(0)
1472 {
1473 }
1474 
1475 /** Initialize buffer object with test data using ssbo writes
1476  *
1477  **/
initializeBufferObjectData()1478 void TextureBufferOperationsViaSSBOWrites::initializeBufferObjectData()
1479 {
1480 	/* Get Gl entry points */
1481 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1482 
1483 	/* Configure program object */
1484 	m_ssbo_po_id = gl.createProgram();
1485 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
1486 
1487 	m_ssbo_cs_id = gl.createShader(GL_COMPUTE_SHADER);
1488 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
1489 
1490 	std::string csSource = getSSBOComputeShaderCode();
1491 	const char* csCode   = csSource.c_str();
1492 
1493 	if (!buildProgram(m_ssbo_po_id, m_ssbo_cs_id, 1, &csCode))
1494 	{
1495 		TCU_FAIL("Could not create a program from valid compute shader source!");
1496 	}
1497 
1498 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_tb_bo_id);
1499 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
1500 
1501 	gl.useProgram(m_ssbo_po_id);
1502 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
1503 
1504 	gl.dispatchCompute(1, 1, 1);
1505 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
1506 
1507 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1508 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
1509 
1510 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1511 	gl.useProgram(0);
1512 }
1513 
1514 /** Returns Compute Shader Code
1515  *
1516  * @return pointer to literal with Compute Shader Code
1517  */
getSSBOComputeShaderCode() const1518 std::string TextureBufferOperationsViaSSBOWrites::getSSBOComputeShaderCode() const
1519 {
1520 	std::stringstream strstream;
1521 
1522 	strstream << "${VERSION}\n"
1523 				 "\n"
1524 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1525 				 "\n"
1526 				 "precision highp float;\n"
1527 				 "\n"
1528 				 "buffer ComputeSSBO\n"
1529 				 "{\n"
1530 				 "    ivec4 value[];\n"
1531 				 "} computeSSBO;\n"
1532 				 "\n"
1533 				 "layout (local_size_x = "
1534 			  << m_n_vectors_in_buffer_texture
1535 			  << " ) in;\n"
1536 				 "\n"
1537 				 "void main(void)\n"
1538 				 "{\n"
1539 				 "    computeSSBO.value[gl_LocalInvocationID.x] = ivec4(gl_LocalInvocationID.x);\n"
1540 				 "}\n";
1541 
1542 	return strstream.str();
1543 }
1544 
1545 /** Fill buffer with test data
1546  *
1547  * @param buffer      pointer to buffer
1548  * @param bufferLenth buffer length
1549  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)1550 void TextureBufferOperationsViaSSBOWrites::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
1551 {
1552 	for (glw::GLuint i = 0; i < bufferLength; ++i)
1553 	{
1554 		buffer[i] = (glw::GLint)(i / m_n_vector_components);
1555 	}
1556 }
1557 
1558 /** Deinitializes GLES objects created during the test. */
deinit(void)1559 void TextureBufferOperationsViaSSBOWrites::deinit(void)
1560 {
1561 	/* Get Gl entry points */
1562 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1563 
1564 	/* Reset GLES state */
1565 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1566 	gl.useProgram(0);
1567 
1568 	/* Delete GLES objects */
1569 	if (0 != m_ssbo_po_id)
1570 	{
1571 		gl.deleteProgram(m_ssbo_po_id);
1572 		m_ssbo_po_id = 0;
1573 	}
1574 
1575 	if (0 != m_ssbo_cs_id)
1576 	{
1577 		gl.deleteShader(m_ssbo_cs_id);
1578 		m_ssbo_cs_id = 0;
1579 	}
1580 
1581 	/* Deinitalize base class */
1582 	TextureBufferOperations::deinit();
1583 }
1584 
1585 } // namespace glcts
1586