Always apply flat qualifier to double inputs, same as int/uint
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcLimitTest.inl
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file glcLimitTest.cpp
21  * \brief Definition of template class.
22  */ /*-------------------------------------------------------------------*/
23
24 using namespace glw;
25
26 template<typename DataType>
27 LimitCase<DataType>::LimitCase(deqp::Context& context,
28                                                            const char* caseName,
29                                                            deUint32 limitToken,
30                                                            DataType limitBoundry,
31                                                            bool isBoundryMaximum,
32                                                            const char* glslVersion,
33                                                            const char* glslBuiltin,
34                                                            const char* glslExtension)
35         : deqp::TestCase(context, caseName, "Token limit validation.")
36         , m_limitToken(limitToken)
37         , m_limitBoundry(limitBoundry)
38         , m_isBoundryMaximum(isBoundryMaximum)
39         , m_glslVersion(glslVersion)
40         , m_glslBuiltin(glslBuiltin)
41         , m_glslExtension(glslExtension)
42 {
43 }
44
45 template<typename DataType>
46 LimitCase<DataType>::~LimitCase(void)
47 {
48 }
49
50 template<typename DataType>
51 tcu::TestNode::IterateResult LimitCase<DataType>::iterate(void)
52 {
53         DataType limitValue = DataType();
54         const Functions& gl = m_context.getRenderContext().getFunctions();
55
56         // make sure that limit or builtin was specified
57         DE_ASSERT(m_limitToken || !m_glslBuiltin.empty());
58
59         // check if limit was specified
60         if (m_limitToken)
61         {
62                 // check if limit is not smaller or greater then boundry defined in specification
63                 limitValue = getLimitValue(gl);
64                 if (!isWithinBoundry(limitValue))
65                 {
66                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
67                         return STOP;
68                 }
69
70                 // if glsl builtin wasn't defined then test already passed
71                 if (m_glslBuiltin.empty())
72                 {
73                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
74                         return STOP;
75                 }
76         }
77
78         // create compute shader to check glsl builtin
79         std::string shaderSource = createShader();
80         const GLchar* source = shaderSource.c_str();
81         const GLuint program = gl.createProgram();
82         GLuint shader = gl.createShader(GL_COMPUTE_SHADER);
83         gl.attachShader(program, shader);
84         gl.deleteShader(shader);
85         gl.shaderSource(shader, 1, &source, NULL);
86         gl.compileShader(shader);
87         gl.linkProgram(program);
88
89         GLint status;
90         gl.getProgramiv(program, GL_LINK_STATUS, &status);
91         GLint length;
92         gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &length);
93         if (length > 1)
94         {
95                 std::vector<GLchar> log(length);
96                 gl.getProgramInfoLog(program, length, NULL, &log[0]);
97                 m_testCtx.getLog() << tcu::TestLog::Message
98                                                    << &log[0]
99                                                    << tcu::TestLog::EndMessage;
100         }
101         if (status == GL_FALSE)
102         {
103                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
104                 return STOP;
105         }
106
107         gl.useProgram(program);
108
109         GLuint buffer;
110         gl.genBuffers(1, &buffer);
111         gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
112         gl.bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(DataType), NULL, GL_DYNAMIC_DRAW);
113         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
114
115         gl.dispatchCompute(1, 1, 1);
116
117         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
118         gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
119         DataType* data = static_cast<DataType*>(gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(DataType), GL_MAP_READ_BIT));
120         DataType builtinValue = data[0];
121         gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
122         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
123
124         if (m_limitToken)
125         {
126                 // limit token was specified - compare builtin to it
127                 if (isEqual(limitValue, builtinValue))
128                 {
129                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
130                 }
131                 else
132                 {
133                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
134                         m_testCtx.getLog() << tcu::TestLog::Message
135                                                            << "Shader builtin has value: "
136                                                            << builtinValue
137                                                            << " which is different then the value of corresponding limit: "
138                                                            << limitValue
139                                                            << tcu::TestLog::EndMessage;
140                 }
141         }
142         else
143         {
144                 // limit token was not specified - compare builtin to the boundry
145                 if (isWithinBoundry(builtinValue, true))
146                 {
147                         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
148                 }
149                 else
150                 {
151                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
152                         m_testCtx.getLog() << tcu::TestLog::Message
153                                                            << "Shader builtin value is: "
154                                                            << builtinValue
155                                                            << " which is outside of specified boundry."
156                                                            << tcu::TestLog::EndMessage;
157                 }
158         }
159
160         return STOP;
161 }
162
163 template<typename DataType>
164 bool LimitCase<DataType>::isWithinBoundry(DataType value, bool isBuiltin) const
165 {
166         if (m_isBoundryMaximum)
167         {
168                 // value should be smaller or euqual to boundry
169                 if (isGreater(value, m_limitBoundry))
170                 {
171                         m_testCtx.getLog() << tcu::TestLog::Message
172                                                            << (isBuiltin ? "Builtin" : "Limit")
173                                                            << " value is: "
174                                                            << value
175                                                            << " when it should not be greater than "
176                                                            << m_limitBoundry
177                                                            << tcu::TestLog::EndMessage;
178                         return false;
179                 }
180         }
181         else
182         {
183                 // value should be greater or euqual to boundry
184                 if (isSmaller(value, m_limitBoundry))
185                 {
186                         m_testCtx.getLog() << tcu::TestLog::Message
187                                                            << (isBuiltin ? "Builtin" : "Limit")
188                                                            << " value is: "
189                                                            << value
190                                                            << "when it should not be smaller than "
191                                                            << m_limitBoundry
192                                                            << tcu::TestLog::EndMessage;
193                         return false;
194                 }
195         }
196
197         return true;
198 }
199
200 template<typename DataType>
201 std::string LimitCase<DataType>::createShader() const
202 {
203                 std::stringstream shader;
204                 shader << "#version " << m_glslVersion << "\n";
205                 if (!m_glslExtension.empty())
206                         shader << "#extension " + m_glslExtension + " : require\n";
207                 shader << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
208                                   "layout(std430) buffer Output {\n"
209                            << getGLSLDataType() <<" data; } g_out;"
210                                   "void main() { "
211                                   "g_out.data = " << m_glslBuiltin << "; }";
212                 return shader.str();
213 }
214
215 template<typename DataType>
216 std::string LimitCase<DataType>::getGLSLDataType() const
217 {
218         return "int";
219 }
220
221 template<>
222 std::string LimitCase<GLfloat>::getGLSLDataType() const
223 {
224         return "float";
225 }
226
227 template<>
228 std::string LimitCase<tcu::IVec3>::getGLSLDataType() const
229 {
230         return "ivec3";
231 }
232
233 template<typename DataType>
234 bool LimitCase<DataType>::isEqual(DataType a, DataType b) const
235 {
236         return a == b;
237 }
238
239 template<>
240 bool LimitCase<tcu::IVec3>::isEqual(tcu::IVec3 a, tcu::IVec3 b) const
241 {
242         tcu::BVec3 bVec = tcu::equal(a, b);
243         return tcu::boolAll(bVec);
244 }
245
246 template<typename DataType>
247 bool LimitCase<DataType>::isGreater(DataType a, DataType b) const
248 {
249         return a > b;
250 }
251
252 template<>
253 bool LimitCase<tcu::IVec3>::isGreater(tcu::IVec3 a, tcu::IVec3 b) const
254 {
255         tcu::BVec3 bVec = tcu::greaterThan(a, b);
256         return tcu::boolAll(bVec);
257 }
258
259 template<typename DataType>
260 bool LimitCase<DataType>::isSmaller(DataType a, DataType b) const
261 {
262         return a < b;
263 }
264
265 template<>
266 bool LimitCase<tcu::IVec3>::isSmaller(tcu::IVec3 a, tcu::IVec3 b) const
267 {
268         tcu::BVec3 bVec = tcu::lessThan(a, b);
269         return tcu::boolAll(bVec);
270 }
271
272 template<typename DataType>
273 DataType LimitCase<DataType>::getLimitValue(const Functions&) const
274 {
275         return DataType();
276 }
277
278 template<>
279 GLint LimitCase<GLint>::getLimitValue(const Functions& gl) const
280 {
281         GLint value = -1;
282         gl.getIntegerv(m_limitToken, &value);
283         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv");
284         return value;
285 }
286
287 template<>
288 GLint64 LimitCase<GLint64>::getLimitValue(const Functions& gl) const
289 {
290         GLint64 value = -1;
291         gl.getInteger64v(m_limitToken, &value);
292         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v");
293         return value;
294 }
295
296 template<>
297 GLuint64 LimitCase<GLuint64>::getLimitValue(const Functions& gl) const
298 {
299         GLint64 value = -1;
300         gl.getInteger64v(m_limitToken, &value);
301         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetInteger64v");
302         return static_cast<GLuint64>(value);
303 }
304
305 template<>
306 GLfloat LimitCase<GLfloat>::getLimitValue(const Functions& gl) const
307 {
308         GLfloat value = -1;
309         gl.getFloatv(m_limitToken, &value);
310         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv");
311         return value;
312 }
313
314 template<>
315 tcu::IVec3 LimitCase<tcu::IVec3>::getLimitValue(const Functions& gl) const
316 {
317         tcu::IVec3 value(-1);
318         for (int i = 0; i < 3; i++)
319                 gl.getIntegeri_v(m_limitToken, (GLuint)i, &value[i]);
320         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegeri_v");
321         return value;
322 }
323