1 #ifndef _ESEXTCGPUSHADER5FMAPRECISION_HPP
2 #define _ESEXTCGPUSHADER5FMAPRECISION_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 esextcGPUShader5FmaPrecision.hpp
28  * \brief gpu_shader5 extension - fma precision Test (Test 8)
29  */ /*-------------------------------------------------------------------*/
30 
31 #include "../esextcTestCaseBase.hpp"
32 
33 #include "tcuVector.hpp"
34 #include <cstdlib>
35 #include <iostream>
36 
37 namespace glcts
38 {
39 /** Implementation of "Test 8" from CTS_EXT_gpu_shader5. Description follows
40  *
41  *  Test whether the precision of fma() is conformant to the required
42  *  precisions from Section 4.5.1 of the GLSL-ES 3.0 spec.
43  *
44  *  Category:   API,
45  *              Functional Test.
46  *
47  *  Write a vertex shader that declares three input attributes and
48  *  two output variables
49  *
50  *  in float a;
51  *  in float b;
52  *  in float c;
53  *
54  *  precise out float resultStd;
55  *  out float resultFma;
56  *
57  *  In the vertex shader compute:
58  *
59  *  resultStd = a*b+c;
60  *  resultFma = fma(a,b,c);
61  *
62  *  Write a boilerplate fragment shader.
63  *
64  *  Create a program from the vertex shader and fragment shader and use it. resultStd
65  *  must use "precise" so that number of operations for a*b+c is well defined.
66  *
67  *  Initialize a set of buffer objects to be assigned as attributes data
68  *  sources and fill each of them with 100 random float values from range
69  *  [-100.0,100.0] generated using a consistent seed.
70  *
71  *  Configure transform feedback to capture the values of resultStd and
72  *  resultFma.
73  *
74  *  Execute a draw call glDrawArrays(GL_POINTS, 0, 100).
75  *
76  *  Copy the captured results from the buffer objects bound to transform
77  *  feedback binding points to unionFloatInt resultStd[100] and
78  *  unionFloatInt resultFma[100].
79  *
80  *  Compute:
81  *
82  *  unionFloatInt resultCPU[100];
83  *
84  *  for(unsigned int i = 0; i < 100; ++i)
85  *  {
86  *      resultCPU[i].floatValue = data[i]*dataB[i] + dataC[i];
87  *  }
88  *
89  *  The test is successful if
90  *
91  *  abs( resultCPU.intValue - resultStd.intValue ) <= 2 &&
92  *  abs( resultCPU.intValue - resultFma.intValue ) <= 2 &&
93  *  abs( resultStd.intValue - resultFma.intValue ) <= 2
94  *
95  *  for i = 0..99.
96  *
97  *  This test should be run against all genTypes applicable to fma.
98  *  For integers the calculations should be exact.
99  *
100  **/
101 
102 /* Define type of input data */
103 enum INPUT_DATA_TYPE
104 {
105     IDT_FLOAT = 1,
106     IDT_VEC2  = 2,
107     IDT_VEC3  = 3,
108     IDT_VEC4  = 4,
109 };
110 
111 /* Helper for bitwise operation */
112 union FloatConverter
113 {
114     glw::GLfloat m_float;
115     glw::GLint m_int;
116 };
117 
118 template <INPUT_DATA_TYPE S>
119 class GPUShader5FmaPrecision : public TestCaseBase
120 {
121 public:
122     /* Public methods */
123     GPUShader5FmaPrecision(Context &context, const ExtParameters &extParams, const char *name, const char *description);
124 
~GPUShader5FmaPrecision(void)125     virtual ~GPUShader5FmaPrecision(void)
126     {
127     }
128 
129     virtual void deinit(void);
130     virtual IterateResult iterate(void);
131 
132 private:
133     /* Private methods */
134     std::string generateVertexShaderCode();
135     const char *getFragmentShaderCode();
136     void generateData();
137     void initTest(void);
138 
139     /* Static variables */
140     static const glw::GLuint m_n_elements = 100;
141 
142     /* Variables for general usage */
143     const glw::GLfloat m_amplitude;
144     glw::GLfloat m_data_a[m_n_elements * S];
145     glw::GLfloat m_data_b[m_n_elements * S];
146     glw::GLfloat m_data_c[m_n_elements * S];
147     glw::GLuint m_fs_id;
148     glw::GLuint m_po_id;
149     glw::GLuint m_vao_id;
150     glw::GLuint m_vbo_a_id;
151     glw::GLuint m_vbo_b_id;
152     glw::GLuint m_vbo_c_id;
153     glw::GLuint m_vbo_result_fma_id;
154     glw::GLuint m_vbo_result_std_id;
155     glw::GLuint m_vs_id;
156 };
157 
158 } // namespace glcts
159 
160 #endif // _ESEXTCGPUSHADER5FMAPRECISION_HPP
161