1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
3e5c31af7Sopenharmony_ci * -----------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2020 Google Inc.
6e5c31af7Sopenharmony_ci * Copyright (c) 2020 The Khronos Group Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci */ /*!
21e5c31af7Sopenharmony_ci * \file  es3cNumberParsingTests.cpp
22e5c31af7Sopenharmony_ci * \brief Tests for numeric value parsing in GLSL ES 3.0
23e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "es3cNumberParsingTests.hpp"
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci#include "gluDefs.hpp"
28e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp"
29e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp"
30e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include "glwDefs.hpp"
33e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
34e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
35e5c31af7Sopenharmony_ci
36e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
37e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
38e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_ci#include <string>
41e5c31af7Sopenharmony_ci#include <vector>
42e5c31af7Sopenharmony_ci#include <map>
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_ci#include <functional>
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cinamespace es3cts
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cinamespace
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ciusing std::string;
52e5c31af7Sopenharmony_ciusing std::vector;
53e5c31af7Sopenharmony_ciusing std::map;
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_ciusing std::function;
56e5c31af7Sopenharmony_ciusing std::bind;
57e5c31af7Sopenharmony_ciusing namespace std::placeholders;
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_cistatic const string					defaultVertexShader					=
60e5c31af7Sopenharmony_ci	"#version 300 es\n"
61e5c31af7Sopenharmony_ci	"in vec4 vPosition;\n"
62e5c31af7Sopenharmony_ci	"void main()\n"
63e5c31af7Sopenharmony_ci	"{\n"
64e5c31af7Sopenharmony_ci	"    gl_Position = vPosition;\n"
65e5c31af7Sopenharmony_ci	"}\n";
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_cistatic const string					fragmentShaderTemplate				=
68e5c31af7Sopenharmony_ci	"#version 300 es\n"
69e5c31af7Sopenharmony_ci	"precision highp float;\n"
70e5c31af7Sopenharmony_ci	"precision highp int;\n"
71e5c31af7Sopenharmony_ci	"out vec4 my_FragColor;\n"
72e5c31af7Sopenharmony_ci	"${TEST_GLOBALS}"
73e5c31af7Sopenharmony_ci	"void main()\n"
74e5c31af7Sopenharmony_ci	"{\n"
75e5c31af7Sopenharmony_ci    "${TEST_CODE}"
76e5c31af7Sopenharmony_ci    "    my_FragColor = vec4(0.0, correct, 0.0, 1.0);\n"
77e5c31af7Sopenharmony_ci	"}\n";
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_citypedef function<void (const glu::ShaderProgram&, const glw::Functions&)> SetupUniformsFn;
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_cienum struct TestType
82e5c31af7Sopenharmony_ci{
83e5c31af7Sopenharmony_ci	NORMAL				= 0,
84e5c31af7Sopenharmony_ci	EXPECT_SHADER_FAIL
85e5c31af7Sopenharmony_ci};
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_cistruct TestParams
88e5c31af7Sopenharmony_ci{
89e5c31af7Sopenharmony_ci	TestType			testType;
90e5c31af7Sopenharmony_ci	string				name;
91e5c31af7Sopenharmony_ci	string				description;
92e5c31af7Sopenharmony_ci	string				testGlobals;
93e5c31af7Sopenharmony_ci	string				testCode;
94e5c31af7Sopenharmony_ci	SetupUniformsFn	setupUniformsFn;
95e5c31af7Sopenharmony_ci};
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_cistatic void initializeExpectedValue(const glu::ShaderProgram& program, const glw::Functions& gl, const deUint32 value);
98e5c31af7Sopenharmony_cistatic void initializeZeroValue(const glu::ShaderProgram& program, const glw::Functions& gl);
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_cistatic const TestParams			tests[]									=
101e5c31af7Sopenharmony_ci{
102e5c31af7Sopenharmony_ci	{
103e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
104e5c31af7Sopenharmony_ci		"unsigned_integer_above_signed_range_decimal",																	// string			name
105e5c31af7Sopenharmony_ci		"Test that uint value higher than INT_MAX is parsed correctly",													// string			description
106e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
107e5c31af7Sopenharmony_ci		"    uint i        = 3221225472u;\n"
108e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
109e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 3221225472u)																// SetupUniformsFn	setupUniformsFn
110e5c31af7Sopenharmony_ci	},
111e5c31af7Sopenharmony_ci	{
112e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
113e5c31af7Sopenharmony_ci		"unsigned_integer_above_signed_range_base8",																	// string			name
114e5c31af7Sopenharmony_ci		"Test that uint value higher than INT_MAX is parsed correctly in base 8 (octal)",								// string			description
115e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
116e5c31af7Sopenharmony_ci		"    uint i        = 030000000000u;\n"
117e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
118e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 3221225472u)																// SetupUniformsFn	setupUniformsFn
119e5c31af7Sopenharmony_ci	},
120e5c31af7Sopenharmony_ci	{
121e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
122e5c31af7Sopenharmony_ci		"unsigned_integer_above_signed_range_base16",																	// string			name
123e5c31af7Sopenharmony_ci		"Test that uint value higher than INT_MAX is parsed correctly in base 16 (hex)",								// string			description
124e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
125e5c31af7Sopenharmony_ci		"    uint i        = 0xc0000000u;\n"
126e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
127e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 3221225472u)																// SetupUniformsFn	setupUniformsFn
128e5c31af7Sopenharmony_ci	},
129e5c31af7Sopenharmony_ci	{
130e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
131e5c31af7Sopenharmony_ci		"unsigned_integer_smallest_value_above_signed_range_decimal",													// string			name
132e5c31af7Sopenharmony_ci		"Test that uint value equal to INT_MAX+1 is parsed correctly",													// string			description
133e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
134e5c31af7Sopenharmony_ci		"    uint i        = 2147483648u;\n"
135e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
136e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 2147483648u)																// SetupUniformsFn	setupUniformsFn
137e5c31af7Sopenharmony_ci	},
138e5c31af7Sopenharmony_ci	{
139e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
140e5c31af7Sopenharmony_ci		"unsigned_integer_smallest_value_above_signed_range_base8",														// string			name
141e5c31af7Sopenharmony_ci		"Test that uint value equal to INT_MAX+1 is parsed correctly in base 8 (octal)",								// string			description
142e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
143e5c31af7Sopenharmony_ci		"    uint i        = 020000000000u;\n"
144e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
145e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 2147483648u)																// SetupUniformsFn	setupUniformsFn
146e5c31af7Sopenharmony_ci	},
147e5c31af7Sopenharmony_ci	{
148e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
149e5c31af7Sopenharmony_ci		"unsigned_integer_smallest_value_above_signed_range_base16",													// string			name
150e5c31af7Sopenharmony_ci		"Test that uint value equal to INT_MAX+1 is parsed correctly in base 16 (hex)",									// string			description
151e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
152e5c31af7Sopenharmony_ci		"    uint i        = 0x80000000u;\n"
153e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
154e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 2147483648u)																// SetupUniformsFn	setupUniformsFn
155e5c31af7Sopenharmony_ci	},
156e5c31af7Sopenharmony_ci	{
157e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
158e5c31af7Sopenharmony_ci		"unsigned_integer_max_value_decimal",																			// string			name
159e5c31af7Sopenharmony_ci		"Test that uint value equal to UINT_MAX is parsed correctly",													// string			description
160e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
161e5c31af7Sopenharmony_ci		"    uint i        = 4294967295u;\n"
162e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
163e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 4294967295u)																// SetupUniformsFn	setupUniformsFn
164e5c31af7Sopenharmony_ci	},
165e5c31af7Sopenharmony_ci	{
166e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
167e5c31af7Sopenharmony_ci		"unsigned_integer_max_value_base8",																				// string			name
168e5c31af7Sopenharmony_ci		"Test that uint value equal to UINT_MAX is parsed correctly in base 8 (octal)",									// string			description
169e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
170e5c31af7Sopenharmony_ci		"    uint i        = 037777777777u;\n"
171e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
172e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 4294967295u)																// SetupUniformsFn	setupUniformsFn
173e5c31af7Sopenharmony_ci	},
174e5c31af7Sopenharmony_ci	{
175e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
176e5c31af7Sopenharmony_ci		"unsigned_integer_max_value_base16",																			// string			name
177e5c31af7Sopenharmony_ci		"Test that uint value equal to UINT_MAX is parsed correctly in base 16 (hex)",									// string			description
178e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
179e5c31af7Sopenharmony_ci		"    uint i        = 0xffffffffu;\n"
180e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
181e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 4294967295u)																// SetupUniformsFn	setupUniformsFn
182e5c31af7Sopenharmony_ci	},
183e5c31af7Sopenharmony_ci	{
184e5c31af7Sopenharmony_ci		TestType::EXPECT_SHADER_FAIL,																					// TestType			testType
185e5c31af7Sopenharmony_ci		"unsigned_integer_too_large_value_invalid",																		// string			name
186e5c31af7Sopenharmony_ci		"Test that uint value outside uint range fails to compile",														// string			description
187e5c31af7Sopenharmony_ci		"",																												// string			testGlobals
188e5c31af7Sopenharmony_ci		"    uint i        = 0xfffffffffu;"
189e5c31af7Sopenharmony_ci		"    float correct = 0.0;",
190e5c31af7Sopenharmony_ci		nullptr																											// SetupUniformsFn	setupUniformsFn
191e5c31af7Sopenharmony_ci	},
192e5c31af7Sopenharmony_ci	{
193e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
194e5c31af7Sopenharmony_ci		"unsigned_integer_negative_value_as_uint",																		// string			name
195e5c31af7Sopenharmony_ci		"Test that -1u is parsed correctly",																			// string			description
196e5c31af7Sopenharmony_ci		"uniform uint expected;\n",																						// string			testGlobals
197e5c31af7Sopenharmony_ci		"    uint i        = -1u;"
198e5c31af7Sopenharmony_ci		"    float correct = (i == expected) ? 1.0 : 0.0;\n",
199e5c31af7Sopenharmony_ci		bind(initializeExpectedValue, _1, _2, 0xffffffffu)																// SetupUniformsFn	setupUniformsFn
200e5c31af7Sopenharmony_ci	},
201e5c31af7Sopenharmony_ci	/* The following floating point parsing tests are taken from the Khronos WebGL conformance tests at:
202e5c31af7Sopenharmony_ci	 *     https://www.khronos.org/registry/webgl/sdk/tests/conformance2/glsl3/float-parsing.html */
203e5c31af7Sopenharmony_ci	{
204e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
205e5c31af7Sopenharmony_ci		"float_out_of_range_as_infinity",																				// string			name
206e5c31af7Sopenharmony_ci		"Floats of too large magnitude should be converted infinity",													// string			description
207e5c31af7Sopenharmony_ci		"",																												// string			testGlobals
208e5c31af7Sopenharmony_ci		"    // Out-of-range floats should overflow to infinity\n"														// string			testCode
209e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"
210e5c31af7Sopenharmony_ci		"    // \"If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity\"\n"
211e5c31af7Sopenharmony_ci		"    float correct = isinf(1.0e40) ? 1.0 : 0.0;\n",
212e5c31af7Sopenharmony_ci		nullptr																											// SetupUniformsFn	setupUniformsFn
213e5c31af7Sopenharmony_ci	},
214e5c31af7Sopenharmony_ci	{
215e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
216e5c31af7Sopenharmony_ci		"float_out_of_range_as_zero",																					// string			name
217e5c31af7Sopenharmony_ci		"Floats of too small magnitude should be converted to zero",													// string			description
218e5c31af7Sopenharmony_ci		"",																												// string			testGlobals
219e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"																	// string			testCode
220e5c31af7Sopenharmony_ci		"    // \"A value with a magnitude too small to be represented as a mantissa and exponent is converted to zero.\"\n"
221e5c31af7Sopenharmony_ci		"    // 1.0e-50 is small enough that it can't even be stored as subnormal.\n"
222e5c31af7Sopenharmony_ci		"    float correct = (1.0e-50 == 0.0) ? 1.0 : 0.0;\n",
223e5c31af7Sopenharmony_ci		nullptr																											// SetupUniformsFn	setupUniformsFn
224e5c31af7Sopenharmony_ci	},
225e5c31af7Sopenharmony_ci	{
226e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
227e5c31af7Sopenharmony_ci		"float_no_limit_on_number_of_digits_positive_exponent",															// string			name
228e5c31af7Sopenharmony_ci		"Number of digits in any digit-sequence is not limited - test with a small mantissa and large exponent",		// string			description
229e5c31af7Sopenharmony_ci		"",																												// string			testGlobals
230e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"																	// string			testCode
231e5c31af7Sopenharmony_ci		"    // \"There is no limit on the number of digits in any digit-sequence.\"\n"
232e5c31af7Sopenharmony_ci		"    // The below float string has 100 zeros after the decimal point, but represents 1.0.\n"
233e5c31af7Sopenharmony_ci		"    float x = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e101;\n"
234e5c31af7Sopenharmony_ci		"    float correct = (x == 1.0) ? 1.0 : 0.0;\n",
235e5c31af7Sopenharmony_ci		nullptr																											// SetupUniformsFn	setupUniformsFn
236e5c31af7Sopenharmony_ci	},
237e5c31af7Sopenharmony_ci	{
238e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
239e5c31af7Sopenharmony_ci		"float_no_limit_on_number_of_digits_negative_exponent",															// string			name
240e5c31af7Sopenharmony_ci		"Number of digits in any digit-sequence is not limited - test with a large mantissa and negative exponent",		// string			description
241e5c31af7Sopenharmony_ci		"",																												// string			testGlobals
242e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"																	// string			testCode
243e5c31af7Sopenharmony_ci		"    // \"There is no limit on the number of digits in any digit-sequence.\"\n"
244e5c31af7Sopenharmony_ci		"    // The below float string has 100 zeros, but represents 1.0.\n"
245e5c31af7Sopenharmony_ci		"    float x = 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0e-100;\n"
246e5c31af7Sopenharmony_ci		"    float correct = (x == 1.0) ? 1.0 : 0.0;\n",
247e5c31af7Sopenharmony_ci		nullptr																											// SetupUniformsFn	setupUniformsFn
248e5c31af7Sopenharmony_ci	},
249e5c31af7Sopenharmony_ci	{
250e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
251e5c31af7Sopenharmony_ci		"float_slightly_out_of_range_exponent_as_positive_infinity",													// string			name
252e5c31af7Sopenharmony_ci		"Test that an exponent that slightly overflows signed 32-bit int range works",									// string			description
253e5c31af7Sopenharmony_ci		"",																												// string			testGlobals
254e5c31af7Sopenharmony_ci		"    // Out-of-range floats should overflow to infinity\n"														// string			testCode
255e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"
256e5c31af7Sopenharmony_ci		"    // \"If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity\"\n"
257e5c31af7Sopenharmony_ci		"    float correct = isinf(1.0e2147483649) ? 1.0 : 0.0;\n",
258e5c31af7Sopenharmony_ci		nullptr																											// SetupUniformsFn	setupUniformsFn
259e5c31af7Sopenharmony_ci	},
260e5c31af7Sopenharmony_ci	{
261e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
262e5c31af7Sopenharmony_ci		"float_overflow_to_positive_infinity",																			// string			name
263e5c31af7Sopenharmony_ci		"Out-of-range floats greater than zero should overflow to positive infinity",									// string			description
264e5c31af7Sopenharmony_ci		"uniform float zero;\n",																						// string			testGlobals
265e5c31af7Sopenharmony_ci		"    // Out-of-range floats should overflow to infinity\n"														// string			testCode
266e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"
267e5c31af7Sopenharmony_ci		"    // \"If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity\"\n"
268e5c31af7Sopenharmony_ci		"    float f = 1.0e2048 - zero;\n"
269e5c31af7Sopenharmony_ci		"    float correct = (isinf(f) && f > 0.0) ? 1.0 : 0.0;\n",
270e5c31af7Sopenharmony_ci		initializeZeroValue																								// SetupUniformsFn	setupUniformsFn
271e5c31af7Sopenharmony_ci	},
272e5c31af7Sopenharmony_ci	{
273e5c31af7Sopenharmony_ci		TestType::NORMAL,																								// TestType			testType
274e5c31af7Sopenharmony_ci		"float_overflow_to_negative_infinity",																			// string			name
275e5c31af7Sopenharmony_ci		"Out-of-range floats less than zero should overflow to negative infinity",										// string			description
276e5c31af7Sopenharmony_ci		"uniform float zero;\n",																						// string			testGlobals
277e5c31af7Sopenharmony_ci		"    // Out-of-range floats should overflow to infinity\n"														// string			testCode
278e5c31af7Sopenharmony_ci		"    // GLSL ES 3.00.6 section 4.1.4 Floats:\n"
279e5c31af7Sopenharmony_ci		"    // \"If the value of the floating point number is too large (small) to be stored as a single precision value, it is converted to positive (negative) infinity\"\n"
280e5c31af7Sopenharmony_ci		"    float f = -1.0e2048 + zero;\n"
281e5c31af7Sopenharmony_ci		"    float correct = (isinf(f) && f < 0.0) ? 1.0 : 0.0;\n",
282e5c31af7Sopenharmony_ci		initializeZeroValue																								// SetupUniformsFn	setupUniformsFn
283e5c31af7Sopenharmony_ci	}
284e5c31af7Sopenharmony_ci};
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_cistatic void initializeExpectedValue(const glu::ShaderProgram& program, const glw::Functions& gl, const deUint32 value)
287e5c31af7Sopenharmony_ci{
288e5c31af7Sopenharmony_ci	const auto location = gl.getUniformLocation(program.getProgram(), "expected");
289e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation call failed");
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci	gl.uniform1ui(location, value);
292e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Set uniform value failed");
293e5c31af7Sopenharmony_ci}
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_cistatic void initializeZeroValue(const glu::ShaderProgram& program, const glw::Functions& gl)
296e5c31af7Sopenharmony_ci{
297e5c31af7Sopenharmony_ci	const auto location = gl.getUniformLocation(program.getProgram(), "zero");
298e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation call failed");
299e5c31af7Sopenharmony_ci
300e5c31af7Sopenharmony_ci	gl.uniform1f(location, 0.0f);
301e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Set uniform value failed");
302e5c31af7Sopenharmony_ci}
303e5c31af7Sopenharmony_ci
304e5c31af7Sopenharmony_cistatic string replacePlaceholders(const string& shaderTemplate, const TestParams& params)
305e5c31af7Sopenharmony_ci{
306e5c31af7Sopenharmony_ci	map<string,string> fields;
307e5c31af7Sopenharmony_ci	fields["TEST_GLOBALS"]	= params.testGlobals;
308e5c31af7Sopenharmony_ci	fields["TEST_CODE"]		= params.testCode;
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci	tcu::StringTemplate output(shaderTemplate);
311e5c31af7Sopenharmony_ci	return output.specialize(fields);
312e5c31af7Sopenharmony_ci}
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_cistatic const std::vector<float>		positions				=
315e5c31af7Sopenharmony_ci{
316e5c31af7Sopenharmony_ci	-1.0f, -1.0f,
317e5c31af7Sopenharmony_ci	 1.0f, -1.0f,
318e5c31af7Sopenharmony_ci	-1.0f,  1.0f,
319e5c31af7Sopenharmony_ci	 1.0f,  1.0f
320e5c31af7Sopenharmony_ci};
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_cistatic const std::vector<deUint32>	indices					= { 0, 1, 2, 3 };
323e5c31af7Sopenharmony_ci
324e5c31af7Sopenharmony_ciconst deInt32						RENDERTARGET_WIDTH		= 16;
325e5c31af7Sopenharmony_ciconst deInt32						RENDERTARGET_HEIGHT		= 16;
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ciclass NumberParsingCase : public deqp::TestCase
328e5c31af7Sopenharmony_ci{
329e5c31af7Sopenharmony_cipublic:
330e5c31af7Sopenharmony_ci	NumberParsingCase(deqp::Context& context, const string& name, const TestParams& params, const string& vertexShader, const string& fragmentShader);
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	IterateResult iterate();
333e5c31af7Sopenharmony_ci
334e5c31af7Sopenharmony_ciprivate:
335e5c31af7Sopenharmony_ci	void setupRenderTarget();
336e5c31af7Sopenharmony_ci	void releaseRenderTarget();
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ci	glw::GLuint			m_fboId;
339e5c31af7Sopenharmony_ci	glw::GLuint			m_rboId;
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci	const TestParams&	m_params;
342e5c31af7Sopenharmony_ci	string				m_vertexShader;
343e5c31af7Sopenharmony_ci	string				m_fragmentShader;
344e5c31af7Sopenharmony_ci};
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ciNumberParsingCase::NumberParsingCase(deqp::Context& context, const string& name, const TestParams& params, const string& vertexShader, const string& fragmentShader)
347e5c31af7Sopenharmony_ci	: TestCase(context, name.c_str(), params.description.c_str())
348e5c31af7Sopenharmony_ci	, m_fboId(0)
349e5c31af7Sopenharmony_ci	, m_rboId(0)
350e5c31af7Sopenharmony_ci	, m_params(params)
351e5c31af7Sopenharmony_ci	, m_vertexShader(vertexShader)
352e5c31af7Sopenharmony_ci	, m_fragmentShader(fragmentShader)
353e5c31af7Sopenharmony_ci{
354e5c31af7Sopenharmony_ci}
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ciNumberParsingCase::IterateResult NumberParsingCase::iterate(void)
357e5c31af7Sopenharmony_ci{
358e5c31af7Sopenharmony_ci	const auto&	renderContext	= m_context.getRenderContext();
359e5c31af7Sopenharmony_ci	const auto&	gl				= renderContext.getFunctions();
360e5c31af7Sopenharmony_ci	const auto	textureFormat	= tcu::TextureFormat(tcu::TextureFormat::RGBA,	tcu::TextureFormat::UNORM_INT8);
361e5c31af7Sopenharmony_ci	const auto	transferFormat	= glu::getTransferFormat(textureFormat);
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci	setupRenderTarget();
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ci	glu::ShaderProgram program(renderContext, glu::makeVtxFragSources(m_vertexShader, m_fragmentShader));
366e5c31af7Sopenharmony_ci	if (!program.isOk())
367e5c31af7Sopenharmony_ci		switch(m_params.testType)
368e5c31af7Sopenharmony_ci		{
369e5c31af7Sopenharmony_ci		case TestType::EXPECT_SHADER_FAIL:
370e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
371e5c31af7Sopenharmony_ci			return STOP;
372e5c31af7Sopenharmony_ci		default:
373e5c31af7Sopenharmony_ci			TCU_FAIL("Shader compilation failed:\nVertex shader:\n" + m_vertexShader + "\nFragment shader:\n" + m_fragmentShader);
374e5c31af7Sopenharmony_ci		}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ci	const std::vector<glu::VertexArrayBinding> vertexArrays =
377e5c31af7Sopenharmony_ci	{
378e5c31af7Sopenharmony_ci		glu::va::Float("vPosition", 2, positions.size(), 0, positions.data()),
379e5c31af7Sopenharmony_ci	};
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci	gl.useProgram(program.getProgram());
382e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram failed");
383e5c31af7Sopenharmony_ci
384e5c31af7Sopenharmony_ci	if (m_params.setupUniformsFn != DE_NULL)
385e5c31af7Sopenharmony_ci		m_params.setupUniformsFn(program, gl);
386e5c31af7Sopenharmony_ci
387e5c31af7Sopenharmony_ci	gl.clear(GL_COLOR_BUFFER_BIT);
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ci	glu::draw(renderContext, program.getProgram(),
391e5c31af7Sopenharmony_ci			  static_cast<int>(vertexArrays.size()), vertexArrays.data(),
392e5c31af7Sopenharmony_ci			  glu::pr::TriangleStrip(static_cast<int>(indices.size()), indices.data()));
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	const auto						pixelSize				= tcu::getPixelSize(textureFormat);
395e5c31af7Sopenharmony_ci	std::vector<deUint8>			fbData					(RENDERTARGET_WIDTH * RENDERTARGET_HEIGHT * pixelSize);
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	if (pixelSize < 4)
398e5c31af7Sopenharmony_ci		gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	gl.readPixels(0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, transferFormat.format, transferFormat.dataType, fbData.data());
401e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
402e5c31af7Sopenharmony_ci
403e5c31af7Sopenharmony_ci	tcu::ConstPixelBufferAccess		fbAccess				{ textureFormat, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT, 1, fbData.data() };
404e5c31af7Sopenharmony_ci	const auto						expectedColor			= tcu::RGBA::green().toVec();
405e5c31af7Sopenharmony_ci	bool pass = true;
406e5c31af7Sopenharmony_ci	for(int y = 0; pass && y < RENDERTARGET_HEIGHT; ++y)
407e5c31af7Sopenharmony_ci		for(int x = 0; x < RENDERTARGET_WIDTH; ++x)
408e5c31af7Sopenharmony_ci			if (fbAccess.getPixel(x,y) != expectedColor)
409e5c31af7Sopenharmony_ci			{
410e5c31af7Sopenharmony_ci				pass = false;
411e5c31af7Sopenharmony_ci				break;
412e5c31af7Sopenharmony_ci			}
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci	releaseRenderTarget();
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ci	const qpTestResult				result					= (pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL);
417e5c31af7Sopenharmony_ci	const char*						desc					= (pass ? "Pass" : "Pixel mismatch; numeric value parsed incorrectly");
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(result, desc);
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci	return STOP;
422e5c31af7Sopenharmony_ci}
423e5c31af7Sopenharmony_ci
424e5c31af7Sopenharmony_civoid NumberParsingCase::setupRenderTarget()
425e5c31af7Sopenharmony_ci{
426e5c31af7Sopenharmony_ci	const auto&	renderContext	= m_context.getRenderContext();
427e5c31af7Sopenharmony_ci	const auto&	gl				= renderContext.getFunctions();
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &m_fboId);
430e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci	gl.genRenderbuffers(1, &m_rboId);
433e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "GenRenderBuffers");
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, m_rboId);
436e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "BindRenderBuffer");
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT);
439e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "RenderBufferStorage");
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fboId);
442e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFrameBuffer");
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rboId);
445e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "FrameBufferRenderBuffer");
446e5c31af7Sopenharmony_ci
447e5c31af7Sopenharmony_ci	glw::GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
448e5c31af7Sopenharmony_ci	gl.drawBuffers(1, &drawBuffer);
449e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawBuffers");
450e5c31af7Sopenharmony_ci
451e5c31af7Sopenharmony_ci	glw::GLfloat clearColor[4] = { 0, 0, 0, 0 };
452e5c31af7Sopenharmony_ci	gl.clearBufferfv(GL_COLOR, 0, clearColor);
453e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "ClearBuffers");
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci	gl.viewport(0, 0, RENDERTARGET_WIDTH, RENDERTARGET_HEIGHT);
456e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
457e5c31af7Sopenharmony_ci}
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_civoid NumberParsingCase::releaseRenderTarget()
460e5c31af7Sopenharmony_ci{
461e5c31af7Sopenharmony_ci	const auto&	renderContext	= m_context.getRenderContext();
462e5c31af7Sopenharmony_ci	const auto&	gl				= renderContext.getFunctions();
463e5c31af7Sopenharmony_ci	if (m_fboId != 0)
464e5c31af7Sopenharmony_ci	{
465e5c31af7Sopenharmony_ci		gl.deleteFramebuffers(1, &m_fboId);
466e5c31af7Sopenharmony_ci		m_fboId = 0;
467e5c31af7Sopenharmony_ci	}
468e5c31af7Sopenharmony_ci	if (m_rboId != 0)
469e5c31af7Sopenharmony_ci	{
470e5c31af7Sopenharmony_ci		gl.deleteRenderbuffers(1, &m_rboId);
471e5c31af7Sopenharmony_ci		m_rboId = 0;
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci}
474e5c31af7Sopenharmony_ci
475e5c31af7Sopenharmony_ci}
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_ciNumberParsingTests::NumberParsingTests(deqp::Context& context)
478e5c31af7Sopenharmony_ci	: deqp::TestCaseGroup(context, "number_parsing", "GLSL number parsing tests")
479e5c31af7Sopenharmony_ci{
480e5c31af7Sopenharmony_ci}
481e5c31af7Sopenharmony_ci
482e5c31af7Sopenharmony_ciNumberParsingTests::~NumberParsingTests(void)
483e5c31af7Sopenharmony_ci{
484e5c31af7Sopenharmony_ci}
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_civoid NumberParsingTests::init(void)
487e5c31af7Sopenharmony_ci{
488e5c31af7Sopenharmony_ci	for(const auto& params : tests)
489e5c31af7Sopenharmony_ci	{
490e5c31af7Sopenharmony_ci		addChild(new NumberParsingCase(m_context, params.name, params, defaultVertexShader, replacePlaceholders(fragmentShaderTemplate, params)));
491e5c31af7Sopenharmony_ci	}
492e5c31af7Sopenharmony_ci}
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ci}
495