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