1 #ifndef _ESEXTCGPUSHADER5PRECISEQUALIFIER_HPP 2 #define _ESEXTCGPUSHADER5PRECISEQUALIFIER_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 2014-2016 The Khronos Group Inc. 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 */ /*! 22 * \file 23 * \brief 24 */ /*-------------------------------------------------------------------*/ 25 26 /*! 27 * \file esextcGPUShader5PreciseQualifier.hpp 28 * \brief GPUShader5 Precise Float Test (Test Group 6) 29 */ /*-------------------------------------------------------------------*/ 30 31 #include "../esextcTestCaseBase.hpp" 32 33 namespace glcts 34 { 35 /** Implementation of "Test 6" from CTS_EXT_gpu_shader5. Description follows: 36 * 37 * Test whether the qualifier 'precise' prevents implementations from 38 * performing optimizations that produce slightly different results 39 * than unoptimized code. The optimizations may lead to cracks in position 40 * calculations during tessellation. 41 * 42 * Category: API, 43 * Functional Test. 44 * 45 * The test simulates computing a position of a vertex inside a patch 46 * using weighted sum of the patch vertices. To ensure that we have 47 * crack-free position calculation during tessellation, we should get 48 * with using 'precise' a bitwise accurate result regardless of the order 49 * in which the patch edges are traversed. 50 * 51 * Create a vertex shader. Declare two input variables 52 * 53 * in vec4 positions; 54 * in vec4 weights; 55 * 56 * and one output variable 57 * 58 * out vec4 weightedSum; 59 * 60 * Declare functions: 61 * 62 * void eval(in vec4 p, in vec4 w, precise out float result) 63 * { 64 * result = (p.x*w.x + p.y*w.y) + (p.z*w.z + p.w*w.w); 65 * } 66 * 67 * float eval(in vec4 p, in vec4 w) 68 * { 69 * precise float result = (p.x*w.x + p.y*w.y) + (p.z*w.z + p.w*w.w); 70 * return result; 71 * } 72 * 73 * In the vertex shader main function compute: 74 * 75 * eval(positions, weights, weightedSum.x); 76 * 77 * weightedSum.y = eval(positions, weights); 78 * 79 * float result = 0; 80 * precise result; 81 * result = (positions.x* weights.x + positions.y* weights.y) + 82 * (positions.z* weights.z + positions.w* weights.w); 83 * weightedSum.z = result; 84 * 85 * weightedSum.w = (positions.x* weights.x + positions.y* weights.y) + 86 * (positions.z* weights.z + positions.w* weights.w); 87 * 88 * Create a boilerplate fragment shader. 89 * 90 * Create a program from the above vertex shader and fragment shader 91 * and use it. 92 * 93 * Configure transform feedback to capture the value of weightedSum. 94 * 95 * Configure two buffer objects as data sources for the positions 96 * and weights attributes. 97 * 98 * The buffer object being a data source for the positions attribute 99 * should be filled 4 random float values p1,p2,p3,p4 from range 100 * [-100.0,100.0] generated using a consistent seed. 101 * 102 * The buffer object being a data source for the weights attribute 103 * should be filled with 4 random float values w1,w2,w3,w4 from range [0,1] 104 * generated using a consistent seed satisfying condition 105 * (w1 + w2 + w3 + w4) == 1.0 106 * 107 * Execute a draw call glDrawArrays(GL_POINTS, 0, 1); 108 * 109 * Copy the captured results from the buffer object bound to transform 110 * feedback binding point to float weightedSumForward[4] array. 111 * 112 * Reverse the contents of the buffers that are fed into the shader. 113 * 114 * Execute a draw call glDrawArrays(GL_POINTS, 0, 1); 115 * 116 * Copy the captured results from the buffer object bound to transform 117 * feedback binding point to float weightedSumBackward[4] array. 118 * 119 * The test is successful if values of 120 * 121 * weightedSumForward[0], weightedSumForward[1], weightedSumForward[2], 122 * weightedSumBackward[0], weightedSumBackward[1], weightedSumBackward[2] 123 * 124 * are all bitwise accurate. 125 * 126 * On the other hand weightedSumForward[3] and weightedSumBackward[3] 127 * are not necessary bitwise accurate with any of the above values or even 128 * compared to each other. If precise is not used, it is likely that 129 * compiler optimizations will result in MAD or fma operations that 130 * are not exactly commutative and thus will not provide bitwise 131 * accurate results. 132 * 133 * The test should be run in a loop at least 100 times, each time generating 134 * different values for positions and weights. 135 */ 136 137 union WeightedSum { 138 float floatv; 139 unsigned int intv; 140 }; 141 142 class GPUShader5PreciseQualifier : public TestCaseBase 143 { 144 public: 145 /* Public variables */ 146 GPUShader5PreciseQualifier(Context& context, const ExtParameters& extParams, const char* name, 147 const char* description); 148 ~GPUShader5PreciseQualifier()149 virtual ~GPUShader5PreciseQualifier() 150 { 151 } 152 153 virtual void deinit(void); 154 virtual IterateResult iterate(void); 155 156 private: 157 /* Private variables */ 158 static const char* m_fragment_shader_code; 159 static const char* m_vertex_shader_code; 160 static const glw::GLuint m_n_components; 161 static const glw::GLuint m_n_iterations; 162 static const glw::GLint m_position_range; 163 164 glw::GLuint m_fragment_shader_id; 165 glw::GLuint m_program_id; 166 glw::GLuint m_tf_buffer_id; 167 glw::GLuint m_vao_id; 168 glw::GLuint m_vertex_shader_id; 169 glw::GLuint m_vertex_positions_buffer_id; 170 glw::GLuint m_vertex_weights_buffer_id; 171 172 /* Private functions */ 173 void drawAndGetFeedbackResult(const glw::GLfloat* vertex_data_positions, const glw::GLfloat* vertex_data_weights, 174 WeightedSum* feedback_result); 175 void initTest(void); 176 }; 177 178 } // namespace glcts 179 180 #endif // _ESEXTCGPUSHADER5PRECISEQUALIFIER_HPP 181