• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
396 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
397 
398 	gl.bindImageTexture(0, m_texbuff_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32I);
399 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture to image unit!");
400 
401 	gl.dispatchCompute(1, 1, 1);
402 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
403 
404 	gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
405 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
406 
407 	/* Get result data */
408 	glw::GLint* result_mapped = (glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, size, GL_MAP_READ_BIT);
409 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space!");
410 
411 	memcpy(result, result_mapped, size);
412 
413 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
414 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping buffer object's data store from client's address space!");
415 
416 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
417 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
418 	gl.useProgram(0);
419 }
420 
iterateSecondPhase(glw::GLint * result)421 void TextureBufferOperations::iterateSecondPhase(glw::GLint* result)
422 {
423 	/* Get GL entry points */
424 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
425 
426 	gl.bindVertexArray(m_vao_id);
427 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
428 
429 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
430 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!");
431 
432 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
433 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
434 
435 	/* Attach output texture to framebuffer */
436 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0);
437 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to framebuffer's color attachment");
438 
439 	/* Check framebuffer status */
440 	checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
441 
442 	/* Configure view port */
443 	gl.viewport(0, 0, m_n_vectors_in_buffer_texture, 1);
444 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting viewport!");
445 
446 	/* Use program */
447 	gl.useProgram(m_po_vs_fs_id);
448 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error using program object!");
449 
450 	glw::GLint sampler_location = gl.getUniformLocation(m_po_vs_fs_id, "sampler_buffer");
451 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
452 	if (sampler_location == -1)
453 	{
454 		TCU_FAIL("Could not get uniform location");
455 	}
456 
457 	gl.uniform1i(sampler_location, 0);
458 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding sampler with texture unit!");
459 
460 	/* Configure vertex position attribute */
461 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
462 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
463 
464 	m_vertex_location = gl.getAttribLocation(m_po_vs_fs_id, "vs_position");
465 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
466 	if (m_vertex_location == -1)
467 	{
468 		TCU_FAIL("Could not get uniform location");
469 	}
470 
471 	gl.vertexAttribPointer(m_vertex_location, 4, GL_FLOAT, GL_FALSE, 0, 0);
472 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
473 
474 	gl.enableVertexAttribArray(m_vertex_location);
475 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
476 
477 	/* Configure index attribute */
478 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_indicies_id);
479 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
480 
481 	m_index_location = gl.getAttribLocation(m_po_vs_fs_id, "vs_index");
482 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
483 	if (m_index_location == -1)
484 	{
485 		TCU_FAIL("Could not get uniform location");
486 	}
487 
488 	gl.vertexAttribPointer(m_index_location, 1, GL_FLOAT, GL_FALSE, 0, 0);
489 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
490 
491 	gl.enableVertexAttribArray(m_index_location);
492 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
493 
494 	/* Clear texture */
495 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
496 	gl.clear(GL_COLOR_BUFFER_BIT);
497 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer");
498 
499 	/* Render */
500 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
501 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
502 
503 	/* Read result data */
504 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
505 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object !");
506 
507 	gl.readPixels(0, 0, m_n_vectors_in_buffer_texture, 1, GL_RGBA_INTEGER, GL_INT, result);
508 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels !");
509 
510 	gl.bindVertexArray(0);
511 	gl.bindTexture(GL_TEXTURE_2D, 0);
512 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
513 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
514 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
515 	gl.disableVertexAttribArray(m_vertex_location);
516 	gl.disableVertexAttribArray(m_index_location);
517 	gl.useProgram(0);
518 
519 	m_vertex_location = -1;
520 	m_index_location  = -1;
521 }
522 
523 /** Check if result data is the same as reference data - log error if not
524  *
525  * @param  reference pointer to buffer with reference data
526  * @param  result    pointer to buffer with result data
527  * @param  size      size of buffers
528  * @param  message   pointer to literal with message (informing about test phase)
529  *
530  * @return           returns true if reference data equals result data, otherwise log error and return false
531  */
verifyResults(glw::GLint * reference,glw::GLint * result,glw::GLuint size,const char * message)532 glw::GLboolean TextureBufferOperations::verifyResults(glw::GLint* reference, glw::GLint* result, glw::GLuint size,
533 													  const char* message)
534 {
535 	/* Log error if expected and result data is not equal */
536 	if (memcmp(reference, result, size))
537 	{
538 		std::stringstream referenceData;
539 		std::stringstream resultData;
540 
541 		referenceData << "[";
542 		resultData << "[";
543 
544 		glw::GLuint n_entries = static_cast<glw::GLuint>(size / sizeof(glw::GLint));
545 
546 		for (glw::GLuint i = 0; i < n_entries; ++i)
547 		{
548 			referenceData << reference[i] << ",";
549 			resultData << result[i] << ",";
550 		}
551 
552 		referenceData << "]";
553 		resultData << "]";
554 
555 		m_testCtx.getLog() << tcu::TestLog::Message << message
556 						   << "Result buffer contains different data than reference buffer\n"
557 						   << "Reference Buffer: " << referenceData.str() << "\n"
558 						   << "Result Buffer: " << resultData.str() << "\n"
559 						   << tcu::TestLog::EndMessage;
560 		return false;
561 	}
562 
563 	return true;
564 }
565 
566 /** Fill buffer with test data
567  *
568  * @param buffer      pointer to buffer
569  * @param bufferLenth buffer length
570  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)571 void TextureBufferOperations::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
572 {
573 	for (glw::GLuint i = 0; i < bufferLength; ++i)
574 	{
575 		buffer[i] = (glw::GLint)i;
576 	}
577 }
578 
579 /** Check Framebuffer Status - throw exception if status is different than GL_FRAMEBUFFER_COMPLETE
580  *
581  * @param framebuffer  - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
582  *
583  */
checkFramebufferStatus(glw::GLenum framebuffer)584 void TextureBufferOperations::checkFramebufferStatus(glw::GLenum framebuffer)
585 {
586 	/* Get GL entry points */
587 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
588 
589 	/* Check framebuffer status */
590 	glw::GLenum framebufferStatus = gl.checkFramebufferStatus(framebuffer);
591 
592 	if (GL_FRAMEBUFFER_COMPLETE != framebufferStatus)
593 	{
594 		switch (framebufferStatus)
595 		{
596 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
597 		{
598 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
599 		}
600 
601 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
602 		{
603 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
604 		}
605 
606 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
607 		{
608 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
609 		}
610 
611 		case GL_FRAMEBUFFER_UNSUPPORTED:
612 		{
613 			TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_UNSUPPORTED");
614 		}
615 
616 		default:
617 		{
618 			TCU_FAIL("Framebuffer incomplete, status not recognized");
619 		}
620 		}
621 	} /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
622 }
623 
624 /** Deinitializes GLES objects created during the test.
625  *
626  */
deinit(void)627 void TextureBufferOperations::deinit(void)
628 {
629 	/* Get GLES entry points */
630 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
631 
632 	/* Reset GLES state */
633 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, 0);
634 	gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, 0);
635 
636 	/* Delete GLES objects */
637 	if (0 != m_texbuff_id)
638 	{
639 		gl.deleteTextures(1, &m_texbuff_id);
640 		m_texbuff_id = 0;
641 	}
642 
643 	if (0 != m_tb_bo_id)
644 	{
645 		gl.deleteBuffers(1, &m_tb_bo_id);
646 		m_tb_bo_id = 0;
647 	}
648 
649 	deinitFirstPhase();
650 	deinitSecondPhase();
651 
652 	/* Deinitialize base class */
653 	TestCaseBase::deinit();
654 }
655 
deinitFirstPhase(void)656 void TextureBufferOperations::deinitFirstPhase(void)
657 {
658 	/* Get GLES entry points */
659 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
660 
661 	/* Reset GLES state */
662 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
663 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
664 	gl.useProgram(0);
665 
666 	/* Delete GLES objects */
667 	if (0 != m_po_cs_id)
668 	{
669 		gl.deleteProgram(m_po_cs_id);
670 		m_po_cs_id = 0;
671 	}
672 
673 	if (0 != m_cs_id)
674 	{
675 		gl.deleteShader(m_cs_id);
676 		m_cs_id = 0;
677 	}
678 
679 	if (0 != m_ssbo_bo_id)
680 	{
681 		gl.deleteBuffers(1, &m_ssbo_bo_id);
682 		m_ssbo_bo_id = 0;
683 	}
684 }
685 
deinitSecondPhase(void)686 void TextureBufferOperations::deinitSecondPhase(void)
687 {
688 	/* Get GLES entry points */
689 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
690 
691 	/* Reset GLES state */
692 	gl.bindVertexArray(0);
693 	gl.bindTexture(GL_TEXTURE_2D, 0);
694 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
695 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
696 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
697 
698 	if (m_vertex_location != -1)
699 	{
700 		gl.disableVertexAttribArray(m_vertex_location);
701 		m_vertex_location = -1;
702 	}
703 
704 	if (m_index_location != -1)
705 	{
706 		gl.disableVertexAttribArray(m_index_location);
707 		m_index_location = -1;
708 	}
709 
710 	gl.useProgram(0);
711 
712 	/* Delete GLES objects */
713 	if (0 != m_po_vs_fs_id)
714 	{
715 		gl.deleteProgram(m_po_vs_fs_id);
716 		m_po_vs_fs_id = 0;
717 	}
718 
719 	if (0 != m_fs_id)
720 	{
721 		gl.deleteShader(m_fs_id);
722 		m_fs_id = 0;
723 	}
724 
725 	if (0 != m_vs_id)
726 	{
727 		gl.deleteShader(m_vs_id);
728 		m_vs_id = 0;
729 	}
730 
731 	if (0 != m_fbo_id)
732 	{
733 		gl.deleteFramebuffers(1, &m_fbo_id);
734 		m_fbo_id = 0;
735 	}
736 
737 	if (0 != m_to_id)
738 	{
739 		gl.deleteTextures(1, &m_to_id);
740 		m_to_id = 0;
741 	}
742 
743 	if (0 != m_vao_id)
744 	{
745 		gl.deleteVertexArrays(1, &m_vao_id);
746 		m_vao_id = 0;
747 	}
748 
749 	if (0 != m_vbo_id)
750 	{
751 		gl.deleteBuffers(1, &m_vbo_id);
752 		m_vbo_id = 0;
753 	}
754 
755 	if (0 != m_vbo_indicies_id)
756 	{
757 		gl.deleteBuffers(1, &m_vbo_indicies_id);
758 		m_vbo_indicies_id = 0;
759 	}
760 }
761 
762 /** Constructor for Test Case 1
763  *
764  *  @param context     Test context
765  *  @param name        Test case's name
766  *  @param description Test case's description
767  **/
TextureBufferOperationsViaBufferObjectLoad(Context & context,const ExtParameters & extParams,const char * name,const char * description)768 TextureBufferOperationsViaBufferObjectLoad::TextureBufferOperationsViaBufferObjectLoad(Context&				context,
769 																					   const ExtParameters& extParams,
770 																					   const char*			name,
771 																					   const char*			description)
772 	: TextureBufferOperations(context, extParams, name, description)
773 {
774 }
775 
776 /** Initialize texture buffer object with test data using glBufferSubData()
777  *
778  **/
initializeBufferObjectData(void)779 void TextureBufferOperationsViaBufferObjectLoad::initializeBufferObjectData(void)
780 {
781 	/* Get GL entry points */
782 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
783 
784 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
785 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
786 
787 	gl.bufferSubData(m_glExtTokens.TEXTURE_BUFFER, 0,
788 					 m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), &data[0]);
789 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting buffer object data!");
790 }
791 
792 /** Constructor for Test Case 2
793  *
794  *  @param context     Test context
795  *  @param name        Test case's name
796  *  @param description Test case's description
797  **/
TextureBufferOperationsViaCPUWrites(Context & context,const ExtParameters & extParams,const char * name,const char * description)798 TextureBufferOperationsViaCPUWrites::TextureBufferOperationsViaCPUWrites(Context&			  context,
799 																		 const ExtParameters& extParams,
800 																		 const char* name, const char* description)
801 	: TextureBufferOperations(context, extParams, name, description)
802 {
803 }
804 
805 /** Initialize texture buffer object with test data using CPU Write
806  *
807  **/
initializeBufferObjectData(void)808 void TextureBufferOperationsViaCPUWrites::initializeBufferObjectData(void)
809 {
810 	/* Get GL entry points */
811 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
812 
813 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
814 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
815 
816 	glw::GLint* tempBuffer = (glw::GLint*)gl.mapBufferRange(
817 		m_glExtTokens.TEXTURE_BUFFER, 0, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint),
818 		GL_MAP_WRITE_BIT);
819 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space!");
820 
821 	for (glw::GLuint i = 0; i < data.size(); ++i)
822 	{
823 		tempBuffer[i] = data[i];
824 	}
825 
826 	gl.unmapBuffer(m_glExtTokens.TEXTURE_BUFFER);
827 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error ummapping buffer object's data store from client's address space!");
828 }
829 
830 /** Constructor for Test Case 3
831  *
832  *  @param context     Test context
833  *  @param name        Test case's name
834  *  @param description Test case's description
835  **/
TextureBufferOperationsViaFrambufferReadBack(Context & context,const ExtParameters & extParams,const char * name,const char * description)836 TextureBufferOperationsViaFrambufferReadBack::TextureBufferOperationsViaFrambufferReadBack(
837 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
838 	: TextureBufferOperations(context, extParams, name, description)
839 	, m_fb_fbo_id(0)
840 	, m_fb_fs_id(0)
841 	, m_fb_po_id(0)
842 	, m_fb_to_id(0)
843 	, m_fb_vao_id(0)
844 	, m_fb_vbo_id(0)
845 	, m_fb_vs_id(0)
846 	, m_position_location(-1)
847 {
848 }
849 
850 /** Initialize texture buffer object with test data using framebuffer readbacks to pixel buffer object
851  *
852  **/
initializeBufferObjectData()853 void TextureBufferOperationsViaFrambufferReadBack::initializeBufferObjectData()
854 {
855 	/* Get GL entry points */
856 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
857 
858 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
859 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
860 
861 	/* Configure vertex array object */
862 	gl.genVertexArrays(1, &m_fb_vao_id);
863 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
864 
865 	gl.bindVertexArray(m_fb_vao_id);
866 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
867 
868 	/* Prepare framebuffer object */
869 	gl.genFramebuffers(1, &m_fb_fbo_id);
870 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing framebuffer object!");
871 
872 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb_fbo_id);
873 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!");
874 
875 	/* Prepare texture object */
876 	gl.genTextures(1, &m_fb_to_id);
877 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
878 
879 	gl.bindTexture(GL_TEXTURE_2D, m_fb_to_id);
880 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
881 
882 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32I, m_n_vectors_in_buffer_texture /* width */, 1 /* height */);
883 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store!");
884 
885 	/* Attach texture to framebuffer */
886 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fb_to_id, 0);
887 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to framebuffer's color attachment!");
888 
889 	/* Check framebuffer status */
890 	checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
891 
892 	/* Configure view port */
893 	gl.viewport(0, 0, m_n_vectors_in_buffer_texture, 1);
894 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting viewport!");
895 
896 	/* Create program object */
897 	m_fb_po_id = gl.createProgram();
898 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
899 
900 	m_fb_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
901 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
902 
903 	m_fb_vs_id = gl.createShader(GL_VERTEX_SHADER);
904 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
905 
906 	std::string fsSource = getFBFragmentShaderCode();
907 	std::string vsSource = getFBVertexShaderCode();
908 
909 	const char* fsCode = fsSource.c_str();
910 	const char* vsCode = vsSource.c_str();
911 
912 	if (!buildProgram(m_fb_po_id, m_fb_fs_id, 1, &fsCode, m_fb_vs_id, 1, &vsCode))
913 	{
914 		TCU_FAIL("Could not create a program from valid vertex/fragment shader code!");
915 	}
916 
917 	/* Full screen quad */
918 	glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
919 								1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
920 
921 	/* Generate buffer object */
922 	gl.genBuffers(1, &m_fb_vbo_id);
923 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
924 
925 	/* Bind buffer object */
926 	gl.bindBuffer(GL_ARRAY_BUFFER, m_fb_vbo_id);
927 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
928 
929 	/* Set data for buffer object */
930 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
931 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting data for buffer object!");
932 
933 	gl.useProgram(m_fb_po_id);
934 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
935 
936 	m_position_location = gl.getAttribLocation(m_fb_po_id, "inPosition");
937 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
938 	if (m_position_location == -1)
939 	{
940 		TCU_FAIL("Could not get uniform location");
941 	}
942 
943 	gl.vertexAttribPointer(m_position_location, 4, GL_FLOAT, GL_FALSE, 0, 0);
944 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
945 
946 	gl.enableVertexAttribArray(m_position_location);
947 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
948 
949 	/* Clear texture */
950 	gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
951 	gl.clear(GL_COLOR_BUFFER_BIT);
952 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer");
953 
954 	/* Render */
955 	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
956 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
957 
958 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fb_fbo_id);
959 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding frame buffer object!");
960 
961 	/* Bind buffer object to pixel pack buffer */
962 	gl.bindBuffer(GL_PIXEL_PACK_BUFFER, m_tb_bo_id);
963 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object !");
964 
965 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
966 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_UNPACK_ALIGNMENT parameter to 1");
967 
968 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
969 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_PACK_ALIGNMENT parameter to 1");
970 
971 	/* Fill buffer object with data from framebuffer object's color attachment */
972 	gl.readPixels(0, 0, m_n_vectors_in_buffer_texture, 1, GL_RGBA_INTEGER, GL_INT, 0);
973 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels !");
974 
975 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
976 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_UNPACK_ALIGNMENT parameter to default value");
977 
978 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
979 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_PACK_ALIGNMENT parameter to default value");
980 
981 	gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
982 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
983 
984 	gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, m_tb_bo_id);
985 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
986 
987 	gl.bindVertexArray(0);
988 	gl.bindTexture(GL_TEXTURE_2D, 0);
989 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
990 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
991 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
992 
993 	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
994 		gl.disableVertexAttribArray(m_position_location);
995 
996 	gl.useProgram(0);
997 
998 	m_position_location = -1;
999 }
1000 
1001 /** Returns Fragment Shader Code
1002  *
1003  * @return pointer to literal with Fragment Shader Code
1004  */
getFBFragmentShaderCode() const1005 std::string TextureBufferOperationsViaFrambufferReadBack::getFBFragmentShaderCode() const
1006 {
1007 	std::stringstream strstream;
1008 
1009 	strstream << "${VERSION}\n"
1010 				 "\n"
1011 				 "precision highp float;\n"
1012 				 "\n"
1013 				 "out ivec4 color;\n"
1014 				 "\n"
1015 				 "void main(void)\n"
1016 				 "{\n"
1017 				 "    color = ivec4(0, 1, 0, 1);\n"
1018 				 "}\n";
1019 
1020 	return strstream.str();
1021 }
1022 
1023 /** Returns Vertex Shader Code
1024  *
1025  * @return pointer to literal with Vertex Shader Code
1026  */
getFBVertexShaderCode() const1027 std::string TextureBufferOperationsViaFrambufferReadBack::getFBVertexShaderCode() const
1028 {
1029 	std::stringstream strstream;
1030 
1031 	strstream << "${VERSION}\n"
1032 				 "\n"
1033 				 "precision highp float;\n"
1034 				 "\n"
1035 				 "in vec4 inPosition;\n"
1036 				 "\n"
1037 				 "void main(void)\n"
1038 				 "{\n"
1039 				 "    gl_Position = inPosition;\n"
1040 				 "}\n";
1041 
1042 	return strstream.str();
1043 }
1044 
1045 /** Fills buffer with test data
1046  *
1047  * @param buffer      pointer to buffer
1048  * @param bufferLenth buffer length
1049  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)1050 void TextureBufferOperationsViaFrambufferReadBack::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
1051 {
1052 	for (glw::GLuint i = 0; i < bufferLength; ++i)
1053 	{
1054 		buffer[i] = (glw::GLint)(i % 2); /* Reference color is 0, 1, 0, 1 */
1055 	}
1056 }
1057 
1058 /** Deinitializes GLES objects created during the test.
1059  *
1060  */
deinit(void)1061 void TextureBufferOperationsViaFrambufferReadBack::deinit(void)
1062 {
1063 	/* Get GL entry points */
1064 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1065 
1066 	/* Reset GLES state */
1067 	gl.bindVertexArray(0);
1068 	gl.bindTexture(GL_TEXTURE_2D, 0);
1069 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1070 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1071 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1072 
1073 	if (m_position_location != -1)
1074 	{
1075 		gl.disableVertexAttribArray(m_position_location);
1076 		m_position_location = -1;
1077 	}
1078 
1079 	gl.useProgram(0);
1080 
1081 	/* Delete GLES objects */
1082 	if (0 != m_fb_po_id)
1083 	{
1084 		gl.deleteProgram(m_fb_po_id);
1085 		m_fb_po_id = 0;
1086 	}
1087 
1088 	if (0 != m_fb_fs_id)
1089 	{
1090 		gl.deleteShader(m_fb_fs_id);
1091 		m_fb_fs_id = 0;
1092 	}
1093 
1094 	if (0 != m_fb_vs_id)
1095 	{
1096 		gl.deleteShader(m_fb_vs_id);
1097 		m_fb_vs_id = 0;
1098 	}
1099 
1100 	if (0 != m_fb_fbo_id)
1101 	{
1102 		gl.deleteFramebuffers(1, &m_fb_fbo_id);
1103 		m_fb_fbo_id = 0;
1104 	}
1105 
1106 	if (0 != m_fb_to_id)
1107 	{
1108 		gl.deleteTextures(1, &m_fb_to_id);
1109 		m_fb_to_id = 0;
1110 	}
1111 
1112 	if (0 != m_fb_vbo_id)
1113 	{
1114 		gl.deleteBuffers(1, &m_fb_vbo_id);
1115 		m_fb_vbo_id = 0;
1116 	}
1117 
1118 	if (0 != m_fb_vao_id)
1119 	{
1120 		gl.deleteVertexArrays(1, &m_fb_vao_id);
1121 		m_fb_vao_id = 0;
1122 	}
1123 
1124 	/* Deinitialize base class */
1125 	TextureBufferOperations::deinit();
1126 }
1127 
1128 /** Constructor for Test Case 4
1129  *
1130  *  @param context     Test context
1131  *  @param name        Test case's name
1132  *  @param description Test case's description
1133  **/
TextureBufferOperationsViaTransformFeedback(Context & context,const ExtParameters & extParams,const char * name,const char * description)1134 TextureBufferOperationsViaTransformFeedback::TextureBufferOperationsViaTransformFeedback(Context&			  context,
1135 																						 const ExtParameters& extParams,
1136 																						 const char*		  name,
1137 																						 const char* description)
1138 	: TextureBufferOperations(context, extParams, name, description)
1139 	, m_tf_fs_id(0)
1140 	, m_tf_po_id(0)
1141 	, m_tf_vao_id(0)
1142 	, m_tf_vbo_id(0)
1143 	, m_tf_vs_id(0)
1144 	, m_position_location(-1)
1145 {
1146 }
1147 
1148 /** Initialize buffer object with test data using transform feedback
1149  *
1150  **/
initializeBufferObjectData()1151 void TextureBufferOperationsViaTransformFeedback::initializeBufferObjectData()
1152 {
1153 	/* Get GL entry points */
1154 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1155 
1156 	std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
1157 	fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
1158 
1159 	/* Configure vertex array object */
1160 	gl.genVertexArrays(1, &m_tf_vao_id);
1161 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
1162 
1163 	gl.bindVertexArray(m_tf_vao_id);
1164 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
1165 
1166 	/* Configure buffer object*/
1167 	gl.genBuffers(1, &m_tf_vbo_id);
1168 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex buffer object!");
1169 
1170 	gl.bindBuffer(GL_ARRAY_BUFFER, m_tf_vbo_id);
1171 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex buffer object!");
1172 
1173 	gl.bufferData(GL_ARRAY_BUFFER, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), &data[0],
1174 				  GL_DYNAMIC_DRAW);
1175 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating buffer object's data store!");
1176 
1177 	m_tf_po_id = gl.createProgram();
1178 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
1179 
1180 	/* Setup transform feedback varyings */
1181 	const char* varyings[] = { "outPosition" };
1182 	gl.transformFeedbackVaryings(m_tf_po_id, 1, varyings, GL_SEPARATE_ATTRIBS);
1183 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error specifying transform feedback varyings!");
1184 
1185 	m_tf_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1186 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
1187 
1188 	m_tf_vs_id = gl.createShader(GL_VERTEX_SHADER);
1189 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
1190 
1191 	std::string fsSource = getTFFragmentShaderCode();
1192 	std::string vsSource = getTFVertexShaderCode();
1193 
1194 	const char* fsCode = fsSource.c_str();
1195 	const char* vsCode = vsSource.c_str();
1196 
1197 	if (!buildProgram(m_tf_po_id, m_tf_fs_id, 1, &fsCode, m_tf_vs_id, 1, &vsCode))
1198 	{
1199 		TCU_FAIL("Could not create a program from valid vertex/fragment shader code!");
1200 	}
1201 
1202 	gl.useProgram(m_tf_po_id);
1203 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
1204 
1205 	m_position_location = gl.getAttribLocation(m_tf_po_id, "inPosition");
1206 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting attrib location!");
1207 
1208 	gl.vertexAttribIPointer(m_position_location, m_n_vector_components, GL_INT, 0, 0);
1209 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting vertex attrib pointer!");
1210 
1211 	gl.enableVertexAttribArray(m_position_location);
1212 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error enabling vertex attrib array!");
1213 
1214 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tb_bo_id);
1215 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object to transform feedback binding point!");
1216 
1217 	gl.beginTransformFeedback(GL_POINTS);
1218 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error starting transform feedback!");
1219 
1220 	/* Render */
1221 	gl.drawArrays(GL_POINTS, 0, m_n_vectors_in_buffer_texture);
1222 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error during rendering!");
1223 
1224 	gl.endTransformFeedback();
1225 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error ending transform feedback!");
1226 
1227 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
1228 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1229 	gl.bindVertexArray(0);
1230 
1231 	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
1232 		gl.disableVertexAttribArray(m_position_location);
1233 
1234 	gl.useProgram(0);
1235 
1236 	gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1237 
1238 	m_position_location = -1;
1239 }
1240 
1241 /** Returns Fragment shader Code
1242  *
1243  * @return pointer to literal with Fragment Shader Code
1244  */
getTFFragmentShaderCode() const1245 std::string TextureBufferOperationsViaTransformFeedback::getTFFragmentShaderCode() const
1246 {
1247 	std::stringstream strstream;
1248 
1249 	strstream << "${VERSION}\n"
1250 				 "\n"
1251 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1252 				 "\n"
1253 				 "in flat ivec4 outPosition;\n"
1254 				 "\n"
1255 				 "precision highp float;\n"
1256 				 "\n"
1257 				 "void main(void)\n"
1258 				 "{\n"
1259 				 "}\n";
1260 
1261 	return strstream.str();
1262 }
1263 
1264 /** Returns Vertex Shader Code
1265  *
1266  * @return pointer to literal with Vertex Shader Code
1267  */
getTFVertexShaderCode() const1268 std::string TextureBufferOperationsViaTransformFeedback::getTFVertexShaderCode() const
1269 {
1270 	std::stringstream strstream;
1271 
1272 	strstream << "${VERSION}\n"
1273 				 "\n"
1274 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1275 				 "\n"
1276 				 "precision highp float;\n"
1277 				 "\n"
1278 				 "in ivec4 inPosition;\n"
1279 				 "\n"
1280 				 "flat out ivec4 outPosition;\n"
1281 				 "\n"
1282 				 "void main(void)\n"
1283 				 "{\n"
1284 				 "    gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
1285 				 "    outPosition = inPosition;\n"
1286 				 "}\n";
1287 
1288 	return strstream.str();
1289 }
1290 
1291 /** Deinitializes GLES objects created during the test. */
deinit(void)1292 void TextureBufferOperationsViaTransformFeedback::deinit(void)
1293 {
1294 	/* Get GL entry points */
1295 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1296 
1297 	/* Reset GLES state */
1298 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
1299 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1300 	gl.bindVertexArray(0);
1301 
1302 	if (m_position_location != -1)
1303 	{
1304 		gl.disableVertexAttribArray(m_position_location);
1305 		m_position_location = -1;
1306 	}
1307 
1308 	gl.useProgram(0);
1309 
1310 	/* Delete GLES objects */
1311 	if (0 != m_tf_po_id)
1312 	{
1313 		gl.deleteProgram(m_tf_po_id);
1314 		m_tf_po_id = 0;
1315 	}
1316 
1317 	if (0 != m_tf_vs_id)
1318 	{
1319 		gl.deleteShader(m_tf_vs_id);
1320 		m_tf_vs_id = 0;
1321 	}
1322 
1323 	if (0 != m_tf_fs_id)
1324 	{
1325 		gl.deleteShader(m_tf_fs_id);
1326 		m_tf_fs_id = 0;
1327 	}
1328 
1329 	if (0 != m_tf_vbo_id)
1330 	{
1331 		gl.deleteBuffers(1, &m_tf_vbo_id);
1332 		m_tf_vbo_id = 0;
1333 	}
1334 
1335 	if (0 != m_tf_vao_id)
1336 	{
1337 		gl.deleteVertexArrays(1, &m_tf_vao_id);
1338 		m_tf_vao_id = 0;
1339 	}
1340 
1341 	/* Deinitialize base class */
1342 	TextureBufferOperations::deinit();
1343 }
1344 
1345 const glw::GLuint TextureBufferOperationsViaImageStore::m_image_unit = 0;
1346 
1347 /** Constructor for Test Case 5
1348  *
1349  *  @param context     Test context
1350  *  @param name        Test case's name
1351  *  @param description Test case's description
1352  **/
TextureBufferOperationsViaImageStore(Context & context,const ExtParameters & extParams,const char * name,const char * description)1353 TextureBufferOperationsViaImageStore::TextureBufferOperationsViaImageStore(Context&				context,
1354 																		   const ExtParameters& extParams,
1355 																		   const char* name, const char* description)
1356 	: TextureBufferOperations(context, extParams, name, description), m_is_cs_id(0), m_is_po_id(0)
1357 {
1358 }
1359 
1360 /** Initialize buffer object with test data using image store
1361  *
1362  **/
initializeBufferObjectData()1363 void TextureBufferOperationsViaImageStore::initializeBufferObjectData()
1364 {
1365 	/* Get Gl entry points */
1366 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1367 
1368 	/* Configure program object */
1369 	m_is_po_id = gl.createProgram();
1370 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
1371 
1372 	m_is_cs_id = gl.createShader(GL_COMPUTE_SHADER);
1373 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
1374 
1375 	std::string csSource = getISComputeShaderCode();
1376 	const char* csCode   = csSource.c_str();
1377 
1378 	if (!buildProgram(m_is_po_id, m_is_cs_id, 1, &csCode))
1379 	{
1380 		TCU_FAIL("Could not create a program from valid compute shader source!");
1381 	}
1382 
1383 	gl.useProgram(m_is_po_id);
1384 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
1385 
1386 	gl.bindImageTexture(m_image_unit, m_texbuff_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I);
1387 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
1388 
1389 	gl.dispatchCompute(1, 1, 1);
1390 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
1391 
1392 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1393 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
1394 
1395 	gl.useProgram(0);
1396 }
1397 
1398 /** Returns Compute Shader Code
1399  *
1400  * @return pointer to literal with Compute Shader Code
1401  */
getISComputeShaderCode() const1402 std::string TextureBufferOperationsViaImageStore::getISComputeShaderCode() const
1403 {
1404 	std::stringstream strstream;
1405 
1406 	strstream << "${VERSION}\n"
1407 				 "\n"
1408 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1409 				 "\n"
1410 				 "precision highp float;\n"
1411 				 "\n"
1412 				 "layout(rgba32i, binding = 0) uniform writeonly highp iimageBuffer image_buffer;\n"
1413 				 "\n"
1414 				 "layout (local_size_x = "
1415 			  << m_n_vectors_in_buffer_texture
1416 			  << " ) in;\n"
1417 				 "\n"
1418 				 "void main(void)\n"
1419 				 "{\n"
1420 				 "    imageStore(image_buffer, int(gl_LocalInvocationID.x), ivec4(gl_LocalInvocationID.x) );\n"
1421 				 "}\n";
1422 
1423 	return strstream.str();
1424 }
1425 
1426 /** Fill buffer with test data
1427  *
1428  * @param buffer      pointer to buffer
1429  * @param bufferLenth buffer length
1430  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)1431 void TextureBufferOperationsViaImageStore::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
1432 {
1433 	for (glw::GLuint i = 0; i < bufferLength; ++i)
1434 	{
1435 		buffer[i] = (glw::GLint)(i / m_n_vector_components);
1436 	}
1437 }
1438 
1439 /** Deinitializes GLES objects created during the test. */
deinit(void)1440 void TextureBufferOperationsViaImageStore::deinit(void)
1441 {
1442 	/* Get Gl entry points */
1443 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1444 
1445 	/* Reset GLES state */
1446 	gl.useProgram(0);
1447 
1448 	/* Delete GLES objects */
1449 	if (0 != m_is_po_id)
1450 	{
1451 		gl.deleteProgram(m_is_po_id);
1452 		m_is_po_id = 0;
1453 	}
1454 
1455 	if (0 != m_is_cs_id)
1456 	{
1457 		gl.deleteShader(m_is_cs_id);
1458 		m_is_cs_id = 0;
1459 	}
1460 
1461 	/* Deinitalize base class */
1462 	TextureBufferOperations::deinit();
1463 }
1464 
1465 /** Constructor for Test Case 6
1466  *
1467  *  @param context     Test context
1468  *  @param name        Test case's name
1469  *  @param description Test case's description
1470  **/
TextureBufferOperationsViaSSBOWrites(Context & context,const ExtParameters & extParams,const char * name,const char * description)1471 TextureBufferOperationsViaSSBOWrites::TextureBufferOperationsViaSSBOWrites(Context&				context,
1472 																		   const ExtParameters& extParams,
1473 																		   const char* name, const char* description)
1474 	: TextureBufferOperations(context, extParams, name, description), m_ssbo_cs_id(0), m_ssbo_po_id(0)
1475 {
1476 }
1477 
1478 /** Initialize buffer object with test data using ssbo writes
1479  *
1480  **/
initializeBufferObjectData()1481 void TextureBufferOperationsViaSSBOWrites::initializeBufferObjectData()
1482 {
1483 	/* Get Gl entry points */
1484 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1485 
1486 	/* Configure program object */
1487 	m_ssbo_po_id = gl.createProgram();
1488 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
1489 
1490 	m_ssbo_cs_id = gl.createShader(GL_COMPUTE_SHADER);
1491 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
1492 
1493 	std::string csSource = getSSBOComputeShaderCode();
1494 	const char* csCode   = csSource.c_str();
1495 
1496 	if (!buildProgram(m_ssbo_po_id, m_ssbo_cs_id, 1, &csCode))
1497 	{
1498 		TCU_FAIL("Could not create a program from valid compute shader source!");
1499 	}
1500 
1501 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_tb_bo_id);
1502 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
1503 
1504 	gl.useProgram(m_ssbo_po_id);
1505 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
1506 
1507 	gl.dispatchCompute(1, 1, 1);
1508 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
1509 
1510 	gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1511 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
1512 
1513 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1514 	gl.useProgram(0);
1515 }
1516 
1517 /** Returns Compute Shader Code
1518  *
1519  * @return pointer to literal with Compute Shader Code
1520  */
getSSBOComputeShaderCode() const1521 std::string TextureBufferOperationsViaSSBOWrites::getSSBOComputeShaderCode() const
1522 {
1523 	std::stringstream strstream;
1524 
1525 	strstream << "${VERSION}\n"
1526 				 "\n"
1527 				 "${TEXTURE_BUFFER_REQUIRE}\n"
1528 				 "\n"
1529 				 "precision highp float;\n"
1530 				 "\n"
1531 				 "buffer ComputeSSBO\n"
1532 				 "{\n"
1533 				 "    ivec4 value[];\n"
1534 				 "} computeSSBO;\n"
1535 				 "\n"
1536 				 "layout (local_size_x = "
1537 			  << m_n_vectors_in_buffer_texture
1538 			  << " ) in;\n"
1539 				 "\n"
1540 				 "void main(void)\n"
1541 				 "{\n"
1542 				 "    computeSSBO.value[gl_LocalInvocationID.x] = ivec4(gl_LocalInvocationID.x);\n"
1543 				 "}\n";
1544 
1545 	return strstream.str();
1546 }
1547 
1548 /** Fill buffer with test data
1549  *
1550  * @param buffer      pointer to buffer
1551  * @param bufferLenth buffer length
1552  */
fillBufferWithData(glw::GLint * buffer,glw::GLuint bufferLength)1553 void TextureBufferOperationsViaSSBOWrites::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
1554 {
1555 	for (glw::GLuint i = 0; i < bufferLength; ++i)
1556 	{
1557 		buffer[i] = (glw::GLint)(i / m_n_vector_components);
1558 	}
1559 }
1560 
1561 /** Deinitializes GLES objects created during the test. */
deinit(void)1562 void TextureBufferOperationsViaSSBOWrites::deinit(void)
1563 {
1564 	/* Get Gl entry points */
1565 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1566 
1567 	/* Reset GLES state */
1568 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1569 	gl.useProgram(0);
1570 
1571 	/* Delete GLES objects */
1572 	if (0 != m_ssbo_po_id)
1573 	{
1574 		gl.deleteProgram(m_ssbo_po_id);
1575 		m_ssbo_po_id = 0;
1576 	}
1577 
1578 	if (0 != m_ssbo_cs_id)
1579 	{
1580 		gl.deleteShader(m_ssbo_cs_id);
1581 		m_ssbo_cs_id = 0;
1582 	}
1583 
1584 	/* Deinitalize base class */
1585 	TextureBufferOperations::deinit();
1586 }
1587 
1588 } // namespace glcts
1589