blob: cfb69b6a0d7861eb9a2ec888b032a5785e53fa70 [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 esextcTextureCubeMapArrayImageTextureSize.cpp
* \brief texture_cube_map_array extension - Image Texture Size (Test 10)
*/ /*-------------------------------------------------------------------*/
#include "esextcTextureCubeMapArrayImageTextureSize.hpp"
#include "gluContextInfo.hpp"
#include "gluStrUtil.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuTestLog.hpp"
#include <cmath>
#include <iostream>
namespace glcts
{
/* Static const variables used for configuring tests */
const glw::GLuint TextureCubeMapArrayTextureSizeBase::m_n_dimensions = 3;
const glw::GLuint TextureCubeMapArrayTextureSizeBase::m_n_resolutions = 4;
const glw::GLuint TextureCubeMapArrayTextureSizeBase::m_n_layers_per_cube = 6;
const glw::GLuint TextureCubeMapArrayTextureSizeBase::m_n_storage_types = 2;
const glw::GLuint TextureCubeMapArrayTextureSizeBase::m_n_texture_components = 4;
/* Array with resolutions */
glw::GLuint resolutionArray[TextureCubeMapArrayTextureSizeBase::m_n_resolutions]
[TextureCubeMapArrayTextureSizeBase::m_n_dimensions] = { { 32, 32, 18 },
{ 64, 64, 6 },
{ 128, 128, 12 },
{ 256, 256, 12 } };
/* Names of storage types */
static const char* mutableStorage = "MUTABLE";
static const char* imMutableStorage = "IMMUTABLE";
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeBase::TextureCubeMapArrayTextureSizeBase(Context& context, const ExtParameters& extParams,
const char* name, const char* description)
: TestCaseBase(context, extParams, name, description), m_po_id(0), m_to_std_id(0), m_to_shw_id(0), m_vao_id(0)
{
/* Nothing to be done here */
}
/** Initialize test case */
void TextureCubeMapArrayTextureSizeBase::initTest(void)
{
/* Check if texture_cube_map_array extension is supported */
if (!m_is_texture_cube_map_array_supported)
{
throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
}
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Generate and bind VAO */
gl.genVertexArrays(1, &m_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
gl.bindVertexArray(m_vao_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
/* Create program object */
m_po_id = gl.createProgram();
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object.");
/* Create program object */
configureProgram();
/* Create GLES objects specific for the test */
configureTestSpecificObjects();
}
/** Deinitialize test case */
void TextureCubeMapArrayTextureSizeBase::deinit(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset Opengl ES configuration */
gl.useProgram(0);
gl.bindVertexArray(0);
/* Delete GLES objects specific for the test */
deleteTestSpecificObjects();
/* Delete shader objects */
deleteProgram();
if (m_po_id != 0)
{
gl.deleteProgram(m_po_id);
m_po_id = 0;
}
if (m_vao_id != 0)
{
gl.deleteVertexArrays(1, &m_vao_id);
m_vao_id = 0;
}
/* Delete texture objects */
deleteTextures();
/* Deinitialize base class */
TestCaseBase::deinit();
}
/** 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::TestCase::IterateResult TextureCubeMapArrayTextureSizeBase::iterate(void)
{
/* Initialize test case */
initTest();
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLboolean test_passed = true;
/* Use program object */
gl.useProgram(m_po_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set active program object.");
glw::GLuint width = 0;
glw::GLuint height = 0;
glw::GLuint depth = 0;
/* Go through IMMUTABLE AND MUTABLE storages */
for (glw::GLuint i = 0; i < m_n_storage_types; ++i)
{
if (!isMutableTextureTestable() && (STORAGE_TYPE)i == ST_MUTABLE)
{
continue;
}
/* Go through all resolutions */
for (glw::GLuint j = 0; j < m_n_resolutions; ++j)
{
width = resolutionArray[j][0];
height = resolutionArray[j][1];
depth = resolutionArray[j][2];
/* Configure texture objects */
configureTextures(width, height, depth, (STORAGE_TYPE)i);
/* Configure uniforms */
configureUniforms();
/* Run shaders to get texture size */
runShaders();
/* Check if results are as expected */
if (!checkResults(width, height, depth, (STORAGE_TYPE)i))
{
test_passed = false;
}
/* Delete texture objects used for this iteration */
deleteTextures();
}
}
/* Set proper test result */
if (test_passed)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
/** Method to check if the test supports mutable textures.
*
* @return return true if mutable textures work with the test
**/
glw::GLboolean TextureCubeMapArrayTextureSizeBase::isMutableTextureTestable(void)
{
return true;
}
/** Method to create texture cube map array with proper configuration
@param texId pointer to variable where texture id will be stored
@param width texture width
@param height texture height
@param depth texture depth
@param storType inform if texture should be mutable or immutable
@param shadow inform if texture should be shadow texture or not
*/
void TextureCubeMapArrayTextureSizeBase::createCubeMapArrayTexture(glw::GLuint& texId, glw::GLuint width,
glw::GLuint height, glw::GLuint depth,
STORAGE_TYPE storType, glw::GLboolean shadow)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Save the current binding */
glw::GLuint savedTexId = 0;
gl.getIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARRAY, (glw::GLint*)&savedTexId);
/* Generate Texture object */
gl.genTextures(1, &texId);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object.");
/* Bind texture object */
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texId);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object.");
/* Create immutable texture storage */
if (storType == ST_IMMUTABLE)
{
/* Create shadow texture object */
if (shadow)
{
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_DEPTH_COMPONENT32F, width, height, depth);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating immutable texture storage.");
}
/* Create texture object */
else
{
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 1, GL_RGBA32F, width, height, depth);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating immutable texture storage.");
}
}
/* Create mutable texture storage */
else
{
std::vector<glw::GLfloat> data(width * height * depth * m_n_texture_components, 0);
/* Create shadow texture object */
if (shadow)
{
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_DEPTH_COMPONENT32F, width, height, depth, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, &data[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating mutable texture storage.");
}
/* Create texture object */
else
{
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAX_LEVEL, 0);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture parameter.");
gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA, GL_FLOAT,
&data[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating mutable texture storage.");
}
}
/* Restore the original texture binding */
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, savedTexId);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object.");
}
/** Configure textures used in the test for textureSize() and imageSize() calls
@param width texture width
@param height texture height
@param depth texture depth
@param storType inform if texture should be mutable or immutable
*/
void TextureCubeMapArrayTextureSizeBase::configureTextures(glw::GLuint width, glw::GLuint height, glw::GLuint depth,
STORAGE_TYPE storType)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Create texture objects which will be tested */
createCubeMapArrayTexture(m_to_std_id, width, height, depth, storType, false);
createCubeMapArrayTexture(m_to_shw_id, width, height, depth, storType, true);
/* Binding texture object to texture unit */
gl.activeTexture(GL_TEXTURE0);
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_to_std_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
/* Binding texture object to texture unit */
gl.activeTexture(GL_TEXTURE1);
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_to_shw_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
}
/** Delete textures used in the test for textureSize() and imageSize() calls */
void TextureCubeMapArrayTextureSizeBase::deleteTextures(void)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.activeTexture(GL_TEXTURE0);
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
gl.activeTexture(GL_TEXTURE1);
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
gl.activeTexture(GL_TEXTURE0);
/* Delete GLES objects */
if (m_to_std_id != 0)
{
gl.deleteTextures(1, &m_to_std_id);
m_to_std_id = 0;
}
if (m_to_shw_id != 0)
{
gl.deleteTextures(1, &m_to_shw_id);
m_to_shw_id = 0;
}
}
/** Configure uniform variables */
void TextureCubeMapArrayTextureSizeBase::configureUniforms(void)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Bind uniform samplers to texture units */
glw::GLint texture_std_location = gl.getUniformLocation(m_po_id, "texture_std_sampler");
GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting sampler location!");
gl.uniform1i(texture_std_location, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding sampler to texture unit!");
glw::GLint texture_shw_location = gl.getUniformLocation(m_po_id, "texture_shw_sampler");
GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting sampler location!");
gl.uniform1i(texture_shw_location, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding sampler to texture unit!");
}
/* Static const variables used for configuring tests */
const glw::GLsizei TextureCubeMapArrayTextureSizeTFBase::m_n_varyings = 2;
const glw::GLuint TextureCubeMapArrayTextureSizeTFBase::m_n_tf_components = 3;
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeTFBase::TextureCubeMapArrayTextureSizeTFBase(Context& context,
const ExtParameters& extParams,
const char* name, const char* description)
: TextureCubeMapArrayTextureSizeBase(context, extParams, name, description), m_tf_bo_id(0)
{
/* Nothing to be done here */
}
/** Configure GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeTFBase::configureTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.genBuffers(1, &m_tf_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object.");
gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_tf_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object.");
std::vector<glw::GLint> buffer_data(m_n_varyings * m_n_tf_components, 0);
gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_n_varyings * m_n_tf_components * sizeof(glw::GLint), &buffer_data[0],
GL_DYNAMIC_COPY);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating buffer object's data store.");
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tf_bo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object to transform feedback binding point.");
}
/** Delete GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeTFBase::deleteTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
/* Delete transform feedback buffer */
if (m_tf_bo_id != 0)
{
gl.deleteBuffers(1, &m_tf_bo_id);
m_tf_bo_id = 0;
}
}
/** Configure textures used in the test for textureSize() and imageSize() calls
@param width texture width
@param height texture height
@param depth texture depth
@param storType inform if texture should be mutable or immutable
*/
void TextureCubeMapArrayTextureSizeTFBase::configureTextures(glw::GLuint width, glw::GLuint height, glw::GLuint depth,
STORAGE_TYPE storType)
{
TextureCubeMapArrayTextureSizeBase::configureTextures(width, height, depth, storType);
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
std::vector<glw::GLint> buffer_data(m_n_varyings * m_n_tf_components, 0);
gl.bufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_n_varyings * m_n_tf_components * sizeof(glw::GLint),
&buffer_data[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling buffer object's data store with data.");
}
/** Check textureSize() and imageSize() methods returned proper values
* @param width texture width
* @param height texture height
* @param depth texture depth
* @param storType inform if texture is mutable or immutable
* @return return true if result data is as expected
*/
glw::GLboolean TextureCubeMapArrayTextureSizeTFBase::checkResults(glw::GLuint width, glw::GLuint height,
glw::GLuint depth, STORAGE_TYPE storType)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Read results from transform feedback */
glw::GLuint* temp_buff = (glw::GLuint*)gl.mapBufferRange(
GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_n_varyings * m_n_tf_components * sizeof(glw::GLuint), GL_MAP_READ_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error mapping buffer object's data store to client's address space.");
/* Copy results to helper buffer */
glw::GLuint read_size[m_n_varyings * m_n_tf_components];
memcpy(read_size, temp_buff, m_n_varyings * m_n_tf_components * sizeof(glw::GLint));
gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error ummapping transform feedback buffer.");
glw::GLboolean test_passed = true;
/* Elements under index 0-2 contain result of textureSize called for samplerCubeArray sampler */
if (read_size[0] != width || read_size[1] != height || read_size[2] != (depth / m_n_layers_per_cube))
{
getTestContext().getLog()
<< tcu::TestLog::Message
<< "Storage Type: " << ((storType == ST_MUTABLE) ? mutableStorage : imMutableStorage) << "\n"
<< "textureSize() for samplerCubeArray returned wrong values. [width][height][layers]. They are equal "
<< "[" << read_size[0] << "][" << read_size[1] << "][" << read_size[2] << "] but should be "
<< "[" << width << "][" << height << "][" << depth / m_n_layers_per_cube << "]."
<< tcu::TestLog::EndMessage;
test_passed = false;
}
/* Elements under index 3-5 contain result of textureSize called for samplerCubeArrayShadow sampler */
if (read_size[3] != width || read_size[4] != height || read_size[5] != (depth / m_n_layers_per_cube))
{
getTestContext().getLog() << tcu::TestLog::Message
<< "Storage Type: " << ((storType == ST_MUTABLE) ? mutableStorage : imMutableStorage)
<< "\n"
<< "textureSize() for samplerCubeArrayShadow returned wrong values. "
"[width][height][layers]. They are equal "
<< "[" << read_size[3] << "][" << read_size[4] << "][" << read_size[5]
<< "] but should be "
<< "[" << width << "][" << height << "][" << depth / m_n_layers_per_cube << "]."
<< tcu::TestLog::EndMessage;
test_passed = false;
}
return test_passed;
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeTFVertexShader::TextureCubeMapArrayTextureSizeTFVertexShader(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureCubeMapArrayTextureSizeTFBase(context, extParams, name, description), m_vs_id(0), m_fs_id(0)
{
/* Nothing to be done here */
}
/* Configure program object */
void TextureCubeMapArrayTextureSizeTFVertexShader::configureProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Set transform feedback varyings */
const char* varyings[] = { "texture_std_size", "texture_shw_size" };
gl.transformFeedbackVaryings(m_po_id, m_n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting transform feedback varyings.");
const char* vsCode = getVertexShaderCode();
const char* fsCode = getFragmentShaderCode();
m_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_vs_id, 1 /* part */, &vsCode))
{
TCU_FAIL("Could not compile/link program object from valid shader code.");
}
}
/** Delete program object */
void TextureCubeMapArrayTextureSizeTFVertexShader::deleteProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete shader objects */
if (m_vs_id != 0)
{
gl.deleteShader(m_vs_id);
m_vs_id = 0;
}
if (m_fs_id != 0)
{
gl.deleteShader(m_fs_id);
m_fs_id = 0;
}
}
/** Render or dispatch compute */
void TextureCubeMapArrayTextureSizeTFVertexShader::runShaders(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.beginTransformFeedback(GL_POINTS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error beginning transform feedback.");
gl.drawArrays(GL_POINTS, 0, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
gl.endTransformFeedback();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error ending transform feedback.");
}
/** Returns code for Vertex Shader
* @return pointer to literal with Vertex Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFVertexShader::getVertexShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"uniform highp samplerCubeArray texture_std_sampler;\n"
"uniform highp samplerCubeArrayShadow texture_shw_sampler;\n"
"\n"
"layout (location = 0) out flat uvec3 texture_std_size;\n"
"layout (location = 1) out flat uvec3 texture_shw_size;\n"
"\n"
"void main()\n"
"{\n"
" gl_PointSize = 1.0f;\n"
"\n"
" texture_std_size = uvec3( textureSize(texture_std_sampler, 0) );\n"
" texture_shw_size = uvec3( textureSize(texture_shw_sampler, 0) );\n"
" gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
/** Return code for Fragment Shader
* @return pointer to literal with Fragment Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFVertexShader::getFragmentShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
"}\n";
return result;
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeTFGeometryShader::TextureCubeMapArrayTextureSizeTFGeometryShader(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureCubeMapArrayTextureSizeTFBase(context, extParams, name, description), m_vs_id(0), m_gs_id(0), m_fs_id(0)
{
/* Nothing to be done here */
}
/* Configure program object */
void TextureCubeMapArrayTextureSizeTFGeometryShader::configureProgram(void)
{
/* Check if geometry_shader extension is supported */
if (!m_is_geometry_shader_extension_supported)
{
throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
}
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Set transform feedback varyings */
const char* varyings[] = { "texture_std_size", "texture_shw_size" };
gl.transformFeedbackVaryings(m_po_id, m_n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting transform feedback varyings.");
const char* vsCode = getVertexShaderCode();
const char* gsCode = getGeometryShaderCode();
const char* fsCode = getFragmentShaderCode();
m_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_gs_id, 1 /* part */, &gsCode, m_vs_id, 1 /* part */,
&vsCode))
{
TCU_FAIL("Could not compile/link program object from valid shader code.");
}
}
/** Delete program object */
void TextureCubeMapArrayTextureSizeTFGeometryShader::deleteProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete shader objects */
if (m_vs_id != 0)
{
gl.deleteShader(m_vs_id);
m_vs_id = 0;
}
if (m_gs_id != 0)
{
gl.deleteShader(m_gs_id);
m_gs_id = 0;
}
if (m_fs_id != 0)
{
gl.deleteShader(m_fs_id);
m_fs_id = 0;
}
}
void TextureCubeMapArrayTextureSizeTFGeometryShader::runShaders(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.beginTransformFeedback(GL_POINTS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error beginning transform feedback.");
gl.drawArrays(GL_POINTS, 0, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
gl.endTransformFeedback();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error ending transform feedback.");
}
/** Returns code for Vertex Shader
* @return pointer to literal with Vertex Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFGeometryShader::getVertexShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
/** Return code for Geometry Shader
* @return pointer to literal with Geometry Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFGeometryShader::getGeometryShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"${GEOMETRY_SHADER_ENABLE}\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"uniform highp samplerCubeArray texture_std_sampler;\n"
"uniform highp samplerCubeArrayShadow texture_shw_sampler;\n"
"\n"
"layout (location = 0) out flat uvec3 texture_std_size;\n"
"layout (location = 1) out flat uvec3 texture_shw_size;\n"
"\n"
"layout(points) in;\n"
"layout(points, max_vertices=1) out;\n"
"\n"
"void main()\n"
"{\n"
" texture_std_size = uvec3( textureSize(texture_std_sampler, 0) );\n"
" texture_shw_size = uvec3( textureSize(texture_shw_sampler, 0) );\n"
" gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
" EmitVertex();\n"
" EndPrimitive();\n"
"}\n";
return result;
}
/** Return code for Fragment Shader
* @return pointer to literal with Fragment Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFGeometryShader::getFragmentShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
"}\n";
return result;
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeTFTessControlShader::TextureCubeMapArrayTextureSizeTFTessControlShader(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureCubeMapArrayTextureSizeTFBase(context, extParams, name, description)
, m_vs_id(0)
, m_tcs_id(0)
, m_tes_id(0)
, m_fs_id(0)
{
/* Nothing to be done here */
}
/* Configure program object */
void TextureCubeMapArrayTextureSizeTFTessControlShader::configureProgram(void)
{
/* Check if tessellation_shader extension is supported */
if (!m_is_tessellation_shader_supported)
{
throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
}
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Set transform feedback varyings */
const char* varyings[] = { "texture_std_size", "texture_shw_size" };
gl.transformFeedbackVaryings(m_po_id, m_n_varyings, varyings, GL_INTERLEAVED_ATTRIBS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting transform feedback varyings.");
const char* vsCode = getVertexShaderCode();
const char* tcsCode = getTessellationControlShaderCode();
const char* tesCode = getTessellationEvaluationShaderCode();
const char* fsCode = getFragmentShaderCode();
m_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_tcs_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_tes_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_tcs_id, 1 /* part */, &tcsCode, m_tes_id, 1 /* part */,
&tesCode, m_vs_id, 1 /* part */, &vsCode))
{
TCU_FAIL("Could not compile/link program object from valid shader code.");
}
}
/** Delete program object */
void TextureCubeMapArrayTextureSizeTFTessControlShader::deleteProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete shader objects */
if (m_vs_id != 0)
{
gl.deleteShader(m_vs_id);
m_vs_id = 0;
}
if (m_tcs_id != 0)
{
gl.deleteShader(m_tcs_id);
m_tcs_id = 0;
}
if (m_tes_id != 0)
{
gl.deleteShader(m_tes_id);
m_tes_id = 0;
}
if (m_fs_id != 0)
{
gl.deleteShader(m_fs_id);
m_fs_id = 0;
}
}
/** Render or dispatch compute */
void TextureCubeMapArrayTextureSizeTFTessControlShader::runShaders(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.beginTransformFeedback(GL_POINTS);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error beginning transform feedback.");
gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Setting number of vertices per patch failed");
gl.drawArrays(m_glExtTokens.PATCHES, 0, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
GLU_EXPECT_NO_ERROR(gl.getError(), "Setting number of vertices per patch failed");
gl.endTransformFeedback();
GLU_EXPECT_NO_ERROR(gl.getError(), "Error ending transform feedback.");
}
/** Returns code for Vertex Shader
* @return pointer to literal with Vertex Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFTessControlShader::getVertexShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
/** Return code for Tessellation Control Shader
* @return pointer to literal with Tessellation Control Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFTessControlShader::getTessellationControlShaderCode(void)
{
static const char* result =
"${VERSION}\n"
"\n"
"${TESSELLATION_SHADER_ENABLE}\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"uniform highp samplerCubeArray texture_std_sampler;\n"
"uniform highp samplerCubeArrayShadow texture_shw_sampler;\n"
"\n"
"layout (location = 0) out flat uvec3 texture_std_size_array[];\n"
"layout (location = 1) out flat uvec3 texture_shw_size_array[];\n"
"\n"
"layout (vertices = 1) out;\n"
"\n"
"void main()\n"
"{\n"
" gl_TessLevelInner[0] = 1.0;\n"
" gl_TessLevelInner[1] = 1.0;\n"
" gl_TessLevelOuter[0] = 1.0;\n"
" gl_TessLevelOuter[1] = 1.0;\n"
" gl_TessLevelOuter[2] = 1.0;\n"
" gl_TessLevelOuter[3] = 1.0;\n"
" texture_std_size_array[gl_InvocationID] = uvec3( textureSize(texture_std_sampler, 0) );\n"
" texture_shw_size_array[gl_InvocationID] = uvec3( textureSize(texture_shw_sampler, 0) );\n"
" gl_out[gl_InvocationID].gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
/** Returns code for Tessellation Evaluation Shader
* @return pointer to literal with Tessellation Evaluation code
**/
const char* TextureCubeMapArrayTextureSizeTFTessControlShader::getTessellationEvaluationShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"${TESSELLATION_SHADER_REQUIRE}\n"
"\n"
"layout(isolines, point_mode) in;\n"
"\n"
"in layout(location = 0) flat uvec3 texture_std_size_array[];\n"
"in layout(location = 1) flat uvec3 texture_shw_size_array[];\n"
"\n"
"out flat uvec3 texture_std_size;\n"
"out flat uvec3 texture_shw_size;\n"
"\n"
"void main()\n"
"{\n"
" texture_std_size = texture_std_size_array[0];\n"
" texture_shw_size = texture_shw_size_array[0];\n"
" gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
/** Return code for Fragment Shader
* @return pointer to literal with Fragment Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFTessControlShader::getFragmentShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
"}\n";
return result;
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeTFTessEvaluationShader::TextureCubeMapArrayTextureSizeTFTessEvaluationShader(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureCubeMapArrayTextureSizeTFTessControlShader(context, extParams, name, description)
{
/* Nothing to be done here */
}
/** Return code for Tessellation Control Shader
* @return pointer to literal with Tessellation Control Shader code
**/
const char* TextureCubeMapArrayTextureSizeTFTessEvaluationShader::getTessellationControlShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"${TESSELLATION_SHADER_ENABLE}\n"
"\n"
"precision highp float;\n"
"\n"
"layout (vertices = 1) out;\n"
"\n"
"void main()\n"
"{\n"
" gl_TessLevelInner[0] = 1.0;\n"
" gl_TessLevelInner[1] = 1.0;\n"
" gl_TessLevelOuter[0] = 1.0;\n"
" gl_TessLevelOuter[1] = 1.0;\n"
" gl_TessLevelOuter[2] = 1.0;\n"
" gl_TessLevelOuter[3] = 1.0;\n"
" gl_out[gl_InvocationID].gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
/** Returns code for Tessellation Evaluation Shader
* @return pointer to literal with Tessellation Evaluation code
**/
const char* TextureCubeMapArrayTextureSizeTFTessEvaluationShader::getTessellationEvaluationShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"${TESSELLATION_SHADER_REQUIRE}\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n"
"layout(isolines, point_mode) in;\n"
"\n"
"uniform highp samplerCubeArray texture_std_sampler;\n"
"uniform highp samplerCubeArrayShadow texture_shw_sampler;\n"
"\n"
"layout (location = 0) out flat uvec3 texture_std_size;\n"
"layout (location = 1) out flat uvec3 texture_shw_size;\n"
"\n"
"void main()\n"
"{\n"
" texture_std_size = uvec3( textureSize(texture_std_sampler, 0) );\n"
" texture_shw_size = uvec3( textureSize(texture_shw_sampler, 0) );\n"
" gl_Position = vec4(0.0f,0.0f,0.0f,0.0f);\n"
"}\n";
return result;
}
const glw::GLuint TextureCubeMapArrayTextureSizeRTBase::m_n_rt_components = 4;
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeRTBase::TextureCubeMapArrayTextureSizeRTBase(Context& context,
const ExtParameters& extParams,
const char* name, const char* description)
: TextureCubeMapArrayTextureSizeBase(context, extParams, name, description)
, m_read_fbo_id(0)
, m_rt_std_id(0)
, m_rt_shw_id(0)
{
/* Nothing to be done here */
}
/** Configure GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeRTBase::configureTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLint rt_data[m_n_rt_components];
memset(rt_data, 0, m_n_rt_components * sizeof(glw::GLuint));
/* Create texture which will store result of textureSize() for samplerCubeArray sampler */
gl.genTextures(1, &m_rt_std_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
gl.activeTexture(GL_TEXTURE0);
gl.bindTexture(GL_TEXTURE_2D, m_rt_std_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating storage for texture object!");
gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, rt_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
/* Create texture which will store result of textureSize() for samplerCubeArrayShadow sampler */
gl.genTextures(1, &m_rt_shw_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
gl.activeTexture(GL_TEXTURE1);
gl.bindTexture(GL_TEXTURE_2D, m_rt_shw_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating storage for texture object!");
gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, rt_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
/* Generate frame buffer object */
gl.genFramebuffers(1, &m_read_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating frame buffer object!");
}
/** Delete GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeRTBase::deleteTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GL state */
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
gl.activeTexture(GL_TEXTURE0);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.activeTexture(GL_TEXTURE1);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.activeTexture(GL_TEXTURE0);
/* Delete GL objects */
if (m_read_fbo_id != 0)
{
gl.deleteFramebuffers(1, &m_read_fbo_id);
m_read_fbo_id = 0;
}
if (m_rt_std_id != 0)
{
gl.deleteTextures(1, &m_rt_std_id);
m_rt_std_id = 0;
}
if (m_rt_shw_id != 0)
{
gl.deleteTextures(1, &m_rt_shw_id);
m_rt_shw_id = 0;
}
}
/** Check textureSize() and imageSize() methods returned proper values
* @param width texture width
* @param height texture height
* @param depth texture depth
* @param storType inform if texture is mutable or immutable
* @return return true if result data is as expected
*/
glw::GLboolean TextureCubeMapArrayTextureSizeRTBase::checkResults(glw::GLuint width, glw::GLuint height,
glw::GLuint depth, STORAGE_TYPE storType)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLboolean test_passed = true;
glw::GLuint read_size[m_n_rt_components];
memset(read_size, 0, m_n_rt_components * sizeof(glw::GLuint));
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
/* Compare returned results of textureSize() called for samplerCubeArray sampler*/
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt_std_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to frame buffer");
/* Check framebuffer status */
checkFramebufferStatus(GL_READ_FRAMEBUFFER);
gl.readPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, read_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixles from frame buffer!");
if (read_size[0] != width || read_size[1] != height || read_size[2] != (depth / m_n_layers_per_cube))
{
getTestContext().getLog()
<< tcu::TestLog::Message
<< "Storage Type: " << ((storType == ST_MUTABLE) ? mutableStorage : imMutableStorage) << "\n"
<< "textureSize() for samplerCubeArray returned wrong values of [width][height][layers]. They are equal to"
<< "[" << read_size[0] << "][" << read_size[1] << "][" << read_size[2] << "] but should be "
<< "[" << width << "][" << height << "][" << depth / m_n_layers_per_cube << "]."
<< tcu::TestLog::EndMessage;
test_passed = false;
}
/* Compare returned results of textureSize() for samplerCubeArrayShadow sampler*/
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt_shw_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to frame buffer");
/* Check framebuffer status */
checkFramebufferStatus(GL_READ_FRAMEBUFFER);
gl.readPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, read_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixles from frame buffer!");
if (read_size[0] != width || read_size[1] != height || read_size[2] != (depth / m_n_layers_per_cube))
{
getTestContext().getLog() << tcu::TestLog::Message
<< "Storage Type: " << ((storType == ST_MUTABLE) ? mutableStorage : imMutableStorage)
<< "\n"
<< "textureSize() for samplerCubeArrayShadow returned wrong values of "
"[width][height][layers]. They are equal to"
<< "[" << read_size[0] << "][" << read_size[1] << "][" << read_size[2]
<< "] but should be "
<< "[" << width << "][" << height << "][" << depth / m_n_layers_per_cube << "]."
<< tcu::TestLog::EndMessage;
test_passed = false;
}
return test_passed;
}
/** Check Framebuffer Status. Throws a TestError exception, should the framebuffer status
* be found incomplete.
*
* @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER
*
*/
void TextureCubeMapArrayTextureSizeRTBase::checkFramebufferStatus(glw::GLenum framebuffer)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLenum framebuffer_status = gl.checkFramebufferStatus(framebuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting framebuffer status!");
if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status)
{
switch (framebuffer_status)
{
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: Error: GL_FRAMEBUFFER_UNSUPPORTED");
}
default:
{
TCU_FAIL("Framebuffer incomplete, status not recognized");
}
} /* switch (framebuffer_status) */
} /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeRTFragmentShader::TextureCubeMapArrayTextureSizeRTFragmentShader(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureCubeMapArrayTextureSizeRTBase(context, extParams, name, description)
, m_draw_fbo_id(0)
, m_vs_id(0)
, m_fs_id(0)
{
/* Nothing to be done here */
}
/** Configure GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeRTFragmentShader::configureTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
TextureCubeMapArrayTextureSizeRTBase::configureTestSpecificObjects();
/* Generate frame buffer object */
gl.genFramebuffers(1, &m_draw_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating frame buffer object!");
}
/** Delete GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeRTFragmentShader::deleteTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
/* Delete GLEs objects */
if (m_draw_fbo_id != 0)
{
gl.deleteFramebuffers(1, &m_draw_fbo_id);
m_draw_fbo_id = 0;
}
TextureCubeMapArrayTextureSizeRTBase::deleteTestSpecificObjects();
}
/* Configure program object */
void TextureCubeMapArrayTextureSizeRTFragmentShader::configureProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
const char* vsCode = getVertexShaderCode();
const char* fsCode = getFragmentShaderCode();
m_vs_id = gl.createShader(GL_VERTEX_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fsCode, m_vs_id, 1 /* part */, &vsCode))
{
TCU_FAIL("Could not compile/link program object from valid shader code.");
}
}
/** Delete program object */
void TextureCubeMapArrayTextureSizeRTFragmentShader::deleteProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete shader objects */
if (m_vs_id != 0)
{
gl.deleteShader(m_vs_id);
m_vs_id = 0;
}
if (m_fs_id != 0)
{
gl.deleteShader(m_fs_id);
m_fs_id = 0;
}
}
/** Return code for bolierPlate Vertex Shader
* @return pointer to literal with Vertex Shader code
**/
const char* TextureCubeMapArrayTextureSizeRTFragmentShader::getVertexShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"precision highp float;\n"
"\n"
"void main()\n"
"{\n"
" gl_PointSize = 1.0f;\n"
" gl_Position = vec4(0, 0, 0, 1.0f);\n"
"}\n";
return result;
}
/** Return code for Fragment Shader
* @return pointer to literal with Fragment Shader code
**/
const char* TextureCubeMapArrayTextureSizeRTFragmentShader::getFragmentShaderCode(void)
{
static const char* result = "${VERSION}\n"
"\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"uniform highp samplerCubeArray texture_std_sampler;\n"
"uniform highp samplerCubeArrayShadow texture_shw_sampler;\n"
"\n"
"layout (location = 0) out uvec4 texture_std_size;\n"
"layout (location = 1) out uvec4 texture_shw_size;\n"
"\n"
"void main()\n"
"{\n"
" texture_std_size = uvec4( textureSize(texture_std_sampler, 0), 0 );\n"
" texture_shw_size = uvec4( textureSize(texture_shw_sampler, 0), 0 );\n"
"}\n";
return result;
}
void TextureCubeMapArrayTextureSizeRTFragmentShader::runShaders(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Configure draw framebuffer */
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_draw_fbo_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object");
gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt_std_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to GL_COLOR_ATTACHMENT0");
gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_rt_shw_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to GL_COLOR_ATTACHMENT0");
/* Check framebuffer status */
checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
/* Configure draw buffers for fragment shader */
const glw::GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
gl.drawBuffers(2, drawBuffers);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting draw buffers");
glw::GLint viewport_size[4];
gl.getIntegerv(GL_VIEWPORT, viewport_size);
gl.viewport(0, 0, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Setting viewport");
gl.drawArrays(GL_POINTS, 0, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!");
gl.viewport(viewport_size[0], viewport_size[1], viewport_size[2], viewport_size[3]);
GLU_EXPECT_NO_ERROR(gl.getError(), "Setting viewport");
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's description
**/
TextureCubeMapArrayTextureSizeRTComputeShader::TextureCubeMapArrayTextureSizeRTComputeShader(
Context& context, const ExtParameters& extParams, const char* name, const char* description)
: TextureCubeMapArrayTextureSizeRTBase(context, extParams, name, description)
, m_cs_id(0)
, m_to_img_id(0)
, m_rt_img_id(0)
{
/* Nothing to be done here */
}
/** Configure program object */
void TextureCubeMapArrayTextureSizeRTComputeShader::configureProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
const char* csCode = getComputeShaderCode();
m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader object.");
/* Build program */
if (!buildProgram(m_po_id, m_cs_id, 1 /* part */, &csCode))
{
TCU_FAIL("Could not compile/link program object from valid shader code.");
}
}
/** Delete program object */
void TextureCubeMapArrayTextureSizeRTComputeShader::deleteProgram(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Delete shader objects */
if (m_cs_id != 0)
{
gl.deleteShader(m_cs_id);
m_cs_id = 0;
}
}
/** Returns code for Compute Shader
* @return pointer to literal with Compute Shader code
**/
const char* TextureCubeMapArrayTextureSizeRTComputeShader::getComputeShaderCode(void)
{
static const char* result =
"${VERSION}\n"
"\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n"
"precision highp float;\n"
"\n"
"layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
" uniform highp samplerCubeArray texture_std_sampler;\n"
" uniform highp samplerCubeArrayShadow texture_shw_sampler;\n"
"layout(rgba32f, binding = 0) writeonly uniform highp imageCubeArray texture_img_sampler;\n"
"\n"
"layout (rgba32ui, binding = 1) uniform highp writeonly uimage2D image_std_size;\n"
"layout (rgba32ui, binding = 2) uniform highp writeonly uimage2D image_shw_size;\n"
"layout (rgba32ui, binding = 3) uniform highp writeonly uimage2D image_img_size;\n"
"\n"
"void main(void)\n"
"{\n"
" imageStore(image_std_size, ivec2(0,0), uvec4(uvec3( textureSize(texture_std_sampler, 0)), 0) );\n"
" imageStore(image_shw_size, ivec2(0,0), uvec4(uvec3( textureSize(texture_shw_sampler, 0)), 0) );\n"
" imageStore(image_img_size, ivec2(0,0), uvec4(uvec3( imageSize (texture_img_sampler)), 0) );\n"
"}\n";
return result;
}
/** Configure GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeRTComputeShader::configureTestSpecificObjects(void)
{
TextureCubeMapArrayTextureSizeRTBase::configureTestSpecificObjects();
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLuint rt_data[m_n_rt_components];
memset(rt_data, 0, m_n_rt_components * sizeof(glw::GLuint));
/* Create texture which will store result of imageSize() for imageCubeArray image */
gl.genTextures(1, &m_rt_img_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!");
gl.activeTexture(GL_TEXTURE2);
gl.bindTexture(GL_TEXTURE_2D, m_rt_img_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating storage for texture object!");
gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, rt_data);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture object's data store with data!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting texture object's filter mode!");
/* Image unit binding start from index 1 for compute shader results */
gl.bindImageTexture(1, m_rt_std_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit");
gl.bindImageTexture(2, m_rt_shw_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit");
gl.bindImageTexture(3, m_rt_img_id, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit");
}
/** Delete GLES objects specific for the test configuration */
void TextureCubeMapArrayTextureSizeRTComputeShader::deleteTestSpecificObjects(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GL state */
gl.activeTexture(GL_TEXTURE2);
gl.bindTexture(GL_TEXTURE_2D, 0);
/* Delete GL objects */
if (m_rt_img_id != 0)
{
gl.deleteTextures(1, &m_rt_img_id);
m_rt_img_id = 0;
}
TextureCubeMapArrayTextureSizeRTBase::deleteTestSpecificObjects();
}
/** Configure textures used in the test for textureSize() and imageSize() calls
@param width texture width
@param height texture height
@param depth texture depth
@param storType inform if texture should be mutable or immutable
*/
void TextureCubeMapArrayTextureSizeRTComputeShader::configureTextures(glw::GLuint width, glw::GLuint height,
glw::GLuint depth, STORAGE_TYPE storType)
{
TextureCubeMapArrayTextureSizeRTBase::configureTextures(width, height, depth, storType);
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
createCubeMapArrayTexture(m_to_img_id, width, height, depth, storType, false);
/* Binding texture object to texture unit */
gl.activeTexture(GL_TEXTURE2);
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_to_img_id);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!");
gl.bindImageTexture(0, m_to_img_id, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA32F);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object to image unit");
}
/** Delete textures used in the test for textureSize() and imageSize() calls */
void TextureCubeMapArrayTextureSizeRTComputeShader::deleteTextures(void)
{
/* Get Gl entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
/* Reset GLES state */
gl.activeTexture(GL_TEXTURE2);
gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
/* Delete GLES objects */
if (m_to_img_id != 0)
{
gl.deleteTextures(1, &m_to_img_id);
m_to_img_id = 0;
}
TextureCubeMapArrayTextureSizeRTBase::deleteTextures();
}
/** Render or dispatch compute */
void TextureCubeMapArrayTextureSizeRTComputeShader::runShaders(void)
{
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.dispatchCompute(1, 1, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error executing compute shader");
gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting memory barrier!");
}
/** Check textureSize() and imageSize() methods returned proper values
* @param width texture width
* @param height texture height
* @param depth texture depth
* @param storType inform if texture is mutable or immutable
* @return return true if result data is as expected
*/
glw::GLboolean TextureCubeMapArrayTextureSizeRTComputeShader::checkResults(glw::GLuint width, glw::GLuint height,
glw::GLuint depth, STORAGE_TYPE storType)
{
glw::GLboolean test_passed = TextureCubeMapArrayTextureSizeRTBase::checkResults(width, height, depth, storType);
/* Get GL entry points */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLuint read_size[m_n_rt_components];
memset(read_size, 0, m_n_rt_components * sizeof(glw::GLuint));
/* Compare returned results of imageSize() for imageCubeArray image */
gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt_img_id, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to frame buffer");
/* Check framebuffer status */
checkFramebufferStatus(GL_READ_FRAMEBUFFER);
gl.readPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, read_size);
GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixles from frame buffer!");
if (read_size[0] != width || read_size[1] != height || read_size[2] != (depth / m_n_layers_per_cube))
{
getTestContext().getLog()
<< tcu::TestLog::Message
<< "Storage Type: " << ((storType == ST_MUTABLE) ? mutableStorage : imMutableStorage) << "\n"
<< "imageSize() for imageCubeArray returned wrong values of [width][height][layers]. They are equal to"
<< "[" << read_size[0] << "][" << read_size[1] << "][" << read_size[2] << "] but should be "
<< "[" << width << "][" << height << "][" << depth / m_n_layers_per_cube << "]."
<< tcu::TestLog::EndMessage;
test_passed = false;
}
return test_passed;
}
/** Method to check if the test supports mutable textures.
*
* @return return true if mutable textures work with the test
*/
glw::GLboolean TextureCubeMapArrayTextureSizeRTComputeShader::isMutableTextureTestable(void)
{
/**
* Mutable textures cannot be bound as image textures on ES, but can be on
* desktop GL. This check enables/disables testing of mutable image textures.
*/
if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
{
return true;
}
else
{
return false;
}
}
} /* glcts */