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