blob: 0d80ba01d9eb580c446ae5c75b422ad8f9e4265d [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2014-2016 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/ /*!
* \file
* \brief
*/ /*-------------------------------------------------------------------*/
/*!
* \file esextcTextureBufferOperations.cpp
* \brief Texture Buffer Operations (Test 1)
*/ /*-------------------------------------------------------------------*/
#include "esextcTextureBufferOperations.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuTestLog.hpp"
#include <cstring>
#include <iostream>
#include <vector>
namespace glcts
{
const glw::GLuint TextureBufferOperations::m_n_vector_components = 4;
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperations::TextureBufferOperations(Context& context, const ExtParameters& extParams, const char* name,
const char* description)
: TestCaseBase(context, extParams, name, description)
, m_n_vectors_in_buffer_texture(0)
, m_tb_bo_id(0)
, m_texbuff_id(0)
, m_cs_id(0)
, m_po_cs_id(0)
, m_ssbo_bo_id(0)
, m_fbo_id(0)
, m_fs_id(0)
, m_po_vs_fs_id(0)
, m_to_id(0)
, m_vao_id(0)
, m_vbo_id(0)
, m_vbo_indicies_id(0)
, m_vs_id(0)
, m_vertex_location(-1)
, m_index_location(-1)
{
/* Nothing to be done here */
}
/** Initializes GLES objects used during the test.
*
*/
void TextureBufferOperations::initTest(void)
{
/* Check if texture buffer extension is supported */
if (!m_is_texture_buffer_supported)
{
throw tcu::NotSupportedError(TEXTURE_BUFFER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
}
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.getIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &m_n_vectors_in_buffer_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting GL_MAX_COMPUTE_WORK_GROUP_SIZE parameter value!");
/* Create buffer object*/
gl.genBuffers(1, &m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object !");
gl.bufferData(m_glExtTokens.TEXTURE_BUFFER,
m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), 0, GL_DYNAMIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating data store for buffer object!");
/* Create texture buffer */
gl.genTextures(1, &m_texbuff_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active texture unit!");
gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, m_texbuff_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.texBuffer(m_glExtTokens.TEXTURE_BUFFER, GL_RGBA32I, m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object to texture buffer!");
/* Initialize texture buffer object */
initializeBufferObjectData();
/* Initialize first phase */
initFirstPhase();
/* Initialize second phase */
initSecondPhase();
}
void TextureBufferOperations::initFirstPhase(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Create program object */
m_po_cs_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating shader object!");
std::string csSource = getComputeShaderCode();
const char* csCode = csSource.c_str();
if (!buildProgram(m_po_cs_id, m_cs_id, 1, &csCode))
{
TCU_FAIL("Could not create a program from valid compute shader code!");
}
/* Create Shader Storage Buffer Object */
gl.genBuffers(1, &m_ssbo_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
gl.bindBuffer(GL_ARRAY_BUFFER, m_ssbo_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
gl.bufferData(GL_ARRAY_BUFFER, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), 0,
GL_DYNAMIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating data store for buffer object!");
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
}
/** Returns Compute shader Code
*
* @return pointer to literal with Compute Shader Code
*/
std::string TextureBufferOperations::getComputeShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"layout(rgba32i, binding = 0) uniform readonly highp iimageBuffer image_buffer;\n"
"\n"
"buffer ComputeSSBO\n"
"{\n"
" ivec4 value[];\n"
"} computeSSBO;\n"
"\n"
"layout (local_size_x = "
<< m_n_vectors_in_buffer_texture << " ) in;\n"
"\n"
"void main(void)\n"
"{\n"
" int index = int(gl_LocalInvocationID.x);\n"
" computeSSBO.value[index] = imageLoad( image_buffer, index);\n"
"}\n";
return strstream.str();
}
void TextureBufferOperations::initSecondPhase(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Create vertex array object */
gl.genVertexArrays(1, &m_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
/* Create framebuffer object */
gl.genFramebuffers(1, &m_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing framebuffer object!");
/* Prepare texture object */
gl.genTextures(1, &m_to_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing texture buffer!");
gl.bindTexture(GL_TEXTURE_2D, m_to_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32I, m_n_vectors_in_buffer_texture /* width */, 1 /* height */);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's texel data!");
/* Set GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER parameters values to GL_NEAREST*/
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for GL_TEXTURE_MAG_FILTER parameter!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for GL_TEXTURE_MIN_FILTER parameter!");
gl.bindTexture(GL_TEXTURE_2D, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
/* Create program object */
m_po_vs_fs_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
m_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
std::string fsSource = getFragmentShaderCode();
std::string vsSource = getVertexShaderCode();
const char* fsCode = fsSource.c_str();
const char* vsCode = vsSource.c_str();
if (!buildProgram(m_po_vs_fs_id, m_fs_id, 1, &fsCode, m_vs_id, 1, &vsCode))
{
TCU_FAIL("Could not create a program from valid vertex/fragment shader source!");
}
/* Full screen quad */
glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
/* Generate buffer object */
gl.genBuffers(1, &m_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
/* Bind buffer object */
gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
/* Set data for buffer object */
gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting data for buffer object!");
/* Indicies */
glw::GLfloat indicies[] = { 0.f, 0.f, static_cast<glw::GLfloat>(m_n_vectors_in_buffer_texture) * 1.f,
static_cast<glw::GLfloat>(m_n_vectors_in_buffer_texture) * 1.f };
/* Generate buffer object */
gl.genBuffers(1, &m_vbo_indicies_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
/* Bind buffer object */
gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_indicies_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
/* Set data for buffer object */
gl.bufferData(GL_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error seting data for buffer object!");
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
}
/** Returns Fragment Shader Code
*
* @return pointer to literal with Fragment Shader Code
*/
std::string TextureBufferOperations::getFragmentShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"in float fs_index;\n"
"\n"
"layout(location = 0) out ivec4 color;\n"
"\n"
"uniform highp isamplerBuffer sampler_buffer;\n"
"\n"
"void main(void)\n"
"{\n"
" color = texelFetch( sampler_buffer, int(fs_index) );\n "
"}\n";
return strstream.str();
}
/** Returns Vertex Shader Code
*
* @return pointer to literal with Vertex Shader Code
*/
std::string TextureBufferOperations::getVertexShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"in vec4 vs_position;\n"
"in float vs_index;\n"
"\n"
"out float fs_index;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_Position = vs_position;\n"
" fs_index = vs_index;\n"
"}\n";
return strstream.str();
}
/** Executes the test.
*
* Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
*
* Note the function throws exception should an error occur!
*
* @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
**/
tcu::TestNode::IterateResult TextureBufferOperations::iterate(void)
{
/* Initialize */
initTest();
/* Get GL entry points */
glw::GLboolean test_result = true;
/* Prepare expected data */
std::vector<glw::GLint> reference(m_n_vectors_in_buffer_texture * m_n_vector_components);
fillBufferWithData(&reference[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
std::vector<glw::GLint> result(m_n_vectors_in_buffer_texture * m_n_vector_components);
iterateFirstPhase(&result[0], static_cast<glw::GLuint>(m_n_vectors_in_buffer_texture * m_n_vector_components *
sizeof(glw::GLint)));
if (!verifyResults(&reference[0], &result[0], static_cast<glw::GLuint>(m_n_vectors_in_buffer_texture *
m_n_vector_components * sizeof(glw::GLint)),
"1st Phase Compute Shader\n"))
{
test_result = false;
}
iterateSecondPhase(&result[0]);
if (!verifyResults(&reference[0], &result[0], static_cast<glw::GLuint>(m_n_vectors_in_buffer_texture *
m_n_vector_components * sizeof(glw::GLint)),
"2st Phase Vertex + Fragment Shader\n"))
{
test_result = false;
}
if (test_result)
{
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
}
else
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
return STOP;
}
void TextureBufferOperations::iterateFirstPhase(glw::GLint* result, glw::GLuint size)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindBuffer(GL_ARRAY_BUFFER, m_ssbo_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
gl.useProgram(m_po_cs_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program!");
gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
gl.bindImageTexture(0, m_texbuff_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32I);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture to image unit!");
gl.dispatchCompute(1, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
/* Get result data */
glw::GLint* result_mapped = (glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, size, GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space!");
memcpy(result, result_mapped, size);
gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping buffer object's data store from client's address space!");
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
gl.useProgram(0);
}
void TextureBufferOperations::iterateSecondPhase(glw::GLint* result)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindVertexArray(m_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!");
gl.bindTexture(GL_TEXTURE_2D, m_to_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
/* Attach output texture to framebuffer */
gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to framebuffer's color attachment");
/* Check framebuffer status */
checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
/* Configure view port */
gl.viewport(0, 0, m_n_vectors_in_buffer_texture, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting viewport!");
/* Use program */
gl.useProgram(m_po_vs_fs_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error using program object!");
glw::GLint sampler_location = gl.getUniformLocation(m_po_vs_fs_id, "sampler_buffer");
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
if (sampler_location == -1)
{
TCU_FAIL("Could not get uniform location");
}
gl.uniform1i(sampler_location, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding sampler with texture unit!");
/* Configure vertex position attribute */
gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
m_vertex_location = gl.getAttribLocation(m_po_vs_fs_id, "vs_position");
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
if (m_vertex_location == -1)
{
TCU_FAIL("Could not get uniform location");
}
gl.vertexAttribPointer(m_vertex_location, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
gl.enableVertexAttribArray(m_vertex_location);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
/* Configure index attribute */
gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_indicies_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!");
m_index_location = gl.getAttribLocation(m_po_vs_fs_id, "vs_index");
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
if (m_index_location == -1)
{
TCU_FAIL("Could not get uniform location");
}
gl.vertexAttribPointer(m_index_location, 1, GL_FLOAT, GL_FALSE, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
gl.enableVertexAttribArray(m_index_location);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
/* Clear texture */
gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer");
/* Render */
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
/* Read result data */
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object !");
gl.readPixels(0, 0, m_n_vectors_in_buffer_texture, 1, GL_RGBA_INTEGER, GL_INT, result);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels !");
gl.bindVertexArray(0);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
gl.disableVertexAttribArray(m_vertex_location);
gl.disableVertexAttribArray(m_index_location);
gl.useProgram(0);
m_vertex_location = -1;
m_index_location = -1;
}
/** Check if result data is the same as reference data - log error if not
*
* @param reference pointer to buffer with reference data
* @param result pointer to buffer with result data
* @param size size of buffers
* @param message pointer to literal with message (informing about test phase)
*
* @return returns true if reference data equals result data, otherwise log error and return false
*/
glw::GLboolean TextureBufferOperations::verifyResults(glw::GLint* reference, glw::GLint* result, glw::GLuint size,
const char* message)
{
/* Log error if expected and result data is not equal */
if (memcmp(reference, result, size))
{
std::stringstream referenceData;
std::stringstream resultData;
referenceData << "[";
resultData << "[";
glw::GLuint n_entries = static_cast<glw::GLuint>(size / sizeof(glw::GLint));
for (glw::GLuint i = 0; i < n_entries; ++i)
{
referenceData << reference[i] << ",";
resultData << result[i] << ",";
}
referenceData << "]";
resultData << "]";
m_testCtx.getLog() << tcu::TestLog::Message << message
<< "Result buffer contains different data than reference buffer\n"
<< "Reference Buffer: " << referenceData.str() << "\n"
<< "Result Buffer: " << resultData.str() << "\n"
<< tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** Fill buffer with test data
*
* @param buffer pointer to buffer
* @param bufferLenth buffer length
*/
void TextureBufferOperations::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
{
for (glw::GLuint i = 0; i < bufferLength; ++i)
{
buffer[i] = (glw::GLint)i;
}
}
/** Check Framebuffer Status - throw exception if status is different than GL_FRAMEBUFFER_COMPLETE
*
* @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
*
*/
void TextureBufferOperations::checkFramebufferStatus(glw::GLenum framebuffer)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Check framebuffer status */
glw::GLenum framebufferStatus = gl.checkFramebufferStatus(framebuffer);
if (GL_FRAMEBUFFER_COMPLETE != framebufferStatus)
{
switch (framebufferStatus)
{
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
{
TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
}
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
{
TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
}
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
{
TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
}
case GL_FRAMEBUFFER_UNSUPPORTED:
{
TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_UNSUPPORTED");
}
default:
{
TCU_FAIL("Framebuffer incomplete, status not recognized");
}
}
} /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
}
/** Deinitializes GLES objects created during the test.
*
*/
void TextureBufferOperations::deinit(void)
{
/* Get GLES entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, 0);
gl.bindTexture(m_glExtTokens.TEXTURE_BUFFER, 0);
/* Delete GLES objects */
if (0 != m_texbuff_id)
{
gl.deleteTextures(1, &m_texbuff_id);
m_texbuff_id = 0;
}
if (0 != m_tb_bo_id)
{
gl.deleteBuffers(1, &m_tb_bo_id);
m_tb_bo_id = 0;
}
deinitFirstPhase();
deinitSecondPhase();
/* Deinitialize base class */
TestCaseBase::deinit();
}
void TextureBufferOperations::deinitFirstPhase(void)
{
/* Get GLES entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
gl.useProgram(0);
/* Delete GLES objects */
if (0 != m_po_cs_id)
{
gl.deleteProgram(m_po_cs_id);
m_po_cs_id = 0;
}
if (0 != m_cs_id)
{
gl.deleteShader(m_cs_id);
m_cs_id = 0;
}
if (0 != m_ssbo_bo_id)
{
gl.deleteBuffers(1, &m_ssbo_bo_id);
m_ssbo_bo_id = 0;
}
}
void TextureBufferOperations::deinitSecondPhase(void)
{
/* Get GLES entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindVertexArray(0);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
if (m_vertex_location != -1)
{
gl.disableVertexAttribArray(m_vertex_location);
m_vertex_location = -1;
}
if (m_index_location != -1)
{
gl.disableVertexAttribArray(m_index_location);
m_index_location = -1;
}
gl.useProgram(0);
/* Delete GLES objects */
if (0 != m_po_vs_fs_id)
{
gl.deleteProgram(m_po_vs_fs_id);
m_po_vs_fs_id = 0;
}
if (0 != m_fs_id)
{
gl.deleteShader(m_fs_id);
m_fs_id = 0;
}
if (0 != m_vs_id)
{
gl.deleteShader(m_vs_id);
m_vs_id = 0;
}
if (0 != m_fbo_id)
{
gl.deleteFramebuffers(1, &m_fbo_id);
m_fbo_id = 0;
}
if (0 != m_to_id)
{
gl.deleteTextures(1, &m_to_id);
m_to_id = 0;
}
if (0 != m_vao_id)
{
gl.deleteVertexArrays(1, &m_vao_id);
m_vao_id = 0;
}
if (0 != m_vbo_id)
{
gl.deleteBuffers(1, &m_vbo_id);
m_vbo_id = 0;
}
if (0 != m_vbo_indicies_id)
{
gl.deleteBuffers(1, &m_vbo_indicies_id);
m_vbo_indicies_id = 0;
}
}
/** Constructor for Test Case 1
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperationsViaBufferObjectLoad::TextureBufferOperationsViaBufferObjectLoad(Context& context,
const ExtParameters& extParams,
const char* name,
const char* description)
: TextureBufferOperations(context, extParams, name, description)
{
}
/** Initialize texture buffer object with test data using glBufferSubData()
*
**/
void TextureBufferOperationsViaBufferObjectLoad::initializeBufferObjectData(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
gl.bufferSubData(m_glExtTokens.TEXTURE_BUFFER, 0,
m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), &data[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting buffer object data!");
}
/** Constructor for Test Case 2
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperationsViaCPUWrites::TextureBufferOperationsViaCPUWrites(Context& context,
const ExtParameters& extParams,
const char* name, const char* description)
: TextureBufferOperations(context, extParams, name, description)
{
}
/** Initialize texture buffer object with test data using CPU Write
*
**/
void TextureBufferOperationsViaCPUWrites::initializeBufferObjectData(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
glw::GLint* tempBuffer = (glw::GLint*)gl.mapBufferRange(
m_glExtTokens.TEXTURE_BUFFER, 0, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint),
GL_MAP_WRITE_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space!");
for (glw::GLuint i = 0; i < data.size(); ++i)
{
tempBuffer[i] = data[i];
}
gl.unmapBuffer(m_glExtTokens.TEXTURE_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error ummapping buffer object's data store from client's address space!");
}
/** Constructor for Test Case 3
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperationsViaFrambufferReadBack::TextureBufferOperationsViaFrambufferReadBack(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureBufferOperations(context, extParams, name, description)
, m_fb_fbo_id(0)
, m_fb_fs_id(0)
, m_fb_po_id(0)
, m_fb_to_id(0)
, m_fb_vao_id(0)
, m_fb_vbo_id(0)
, m_fb_vs_id(0)
, m_position_location(-1)
{
}
/** Initialize texture buffer object with test data using framebuffer readbacks to pixel buffer object
*
**/
void TextureBufferOperationsViaFrambufferReadBack::initializeBufferObjectData()
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
/* Configure vertex array object */
gl.genVertexArrays(1, &m_fb_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
gl.bindVertexArray(m_fb_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
/* Prepare framebuffer object */
gl.genFramebuffers(1, &m_fb_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error genertaing framebuffer object!");
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fb_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!");
/* Prepare texture object */
gl.genTextures(1, &m_fb_to_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
gl.bindTexture(GL_TEXTURE_2D, m_fb_to_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32I, m_n_vectors_in_buffer_texture /* width */, 1 /* height */);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating texture object's data store!");
/* Attach texture to framebuffer */
gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_fb_to_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to framebuffer's color attachment!");
/* Check framebuffer status */
checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
/* Configure view port */
gl.viewport(0, 0, m_n_vectors_in_buffer_texture, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting viewport!");
/* Create program object */
m_fb_po_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
m_fb_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
m_fb_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
std::string fsSource = getFBFragmentShaderCode();
std::string vsSource = getFBVertexShaderCode();
const char* fsCode = fsSource.c_str();
const char* vsCode = vsSource.c_str();
if (!buildProgram(m_fb_po_id, m_fb_fs_id, 1, &fsCode, m_fb_vs_id, 1, &vsCode))
{
TCU_FAIL("Could not create a program from valid vertex/fragment shader code!");
}
/* Full screen quad */
glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
/* Generate buffer object */
gl.genBuffers(1, &m_fb_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!");
/* Bind buffer object */
gl.bindBuffer(GL_ARRAY_BUFFER, m_fb_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
/* Set data for buffer object */
gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting data for buffer object!");
gl.useProgram(m_fb_po_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
m_position_location = gl.getAttribLocation(m_fb_po_id, "inPosition");
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!");
if (m_position_location == -1)
{
TCU_FAIL("Could not get uniform location");
}
gl.vertexAttribPointer(m_position_location, 4, GL_FLOAT, GL_FALSE, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!");
gl.enableVertexAttribArray(m_position_location);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!");
/* Clear texture */
gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer");
/* Render */
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fb_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding frame buffer object!");
/* Bind buffer object to pixel pack buffer */
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object !");
gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_UNPACK_ALIGNMENT parameter to 1");
gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_PACK_ALIGNMENT parameter to 1");
/* Fill buffer object with data from framebuffer object's color attachment */
gl.readPixels(0, 0, m_n_vectors_in_buffer_texture, 1, GL_RGBA_INTEGER, GL_INT, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels !");
gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_UNPACK_ALIGNMENT parameter to default value");
gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_PACK_ALIGNMENT parameter to default value");
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
gl.bindBuffer(m_glExtTokens.TEXTURE_BUFFER, m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!");
gl.bindVertexArray(0);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
if (glu::isContextTypeES(m_context.getRenderContext().getType()))
gl.disableVertexAttribArray(m_position_location);
gl.useProgram(0);
m_position_location = -1;
}
/** Returns Fragment Shader Code
*
* @return pointer to literal with Fragment Shader Code
*/
std::string TextureBufferOperationsViaFrambufferReadBack::getFBFragmentShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"out ivec4 color;\n"
"\n"
"void main(void)\n"
"{\n"
" color = ivec4(0, 1, 0, 1);\n"
"}\n";
return strstream.str();
}
/** Returns Vertex Shader Code
*
* @return pointer to literal with Vertex Shader Code
*/
std::string TextureBufferOperationsViaFrambufferReadBack::getFBVertexShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"in vec4 inPosition;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_Position = inPosition;\n"
"}\n";
return strstream.str();
}
/** Fills buffer with test data
*
* @param buffer pointer to buffer
* @param bufferLenth buffer length
*/
void TextureBufferOperationsViaFrambufferReadBack::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
{
for (glw::GLuint i = 0; i < bufferLength; ++i)
{
buffer[i] = (glw::GLint)(i % 2); /* Reference color is 0, 1, 0, 1 */
}
}
/** Deinitializes GLES objects created during the test.
*
*/
void TextureBufferOperationsViaFrambufferReadBack::deinit(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindVertexArray(0);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
if (m_position_location != -1)
{
gl.disableVertexAttribArray(m_position_location);
m_position_location = -1;
}
gl.useProgram(0);
/* Delete GLES objects */
if (0 != m_fb_po_id)
{
gl.deleteProgram(m_fb_po_id);
m_fb_po_id = 0;
}
if (0 != m_fb_fs_id)
{
gl.deleteShader(m_fb_fs_id);
m_fb_fs_id = 0;
}
if (0 != m_fb_vs_id)
{
gl.deleteShader(m_fb_vs_id);
m_fb_vs_id = 0;
}
if (0 != m_fb_fbo_id)
{
gl.deleteFramebuffers(1, &m_fb_fbo_id);
m_fb_fbo_id = 0;
}
if (0 != m_fb_to_id)
{
gl.deleteTextures(1, &m_fb_to_id);
m_fb_to_id = 0;
}
if (0 != m_fb_vbo_id)
{
gl.deleteBuffers(1, &m_fb_vbo_id);
m_fb_vbo_id = 0;
}
if (0 != m_fb_vao_id)
{
gl.deleteVertexArrays(1, &m_fb_vao_id);
m_fb_vao_id = 0;
}
/* Deinitialize base class */
TextureBufferOperations::deinit();
}
/** Constructor for Test Case 4
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperationsViaTransformFeedback::TextureBufferOperationsViaTransformFeedback(Context& context,
const ExtParameters& extParams,
const char* name,
const char* description)
: TextureBufferOperations(context, extParams, name, description)
, m_tf_fs_id(0)
, m_tf_po_id(0)
, m_tf_vao_id(0)
, m_tf_vbo_id(0)
, m_tf_vs_id(0)
, m_position_location(-1)
{
}
/** Initialize buffer object with test data using transform feedback
*
**/
void TextureBufferOperationsViaTransformFeedback::initializeBufferObjectData()
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
std::vector<glw::GLint> data(m_n_vectors_in_buffer_texture * m_n_vector_components);
fillBufferWithData(&data[0], m_n_vectors_in_buffer_texture * m_n_vector_components);
/* Configure vertex array object */
gl.genVertexArrays(1, &m_tf_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex array object!");
gl.bindVertexArray(m_tf_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
/* Configure buffer object*/
gl.genBuffers(1, &m_tf_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating vertex buffer object!");
gl.bindBuffer(GL_ARRAY_BUFFER, m_tf_vbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex buffer object!");
gl.bufferData(GL_ARRAY_BUFFER, m_n_vectors_in_buffer_texture * m_n_vector_components * sizeof(glw::GLint), &data[0],
GL_DYNAMIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating buffer object's data store!");
m_tf_po_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
/* Setup transform feedback varyings */
const char* varyings[] = { "outPosition" };
gl.transformFeedbackVaryings(m_tf_po_id, 1, varyings, GL_SEPARATE_ATTRIBS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error specifying transform feedback varyings!");
m_tf_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating fragment shader object!");
m_tf_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating vertex shader object!");
std::string fsSource = getTFFragmentShaderCode();
std::string vsSource = getTFVertexShaderCode();
const char* fsCode = fsSource.c_str();
const char* vsCode = vsSource.c_str();
if (!buildProgram(m_tf_po_id, m_tf_fs_id, 1, &fsCode, m_tf_vs_id, 1, &vsCode))
{
TCU_FAIL("Could not create a program from valid vertex/fragment shader code!");
}
gl.useProgram(m_tf_po_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
m_position_location = gl.getAttribLocation(m_tf_po_id, "inPosition");
GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting attrib location!");
gl.vertexAttribIPointer(m_position_location, m_n_vector_components, GL_INT, 0, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting vertex attrib pointer!");
gl.enableVertexAttribArray(m_position_location);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error enabling vertex attrib array!");
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object to transform feedback binding point!");
gl.beginTransformFeedback(GL_POINTS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error starting transform feedback!");
/* Render */
gl.drawArrays(GL_POINTS, 0, m_n_vectors_in_buffer_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error during rendering!");
gl.endTransformFeedback();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error ending transform feedback!");
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
gl.bindVertexArray(0);
if (glu::isContextTypeES(m_context.getRenderContext().getType()))
gl.disableVertexAttribArray(m_position_location);
gl.useProgram(0);
gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
m_position_location = -1;
}
/** Returns Fragment shader Code
*
* @return pointer to literal with Fragment Shader Code
*/
std::string TextureBufferOperationsViaTransformFeedback::getTFFragmentShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"in flat ivec4 outPosition;\n"
"\n"
"precision highp float;\n"
"\n"
"void main(void)\n"
"{\n"
"}\n";
return strstream.str();
}
/** Returns Vertex Shader Code
*
* @return pointer to literal with Vertex Shader Code
*/
std::string TextureBufferOperationsViaTransformFeedback::getTFVertexShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"in ivec4 inPosition;\n"
"\n"
"flat out ivec4 outPosition;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
" outPosition = inPosition;\n"
"}\n";
return strstream.str();
}
/** Deinitializes GLES objects created during the test. */
void TextureBufferOperationsViaTransformFeedback::deinit(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
gl.bindBuffer(GL_ARRAY_BUFFER, 0);
gl.bindVertexArray(0);
if (m_position_location != -1)
{
gl.disableVertexAttribArray(m_position_location);
m_position_location = -1;
}
gl.useProgram(0);
/* Delete GLES objects */
if (0 != m_tf_po_id)
{
gl.deleteProgram(m_tf_po_id);
m_tf_po_id = 0;
}
if (0 != m_tf_vs_id)
{
gl.deleteShader(m_tf_vs_id);
m_tf_vs_id = 0;
}
if (0 != m_tf_fs_id)
{
gl.deleteShader(m_tf_fs_id);
m_tf_fs_id = 0;
}
if (0 != m_tf_vbo_id)
{
gl.deleteBuffers(1, &m_tf_vbo_id);
m_tf_vbo_id = 0;
}
if (0 != m_tf_vao_id)
{
gl.deleteVertexArrays(1, &m_tf_vao_id);
m_tf_vao_id = 0;
}
/* Deinitialize base class */
TextureBufferOperations::deinit();
}
const glw::GLuint TextureBufferOperationsViaImageStore::m_image_unit = 0;
/** Constructor for Test Case 5
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperationsViaImageStore::TextureBufferOperationsViaImageStore(Context& context,
const ExtParameters& extParams,
const char* name, const char* description)
: TextureBufferOperations(context, extParams, name, description), m_is_cs_id(0), m_is_po_id(0)
{
}
/** Initialize buffer object with test data using image store
*
**/
void TextureBufferOperationsViaImageStore::initializeBufferObjectData()
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Configure program object */
m_is_po_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
m_is_cs_id = gl.createShader(GL_COMPUTE_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
std::string csSource = getISComputeShaderCode();
const char* csCode = csSource.c_str();
if (!buildProgram(m_is_po_id, m_is_cs_id, 1, &csCode))
{
TCU_FAIL("Could not create a program from valid compute shader source!");
}
gl.useProgram(m_is_po_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
gl.bindImageTexture(m_image_unit, m_texbuff_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit!");
gl.dispatchCompute(1, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
gl.useProgram(0);
}
/** Returns Compute Shader Code
*
* @return pointer to literal with Compute Shader Code
*/
std::string TextureBufferOperationsViaImageStore::getISComputeShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"layout(rgba32i, binding = 0) uniform writeonly highp iimageBuffer image_buffer;\n"
"\n"
"layout (local_size_x = "
<< m_n_vectors_in_buffer_texture
<< " ) in;\n"
"\n"
"void main(void)\n"
"{\n"
" imageStore(image_buffer, int(gl_LocalInvocationID.x), ivec4(gl_LocalInvocationID.x) );\n"
"}\n";
return strstream.str();
}
/** Fill buffer with test data
*
* @param buffer pointer to buffer
* @param bufferLenth buffer length
*/
void TextureBufferOperationsViaImageStore::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
{
for (glw::GLuint i = 0; i < bufferLength; ++i)
{
buffer[i] = (glw::GLint)(i / m_n_vector_components);
}
}
/** Deinitializes GLES objects created during the test. */
void TextureBufferOperationsViaImageStore::deinit(void)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.useProgram(0);
/* Delete GLES objects */
if (0 != m_is_po_id)
{
gl.deleteProgram(m_is_po_id);
m_is_po_id = 0;
}
if (0 != m_is_cs_id)
{
gl.deleteShader(m_is_cs_id);
m_is_cs_id = 0;
}
/* Deinitalize base class */
TextureBufferOperations::deinit();
}
/** Constructor for Test Case 6
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureBufferOperationsViaSSBOWrites::TextureBufferOperationsViaSSBOWrites(Context& context,
const ExtParameters& extParams,
const char* name, const char* description)
: TextureBufferOperations(context, extParams, name, description), m_ssbo_cs_id(0), m_ssbo_po_id(0)
{
}
/** Initialize buffer object with test data using ssbo writes
*
**/
void TextureBufferOperationsViaSSBOWrites::initializeBufferObjectData()
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Configure program object */
m_ssbo_po_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program object!");
m_ssbo_cs_id = gl.createShader(GL_COMPUTE_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating compute shader object!");
std::string csSource = getSSBOComputeShaderCode();
const char* csCode = csSource.c_str();
if (!buildProgram(m_ssbo_po_id, m_ssbo_cs_id, 1, &csCode))
{
TCU_FAIL("Could not create a program from valid compute shader source!");
}
gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_tb_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object to shader storage binding point!");
gl.useProgram(m_ssbo_po_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active program object!");
gl.dispatchCompute(1, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error running compute shader!");
gl.memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
gl.useProgram(0);
}
/** Returns Compute Shader Code
*
* @return pointer to literal with Compute Shader Code
*/
std::string TextureBufferOperationsViaSSBOWrites::getSSBOComputeShaderCode() const
{
std::stringstream strstream;
strstream << "${VERSION}\n"
"\n"
"${TEXTURE_BUFFER_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"buffer ComputeSSBO\n"
"{\n"
" ivec4 value[];\n"
"} computeSSBO;\n"
"\n"
"layout (local_size_x = "
<< m_n_vectors_in_buffer_texture
<< " ) in;\n"
"\n"
"void main(void)\n"
"{\n"
" computeSSBO.value[gl_LocalInvocationID.x] = ivec4(gl_LocalInvocationID.x);\n"
"}\n";
return strstream.str();
}
/** Fill buffer with test data
*
* @param buffer pointer to buffer
* @param bufferLenth buffer length
*/
void TextureBufferOperationsViaSSBOWrites::fillBufferWithData(glw::GLint* buffer, glw::GLuint bufferLength)
{
for (glw::GLuint i = 0; i < bufferLength; ++i)
{
buffer[i] = (glw::GLint)(i / m_n_vector_components);
}
}
/** Deinitializes GLES objects created during the test. */
void TextureBufferOperationsViaSSBOWrites::deinit(void)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
gl.useProgram(0);
/* Delete GLES objects */
if (0 != m_ssbo_po_id)
{
gl.deleteProgram(m_ssbo_po_id);
m_ssbo_po_id = 0;
}
if (0 != m_ssbo_cs_id)
{
gl.deleteShader(m_ssbo_cs_id);
m_ssbo_cs_id = 0;
}
/* Deinitalize base class */
TextureBufferOperations::deinit();
}
} // namespace glcts