| /*------------------------------------------------------------------------- |
| * 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; |
| |
| |