blob: 5a8740c24f85f87678ea11daa0e61e1c2a08b667 [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 esextcTextureCubeMapArraySampling.cpp
* \brief Texture Cube Map Array Sampling (Test 1)
*/ /*-------------------------------------------------------------------*/
/* Control logging of positive results. 0 disabled, 1 enabled */
#define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_LOG 0
/* Control logging of program source for positive results. 0 disabled, 1 enabled */
#define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_PASS_PROGRAM_LOG 1
/* Control logging of negative results. 0 disabled, 1 enabled */
#define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_LOG 1
/* Control logging of program source for negative results. 0 disabled, 1 enabled */
#define TEXTURECUBEMAPARRAYSAMPLINGTEST_IS_FAIL_PROGRAM_LOG 1
/* When enabled, textures will be stored as TGA files. Test will not be executed. 0 disabled, 1 enabled */
#define TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION 0
/* Output path for TGA files */
#define TEXTURECUBEMAPARRAYSAMPLINGTEST_PATH_FOR_COMPRESSION "c:\\textures\\"
#include "esextcTextureCubeMapArraySampling.hpp"
#include "esextcTextureCubeMapArraySamplingResources.hpp"
#include "gluContextInfo.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuTestLog.hpp"
#include <cmath>
#include <sstream>
#include <vector>
#if TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION
#include <fstream>
#endif /* TEXTURECUBEMAPARRAYSAMPLINGTEST_DUMP_TEXTURES_FOR_COMPRESSION */
namespace glcts
{
/** Structure used to write shaders' variables to stream
*
**/
struct var2str
{
public:
/** Constructor. Stores strings used to create variable name
* prefixName[index]
*
* @param prefix Prefix part. Can be null.
* @param name Name part. Must not be null.
* @param index Index part. Can be null.
**/
var2str(const glw::GLchar* prefix, const glw::GLchar* name, const glw::GLchar* index)
: m_prefix(prefix), m_name(name), m_index(index)
{
/* Nothing to be done here */
}
const glw::GLchar* m_prefix;
const glw::GLchar* m_name;
const glw::GLchar* m_index;
};
/* Attribute names */
const glw::GLchar* const TextureCubeMapArraySamplingTest::attribute_grad_x = "grad_x";
const glw::GLchar* const TextureCubeMapArraySamplingTest::attribute_grad_y = "grad_y";
const glw::GLchar* const TextureCubeMapArraySamplingTest::attribute_lod = "lod";
const glw::GLchar* const TextureCubeMapArraySamplingTest::attribute_refZ = "refZ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::attribute_texture_coordinate = "texture_coordinates";
/* Compute shader parts */
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_body =
"void main()\n"
"{\n"
" const int face_width = 3;\n"
" const int face_height = 3;\n"
" const int vertices_per_face = face_width * face_height;\n"
" const int faces_per_layer = 6;\n"
" const int layer_width = faces_per_layer * face_width;\n"
" const int vertices_per_layer = vertices_per_face * faces_per_layer;\n"
"\n"
" ivec2 image_coord = ivec2(gl_WorkGroupID.xy);\n"
" ivec3 texture_size = textureSize(sampler, 0);\n"
"\n"
" int layer = image_coord.x / layer_width;\n"
" int layer_offset = layer * layer_width;\n"
" int layer_index = layer * vertices_per_layer;\n"
" int face = (image_coord.x - layer_offset) / face_width;\n"
" int face_offset = face * face_width;\n"
" int face_index = face * vertices_per_face;\n"
" int vertex = image_coord.x - layer_offset - face_offset;\n"
" int vertex_index = layer_index + face_index + vertex + (face_height - image_coord.y - 1) * "
"face_width;\n"
"\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_layout_binding = "layout(std430, binding=";
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_buffer = ") buffer ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_color = "color";
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_image_store =
" imageStore(image, image_coord, ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_layout =
"layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::compute_shader_param = "cs_";
/* Fragment shader parts */
const glw::GLchar* const TextureCubeMapArraySamplingTest::fragment_shader_input = "fs_in_color";
const glw::GLchar* const TextureCubeMapArraySamplingTest::fragment_shader_output = "fs_out_color";
const glw::GLchar* const TextureCubeMapArraySamplingTest::fragment_shader_pass_through_body_code =
"void main()\n"
"{\n"
" fs_out_color = fs_in_color;\n"
"}\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::fragment_shader_sampling_body_code = "void main()\n"
"{\n";
/* Geometry shader parts */
const glw::GLchar* const TextureCubeMapArraySamplingTest::geometry_shader_emit_vertex_code = " EmitVertex();\n"
"}\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::geometry_shader_extension = "${GEOMETRY_SHADER_REQUIRE}\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::geometry_shader_layout =
"layout(points) in;\n"
"layout(points, max_vertices=1) out;\n"
"\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::geometry_shader_sampling_body_code =
"void main()\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n";
/* Image types and name */
const glw::GLchar* const TextureCubeMapArraySamplingTest::image_float = "image2D ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::image_int = "iimage2D ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::image_name = "image";
const glw::GLchar* const TextureCubeMapArraySamplingTest::image_uint = "uimage2D ";
/* Interpolation */
const glw::GLchar* const TextureCubeMapArraySamplingTest::interpolation_flat = "flat ";
/* Sampler types and name */
const glw::GLchar* const TextureCubeMapArraySamplingTest::sampler_depth = "samplerCubeArrayShadow ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::sampler_float = "samplerCubeArray ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::sampler_int = "isamplerCubeArray ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::sampler_name = "sampler";
const glw::GLchar* const TextureCubeMapArraySamplingTest::sampler_uint = "usamplerCubeArray ";
/* Common shader parts for */
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_code_preamble = "${VERSION}\n"
"${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n"
"\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_precision = "precision highp float;\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_input = "in ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_layout = "layout(location = 0) ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_output = "out ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_uniform = "uniform ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::shader_writeonly = "writeonly ";
/* Tesselation control shader parts */
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_control_shader_layout =
"layout(vertices = 1) out;\n"
"\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_control_shader_sampling_body_code =
"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 = gl_in[gl_InvocationID].gl_Position;\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_control_shader_output = "tcs_out_";
/* Tesselation evaluation shader parts */
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_input = "tes_in_color";
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_layout =
"layout(isolines, point_mode) in;\n"
"\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_pass_through_body_code =
"void main()\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n"
" fs_in_color = tes_in_color[0];\n"
"}\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_evaluation_shader_sampling_body_code =
"void main()\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::tesselation_shader_extension =
"${TESSELLATION_SHADER_REQUIRE}\n";
/* Texture sampling routines */
const glw::GLchar* const TextureCubeMapArraySamplingTest::texture_func = "texture";
const glw::GLchar* const TextureCubeMapArraySamplingTest::textureGather_func = "textureGather";
const glw::GLchar* const TextureCubeMapArraySamplingTest::textureGrad_func = "textureGrad";
const glw::GLchar* const TextureCubeMapArraySamplingTest::textureLod_func = "textureLod";
/* Data types */
const glw::GLchar* const TextureCubeMapArraySamplingTest::type_float = "float ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::type_ivec4 = "ivec4 ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::type_uint = "uint ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::type_uvec4 = "uvec4 ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::type_vec3 = "vec3 ";
const glw::GLchar* const TextureCubeMapArraySamplingTest::type_vec4 = "vec4 ";
/* Vertex shader parts */
const glw::GLchar* const TextureCubeMapArraySamplingTest::vertex_shader_body_code =
"void main()\n"
"{\n"
" gl_PointSize = 1.0f;\n"
" gl_Position = vs_in_position;\n";
const glw::GLchar* const TextureCubeMapArraySamplingTest::vertex_shader_input = "vs_in_";
const glw::GLchar* const TextureCubeMapArraySamplingTest::vertex_shader_output = "vs_out_";
const glw::GLchar* const TextureCubeMapArraySamplingTest::vertex_shader_position = "position";
/* Static constants */
const glw::GLuint TextureCubeMapArraySamplingTest::m_get_type_api_status_program_resource = 0x02;
const glw::GLuint TextureCubeMapArraySamplingTest::m_get_type_api_status_uniform = 0x01;
const glw::GLuint TextureCubeMapArraySamplingTest::bufferDefinition::m_invalid_buffer_object_id = -1;
const glw::GLuint TextureCubeMapArraySamplingTest::programDefinition::m_invalid_program_object_id = 0;
const glw::GLuint TextureCubeMapArraySamplingTest::shaderDefinition::m_invalid_shader_object_id = 0;
const glw::GLuint TextureCubeMapArraySamplingTest::textureDefinition::m_invalid_texture_object_id = -1;
const glw::GLuint TextureCubeMapArraySamplingTest::textureDefinition::m_invalid_uniform_location = -1;
const glw::GLuint TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::m_invalid_attribute_location = -1;
const glw::GLuint TextureCubeMapArraySamplingTest::vertexArrayObjectDefinition::m_invalid_vertex_array_object_id = -1;
/* Functions */
/** Fill image with specified color
* @tparam T Image component type
* @tparam N_Components Number of image components
*
* @param image_width Width of image
* @param image_height Height of image
* @param pixel_components Image will be filled with that color
* @param out_data Image data, storage must be allocated
**/
template <typename T, unsigned int N_Components>
void fillImage(glw::GLsizei image_width, glw::GLsizei image_height, const T* pixel_components, T* out_data)
{
const glw::GLuint n_components_per_pixel = N_Components;
const glw::GLuint n_components_per_line = n_components_per_pixel * image_width;
for (glw::GLsizei y = 0; y < image_height; ++y)
{
const glw::GLuint line_offset = y * n_components_per_line;
for (glw::GLsizei x = 0; x < image_width; ++x)
{
for (glw::GLuint component = 0; component < n_components_per_pixel; ++component)
{
out_data[line_offset + x * n_components_per_pixel + component] = pixel_components[component];
}
}
}
}
/* Out of alphabetical order due to use in other functions */
/** Normalize vector stored in array. Only first N_NormalizedComponents will be normalized.
*
* @tparam N_NormalizedComponents Number of coordinates to normalize
* @tparam N_Components Number of coordinates in vector
*
* @param data Pointer to first coordinate of first vector in array
* @param index Index of vector to be normalized
**/
template <unsigned int N_NormalizedComponents, unsigned int N_Components>
void vectorNormalize(glw::GLfloat* data, glw::GLuint index)
{
glw::GLfloat* components = data + index * N_Components;
glw::GLfloat sqr_length = 0.0f;
for (glw::GLuint i = 0; i < N_NormalizedComponents; ++i)
{
const glw::GLfloat component = components[i];
sqr_length += component * component;
}
const glw::GLfloat length = sqrtf(sqr_length);
const glw::GLfloat factor = 1.0f / length;
for (glw::GLuint i = 0; i < N_NormalizedComponents; ++i)
{
components[i] *= factor;
}
}
/* Out of alphabetical order due to use in other functions */
/** Set coordinates of 4 element vector stored in array
*
* @param data Pointer to first coordinate of first vector in array
* @param index Index of vector to be normalized
* @param x 1st coordinate value
* @param y 2nd coordinate value
* @param z 3rd coordinate value
* @param w 4th coordinate value
**/
void vectorSet4(glw::GLfloat* data, glw::GLuint index, glw::GLfloat x, glw::GLfloat y, glw::GLfloat z, glw::GLfloat w)
{
const glw::GLuint n_components_per_vertex = 4;
const glw::GLuint vector_offset = n_components_per_vertex * index;
data[vector_offset + 0] = x;
data[vector_offset + 1] = y;
data[vector_offset + 2] = z;
data[vector_offset + 3] = w;
}
/* Out of alphabetical order due to use in other functions */
/** Subtract vectors: a = b - a
*
* @tparam N_Components Number of coordinates in vector
*
* @param a Pointer to vector a
* @param b Pointer to vector b
**/
template <unsigned int N_Components>
void vectorSubtractInPlace(glw::GLfloat* a, const glw::GLfloat* b)
{
const glw::GLuint n_components = N_Components;
for (glw::GLuint i = 0; i < n_components; ++i)
{
a[i] -= b[i];
}
}
/** Prepare color for rgba float textures
*
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_data Pointer to components storage
**/
void getColorFloatComponents(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level,
glw::GLint n_elements, glw::GLint n_mipmap_levels, glw::GLfloat* out_data)
{
static const glw::GLfloat n_faces = 6.0f;
out_data[0] = ((glw::GLfloat)(mipmap_level + 1)) / ((glw::GLfloat)n_mipmap_levels);
out_data[1] = ((glw::GLfloat)(cube_face + 1)) / n_faces;
out_data[2] = ((glw::GLfloat)(element_index + 1)) / ((glw::GLfloat)n_elements);
out_data[3] = 1.0f / 4.0f;
}
/** Prepare color for rgba integer textures
*
* @tparam T Type of components
*
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array, ignored
* @param n_mipmap_levels Number of mipmap levels, ignored
* @param out_data Pointer to components storage
**/
template <typename T>
void getColorIntComponents(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level,
glw::GLint /* n_elements */, glw::GLint /* n_mipmap_levels */, T* out_data)
{
out_data[0] = static_cast<T>(mipmap_level + 1);
out_data[1] = static_cast<T>(cube_face + 1);
out_data[2] = static_cast<T>(element_index + 1);
out_data[3] = 1;
}
/** Prepare color for rgba compressed textures
*
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_data Pointer to components storage
**/
void getCompressedColorUByteComponents(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level,
glw::GLint n_elements, glw::GLint n_mipmap_levels, glw::GLubyte* out_data)
{
(void)n_mipmap_levels;
static const glw::GLuint n_faces = 6;
const glw::GLuint n_faces_per_level = n_elements * n_faces;
const glw::GLubyte value =
static_cast<glw::GLubyte>(mipmap_level * n_faces_per_level + element_index * n_faces + cube_face + 1);
out_data[0] = value;
out_data[1] = value;
out_data[2] = value;
out_data[3] = value;
}
/** Get compressed texture data and size from resources. Width, height, number of array elements and mipmap level are used to identify image.
* Width and height are dimmensions of base level image, same values are used to identify all mipmap levels.
*
* @param width Width of texture
* @param height Height of texture
* @param n_array_elements Number of elemnts in array
* @param mipmap_level Level
* @param out_image_data Image data
* @param out_image_size Image size
**/
void getCompressedTexture(glw::GLuint width, glw::GLuint height, glw::GLuint n_array_elements, glw::GLuint mipmap_level,
const glw::GLubyte*& out_image_data, glw::GLuint& out_image_size)
{
for (glw::GLuint i = 0; i < n_compressed_images; ++i)
{
const compressedImage& image = compressed_images[i];
if ((image.width == width) && (image.height == height) && (image.length == n_array_elements) &&
(image.level == mipmap_level))
{
out_image_data = image.image_data;
out_image_size = image.image_size;
return;
}
}
out_image_data = 0;
out_image_size = 0;
}
/** Prepare color for depth textures
*
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_depth Depth value
**/
void getDepthComponent(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level, glw::GLint n_elements,
glw::GLint n_mipmap_levels, glw::GLfloat& out_depth)
{
static const glw::GLuint n_faces = 6;
out_depth = ((glw::GLfloat)(mipmap_level + 1 + cube_face + 1 + element_index + 1)) /
((glw::GLfloat)(n_mipmap_levels + n_faces + n_elements));
}
/** Get expected color sampled by texture or textureGather from rgba float textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
void getExpectedColorFloatComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
glw::GLint element_index, glw::GLint n_layers,
glw::GLint n_mipmap_levels, glw::GLfloat* out_components)
{
getColorFloatComponents(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels, out_components);
}
/** Get expected color sampled by textureLod or textureGrad from rgba float textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
void getExpectedColorFloatComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face,
glw::GLint element_index, glw::GLint n_layers,
glw::GLint n_mipmap_levels, glw::GLfloat* out_components)
{
glw::GLint mipmap_level = 0;
if (1 == pixel_index % 2)
{
mipmap_level = n_mipmap_levels - 1;
}
getColorFloatComponents(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels, out_components);
}
/** Get expected color sampled by texture or textureGather from rgba integer textures
*
* @tparam T Type of image components
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
template <typename T>
void getExpectedColorIntComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
glw::GLint element_index, glw::GLint n_layers, glw::GLint n_mipmap_levels,
T* out_components)
{
getColorIntComponents<T>(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels, out_components);
}
/** Get expected color sampled by textureLod or textureGrad from rgba integer textures
*
* @tparam T Type of image components
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
template <typename T>
void getExpectedColorIntComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face, glw::GLint element_index,
glw::GLint n_layers, glw::GLint n_mipmap_levels, T* out_components)
{
glw::GLint mipmap_level = 0;
if (1 == pixel_index % 2)
{
mipmap_level = n_mipmap_levels - 1;
}
getColorIntComponents<T>(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels, out_components);
}
/** Get expected color sampled by texture or textureGather from rgba compressed textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
void getExpectedCompressedComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
glw::GLint element_index, glw::GLint n_layers,
glw::GLint n_mipmap_levels, glw::GLubyte* out_components)
{
getCompressedColorUByteComponents(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels,
out_components);
}
/** Get expected color sampled by textureLod or textureGrad from rgba compressed textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
void getExpectedCompressedComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face,
glw::GLint element_index, glw::GLint n_layers,
glw::GLint n_mipmap_levels, glw::GLubyte* out_components)
{
glw::GLint mipmap_level = 0;
if (1 == pixel_index % 2)
{
mipmap_level = n_mipmap_levels - 1;
}
getCompressedColorUByteComponents(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels,
out_components);
}
/** Get expected color sampled by texture or textureGather from depth textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>
* @param cube_face Index of cube's face. Ignored.
* @param element_index Index of element in array. Ignored.
* @param n_layers Number of elements in array. Ignored.
* @param n_mipmap_levels Number of mipmap levels. Ignored.
* @param out_components Pointer to components storage
**/
void getExpectedDepthComponentsForTexture(glw::GLuint pixel_index, glw::GLint /* cube_face */,
glw::GLint /* element_index */, glw::GLint /* n_layers */,
glw::GLint /* n_mipmap_levels */, glw::GLfloat* out_components)
{
const glw::GLfloat results[9] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
out_components[0] = results[pixel_index];
}
/** Get expected color sampled by textureLod or textureGrad from depth textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
* @param cube_face Index of cube's face. Ignored.
* @param element_index Index of element in array. Ignored.
* @param n_layers Number of elements in array. Ignored.
* @param n_mipmap_levels Number of mipmap levels. Ignored.
* @param out_components Pointer to components storage
**/
void getExpectedDepthComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint /* cube_face */,
glw::GLint /* element_index */, glw::GLint /* n_layers */,
glw::GLint /* n_mipmap_levels */, glw::GLfloat* out_components)
{
if (0 == pixel_index % 2)
{
out_components[0] = 0.0f;
}
else
{
out_components[0] = 1.0f;
}
}
/* Out of alphabetical order due to use in other functions */
/** Prepare color for stencil textures
*
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_stencil Stencil value
**/
void getStencilComponent(glw::GLint cube_face, glw::GLint element_index, glw::GLint mipmap_level, glw::GLint n_elements,
glw::GLint n_mipmap_levels, glw::GLubyte& out_stencil)
{
static const glw::GLint n_faces = 6;
out_stencil = (glw::GLubyte)((mipmap_level + 1 + cube_face + 1 + element_index + 1) * 255 /
(n_mipmap_levels + n_faces + n_elements));
}
/** Get expected color sampled by texture or textureGather from stencil textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>. Ignored.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
void getExpectedStencilComponentsForTexture(glw::GLuint /* pixel_index */, glw::GLint cube_face,
glw::GLint element_index, glw::GLint n_layers, glw::GLint n_mipmap_levels,
glw::GLuint* out_components)
{
glw::GLubyte value = 0;
getStencilComponent(cube_face, element_index, 0 /* mipmap_level */, n_layers, n_mipmap_levels, value);
out_components[0] = value;
}
/** Get expected color sampled by textureLod or textureGrad from stencil textures
*
* @param pixel_index Index of pixel, identifies pixel at face <0:8> <left-top:rigth-bottom>.
* @param cube_face Index of cube's face
* @param element_index Index of element in array
* @param n_layers Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param out_components Pointer to components storage
**/
void getExpectedStencilComponentsForTextureLod(glw::GLuint pixel_index, glw::GLint cube_face, glw::GLint element_index,
glw::GLint n_layers, glw::GLint n_mipmap_levels,
glw::GLuint* out_components)
{
glw::GLubyte value = 0;
glw::GLint mipmap_level = 0;
if (1 == pixel_index % 2)
{
mipmap_level = n_mipmap_levels - 1;
}
getStencilComponent(cube_face, element_index, mipmap_level, n_layers, n_mipmap_levels, value);
out_components[0] = value;
}
/** Returns number of mipmaps for given image dimmensions
*
* @param texture_width Width of image
* @param texture_height Height of image
*
* @returns Number of mipmaps
**/
glw::GLubyte getMipmapLevelCount(glw::GLsizei texture_width, glw::GLsizei texture_height)
{
glw::GLsizei size = de::max(texture_width, texture_height);
glw::GLuint count = 1;
while (1 < size)
{
size /= 2;
count += 1;
}
return (glw::GLubyte)count;
}
/** Calculate texture coordinates for "right neighbour" of given texture coordinates
*
* @param texture_coordinates Texture coordinates of original point
* @param face Cube map's face index
* @param offset Offset of "neighbour" in "right" direction
* @param width Image width
* @param out_neighbour Texture coordinates of "neighbour" point
**/
void getRightNeighbour(const glw::GLfloat* texture_coordinates, glw::GLuint face, glw::GLuint offset, glw::GLuint width,
glw::GLfloat* out_neighbour)
{
const glw::GLfloat step = (float)offset / (float)width;
glw::GLfloat& x = out_neighbour[0];
glw::GLfloat& y = out_neighbour[1];
glw::GLfloat& z = out_neighbour[2];
const glw::GLfloat coord_x = texture_coordinates[0];
const glw::GLfloat coord_y = texture_coordinates[1];
const glw::GLfloat coord_z = texture_coordinates[2];
switch (face)
{
case 0: // +X
x = coord_x;
y = coord_y - step;
z = coord_z;
break;
case 1: // -X
x = coord_x;
y = coord_y + step;
z = coord_z;
break;
case 2: // +Y
x = coord_x + step;
y = coord_y;
z = coord_z;
break;
case 3: // -Y
x = coord_x - step;
y = coord_y;
z = coord_z;
break;
case 4: // +Z
x = coord_x + step;
y = coord_y;
z = coord_z;
break;
case 5: // -Z
x = coord_x - step;
y = coord_y;
z = coord_z;
break;
}
}
/** Calculate texture coordinates for "top neighbour" of given texture coordinates
*
* @param texture_coordinates Texture coordinates of original point
* @param face Cube map's face index
* @param offset Offset of "neighbour" in "top" direction
* @param width Image width
* @param out_neighbour Texture coordinates of "neighbour" point
**/
void getTopNeighbour(const glw::GLfloat* texture_coordinates, glw::GLuint face, glw::GLuint offset, glw::GLuint width,
glw::GLfloat* out_neighbour)
{
glw::GLfloat step = (float)offset / (float)width;
glw::GLfloat& x = out_neighbour[0];
glw::GLfloat& y = out_neighbour[1];
glw::GLfloat& z = out_neighbour[2];
const glw::GLfloat coord_x = texture_coordinates[0];
const glw::GLfloat coord_y = texture_coordinates[1];
const glw::GLfloat coord_z = texture_coordinates[2];
switch (face)
{
case 0: // +X
x = coord_x;
y = coord_y;
z = coord_z + step;
break;
case 1: // -X
x = coord_x;
y = coord_y;
z = coord_z + step;
break;
case 2: // +Y
x = coord_x;
y = coord_y;
z = coord_z + step;
break;
case 3: // -Y
x = coord_x;
y = coord_y;
z = coord_z + step;
break;
case 4: // +Z
x = coord_x;
y = coord_y - step;
z = coord_z;
break;
case 5: // -Z
x = coord_x;
y = coord_y + step;
z = coord_z;
break;
}
}
/** Write var2str instance to output stream
*
* @param stream Stream instance
* @param var var2str instance
*
* @returns Stream instance
**/
std::ostream& operator<<(std::ostream& stream, const var2str& var)
{
if (0 != var.m_prefix)
{
stream << var.m_prefix;
}
stream << var.m_name;
if (0 != var.m_index)
{
stream << "[" << var.m_index << "]";
}
return stream;
}
/* Out of alphabetical order due to use in other functions */
/** Fill texture's face at given index and level with given color
*
* @tparam T Type of image component
* @tparam N_Components Number of components
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
* @param components Color used to fill texture
**/
template <typename T, unsigned int N_Components>
void prepareDataForTexture(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLenum texture_format, glw::GLenum texture_type,
glw::GLsizei texture_width, glw::GLsizei texture_height, const T* components)
{
static const glw::GLuint n_components_per_pixel = N_Components;
const glw::GLuint n_pixels = texture_width * texture_height;
const glw::GLuint n_total_componenets = n_components_per_pixel * n_pixels;
const glw::GLuint z_offset = element_index * 6 + cube_face;
std::vector<T> texture_data;
texture_data.resize(n_total_componenets);
fillImage<T, N_Components>(texture_width, texture_height, components, &texture_data[0]);
gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mipmap_level, 0 /* x */, 0 /* y */, z_offset, texture_width,
texture_height, 1 /* depth */, texture_format, texture_type, &texture_data[0]);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to update texture data");
}
/** Prepare texture's face at given index and level, for rgba float textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareDataForColorFloatTexture(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
glw::GLfloat components[4];
getColorFloatComponents(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, components);
prepareDataForTexture<glw::GLfloat, 4>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type,
texture_width, texture_height, components);
}
/** Prepare texture's face at given index and level, for rgba integer textures.
*
* @tparam T Type of image component
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
template <typename T>
void prepareDataForColorIntTexture(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
T components[4];
getColorIntComponents<T>(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, components);
prepareDataForTexture<T, 4>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type, texture_width,
texture_height, components);
}
/** Prepare texture's face at given index and level, for depth textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareDataForDepthFloatTexture(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
glw::GLfloat component = 0;
getDepthComponent(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, component);
prepareDataForTexture<glw::GLfloat, 1>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type,
texture_width, texture_height, &component);
}
/** Prepare texture's face at given index and level, for stencil textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareDataForStencilUIntTexture(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
glw::GLubyte component = 0;
getStencilComponent(cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, component);
prepareDataForTexture<glw::GLubyte, 1>(gl, cube_face, element_index, mipmap_level, texture_format, texture_type,
texture_width, texture_height, &component);
}
/** Prepare texture's face at given index and level, for depth textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareDepthTextureFace(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
switch (texture_type)
{
case GL_FLOAT:
prepareDataForDepthFloatTexture(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
texture_format, texture_type, texture_width, texture_height);
break;
default:
TCU_FAIL("Not implemented case !");
break;
}
}
/** Prepare grad_x vector for given texture_coordinates
*
* @param grad_x Storage for grad_x
* @param face Cube map's face index
* @param texture_coordinates Texture coordinate
* @param width Image width
**/
void prepareGradXForFace(glw::GLfloat* grad_x, glw::GLuint face, glw::GLfloat* texture_coordinates, glw::GLuint width)
{
static const glw::GLuint n_points_per_face = 9;
static const glw::GLuint n_texture_coordinates_components = 4;
static const glw::GLuint n_grad_components = 4;
for (glw::GLuint i = 0; i < n_points_per_face; i += 2)
{
const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
const glw::GLuint grad_offset = i * n_grad_components;
getRightNeighbour(texture_coordinates + texture_coordinates_offset, face, 1, width, grad_x + grad_offset);
}
for (glw::GLuint i = 1; i < n_points_per_face; i += 2)
{
const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
const glw::GLuint grad_offset = i * n_grad_components;
getRightNeighbour(texture_coordinates + texture_coordinates_offset, face, 4 * width, width,
grad_x + grad_offset);
}
for (glw::GLuint i = 0; i < n_points_per_face; ++i)
{
const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
const glw::GLuint grad_offset = i * n_grad_components;
vectorSubtractInPlace<3>(grad_x + grad_offset, texture_coordinates + texture_coordinates_offset);
}
}
/** Prepare grad_y vector for given texture_coordinates
*
* @param grad_y Storage for grad_x
* @param face Cube map's face index
* @param texture_coordinates Texture coordinate
* @param width Image width
**/
void prepareGradYForFace(glw::GLfloat* grad_y, glw::GLuint face, glw::GLfloat* texture_coordinates, glw::GLuint width)
{
static const glw::GLuint n_points_per_face = 9;
static const glw::GLuint n_texture_coordinates_components = 4;
static const glw::GLuint n_grad_components = 4;
for (glw::GLuint i = 0; i < n_points_per_face; i += 2)
{
const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
const glw::GLuint grad_offset = i * n_grad_components;
getTopNeighbour(texture_coordinates + texture_coordinates_offset, face, 1, width, grad_y + grad_offset);
}
for (glw::GLuint i = 1; i < n_points_per_face; i += 2)
{
const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
const glw::GLuint grad_offset = i * n_grad_components;
getTopNeighbour(texture_coordinates + texture_coordinates_offset, face, 4 * width, width, grad_y + grad_offset);
}
for (glw::GLuint i = 0; i < n_points_per_face; ++i)
{
const glw::GLuint texture_coordinates_offset = i * n_texture_coordinates_components;
const glw::GLuint grad_offset = i * n_grad_components;
vectorSubtractInPlace<3>(grad_y + grad_offset, texture_coordinates + texture_coordinates_offset);
}
}
/** Prepare "lods" for face.
* Pattern is: B T B
* T B T
* B T B
* B - base, T - top
*
* @param lods Storage for lods
* @param n_mipmap_levels Number of mipmap levels
**/
void prepareLodForFace(glw::GLfloat* lods, glw::GLuint n_mipmap_levels)
{
const glw::GLfloat base_level = 0.0f;
const glw::GLfloat top_level = (glw::GLfloat)(n_mipmap_levels - 1);
lods[0] = base_level;
lods[1] = top_level;
lods[2] = base_level;
lods[3] = top_level;
lods[4] = base_level;
lods[5] = top_level;
lods[6] = base_level;
lods[7] = top_level;
lods[8] = base_level;
}
/** Prepare position for vertices. Each vertex is placed on a unique pixel of output image.
*
* @param positions Storage for positions
* @param cube_face Texture coordinate
* @param element_index Index of element in array
* @param n_layers Image width
**/
void preparePositionForFace(glw::GLfloat* positions, glw::GLuint cube_face, glw::GLuint element_index,
glw::GLuint n_layers)
{
static const glw::GLuint x_offset_per_face = 3;
static const glw::GLuint n_faces = 6;
const glw::GLuint x_offset_for_face = (element_index * n_faces + cube_face) * x_offset_per_face;
const glw::GLfloat x_step = 2.0f / ((glw::GLfloat)(n_layers * 3));
const glw::GLfloat x_mid_step = x_step / 2.0f;
const glw::GLfloat y_step = 2.0f / 3.0f;
const glw::GLfloat y_mid_step = y_step / 2.0f;
const glw::GLfloat x_left = -1.0f + x_mid_step + ((glw::GLfloat)x_offset_for_face) * x_step;
const glw::GLfloat x_middle = x_left + x_step;
const glw::GLfloat x_right = x_middle + x_step;
const glw::GLfloat y_top = 1.0f - y_mid_step;
const glw::GLfloat y_middle = y_top - y_step;
const glw::GLfloat y_bottom = y_middle - y_step;
vectorSet4(positions, 0, x_left, y_top, 0.0f, 1.0f);
vectorSet4(positions, 1, x_middle, y_top, 0.0f, 1.0f);
vectorSet4(positions, 2, x_right, y_top, 0.0f, 1.0f);
vectorSet4(positions, 3, x_left, y_middle, 0.0f, 1.0f);
vectorSet4(positions, 4, x_middle, y_middle, 0.0f, 1.0f);
vectorSet4(positions, 5, x_right, y_middle, 0.0f, 1.0f);
vectorSet4(positions, 6, x_left, y_bottom, 0.0f, 1.0f);
vectorSet4(positions, 7, x_middle, y_bottom, 0.0f, 1.0f);
vectorSet4(positions, 8, x_right, y_bottom, 0.0f, 1.0f);
}
/** Prepare "refZ" for face.
* Pattern is: - = +
* - = +
* - = +
* '-' - lower than depth
* = - eqaul to depth
* + - higher thatn depth
*
* @param refZs Storage for refZs
* @param n_mipmaps Number of mipmap levels
* @param face Cube map's face index
* @param layer Index of element in array
* @param n_layers Number of elements in array
**/
void prepareRefZForFace(glw::GLfloat* refZs, glw::GLuint n_mipmaps, glw::GLuint face, glw::GLuint layer,
glw::GLuint n_layers)
{
glw::GLfloat expected_base_depth_value = 0;
glw::GLfloat expected_top_depth_value = 0;
/* Get depth for top and base levles */
getDepthComponent(face, layer, 0, n_layers, n_mipmaps, expected_base_depth_value);
getDepthComponent(face, layer, n_mipmaps - 1, n_layers, n_mipmaps, expected_top_depth_value);
/* Use step of 10% */
const glw::GLfloat base_depth_step = expected_base_depth_value * 0.1f;
const glw::GLfloat top_depth_step = expected_top_depth_value * 0.1f;
/* Top row */
refZs[0] = expected_base_depth_value - base_depth_step;
refZs[1] = expected_top_depth_value;
refZs[2] = expected_base_depth_value + base_depth_step;
/* Center row */
refZs[3] = expected_top_depth_value - top_depth_step;
refZs[4] = expected_base_depth_value;
refZs[5] = expected_top_depth_value + top_depth_step;
/* Bottom row */
refZs[6] = expected_base_depth_value - base_depth_step;
refZs[7] = expected_top_depth_value;
refZs[8] = expected_base_depth_value + base_depth_step;
}
/** Prepare texture's face at given index and level, for rgba integer textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareRGBAIntegerTextureFace(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
switch (texture_type)
{
case GL_UNSIGNED_INT:
prepareDataForColorIntTexture<glw::GLuint>(gl, cube_face, element_index, mipmap_level, n_elements,
n_mipmap_levels, texture_format, texture_type, texture_width,
texture_height);
break;
case GL_INT:
prepareDataForColorIntTexture<glw::GLint>(gl, cube_face, element_index, mipmap_level, n_elements,
n_mipmap_levels, texture_format, texture_type, texture_width,
texture_height);
break;
default:
TCU_FAIL("Not implemented case !");
break;
}
}
/** Prepare texture's face at given index and level, for rgba textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareRGBATextureFace(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
switch (texture_type)
{
case GL_UNSIGNED_BYTE:
prepareDataForColorIntTexture<glw::GLubyte>(gl, cube_face, element_index, mipmap_level, n_elements,
n_mipmap_levels, texture_format, texture_type, texture_width,
texture_height);
break;
case GL_FLOAT:
prepareDataForColorFloatTexture(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
texture_format, texture_type, texture_width, texture_height);
break;
default:
TCU_FAIL("Not implemented case !");
break;
}
}
/** Prepare texture's face at given index and level, for stencil textures.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareStencilTextureFace(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
switch (texture_type)
{
case GL_UNSIGNED_BYTE:
prepareDataForStencilUIntTexture(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
texture_format, texture_type, texture_width, texture_height);
break;
default:
TCU_FAIL("Not implemented case !");
break;
}
}
/** Prepare texture coordinates for vertices.
* Each vertex has unique value. 4 corners, centers of 4 edges and central points are selected.
*
* @param positions Storage for positions
* @param cube_face Texture coordinate
* @param element_index Index of element in array
* @param n_layers Image width
**/
void prepareTextureCoordinatesForFace(glw::GLfloat* data, glw::GLuint width, glw::GLuint height, glw::GLfloat layer,
glw::GLuint face)
{
const glw::GLfloat x_range = (glw::GLfloat)width;
const glw::GLfloat y_range = (glw::GLfloat)height;
const glw::GLfloat x_step = 2.0f / x_range;
const glw::GLfloat y_step = 2.0f / y_range;
const glw::GLfloat x_mid_step = x_step / 2.0f;
const glw::GLfloat y_mid_step = y_step / 2.0f;
const glw::GLfloat left = -1.0f + x_mid_step;
const glw::GLfloat right = 1.0f - x_mid_step;
const glw::GLfloat top = 1.0f - y_mid_step;
const glw::GLfloat bottom = -1.0f + y_mid_step;
const glw::GLfloat middle = 0.0f;
const glw::GLfloat negative = -1.0f;
const glw::GLfloat positive = 1.0f;
switch (face)
{
case 0:
vectorSet4(data, 0, positive, left, top, layer);
vectorSet4(data, 1, positive, middle, top, layer);
vectorSet4(data, 2, positive, right, top, layer);
vectorSet4(data, 3, positive, left, middle, layer);
vectorSet4(data, 4, positive, middle, middle, layer);
vectorSet4(data, 5, positive, right, middle, layer);
vectorSet4(data, 6, positive, left, bottom, layer);
vectorSet4(data, 7, positive, middle, bottom, layer);
vectorSet4(data, 8, positive, right, bottom, layer);
break;
case 1:
vectorSet4(data, 0, negative, left, top, layer);
vectorSet4(data, 1, negative, middle, top, layer);
vectorSet4(data, 2, negative, right, top, layer);
vectorSet4(data, 3, negative, left, middle, layer);
vectorSet4(data, 4, negative, middle, middle, layer);
vectorSet4(data, 5, negative, right, middle, layer);
vectorSet4(data, 6, negative, left, bottom, layer);
vectorSet4(data, 7, negative, middle, bottom, layer);
vectorSet4(data, 8, negative, right, bottom, layer);
break;
case 2:
vectorSet4(data, 0, left, positive, top, layer);
vectorSet4(data, 1, middle, positive, top, layer);
vectorSet4(data, 2, right, positive, top, layer);
vectorSet4(data, 3, left, positive, middle, layer);
vectorSet4(data, 4, middle, positive, middle, layer);
vectorSet4(data, 5, right, positive, middle, layer);
vectorSet4(data, 6, left, positive, bottom, layer);
vectorSet4(data, 7, middle, positive, bottom, layer);
vectorSet4(data, 8, right, positive, bottom, layer);
break;
case 3:
vectorSet4(data, 0, left, negative, top, layer);
vectorSet4(data, 1, middle, negative, top, layer);
vectorSet4(data, 2, right, negative, top, layer);
vectorSet4(data, 3, left, negative, middle, layer);
vectorSet4(data, 4, middle, negative, middle, layer);
vectorSet4(data, 5, right, negative, middle, layer);
vectorSet4(data, 6, left, negative, bottom, layer);
vectorSet4(data, 7, middle, negative, bottom, layer);
vectorSet4(data, 8, right, negative, bottom, layer);
break;
case 4:
vectorSet4(data, 0, left, top, positive, layer);
vectorSet4(data, 1, middle, top, positive, layer);
vectorSet4(data, 2, right, top, positive, layer);
vectorSet4(data, 3, left, middle, positive, layer);
vectorSet4(data, 4, middle, middle, positive, layer);
vectorSet4(data, 5, right, middle, positive, layer);
vectorSet4(data, 6, left, bottom, positive, layer);
vectorSet4(data, 7, middle, bottom, positive, layer);
vectorSet4(data, 8, right, bottom, positive, layer);
break;
case 5:
vectorSet4(data, 0, left, top, negative, layer);
vectorSet4(data, 1, middle, top, negative, layer);
vectorSet4(data, 2, right, top, negative, layer);
vectorSet4(data, 3, left, middle, negative, layer);
vectorSet4(data, 4, middle, middle, negative, layer);
vectorSet4(data, 5, right, middle, negative, layer);
vectorSet4(data, 6, left, bottom, negative, layer);
vectorSet4(data, 7, middle, bottom, negative, layer);
vectorSet4(data, 8, right, bottom, negative, layer);
break;
};
vectorNormalize<3, 4>(data, 0);
vectorNormalize<3, 4>(data, 1);
vectorNormalize<3, 4>(data, 2);
vectorNormalize<3, 4>(data, 3);
vectorNormalize<3, 4>(data, 4);
vectorNormalize<3, 4>(data, 5);
vectorNormalize<3, 4>(data, 6);
vectorNormalize<3, 4>(data, 7);
vectorNormalize<3, 4>(data, 8);
}
/** Prepare texture coordinates for vertices. For sampling with textureGather routine.
* Each vertex has unique value. 4 corners, centers of 4 edges and central points are selected.
*
* @param positions Storage for positions
* @param cube_face Texture coordinate
* @param element_index Index of element in array
* @param n_layers Image width
**/
void prepareTextureCoordinatesForGatherForFace(glw::GLfloat* data, glw::GLuint width, glw::GLuint height,
glw::GLfloat layer, glw::GLuint face)
{
const glw::GLfloat x_range = (glw::GLfloat)width;
const glw::GLfloat y_range = (glw::GLfloat)height;
const glw::GLfloat x_step = 2.0f / x_range;
const glw::GLfloat y_step = 2.0f / y_range;
const glw::GLfloat x_mid_step = x_step / 2.0f;
const glw::GLfloat y_mid_step = y_step / 2.0f;
const glw::GLfloat left = -1.0f + x_mid_step + x_step;
const glw::GLfloat right = 1.0f - x_mid_step - x_step;
const glw::GLfloat top = 1.0f - y_mid_step - y_step;
const glw::GLfloat bottom = -1.0f + y_mid_step + y_step;
const glw::GLfloat middle = 0.0f;
const glw::GLfloat negative = -1.0f;
const glw::GLfloat positive = 1.0f;
switch (face)
{
case 0:
vectorSet4(data, 0, positive, left, top, layer);
vectorSet4(data, 1, positive, middle, top, layer);
vectorSet4(data, 2, positive, right, top, layer);
vectorSet4(data, 3, positive, left, middle, layer);
vectorSet4(data, 4, positive, middle, middle, layer);
vectorSet4(data, 5, positive, right, middle, layer);
vectorSet4(data, 6, positive, left, bottom, layer);
vectorSet4(data, 7, positive, middle, bottom, layer);
vectorSet4(data, 8, positive, right, bottom, layer);
break;
case 1:
vectorSet4(data, 0, negative, left, top, layer);
vectorSet4(data, 1, negative, middle, top, layer);
vectorSet4(data, 2, negative, right, top, layer);
vectorSet4(data, 3, negative, left, middle, layer);
vectorSet4(data, 4, negative, middle, middle, layer);
vectorSet4(data, 5, negative, right, middle, layer);
vectorSet4(data, 6, negative, left, bottom, layer);
vectorSet4(data, 7, negative, middle, bottom, layer);
vectorSet4(data, 8, negative, right, bottom, layer);
break;
case 2:
vectorSet4(data, 0, left, positive, top, layer);
vectorSet4(data, 1, middle, positive, top, layer);
vectorSet4(data, 2, right, positive, top, layer);
vectorSet4(data, 3, left, positive, middle, layer);
vectorSet4(data, 4, middle, positive, middle, layer);
vectorSet4(data, 5, right, positive, middle, layer);
vectorSet4(data, 6, left, positive, bottom, layer);
vectorSet4(data, 7, middle, positive, bottom, layer);
vectorSet4(data, 8, right, positive, bottom, layer);
break;
case 3:
vectorSet4(data, 0, left, negative, top, layer);
vectorSet4(data, 1, middle, negative, top, layer);
vectorSet4(data, 2, right, negative, top, layer);
vectorSet4(data, 3, left, negative, middle, layer);
vectorSet4(data, 4, middle, negative, middle, layer);
vectorSet4(data, 5, right, negative, middle, layer);
vectorSet4(data, 6, left, negative, bottom, layer);
vectorSet4(data, 7, middle, negative, bottom, layer);
vectorSet4(data, 8, right, negative, bottom, layer);
break;
case 4:
vectorSet4(data, 0, left, top, positive, layer);
vectorSet4(data, 1, middle, top, positive, layer);
vectorSet4(data, 2, right, top, positive, layer);
vectorSet4(data, 3, left, middle, positive, layer);
vectorSet4(data, 4, middle, middle, positive, layer);
vectorSet4(data, 5, right, middle, positive, layer);
vectorSet4(data, 6, left, bottom, positive, layer);
vectorSet4(data, 7, middle, bottom, positive, layer);
vectorSet4(data, 8, right, bottom, positive, layer);
break;
case 5:
vectorSet4(data, 0, left, top, negative, layer);
vectorSet4(data, 1, middle, top, negative, layer);
vectorSet4(data, 2, right, top, negative, layer);
vectorSet4(data, 3, left, middle, negative, layer);
vectorSet4(data, 4, middle, middle, negative, layer);
vectorSet4(data, 5, right, middle, negative, layer);
vectorSet4(data, 6, left, bottom, negative, layer);
vectorSet4(data, 7, middle, bottom, negative, layer);
vectorSet4(data, 8, right, bottom, negative, layer);
break;
};
vectorNormalize<3, 4>(data, 0);
vectorNormalize<3, 4>(data, 1);
vectorNormalize<3, 4>(data, 2);
vectorNormalize<3, 4>(data, 3);
vectorNormalize<3, 4>(data, 4);
vectorNormalize<3, 4>(data, 5);
vectorNormalize<3, 4>(data, 6);
vectorNormalize<3, 4>(data, 7);
vectorNormalize<3, 4>(data, 8);
}
/** Prepare texture's face at given index and level.
*
* @param gl GL functions
* @param cube_face Index of cube map's face
* @param element_index Index of element in array
* @param mipmap_level Mipmap level
* @param n_elements Number of elements in array
* @param n_mipmap_levels Number of mipmap levels
* @param texture_format Texture format
* @param texture_width Texture width
* @param texture_height Texture height
**/
void prepareTextureFace(const glw::Functions& gl, glw::GLint cube_face, glw::GLint element_index,
glw::GLint mipmap_level, glw::GLint n_elements, glw::GLint n_mipmap_levels,
glw::GLenum texture_format, glw::GLenum texture_type, glw::GLsizei texture_width,
glw::GLsizei texture_height)
{
switch (texture_format)
{
case GL_RGBA:
prepareRGBATextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, texture_format,
texture_type, texture_width, texture_height);
break;
case GL_RGBA_INTEGER:
prepareRGBAIntegerTextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
texture_format, texture_type, texture_width, texture_height);
break;
case GL_DEPTH_COMPONENT:
prepareDepthTextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels, texture_format,
texture_type, texture_width, texture_height);
break;
case GL_STENCIL_INDEX:
prepareStencilTextureFace(gl, cube_face, element_index, mipmap_level, n_elements, n_mipmap_levels,
texture_format, texture_type, texture_width, texture_height);
break;
default:
TCU_FAIL("Not implemented case !");
break;
}
}
/** Verifies that all pixels rendered for specific face match expectations
*
* @tparam T Type of image component
* @tparam N_Components Number of image components
* @tparam Width Width of single face
* @tparam Height Height of single face
*
* @param data Rendered data
* @param cube_face Index of face in array
* @param expected_values Expected values
* @param image_width Widht of whole image
**/
template <typename T, unsigned int N_Components, unsigned int Width, unsigned int Height>
bool verifyFace(const T* data, const glw::GLuint cube_face, const T* expected_values, const glw::GLuint image_width)
{
static const glw::GLuint size_of_pixel = N_Components;
const glw::GLuint data_face_offset = N_Components * Width * cube_face;
const glw::GLuint exp_face_offset = N_Components * Width * Height * cube_face;
const glw::GLuint data_size_of_line = image_width * size_of_pixel;
const glw::GLuint exp_size_of_line = Width * size_of_pixel;
for (glw::GLuint y = 0; y < Height; ++y)
{
const glw::GLuint data_line_offset = y * data_size_of_line;
const glw::GLuint exp_line_offset = y * exp_size_of_line;
for (glw::GLuint x = 0; x < Width; ++x)
{
const glw::GLuint data_pixel_offset = data_line_offset + data_face_offset + x * size_of_pixel;
const glw::GLuint exp_pixel_offset = exp_line_offset + exp_face_offset + x * size_of_pixel;
for (glw::GLuint component = 0; component < N_Components; ++component)
{
if (data[data_pixel_offset + component] != expected_values[exp_pixel_offset + component])
{
return false;
}
}
}
}
return true;
}
/** Verifies that all rendered pixels match expectation
*
* @tparam T Type of image component
* @tparam N_Components Number of image components
* @tparam Width Width of single face
* @tparam Height Height of single face
*
* @param data Rendered data
* @param expected_values Expected values
* @param n_layers Number of elements in array
**/
template <typename T, unsigned int N_Components, unsigned int Width, unsigned int Height>
bool verifyImage(const T* data, const T* expected_values, const glw::GLuint n_layers)
{
static const glw::GLuint n_faces = 6;
const glw::GLuint n_total_faces = n_layers * n_faces;
for (glw::GLuint face = 0; face < n_total_faces; ++face)
{
if (false == verifyFace<T, N_Components, Width, Height>(data, face, expected_values, n_total_faces * Width))
{
return false;
}
}
return true;
}
/** Verifies that all rendered pixels match expectation
*
* @tparam T Type of image component
* @tparam N_Components Number of image components
* @tparam Width Width of single face
* @tparam Height Height of single face
*
* @param n_mipmap_levels Number of mipmap levels
* @param n_layers Number of elements in array
* @param getComponents Routine which is used to obtain components
* @param data Rendered data
**/
template <typename T, unsigned int N_Components, unsigned int Width, unsigned int Height>
bool verifyResultImage(glw::GLuint n_mipmap_levels, glw::GLuint n_layers,
void (*getComponents)(glw::GLuint pixel_index, glw::GLint cube_face, glw::GLint layer_index,
glw::GLint n_layers, glw::GLint n_mipmap_levels, T* out_components),
const glw::GLubyte* data)
{
const glw::GLuint n_components = N_Components;
const glw::GLuint face_width = Width;
const glw::GLuint face_height = Height;
const glw::GLuint n_pixels_per_face = face_width * face_height;
const glw::GLuint n_components_per_face = n_pixels_per_face * n_components;
const glw::GLuint n_faces = 6;
const glw::GLuint n_total_faces = n_layers * n_faces;
const glw::GLuint n_total_components = n_total_faces * n_components_per_face;
const T* result_image = (const T*)data;
std::vector<T> expected_values;
expected_values.resize(n_total_components);
for (glw::GLuint layer = 0; layer < n_layers; ++layer)
{
const glw::GLuint layer_offset = layer * n_faces * n_components_per_face;
for (glw::GLuint face = 0; face < n_faces; ++face)
{
const glw::GLuint face_offset = face * n_components_per_face + layer_offset;
for (glw::GLuint pixel = 0; pixel < n_pixels_per_face; ++pixel)
{
const glw::GLuint pixel_offset = pixel * n_components + face_offset;
T components[n_components];
getComponents(pixel, face, layer, n_layers, n_mipmap_levels, components);
for (glw::GLuint component = 0; component < n_components; ++component)
{
const glw::GLuint component_offset = pixel_offset + component;
expected_values[component_offset] = components[component];
}
}
}
}
return verifyImage<T, N_Components, Width, Height>(result_image, &expected_values[0], n_layers);
}
/** Constructor
*
* @param context Test context
* @param name Test case's name
* @param description Test case's desricption
**/
TextureCubeMapArraySamplingTest::TextureCubeMapArraySamplingTest(Context& context, const ExtParameters& extParams,
const char* name, const char* description)
: TestCaseBase(context, extParams, name, description)
, m_framebuffer_object_id(0)
, compiled_shaders(0)
, invalid_shaders(0)
, linked_programs(0)
, invalid_programs(0)
, tested_cases(0)
, failed_cases(0)
, invalid_type_cases(0)
{
/* Prepare formats set */
m_formats.push_back(formatDefinition(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, Float, "GL_RGBA8"));
m_formats.push_back(formatDefinition(GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, false, Int, "GL_RGBA32I"));
m_formats.push_back(formatDefinition(GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, false, UInt, "GL_RGBA32UI"));
m_formats.push_back(formatDefinition(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT, false, GL_RGBA8, GL_RGBA,
GL_UNSIGNED_BYTE, Depth, "GL_DEPTH_COMPONENT32F"));
m_formats.push_back(formatDefinition(GL_STENCIL_INDEX8, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, false, GL_R32UI,
GL_RGBA_INTEGER, GL_UNSIGNED_INT, Stencil, "GL_STENCIL_INDEX8"));
/* Prepare sampling functions set */
m_functions.push_back(samplingFunctionDefinition(Texture, "Texture"));
m_functions.push_back(samplingFunctionDefinition(TextureLod, "TextureLod"));
m_functions.push_back(samplingFunctionDefinition(TextureGrad, "TextureGrad"));
m_functions.push_back(samplingFunctionDefinition(TextureGather, "TextureGather"));
/* Prepare mutabilities set */
m_mutabilities.push_back(true);
m_mutabilities.push_back(false);
/* Prepare resolutions set */
m_resolutions.push_back(resolutionDefinition(64, 64, 18));
m_resolutions.push_back(resolutionDefinition(117, 117, 6));
m_resolutions.push_back(resolutionDefinition(256, 256, 6));
m_resolutions.push_back(resolutionDefinition(173, 173, 12));
/* Prepare resolutions set for compressed formats */
m_compressed_resolutions.push_back(resolutionDefinition(8, 8, 12));
m_compressed_resolutions.push_back(resolutionDefinition(13, 13, 12));
}
/** Check if getActiveUniform and glGetProgramResourceiv returns correct type for cube array samplers.
*
* @param program_id Program id
* @param sampler_name_p Name of sampler
* @param sampler_type Expected type of sampler
*
* @return Status. 1st LSB - glGetActiveUniform, second LSB glGetProgramResourceiv, 0 valid, 1 invalid.
**/
glw::GLuint TextureCubeMapArraySamplingTest::checkUniformAndResourceApi(glw::GLuint program_id,
const glw::GLchar* sampler_name_p,
samplerType sampler_type)
{
/* GL functions */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glw::GLenum expected_type = 0;
glw::GLuint index_getActiveUniform = GL_INVALID_INDEX;
glw::GLuint index_getProgramResourceiv = GL_INVALID_INDEX;
glw::GLenum props = GL_TYPE;
glw::GLuint result = 0;
glw::GLchar* name = 0;
glw::GLint size = 0;
glw::GLenum type_getActiveUniform = 0;
glw::GLint type_getProgramResourceiv = 0;
// Get type by getActiveUniform
gl.getUniformIndices(program_id, 1, &sampler_name_p, &index_getActiveUniform);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformIndices");
if (GL_INVALID_INDEX == index_getActiveUniform)
{
throw tcu::InternalError("glGetUniformIndices: GL_INVALID_INDEX", "", __FILE__, __LINE__);
}
gl.getActiveUniform(program_id, index_getActiveUniform, 0, 0, &size, &type_getActiveUniform, name);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetActiveUniform");
// Get type by gl.getProgramResourceiv
index_getProgramResourceiv = gl.getProgramResourceIndex(program_id, GL_UNIFORM, sampler_name_p);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex");
if (GL_INVALID_INDEX == index_getProgramResourceiv)
{
throw tcu::InternalError("glGetProgramResourceIndex: GL_INVALID_INDEX", "", __FILE__, __LINE__);
}
gl.getProgramResourceiv(program_id, GL_UNIFORM, index_getProgramResourceiv, 1, &props, 1, 0,
&type_getProgramResourceiv);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv");
// Verification
switch (sampler_type)
{
case Float:
expected_type = GL_SAMPLER_CUBE_MAP_ARRAY;
break;
case Int:
expected_type = GL_INT_SAMPLER_CUBE_MAP_ARRAY;
break;
case UInt:
expected_type = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
break;
case Depth:
expected_type = GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW;
break;
case Stencil:
expected_type = GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY;
break;
}
if (expected_type != type_getActiveUniform)
{
result |= m_get_type_api_status_uniform;
}
if (expected_type != (glw::GLuint)type_getProgramResourceiv)
{
result |= m_get_type_api_status_program_resource;
}
return result;
}
/** Compile shader
*
* @param info Shader info
**/
void TextureCubeMapArraySamplingTest::compile(shaderDefinition& info)
{
compiled_shaders += 1;
if (false == info.compile())
{
invalid_shaders += 1;
logCompilationLog(info);
}
}
/** Execute compute shader
*
* @param program_id Program id
* @param width Width of result image
* @param height Height of result image
**/
void TextureCubeMapArraySamplingTest::dispatch(glw::GLuint program_id, glw::GLuint width, glw::GLuint height)
{
(void)program_id;
/* GL functions */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.dispatchCompute(width, height, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glDispatchCompute call.");
}
/** Execute render call
*
* @param program_id Program id
* @param primitive_type Type of primitive
* @param n_vertices Number of vertices
**/
void TextureCubeMapArraySamplingTest::draw(glw::GLuint program_id, glw::GLenum primitive_type, glw::GLuint n_vertices,
glw::GLenum format)
{
(void)program_id;
/* GL functions */
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
const glw::GLenum framebuffer_status = gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status)
{
throw tcu::InternalError("Framebuffer is incomplete", "", __FILE__, __LINE__);
}
switch (format)
{
case GL_RGBA32I:
{
const glw::GLint clearValue[4] = { 255, 255, 255, 255 };
gl.clearBufferiv(GL_COLOR, 0, clearValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearBufferiv call.");
}
break;
case GL_RGBA32UI:
case GL_R32UI:
{
const glw::GLuint clearValue[4] = { 255, 255, 255, 255 };
gl.clearBufferuiv(GL_COLOR, 0, clearValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearBufferuiv call.");
}
break;
case GL_DEPTH_COMPONENT32F:
gl.clearDepthf(1.0f);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearDepthf call.");
break;
case GL_STENCIL_INDEX8:
gl.clearStencil(1);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearStencil call.");
break;
default:
gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClearColor call.");
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glClear call.");
}
gl.drawArrays(primitive_type, 0, n_vertices);
GLU_EXPECT_NO_ERROR(gl.getError(), "Failed glDrawArrays call.");
}
/** Get attributes specific for type of sampler
*
* @param sampler_type Type of sampler
* @param out_attribute_definitions Array of attributes
* @param out_n_attributes Number of attributes
**/
void TextureCubeMapArraySamplingTest::getAttributes(samplerType sampler_type,
const attributeDefinition*& out_attribute_definitions,
glw::GLuint& out_n_attributes)
{
static attributeDefinition depth_attributes[] = { { attribute_refZ, type_float, RefZ, 1 } };
static const glw::GLuint n_depth_attributes = sizeof(depth_attributes) / sizeof(depth_attributes[0]);
switch (sampler_type)
{
case Depth:
out_attribute_definitions = depth_attributes;
out_n_attributes = n_depth_attributes;
break;
default:
out_attribute_definitions = 0;
out_n_attributes = 0;
break;
};
}
/** Get attributes specific for sampling function
*
* @param sampling_function Sampling function
* @param out_attribute_definitions Array of attributes
* @param out_n_attributes Number of attributes
**/
void TextureCubeMapArraySamplingTest::getAttributes(samplingFunction sampling_function,
const attributeDefinition*& out_attribute_definitions,
glw::GLuint& out_n_attributes)
{
static attributeDefinition texture_attributes[] = { { attribute_texture_coordinate, type_vec4, TextureCoordinates,
0 } };
static attributeDefinition textureLod_attributes[] = {
{ attribute_texture_coordinate, type_vec4, TextureCoordinates, 0 }, { attribute_lod, type_float, Lod, 1 }
};
static attributeDefinition textureGrad_attributes[] = { { attribute_texture_coordinate, type_vec4,
TextureCoordinates, 0 },
{ attribute_grad_x, type_vec3, GradX, 1 },
{ attribute_grad_y, type_vec3, GradY, 2 } };
static attributeDefinition textureGather_attributes[] = { { attribute_texture_coordinate, type_vec4,
TextureCoordinatesForGather, 0 } };
static const glw::GLuint n_texture_attributes = sizeof(texture_attributes) / sizeof(texture_attributes[0]);
static const glw::GLuint n_textureLod_attributes = sizeof(textureLod_attributes) / sizeof(textureLod_attributes[0]);
static const glw::GLuint n_textureGrad_attributes =
sizeof(textureGrad_attributes) / sizeof(textureGrad_attributes[0]);
static const glw::GLuint n_textureGather_attributes =
sizeof(textureGather_attributes) / sizeof(textureGather_attributes[0]);
switch (sampling_function)
{
case Texture:
out_attribute_definitions = texture_attributes;
out_n_attributes = n_texture_attributes;
break;
case TextureLod:
out_attribute_definitions = textureLod_attributes;
out_n_attributes = n_textureLod_attributes;
break;
case TextureGrad:
out_attribute_definitions = textureGrad_attributes;
out_n_attributes = n_textureGrad_attributes;
break;
case TextureGather:
out_attribute_definitions = textureGather_attributes;
out_n_attributes = n_textureGather_attributes;
break;
};
}
/** Get information about color type for type of sampler
*
* @param sampler_type Type of sampler
* @param out_color_type Type used for color storage
* @param out_interpolation_type Type of interpolation
* @param out_sampler_type Type of sampler
* @param out_n_components Number of components in color
* @param out_is_shadow If shadow sampler
**/
void TextureCubeMapArraySamplingTest::getColorType(samplerType sampler_type, const glw::GLchar*& out_color_type,
const glw::GLchar*& out_interpolation_type,
const glw::GLchar*& out_sampler_type, glw::GLuint& out_n_components,
bool& out_is_shadow)
{
switch (sampler_type)
{
case Float:
out_color_type = type_vec4;
out_interpolation_type = "";
out_sampler_type = sampler_float;
out_n_components = 4;
out_is_shadow = false;
break;
case Int:
out_color_type = type_ivec4;
out_interpolation_type = interpolation_flat;
out_sampler_type = sampler_int;
out_n_components = 4;
out_is_shadow = false;
break;
case UInt:
out_color_type = type_uvec4;
out_interpolation_type = interpolation_flat;
out_sampler_type = sampler_uint;
out_n_components = 4;
out_is_shadow = false;
break;
case Depth:
out_color_type = type_float;
out_interpolation_type = "";
out_sampler_type = sampler_depth;
out_n_components = 1;
out_is_shadow = true;
break;
case Stencil:
out_color_type = type_uint;
out_interpolation_type = interpolation_flat;
out_sampler_type = sampler_uint;
out_n_components = 1;
out_is_shadow = false;
break;
};
}
/** Get information about color type for type of sampler
*
* @param sampler_type Type of sampler
* @param out_color_type Type used for color storage
* @param out_interpolation_type Type of interpolation
* @param out_sampler_type Type of sampler
* @param out_image_type Type of image
* @param out_n_components Number of components in color
* @param out_is_shadow If shadow sampler
**/
void TextureCubeMapArraySamplingTest::getColorType(samplerType sampler_type, const glw::GLchar*& out_color_type,
const glw::GLchar*& out_interpolation_type,
const glw::GLchar*& out_sampler_type,
const glw::GLchar*& out_image_type,
const glw::GLchar*& out_image_layout, glw::GLuint& out_n_components,
bool& out_is_shadow)
{
getColorType(sampler_type, out_color_type, out_interpolation_type, out_sampler_type, out_n_components,
out_is_shadow);
switch (sampler_type)
{
case Float:
out_image_type = image_float;
out_image_layout = "rgba8";
break;
case Depth:
out_image_type = image_float;
out_image_layout = "rgba8";
break;
case Int:
out_image_type = image_int;
out_image_layout = "rgba32i";
break;
case UInt:
out_image_type = image_uint;
out_image_layout = "rgba32ui";
break;
case Stencil:
out_image_type = image_uint;
out_image_layout = "r32ui";
break;
};
}
/** Prepare code for passthrough fragment shader
*
* @param sampler_type Type of sampler
* @param out_fragment_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getPassThroughFragmentShaderCode(samplerType sampler_type,
std::string& out_fragment_shader_code)
{
std::stringstream stream;
const glw::GLchar* color_type;
const glw::GLchar* interpolation_type;
const glw::GLchar* ignored_sampler_type;
glw::GLuint ignored_n_components;
bool ignored_is_shadow;
/* Get type for color variables */
getColorType(sampler_type, color_type, interpolation_type, ignored_sampler_type, ignored_n_components,
ignored_is_shadow);
/* Preamble */
stream << shader_code_preamble << shader_precision << "/* Pass through fragment shader */" << std::endl;
/* in vec4 fs_in_color */
stream << interpolation_type << shader_input << color_type << fragment_shader_input << ";" << std::endl;
stream << std::endl;
/* layout(location = 0) out vec4 fs_out_color */
stream << shader_layout << shader_output << color_type << fragment_shader_output << ";" << std::endl;
stream << std::endl;
/* Body */
stream << fragment_shader_pass_through_body_code << std::endl;
/* Store result */
out_fragment_shader_code = stream.str();
}
/** Prepare code for passthrough tesselation control shader
*
* @param sampler_type Type of sampler
* @param out_tesselation_control_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getPassThroughTesselationControlShaderCode(
const samplerType& sampler_type, const samplingFunction& sampling_function,
std::string& out_tesselation_control_shader_code)
{
std::stringstream stream;
glw::GLuint n_routine_attributes = 0;
glw::GLuint n_type_attributes = 0;
const attributeDefinition* routine_attribute_definitions = 0;
const attributeDefinition* type_attribute_definitions = 0;
getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
/* Preamble, extension : require */
stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
<< "/* Passthrough tesselation control shader */" << std::endl;
/* layout(vertices = 1) out */
stream << tesselation_control_shader_layout;
/* in type attribute*/
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
<< routine_attribute_definitions[i].name << "[];" << std::endl;
stream << shader_output << routine_attribute_definitions[i].type << tesselation_control_shader_output
<< routine_attribute_definitions[i].name << "[];" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
<< type_attribute_definitions[i].name << "[];" << std::endl;
stream << shader_output << type_attribute_definitions[i].type << tesselation_control_shader_output
<< type_attribute_definitions[i].name << "[];" << std::endl;
}
/* Body */
stream << tesselation_control_shader_sampling_body_code;
/* tcs_out[gl_InvocationID] = vs_out[gl_InvocationID] */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << " " << tesselation_control_shader_output << routine_attribute_definitions[i].name
<< "[gl_InvocationID] = " << vertex_shader_output << routine_attribute_definitions[i].name
<< "[gl_InvocationID];" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << " " << tesselation_control_shader_output << type_attribute_definitions[i].name
<< "[gl_InvocationID] = " << vertex_shader_output << type_attribute_definitions[i].name
<< "[gl_InvocationID];" << std::endl;
}
stream << "}" << std::endl << std::endl;
/* Store result */
out_tesselation_control_shader_code = stream.str();
}
/** Prepare code for passthrough tesselation evaluation shader
*
* @param sampler_type Type of sampler
* @param out_tesselation_evaluation_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getPassThroughTesselationEvaluationShaderCode(
samplerType sampler_type, std::string& out_tesselation_evaluation_shader_code)
{
const glw::GLchar* color_type = 0;
bool ignored_is_shadow = false;
glw::GLuint ignored_n_components = 0;
const glw::GLchar* ignored_sampler_type = 0;
const glw::GLchar* interpolation_type = 0;
std::stringstream stream;
/* Get type for color variables */
getColorType(sampler_type, color_type, interpolation_type, ignored_sampler_type, ignored_n_components,
ignored_is_shadow);
/* Preamble, extension : require */
stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
<< "/* Pass through tesselation evaluation shader */" << std::endl;
/* layout(point_mode) in; */
stream << tesselation_evaluation_shader_layout;
/* in vec4 tes_in_color[] */
stream << interpolation_type << shader_input << color_type << tesselation_evaluation_shader_input << "[];"
<< std::endl;
stream << std::endl;
/* out vec4 fs_in_color[] */
stream << interpolation_type << shader_output << color_type << fragment_shader_input << ";" << std::endl;
stream << std::endl;
/* Body */
stream << tesselation_evaluation_shader_pass_through_body_code << std::endl;
/* Store result */
out_tesselation_evaluation_shader_code = stream.str();
}
/** Prepare code for passthrough vertex shader
*
* @param sampler_type Type of sampler
* @param sampling_function Type of sampling function
* @param out_vertex_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getPassThroughVertexShaderCode(const samplerType& sampler_type,
const samplingFunction& sampling_function,
std::string& out_vertex_shader_code)
{
glw::GLuint n_routine_attributes = 0;
glw::GLuint n_type_attributes = 0;
const attributeDefinition* routine_attribute_definitions = 0;
std::stringstream stream;
const attributeDefinition* type_attribute_definitions = 0;
/* Get attributes for sampling function */
getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
/* Preamble */
stream << shader_code_preamble << "/* Pass through vertex shader */" << std::endl << shader_precision;
/* in vec4 vs_in_position */
stream << shader_input << type_vec4 << vertex_shader_input << vertex_shader_position << ";" << std::endl;
/* in type vs_in_attribute */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_input
<< routine_attribute_definitions[i].name << ";" << std::endl;
}
/* in float vs_in_refZ */
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << shader_input << type_attribute_definitions[i].type << vertex_shader_input
<< type_attribute_definitions[i].name << ";" << std::endl;
}
stream << std::endl;
/* out type vs_out_attribute */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << shader_output << routine_attribute_definitions[i].type << vertex_shader_output
<< routine_attribute_definitions[i].name << ";" << std::endl;
}
/* out float vs_out_refZ */
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << shader_output << type_attribute_definitions[i].type << vertex_shader_output
<< type_attribute_definitions[i].name << ";" << std::endl;
}
stream << std::endl;
/* Body */
stream << vertex_shader_body_code;
/* vs_out = vs_in */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << " " << vertex_shader_output << routine_attribute_definitions[i].name << " = "
<< vertex_shader_input << routine_attribute_definitions[i].name << ";" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << " " << vertex_shader_output << type_attribute_definitions[i].name << " = " << vertex_shader_input
<< type_attribute_definitions[i].name << ";" << std::endl;
}
stream << "}" << std::endl << std::endl;
/* Store result */
out_vertex_shader_code = stream.str();
}
/** Prepare code for sampling compute shader
*
* @param sampler_type Type of sampler
* @param sampling_function Type of sampling function
* @param out_compute_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getSamplingComputeShaderCode(const samplerType& sampler_type,
const samplingFunction& sampling_function,
std::string& out_compute_shader_code)
{
const glw::GLchar* color_type = 0;
const glw::GLchar* image_type_str = 0;
const glw::GLchar* image_layout_str = 0;
const glw::GLchar* interpolation_type = 0;
bool is_shadow_sampler = false;
glw::GLuint n_components = 0;
glw::GLuint n_routine_attributes = 0;
glw::GLuint n_type_attributes = 0;
const attributeDefinition* routine_attribute_definitions = 0;
const attributeDefinition* type_attribute_definitions = 0;
const glw::GLchar* sampler_type_str = 0;
std::string sampling_code;
std::stringstream stream;
/* Get attributes for sampling function */
getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
/* Get type for color variables */
getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, image_type_str, image_layout_str,
n_components, is_shadow_sampler);
/* Get sampling code */
if (false == is_shadow_sampler)
{
getSamplingFunctionCall(sampling_function, color_type, n_components, compute_shader_param, 0,
compute_shader_color, 0, sampler_name, sampling_code);
}
else
{
getShadowSamplingFunctionCall(sampling_function, color_type, n_components, compute_shader_param, 0,
compute_shader_color, 0, sampler_name, sampling_code);
}
/* Preamble */
stream << shader_code_preamble << shader_precision << "/* Sampling compute shader */" << std::endl;
/* uniform samplerType sampler */
stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
/* uniform writeonly image2D image*/
stream << "layout(" << image_layout_str << ") " << shader_uniform << shader_writeonly << "highp " << image_type_str
<< image_name << ";" << std::endl;
/* layout(shared) buffer attribute { type attribute_data[]; }; */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << compute_shader_layout_binding << routine_attribute_definitions[i].binding << compute_shader_buffer
<< routine_attribute_definitions[i].name << std::endl;
stream << "{\n";
stream << " " << routine_attribute_definitions[i].type << " " << routine_attribute_definitions[i].name
<< "_data[];\n";
stream << "};\n";
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << compute_shader_layout_binding << type_attribute_definitions[i].binding << compute_shader_buffer
<< type_attribute_definitions[i].name << std::endl;
stream << "{\n";
stream << " " << type_attribute_definitions[i].type << " " << type_attribute_definitions[i].name
<< "_data[];\n";
stream << "};\n";
}
/* layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; */
stream << compute_shader_layout << std::endl;
/* main + body */
stream << compute_shader_body;
/* type cs_attribute = attribute_data[vertex_index] */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << " " << routine_attribute_definitions[i].type << compute_shader_param
<< routine_attribute_definitions[i].name << " = " << routine_attribute_definitions[i].name
<< "_data[vertex_index];" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << " " << type_attribute_definitions[i].type << compute_shader_param
<< type_attribute_definitions[i].name << " = " << type_attribute_definitions[i].name
<< "_data[vertex_index];" << std::endl;
}
/* type color */
stream << std::endl << " " << color_type << compute_shader_color << ";" << std::endl;
/* color = texture*/
stream << std::endl << sampling_code << std::endl;
//stream << std::endl << compute_shader_color << " = vec4(cs_grad_x, 255.0);" << std::endl;
/* imageStore */
stream << compute_shader_image_store;
switch (n_components)
{
case 1:
/* imageStore(image, image_coord, color.r);*/
if (sampler_type == Depth)
{
stream << "vec4(" << compute_shader_color << ")";
}
else if (sampler_type == Stencil)
{
stream << "uvec4(" << compute_shader_color << ")";
}
else
{
// unexpected case
DE_ASSERT(false);
}
break;
case 4:
/* imageStore(image, image_coord, color);*/
stream << compute_shader_color;
break;
};
stream << ");\n";
stream << "}\n" << std::endl;
out_compute_shader_code = stream.str();
}
/** Prepare code for sampling fragment shader
*
* @param sampler_type Type of sampler
* @param sampling_function Type of sampling function
* @param out_fragment_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getSamplingFragmentShaderCode(const samplerType& sampler_type,
const samplingFunction& sampling_function,
std::string& out_fragment_shader_code)
{
const glw::GLchar* color_type = 0;
const glw::GLchar* interpolation_type = 0;
bool is_shadow_sampler = false;
glw::GLuint n_components = 0;
glw::GLuint n_routine_attributes = 0;
glw::GLuint n_type_attributes = 0;
const attributeDefinition* routine_attribute_definitions = 0;
const attributeDefinition* type_attribute_definitions = 0;
const glw::GLchar* sampler_type_str = 0;
std::string sampling_code;
std::stringstream stream;
/* Get attributes for sampling function */
getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
/* Get type for color variables */
getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
/* Get sampling code */
if (false == is_shadow_sampler)
{
getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, 0,
fragment_shader_output, 0, sampler_name, sampling_code);
}
else
{
getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, 0,
fragment_shader_output, 0, sampler_name, sampling_code);
}
/* Preamble */
stream << shader_code_preamble << shader_precision << "/* Sampling fragment shader */" << std::endl;
/* uniform samplerType sampler */
stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
stream << std::endl;
/* in type attribute */
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
<< routine_attribute_definitions[i].name << ";" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
<< type_attribute_definitions[i].name << ";" << std::endl;
}
stream << std::endl;
/* layout(location = 0) out vec4 fs_out_color */
stream << shader_layout << shader_output << color_type << fragment_shader_output << ";" << std::endl;
stream << std::endl;
/* Body */
stream << fragment_shader_sampling_body_code;
/* Sampling code */
stream << sampling_code;
stream << "}" << std::endl << std::endl;
/* Store result */
out_fragment_shader_code = stream.str();
}
/** Prepare sampling code
*
* @param sampling_function Type of sampling function
* @param color_type Type of color
* @param n_components Number of components
* @param attribute_name_prefix Prefix for attributes
* @param attribute_index Index for attributes
* @param color_variable_name Name of color variable
* @param color_variable_index Index for color variable
* @param sampler_name_p Name of sampler
* @param out_code Result code
**/
void TextureCubeMapArraySamplingTest::getSamplingFunctionCall(samplingFunction sampling_function,
const glw::GLchar* color_type, glw::GLuint n_components,
const glw::GLchar* attribute_name_prefix,
const glw::GLchar* attribute_index,
const glw::GLchar* color_variable_name,
const glw::GLchar* color_variable_index,
const glw::GLchar* sampler_name_p, std::string& out_code)
{
std::stringstream stream;
switch (sampling_function)
{
case Texture:
/* fs_in_color = texture(sampler, vs_out_texture_coordinates); */
stream << " " << var2str(0, color_variable_name, color_variable_index);
stream << " = " << texture_func << "(" << sampler_name_p;
stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index);
if (1 == n_components)
{
stream << ").x;" << std::endl;
}
else
{
stream << ");" << std::endl;
}
break;
case TextureLod:
/* fs_in_color = textureLod(sampler, vs_out_texture_coordinates, lod); */
stream << " " << var2str(0, color_variable_name, color_variable_index);
stream << " = " << textureLod_func << "(" << sampler_name_p;
stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
<< var2str(attribute_name_prefix, attribute_lod, attribute_index);
if (1 == n_components)
{
stream << ").x;" << std::endl;
}
else
{
stream << ");" << std::endl;
}
break;
case TextureGrad:
/* fs_in_color = textureGrad(sampler, vs_out_texture_coordinates, vs_out_grad_x, vs_out_grad_y); */
stream << " " << var2str(0, color_variable_name, color_variable_index);
stream << " = " << textureGrad_func << "(" << sampler_name_p;
stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index) << ", "
<< var2str(attribute_name_prefix, attribute_grad_x, attribute_index) << ", "
<< var2str(attribute_name_prefix, attribute_grad_y, attribute_index);
if (1 == n_components)
{
stream << ").x;" << std::endl;
}
else
{
stream << ");" << std::endl;
}
break;
case TextureGather:
if (4 == n_components)
{
/**
* color_type component_0 = textureGather(sampler, vs_out_texture_coordinates, 0);
* color_type component_1 = textureGather(sampler, vs_out_texture_coordinates, 1);
* color_type component_2 = textureGather(sampler, vs_out_texture_coordinates, 2);
* color_type component_3 = textureGather(sampler, vs_out_texture_coordinates, 3);
* fs_in_color = color_type(component_0.r, component_1.g, component_2.b, component_3.a);
**/
for (glw::GLuint i = 0; i < 4; ++i)
{
stream << " " << color_type << "component_" << i << " = " << textureGather_func << "("
<< sampler_name_p;
stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index);
stream << ", " << i << ");" << std::endl;
}
stream << " " << var2str(0, color_variable_name, color_variable_index);
stream << " = " << color_type << "(component_0.r, "
<< "component_1.g, "
<< "component_2.b, "
<< "component_3.a);" << std::endl;
}
else
{
stream << " " << var2str(0, color_variable_name, color_variable_index);
stream << " = " << textureGather_func << "(" << sampler_name_p;
stream << ", " << var2str(attribute_name_prefix, attribute_texture_coordinate, attribute_index);
stream << ").x;" << std::endl;
}
break;
}
out_code = stream.str();
}
/** Prepare code for sampling geometry shader
*
* @param sampler_type Type of sampler
* @param sampling_function Type of sampling function
* @param out_geometry_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getSamplingGeometryShaderCode(const samplerType& sampler_type,
const samplingFunction& sampling_function,
std::string& out_geometry_shader_code)
{
const glw::GLchar* color_type = 0;
const glw::GLchar* interpolation_type = 0;
bool is_shadow_sampler = false;
glw::GLuint n_components = 0;
glw::GLuint n_routine_attributes = 0;
glw::GLuint n_type_attributes = 0;
const attributeDefinition* routine_attribute_definitions = 0;
const attributeDefinition* type_attribute_definitions = 0;
const glw::GLchar* sampler_type_str = 0;
std::string sampling_code;
std::stringstream stream;
/* Get attributes for sampling function */
getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
/* Get type for color variables */
getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
/* Get sampling code */
if (false == is_shadow_sampler)
{
getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, "0",
fragment_shader_input, 0, sampler_name, sampling_code);
}
else
{
getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, "0",
fragment_shader_input, 0, sampler_name, sampling_code);
}
/* Preamble, extension : require */
stream << shader_code_preamble << geometry_shader_extension << shader_precision << std::endl
<< "/* Sampling geometry shader */" << std::endl;
/* In out layout */
stream << geometry_shader_layout;
/* uniform samplerType sampler */
stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
stream << std::endl;
/* in type attribute[]*/
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
<< routine_attribute_definitions[i].name << "[];" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
<< type_attribute_definitions[i].name << "[];" << std::endl;
}
stream << std::endl;
/* out vec4 fs_in_color */
stream << interpolation_type << shader_output << color_type << fragment_shader_input << ";" << std::endl;
stream << std::endl;
/* Body */
stream << geometry_shader_sampling_body_code;
/* Sampling code */
stream << sampling_code;
stream << geometry_shader_emit_vertex_code << std::endl;
/* Store result */
out_geometry_shader_code = stream.str();
}
/** Prepare code for sampling tesselation control shader
*
* @param sampler_type Type of sampler
* @param sampling_function Type of sampling function
* @param out_tesselation_control_shader_code Storage for code
**/
void TextureCubeMapArraySamplingTest::getSamplingTesselationControlShaderCode(
const samplerType& sampler_type, const samplingFunction& sampling_function,
std::string& out_tesselation_control_shader_code)
{
const glw::GLchar* color_type = 0;
const glw::GLchar* interpolation_type = 0;
bool is_shadow_sampler = false;
glw::GLuint n_components = 0;
glw::GLuint n_routine_attributes = 0;
glw::GLuint n_type_attributes = 0;
const attributeDefinition* routine_attribute_definitions = 0;
const attributeDefinition* type_attribute_definitions = 0;
const glw::GLchar* sampler_type_str = 0;
std::string sampling_code;
std::stringstream stream;
/* Get attributes for sampling function */
getAttributes(sampling_function, routine_attribute_definitions, n_routine_attributes);
getAttributes(sampler_type, type_attribute_definitions, n_type_attributes);
/* Get type for color variables */
getColorType(sampler_type, color_type, interpolation_type, sampler_type_str, n_components, is_shadow_sampler);
/* Get sampling code */
if (false == is_shadow_sampler)
{
getSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output, "gl_InvocationID",
tesselation_evaluation_shader_input, "gl_InvocationID", sampler_name, sampling_code);
}
else
{
getShadowSamplingFunctionCall(sampling_function, color_type, n_components, vertex_shader_output,
"gl_InvocationID", tesselation_evaluation_shader_input, "gl_InvocationID",
sampler_name, sampling_code);
}
/* Preamble, extension : require */
stream << shader_code_preamble << tesselation_shader_extension << shader_precision << std::endl
<< "/* Sampling tesselation control shader */" << std::endl;
/* layout(vertices = 1) out */
stream << tesselation_control_shader_layout;
/* uniform samplerType sampler */
stream << shader_uniform << "highp " << sampler_type_str << sampler_name << ";" << std::endl;
stream << std::endl;
/* in type attribute[]*/
for (glw::GLuint i = 0; i < n_routine_attributes; ++i)
{
stream << shader_input << routine_attribute_definitions[i].type << vertex_shader_output
<< routine_attribute_definitions[i].name << "[];" << std::endl;
}
for (glw::GLuint i = 0; i < n_type_attributes; ++i)
{
stream << shader_input << type_attribute_definitions[i].type << vertex_shader_output
<< type_attribute_definitions[i].name << "[];" << std::endl;
}
stream << std::endl;
/* out vec4 tes_in_color */
stream << interpolation_type << shader_output << color_type << tesselation_evaluation_shader_input << "[];"
<< std::endl;
stream << std::endl;