1fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos/*-------------------------------------------------------------------------
2fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * drawElements Quality Program OpenGL ES Utilities
3fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * ------------------------------------------------
4fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *
5fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * Copyright 2015 The Android Open Source Project
6fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *
7fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
8fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * you may not use this file except in compliance with the License.
9fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * You may obtain a copy of the License at
10fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *
11fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
12fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *
13fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * Unless required by applicable law or agreed to in writing, software
14fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
15fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * See the License for the specific language governing permissions and
17fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * limitations under the License.
18fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *
19fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *//*!
20fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * \file
21fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos * \brief Shader .test file utilities.
22fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos *//*--------------------------------------------------------------------*/
23fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
24fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "gluShaderLibrary.hpp"
25fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
26fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "tcuStringTemplate.hpp"
27fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "tcuResource.hpp"
28fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "tcuTestLog.hpp"
29fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
30fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "deStringUtil.hpp"
31fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "deUniquePtr.hpp"
32fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "deFilePath.hpp"
33fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
34fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include "glwEnums.hpp"
35fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
36fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include <sstream>
37fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include <map>
38fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#include <cstdlib>
39fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
40fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#if 0
41fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#	define PARSE_DBG(X) printf X
42fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#else
43fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#	define PARSE_DBG(X) DE_NULL_STATEMENT
44fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos#endif
45fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
46fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosnamespace glu
47fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
48fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosnamespace sl
49fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
50fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
51fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing namespace tcu;
52fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
53fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing std::vector;
54fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing std::string;
55fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing std::map;
56fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing std::ostringstream;
57fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing std::pair;
58fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosusing de::UniquePtr;
59fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
60fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos// Specification
61fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
62fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosbool isValid (const ValueBlock& block)
63fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
64fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (size_t storageNdx = 0; storageNdx < 3; ++storageNdx)
65fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
66fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const vector<Value>&	values		= storageNdx == 0 ? block.inputs	:
67fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos											  storageNdx == 1 ? block.outputs	:
68fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos																block.uniforms;
69fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const size_t			refArrayLen	= values.empty() ? 0 : (values[0].elements.size() / (size_t)values[0].type.getScalarSize());
70fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
71fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (size_t valNdx = 0; valNdx < values.size(); ++valNdx)
72fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
73fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			const Value&	value	= values[valNdx];
74fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
75fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (!value.type.isBasicType())
76fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
77fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				print("ERROR: Value '%s' is of unsupported type!\n", value.name.c_str());
78fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				return false;
79fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
80fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
81fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (value.elements.size() != refArrayLen*(size_t)value.type.getScalarSize())
82fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
83fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				print("ERROR: Value '%s' has invalid number of scalars!\n", value.name.c_str());
84fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				return false;
85fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
86fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
87fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
88fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
89fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return true;
90fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
91fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
92fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosbool isValid (const ShaderCaseSpecification& spec)
93fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
94fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const deUint32	vtxFragMask			= (1u << SHADERTYPE_VERTEX)
95fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos										| (1u << SHADERTYPE_FRAGMENT);
96fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const deUint32	tessCtrlEvalMask	= (1u << SHADERTYPE_TESSELLATION_CONTROL)
97fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos										| (1u << SHADERTYPE_TESSELLATION_EVALUATION);
98fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const deUint32	supportedStageMask	= vtxFragMask | tessCtrlEvalMask
99fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos										| (1u << SHADERTYPE_GEOMETRY);
100fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const bool		isSeparable			= !spec.programs.empty() && spec.programs[0].sources.separable;
101fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
102fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (spec.programs.empty())
103fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
104fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		print("ERROR: No programs specified!\n");
105fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return false;
106fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
107fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
108fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (spec.fullGLSLES100Required)
109fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
110fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.targetVersion != GLSL_VERSION_100_ES)
111fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
112fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Full GLSL ES 1.00 support requested for other GLSL version!\n");
113fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
114fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
115fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
116fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.expectResult != EXPECT_PASS			&&
117fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.expectResult != EXPECT_VALIDATION_FAIL	&&
118fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.expectResult != EXPECT_BUILD_SUCCESSFUL)
119fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
120fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Full GLSL ES 1.00 support doesn't make sense when expecting compile/link failure!\n");
121fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
122fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
123fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
124fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
125fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (!de::inBounds(spec.caseType, (CaseType)0, CASETYPE_LAST))
126fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
127fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		print("ERROR: Invalid case type!\n");
128fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return false;
129fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
130fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
131fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (!de::inBounds(spec.expectResult, (ExpectResult)0, EXPECT_LAST))
132fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
133fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		print("ERROR: Invalid expected result!\n");
134fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return false;
135fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
136fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
137fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (!isValid(spec.values))
138fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return false;
139fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
140fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (!spec.values.inputs.empty() && !spec.values.outputs.empty() &&
141fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.values.inputs[0].elements.size() / spec.values.inputs[0].type.getScalarSize() != spec.values.outputs[0].elements.size() / spec.values.outputs[0].type.getScalarSize())
142fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
143fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		print("ERROR: Number of input and output elements don't match!\n");
144fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return false;
145fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
146fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
147fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (isSeparable)
148fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
149fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		deUint32	usedStageMask	= 0u;
150fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
151fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.caseType != CASETYPE_COMPLETE)
152fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
153fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Separable shaders supported only for complete cases!\n");
154fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
155fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
156fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
157fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (size_t progNdx = 0; progNdx < spec.programs.size(); ++progNdx)
158fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
159fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			for (int shaderStageNdx = 0; shaderStageNdx < SHADERTYPE_LAST; ++shaderStageNdx)
160fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
161fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				const deUint32	curStageMask	= (1u << shaderStageNdx);
162fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
163fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				if (supportedStageMask & curStageMask)
164fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				{
165fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					const bool		hasShader	= !spec.programs[progNdx].sources.sources[shaderStageNdx].empty();
166fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					const bool		isEnabled	= (spec.programs[progNdx].activeStages & curStageMask) != 0;
167fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
168fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					if (hasShader != isEnabled)
169fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					{
170fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos						print("ERROR: Inconsistent source/enable for shader stage %s!\n", getShaderTypeName((ShaderType)shaderStageNdx));
171fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos						return false;
172fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					}
173fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
174fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					if (hasShader && (usedStageMask & curStageMask) != 0)
175fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					{
176fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos						print("ERROR: Stage %s enabled on multiple programs!\n", getShaderTypeName((ShaderType)shaderStageNdx));
177fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos						return false;
178fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					}
179fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
180677e4644b77c36b99a8959561730c9a519cc37c0Pyry Haulos					if (isEnabled)
181677e4644b77c36b99a8959561730c9a519cc37c0Pyry Haulos						usedStageMask |= curStageMask;
182fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				}
183fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				else if (!spec.programs[progNdx].sources.sources[shaderStageNdx].empty())
184fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				{
185fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					print("ERROR: Source specified for unsupported shader stage %s!\n", getShaderTypeName((ShaderType)shaderStageNdx));
186fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					return false;
187fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				}
188fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
189fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
190fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
191fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if ((usedStageMask & vtxFragMask) != vtxFragMask)
192fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
193fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Vertex and fragment shaders are mandatory!\n");
194fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
195fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
196fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
197fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if ((usedStageMask & tessCtrlEvalMask) != 0 && (usedStageMask & tessCtrlEvalMask) != tessCtrlEvalMask)
198fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
199fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Both tessellation control and eval shaders must be either enabled or disabled!\n");
200fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
201fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
202fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
203fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
204fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
205fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const bool	hasVertex		= !spec.programs[0].sources.sources[SHADERTYPE_VERTEX].empty();
206fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const bool	hasFragment		= !spec.programs[0].sources.sources[SHADERTYPE_FRAGMENT].empty();
207fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
208fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.programs.size() != 1)
209fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
210fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Only cases using separable programs can have multiple programs!\n");
211fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
212fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
213fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
214fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.caseType == CASETYPE_VERTEX_ONLY && (!hasVertex || hasFragment))
215fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
216fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Vertex-only case must have only vertex shader!\n");
217fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
218fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
219fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
220fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.caseType == CASETYPE_FRAGMENT_ONLY && (hasVertex || !hasFragment))
221fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
222fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Fragment-only case must have only fragment shader!\n");
223fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
224fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
225fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
226fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (spec.caseType == CASETYPE_COMPLETE && (!hasVertex || !hasFragment))
227fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
228fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			print("ERROR: Complete case must have at least vertex and fragment shaders\n");
229fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return false;
230fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
231fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
232fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
233fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return true;
234fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
235fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
236fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos// Parser
237fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
238fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstatic const glu::GLSLVersion DEFAULT_GLSL_VERSION = glu::GLSL_VERSION_100_ES;
239fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
240fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosDE_INLINE deBool isWhitespace (char c)
241fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
242fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return (c == ' ') || (c == '\t') || (c == '\r') || (c == '\n');
243fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
244fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
245fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosDE_INLINE deBool isEOL (char c)
246fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
247fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return (c == '\r') || (c == '\n');
248fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
249fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
250fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosDE_INLINE deBool isNumeric (char c)
251fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
252fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return deInRange32(c, '0', '9');
253fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
254fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
255fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosDE_INLINE deBool isAlpha (char c)
256fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
257fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z');
258fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
259fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
260fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosDE_INLINE deBool isCaseNameChar (char c)
261fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
262fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return deInRange32(c, 'a', 'z') || deInRange32(c, 'A', 'Z') || deInRange32(c, '0', '9') || (c == '_') || (c == '-') || (c == '.');
263fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
264fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
265fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstruct CaseRequirement
266fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
267fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	enum Type
268fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
269fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TYPE_EXTENSION = 0,
270fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TYPE_FULL_GLSL_ES_100_SUPPORT,
271fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TYPE_IMPLEMENTATION_LIMIT,
272fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
273fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TYPE_LAST
274fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	};
275fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
276fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	Type					type;
277fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
278fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// TYPE_EXTENSION:
279fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	RequiredExtension		extension;
280fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
281fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// TYPE_IMPLEMENTATION_LIMIT
282fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	RequiredCapability		requiredCap;
283fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
284fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	CaseRequirement (void) : type(TYPE_LAST) {}
285fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
286fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	static CaseRequirement createFullGLSLES100SpecificationRequirement (void)
287fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
288fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		CaseRequirement req;
289fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		req.type		= TYPE_FULL_GLSL_ES_100_SUPPORT;
290fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return req;
291fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
292fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
293fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	static CaseRequirement createAnyExtensionRequirement (const vector<string>& alternatives, deUint32 effectiveStages)
294fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
295fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		CaseRequirement req;
296fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		req.type		= TYPE_EXTENSION;
297fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		req.extension	= RequiredExtension(alternatives, effectiveStages);
298fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return req;
299fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
300fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
301fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	static CaseRequirement createLimitRequirement (deUint32 enumName, int referenceValue)
302fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
303fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		CaseRequirement req;
304fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		req.type		= TYPE_IMPLEMENTATION_LIMIT;
305fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		req.requiredCap	= RequiredCapability(enumName, referenceValue);
306fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return req;
307fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
308fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos};
309fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
310fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosclass ShaderParser
311fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
312fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulospublic:
313fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos							ShaderParser			(const tcu::Archive& archive, const std::string& filename, ShaderCaseFactory* caseFactory);
314fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos							~ShaderParser			(void);
315fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
316fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<tcu::TestNode*>	parse					(void);
317fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
318fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosprivate:
319fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	enum Token
320fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
321fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INVALID = 0,
322fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_EOF,
323fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_STRING,
324fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_SHADER_SOURCE,
325fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
326fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INT_LITERAL,
327fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_LITERAL,
328fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
329fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// identifiers
330fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_IDENTIFIER,
331fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_TRUE,
332fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FALSE,
333fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_DESC,
334fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_EXPECT,
335fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_GROUP,
336fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_CASE,
337fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_END,
338fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_VALUES,
339fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_BOTH,
340fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_VERTEX,
341fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FRAGMENT,
342fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_UNIFORM,
343fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INPUT,
344fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_OUTPUT,
345fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT,
346fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_VEC2,
347fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_VEC3,
348fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_VEC4,
349fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT2,
350fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT2X3,
351fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT2X4,
352fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT3X2,
353fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT3,
354fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT3X4,
355fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT4X2,
356fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT4X3,
357fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_FLOAT_MAT4,
358fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INT,
359fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INT_VEC2,
360fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INT_VEC3,
361fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_INT_VEC4,
362fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_UINT,
363fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_UINT_VEC2,
364fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_UINT_VEC3,
365fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_UINT_VEC4,
366fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_BOOL,
367fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_BOOL_VEC2,
368fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_BOOL_VEC3,
369fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_BOOL_VEC4,
370fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_VERSION,
371fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_TESSELLATION_CONTROL,
372fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_TESSELLATION_EVALUATION,
373fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_GEOMETRY,
374fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_REQUIRE,
375fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_IN,
376fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_IMPORT,
377fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_PIPELINE_PROGRAM,
378fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_ACTIVE_STAGES,
379fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
380fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// symbols
381fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_ASSIGN,
382fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_PLUS,
383fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_MINUS,
384fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_COMMA,
385fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_VERTICAL_BAR,
386fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_SEMI_COLON,
387fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_LEFT_PAREN,
388fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_RIGHT_PAREN,
389fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_LEFT_BRACKET,
390fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_RIGHT_BRACKET,
391fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_LEFT_BRACE,
392fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_RIGHT_BRACE,
393fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_GREATER,
394fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
395fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		TOKEN_LAST
396fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	};
397fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
398fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseError					(const std::string& errorStr);
399fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	float						parseFloatLiteral			(const char* str);
400fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	int							parseIntLiteral				(const char* str);
401fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string						parseStringLiteral			(const char* str);
402fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string						parseShaderSource			(const char* str);
403fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						advanceToken				(void);
404fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						advanceToken				(Token assumed);
405fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						assumeToken					(Token token);
406fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	DataType					mapDataTypeToken			(Token token);
407fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const char*					getTokenName				(Token token);
408fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	deUint32					getShaderStageLiteralFlag	(void);
409fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	deUint32					getGLEnumFromName			(const std::string& enumName);
410fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
411fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseValueElement			(DataType dataType, Value& result);
412fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseValue					(ValueBlock& valueBlock);
413fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseValueBlock				(ValueBlock& valueBlock);
414fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	deUint32					parseShaderStageList		(void);
415fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseRequirement			(CaseRequirement& valueBlock);
416fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseExpectResult			(ExpectResult& expectResult);
417fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseGLSLVersion			(glu::GLSLVersion& version);
418fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parsePipelineProgram		(ProgramSpecification& program);
419fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseShaderCase				(vector<tcu::TestNode*>& shaderNodeList);
420fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseShaderGroup			(vector<tcu::TestNode*>& shaderNodeList);
421fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	void						parseImport					(vector<tcu::TestNode*>& shaderNodeList);
422fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
423fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const tcu::Archive&			m_archive;
424fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const string				m_filename;
425fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ShaderCaseFactory* const	m_caseFactory;
426fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
427fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	UniquePtr<tcu::Resource>	m_resource;
428fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<char>				m_input;
429fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
430fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const char*					m_curPtr;
431fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	Token						m_curToken;
432fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::string					m_curTokenStr;
433fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos};
434fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
435fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosShaderParser::ShaderParser (const tcu::Archive& archive, const string& filename, ShaderCaseFactory* caseFactroy)
436fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	: m_archive			(archive)
437fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	, m_filename		(filename)
438fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	, m_caseFactory		(caseFactroy)
439fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	, m_resource		(archive.getResource(m_filename.c_str()))
440fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	, m_curPtr			(DE_NULL)
441fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	, m_curToken		(TOKEN_LAST)
442fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
443fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
444fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
445fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosShaderParser::~ShaderParser (void)
446fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
447fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
448fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
449fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseError (const std::string& errorStr)
450fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
451fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string atStr = string(m_curPtr, 80);
452fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	throw tcu::InternalError((string("Parser error: ") + errorStr + " near '" + atStr + " ...'").c_str(), DE_NULL, __FILE__, __LINE__);
453fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
454fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
455fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosfloat ShaderParser::parseFloatLiteral (const char* str)
456fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
457fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return (float)atof(str);
458fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
459fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
460fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosint ShaderParser::parseIntLiteral (const char* str)
461fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
462fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return atoi(str);
463fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
464fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
465fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstring ShaderParser::parseStringLiteral (const char* str)
466fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
467fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const char*		p		= str;
468fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	char			endChar = *p++;
469fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ostringstream	o;
470fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
471fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	while (*p != endChar && *p)
472fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
473fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (*p == '\\')
474fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
475fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			switch (p[1])
476fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
477fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case 0:		DE_ASSERT(DE_FALSE);	break;
478fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case 'n':	o << '\n';				break;
479fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case 't':	o << '\t';				break;
480fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				default:	o << p[1];				break;
481fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
482fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
483fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			p += 2;
484fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
485fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
486fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			o << *p++;
487fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
488fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
489fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return o.str();
490fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
491fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
492fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstatic string removeExtraIndentation (const string& source)
493fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
494fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Detect indentation from first line.
495fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	int numIndentChars = 0;
496fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (int ndx = 0; ndx < (int)source.length() && isWhitespace(source[ndx]); ndx++)
497fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		numIndentChars += source[ndx] == '\t' ? 4 : 1;
498fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
499fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Process all lines and remove preceding indentation.
500fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ostringstream processed;
501fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
502fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		bool	atLineStart			= true;
503fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		int		indentCharsOmitted	= 0;
504fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
505fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (int pos = 0; pos < (int)source.length(); pos++)
506fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
507fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			char c = source[pos];
508fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
509fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (atLineStart && indentCharsOmitted < numIndentChars && (c == ' ' || c == '\t'))
510fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
511fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				indentCharsOmitted += c == '\t' ? 4 : 1;
512fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
513fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else if (isEOL(c))
514fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
515fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				if (source[pos] == '\r' && source[pos+1] == '\n')
516fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				{
517fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					pos += 1;
518fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					processed << '\n';
519fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				}
520fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				else
521fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					processed << c;
522fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
523fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				atLineStart			= true;
524fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				indentCharsOmitted	= 0;
525fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
526fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else
527fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
528fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				processed << c;
529fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				atLineStart = false;
530fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
531fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
532fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
533fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
534fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return processed.str();
535fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
536fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
537fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstring ShaderParser::parseShaderSource (const char* str)
538fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
539fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const char*		p = str+2;
540fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ostringstream	o;
541fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
542fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Eat first empty line from beginning.
543fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	while (*p == ' ') p++;
544fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (*p == '\r') p++;
545fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (*p == '\n') p++;
546fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
547fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	while ((p[0] != '"') || (p[1] != '"'))
548fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
549fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (*p == '\\')
550fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
551fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			switch (p[1])
552fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
553fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case 0:		DE_ASSERT(DE_FALSE);	break;
554fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case 'n':	o << '\n';				break;
555fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case 't':	o << '\t';				break;
556fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				default:	o << p[1];				break;
557fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
558fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
559fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			p += 2;
560fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
561fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
562fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			o << *p++;
563fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
564fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
565fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return removeExtraIndentation(o.str());
566fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
567fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
568fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::advanceToken (void)
569fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
570fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Skip old token.
571fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_curPtr += m_curTokenStr.length();
572fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
573fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Reset token (for safety).
574fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_curToken		= TOKEN_INVALID;
575fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_curTokenStr	= "";
576fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
577fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Eat whitespace & comments while they last.
578fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
579fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
580fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		while (isWhitespace(*m_curPtr))
581fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			m_curPtr++;
582fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
583fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// Check for EOL comment.
584fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (*m_curPtr == '#')
585fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
586fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			while (*m_curPtr && !isEOL(*m_curPtr))
587fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				m_curPtr++;
588fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
589fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
590fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
591fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
592fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
593fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (!*m_curPtr)
594fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
595fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curToken = TOKEN_EOF;
596fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curTokenStr = "<EOF>";
597fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
598fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (isAlpha(*m_curPtr))
599fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
600fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		struct Named
601fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
602fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			const char*		str;
603fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			Token			token;
604fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		};
605fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
606fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		static const Named s_named[] =
607fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
608fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "true",						TOKEN_TRUE						},
609fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "false",						TOKEN_FALSE						},
610fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "desc",						TOKEN_DESC						},
611fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "expect",						TOKEN_EXPECT					},
612fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "group",						TOKEN_GROUP						},
613fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "case",						TOKEN_CASE						},
614fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "end",						TOKEN_END						},
615fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "values",						TOKEN_VALUES					},
616fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "both",						TOKEN_BOTH						},
617fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "vertex",						TOKEN_VERTEX					},
618fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "fragment",					TOKEN_FRAGMENT					},
619fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "uniform",					TOKEN_UNIFORM					},
620fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "input",						TOKEN_INPUT						},
621fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "output",						TOKEN_OUTPUT					},
622fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "float",						TOKEN_FLOAT						},
623fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "vec2",						TOKEN_FLOAT_VEC2				},
624fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "vec3",						TOKEN_FLOAT_VEC3				},
625fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "vec4",						TOKEN_FLOAT_VEC4				},
626fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat2",						TOKEN_FLOAT_MAT2				},
627fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat2x3",						TOKEN_FLOAT_MAT2X3				},
628fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat2x4",						TOKEN_FLOAT_MAT2X4				},
629fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat3x2",						TOKEN_FLOAT_MAT3X2				},
630fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat3",						TOKEN_FLOAT_MAT3				},
631fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat3x4",						TOKEN_FLOAT_MAT3X4				},
632fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat4x2",						TOKEN_FLOAT_MAT4X2				},
633fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat4x3",						TOKEN_FLOAT_MAT4X3				},
634fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "mat4",						TOKEN_FLOAT_MAT4				},
635fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "int",						TOKEN_INT						},
636fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "ivec2",						TOKEN_INT_VEC2					},
637fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "ivec3",						TOKEN_INT_VEC3					},
638fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "ivec4",						TOKEN_INT_VEC4					},
639fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "uint",						TOKEN_UINT						},
640fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "uvec2",						TOKEN_UINT_VEC2					},
641fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "uvec3",						TOKEN_UINT_VEC3					},
642fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "uvec4",						TOKEN_UINT_VEC4					},
643fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "bool",						TOKEN_BOOL						},
644fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "bvec2",						TOKEN_BOOL_VEC2					},
645fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "bvec3",						TOKEN_BOOL_VEC3					},
646fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "bvec4",						TOKEN_BOOL_VEC4					},
647fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "version",					TOKEN_VERSION					},
648fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "tessellation_control",		TOKEN_TESSELLATION_CONTROL		},
649fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "tessellation_evaluation",	TOKEN_TESSELLATION_EVALUATION	},
650fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "geometry",					TOKEN_GEOMETRY					},
651fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "require",					TOKEN_REQUIRE					},
652fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "in",							TOKEN_IN						},
653fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "import",						TOKEN_IMPORT					},
654fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "pipeline_program",			TOKEN_PIPELINE_PROGRAM			},
655fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "active_stages",				TOKEN_ACTIVE_STAGES				},
656fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		};
657fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
658fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const char* end = m_curPtr + 1;
659fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		while (isCaseNameChar(*end))
660fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			end++;
661fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curTokenStr = string(m_curPtr, end - m_curPtr);
662fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
663fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curToken = TOKEN_IDENTIFIER;
664fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
665fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_named); ndx++)
666fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
667fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (m_curTokenStr == s_named[ndx].str)
668fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
669fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				m_curToken = s_named[ndx].token;
670fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				break;
671fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
672fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
673fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
674fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (isNumeric(*m_curPtr))
675fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
676fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		/* \todo [2010-03-31 petri] Hex? */
677fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const char* p = m_curPtr;
678fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		while (isNumeric(*p))
679fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			p++;
680fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (*p == '.')
681fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
682fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			p++;
683fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			while (isNumeric(*p))
684fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				p++;
685fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
686fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (*p == 'e' || *p == 'E')
687fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
688fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				p++;
689fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				if (*p == '+' || *p == '-')
690fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					p++;
691fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				DE_ASSERT(isNumeric(*p));
692fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				while (isNumeric(*p))
693fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					p++;
694fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
695fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
696fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			m_curToken = TOKEN_FLOAT_LITERAL;
697fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			m_curTokenStr = string(m_curPtr, p - m_curPtr);
698fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
699fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
700fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
701fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			m_curToken = TOKEN_INT_LITERAL;
702fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			m_curTokenStr = string(m_curPtr, p - m_curPtr);
703fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
704fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
705fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (*m_curPtr == '"' && m_curPtr[1] == '"')
706fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
707fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const char*	p = m_curPtr + 2;
708fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
709fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		while ((p[0] != '"') || (p[1] != '"'))
710fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
711fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			DE_ASSERT(*p);
712fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (*p == '\\')
713fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
714fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				DE_ASSERT(p[1] != 0);
715fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				p += 2;
716fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
717fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else
718fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				p++;
719fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
720fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		p += 2;
721fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
722fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curToken		= TOKEN_SHADER_SOURCE;
723fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curTokenStr	= string(m_curPtr, (int)(p - m_curPtr));
724fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
725fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (*m_curPtr == '"' || *m_curPtr == '\'')
726fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
727fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		char		endChar = *m_curPtr;
728fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const char*	p		= m_curPtr + 1;
729fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
730fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		while (*p != endChar)
731fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
732fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			DE_ASSERT(*p);
733fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (*p == '\\')
734fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
735fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				DE_ASSERT(p[1] != 0);
736fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				p += 2;
737fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
738fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else
739fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				p++;
740fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
741fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		p++;
742fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
743fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curToken		= TOKEN_STRING;
744fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curTokenStr	= string(m_curPtr, (int)(p - m_curPtr));
745fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
746fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
747fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
748fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		struct SimpleToken
749fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
750fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			const char*		str;
751fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			Token			token;
752fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		};
753fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
754fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		static const SimpleToken s_simple[] =
755fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
756fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "=",			TOKEN_ASSIGN		},
757fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "+",			TOKEN_PLUS			},
758fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "-",			TOKEN_MINUS			},
759fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ ",",			TOKEN_COMMA			},
760fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "|",			TOKEN_VERTICAL_BAR	},
761fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ ";",			TOKEN_SEMI_COLON	},
762fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "(",			TOKEN_LEFT_PAREN	},
763fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ ")",			TOKEN_RIGHT_PAREN	},
764fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "[",			TOKEN_LEFT_BRACKET	},
765fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "]",			TOKEN_RIGHT_BRACKET },
766fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "{",			TOKEN_LEFT_BRACE	},
767fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ "}",			TOKEN_RIGHT_BRACE	},
768fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{ ">",			TOKEN_GREATER		},
769fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		};
770fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
771fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_simple); ndx++)
772fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
773fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (strncmp(s_simple[ndx].str, m_curPtr, strlen(s_simple[ndx].str)) == 0)
774fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
775fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				m_curToken		= s_simple[ndx].token;
776fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				m_curTokenStr	= s_simple[ndx].str;
777fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				return;
778fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
779fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
780fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
781fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// Otherwise invalid token.
782fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curToken = TOKEN_INVALID;
783fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		m_curTokenStr = *m_curPtr;
784fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
785fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
786fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
787fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::advanceToken (Token assumed)
788fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
789fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(assumed);
790fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
791fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
792fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
793fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::assumeToken (Token token)
794fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
795fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curToken != token)
796fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError((string("unexpected token '") + m_curTokenStr + "', expecting '" + getTokenName(token) + "'").c_str());
797fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	DE_TEST_ASSERT(m_curToken == token);
798fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
799fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
800fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosDataType ShaderParser::mapDataTypeToken (Token token)
801fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
802fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	switch (token)
803fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
804fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT:			return TYPE_FLOAT;
805fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_VEC2:		return TYPE_FLOAT_VEC2;
806fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_VEC3:		return TYPE_FLOAT_VEC3;
807fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_VEC4:		return TYPE_FLOAT_VEC4;
808fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT2:		return TYPE_FLOAT_MAT2;
809fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT2X3:	return TYPE_FLOAT_MAT2X3;
810fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT2X4:	return TYPE_FLOAT_MAT2X4;
811fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT3X2:	return TYPE_FLOAT_MAT3X2;
812fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT3:		return TYPE_FLOAT_MAT3;
813fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT3X4:	return TYPE_FLOAT_MAT3X4;
814fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT4X2:	return TYPE_FLOAT_MAT4X2;
815fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT4X3:	return TYPE_FLOAT_MAT4X3;
816fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT4:		return TYPE_FLOAT_MAT4;
817fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT:				return TYPE_INT;
818fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_VEC2:		return TYPE_INT_VEC2;
819fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_VEC3:		return TYPE_INT_VEC3;
820fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_VEC4:		return TYPE_INT_VEC4;
821fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT:			return TYPE_UINT;
822fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT_VEC2:		return TYPE_UINT_VEC2;
823fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT_VEC3:		return TYPE_UINT_VEC3;
824fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT_VEC4:		return TYPE_UINT_VEC4;
825fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL:			return TYPE_BOOL;
826fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL_VEC2:		return TYPE_BOOL_VEC2;
827fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL_VEC3:		return TYPE_BOOL_VEC3;
828fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL_VEC4:		return TYPE_BOOL_VEC4;
829fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		default:					return TYPE_INVALID;
830fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
831fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
832fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
833fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosconst char* ShaderParser::getTokenName (Token token)
834fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
835fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	switch (token)
836fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
837fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INVALID:					return "<invalid>";
838fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_EOF:						return "<eof>";
839fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_STRING:					return "<string>";
840fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_SHADER_SOURCE:			return "source";
841fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
842fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_LITERAL:				return "<int>";
843fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_LITERAL:			return "<float>";
844fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
845fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// identifiers
846fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_IDENTIFIER:				return "<identifier>";
847fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_TRUE:					return "true";
848fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FALSE:					return "false";
849fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_DESC:					return "desc";
850fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_EXPECT:					return "expect";
851fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_GROUP:					return "group";
852fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_CASE:					return "case";
853fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_END:						return "end";
854fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_VALUES:					return "values";
855fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOTH:					return "both";
856fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_VERTEX:					return "vertex";
857fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FRAGMENT:				return "fragment";
858fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_TESSELLATION_CONTROL:	return "tessellation_control";
859fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_TESSELLATION_EVALUATION:	return "tessellation_evaluation";
860fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_GEOMETRY:				return "geometry";
861fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_REQUIRE:					return "require";
862fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UNIFORM:					return "uniform";
863fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INPUT:					return "input";
864fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_OUTPUT:					return "output";
865fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT:					return "float";
866fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_VEC2:				return "vec2";
867fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_VEC3:				return "vec3";
868fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_VEC4:				return "vec4";
869fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT2:				return "mat2";
870fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT2X3:			return "mat2x3";
871fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT2X4:			return "mat2x4";
872fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT3X2:			return "mat3x2";
873fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT3:				return "mat3";
874fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT3X4:			return "mat3x4";
875fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT4X2:			return "mat4x2";
876fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT4X3:			return "mat4x3";
877fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FLOAT_MAT4:				return "mat4";
878fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT:						return "int";
879fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_VEC2:				return "ivec2";
880fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_VEC3:				return "ivec3";
881fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_INT_VEC4:				return "ivec4";
882fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT:					return "uint";
883fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT_VEC2:				return "uvec2";
884fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT_VEC3:				return "uvec3";
885fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_UINT_VEC4:				return "uvec4";
886fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL:					return "bool";
887fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL_VEC2:				return "bvec2";
888fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL_VEC3:				return "bvec3";
889fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_BOOL_VEC4:				return "bvec4";
890fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_IN:						return "in";
891fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_IMPORT:					return "import";
892fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_PIPELINE_PROGRAM:		return "pipeline_program";
893fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_ACTIVE_STAGES:			return "active_stages";
894fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
895fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_ASSIGN:					return "=";
896fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_PLUS:					return "+";
897fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_MINUS:					return "-";
898fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_COMMA:					return ",";
899fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_VERTICAL_BAR:			return "|";
900fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_SEMI_COLON:				return ";";
901fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_LEFT_PAREN:				return "(";
902fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_RIGHT_PAREN:				return ")";
903fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_LEFT_BRACKET:			return "[";
904fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_RIGHT_BRACKET:			return "]";
905fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_LEFT_BRACE:				return "{";
906fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_RIGHT_BRACE:				return "}";
907fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_GREATER:					return ">";
908fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
909fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		default:							return "<unknown>";
910fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
911fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
912fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
913fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosdeUint32 ShaderParser::getShaderStageLiteralFlag (void)
914fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
915fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	switch (m_curToken)
916fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
917fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_VERTEX:					return (1 << glu::SHADERTYPE_VERTEX);
918fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_FRAGMENT:				return (1 << glu::SHADERTYPE_FRAGMENT);
919fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_GEOMETRY:				return (1 << glu::SHADERTYPE_GEOMETRY);
920fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_TESSELLATION_CONTROL:	return (1 << glu::SHADERTYPE_TESSELLATION_CONTROL);
921fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		case TOKEN_TESSELLATION_EVALUATION:	return (1 << glu::SHADERTYPE_TESSELLATION_EVALUATION);
922fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
923fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		default:
924fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(std::string() + "invalid shader stage name, got " + m_curTokenStr);
925fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return 0;
926fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
927fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
928fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
929fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosdeUint32 ShaderParser::getGLEnumFromName (const std::string& enumName)
930fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
931fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	static const struct
932fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
933fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const char*	name;
934fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		deUint32	value;
935fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	} names[] =
936fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
937fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{ "GL_MAX_VERTEX_IMAGE_UNIFORMS",			GL_MAX_VERTEX_IMAGE_UNIFORMS			},
938fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{ "GL_MAX_VERTEX_ATOMIC_COUNTERS",			GL_MAX_VERTEX_ATOMIC_COUNTERS			},
939fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{ "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS",	GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS		},
940fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{ "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",	GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS	},
941fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	};
942fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
943fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(names); ++ndx)
944fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (names[ndx].name == enumName)
945fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			return names[ndx].value;
946fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
947fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	parseError(std::string() + "unknown enum name, got " + enumName);
948fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return 0;
949fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
950fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
951fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseValueElement (DataType expectedDataType, Value& result)
952fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
953fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	DataType	scalarType	= getDataTypeScalarType(expectedDataType);
954fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	int			scalarSize	= getDataTypeScalarSize(expectedDataType);
955fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
956fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	/* \todo [2010-04-19 petri] Support arrays. */
957fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	Value::Element elems[16];
958fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
959fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (scalarSize > 1)
960fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
961fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		DE_ASSERT(mapDataTypeToken(m_curToken) == expectedDataType);
962fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken(); // data type (float, vec2, etc.)
963fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken(TOKEN_LEFT_PAREN);
964fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
965fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
966fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
967fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
968fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (scalarType == TYPE_FLOAT)
969fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
970fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			float signMult = 1.0f;
971fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (m_curToken == TOKEN_MINUS)
972fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
973fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				signMult = -1.0f;
974fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				advanceToken();
975fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
976fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
977fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			assumeToken(TOKEN_FLOAT_LITERAL);
978fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			elems[scalarNdx].float32 = signMult * parseFloatLiteral(m_curTokenStr.c_str());
979fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken(TOKEN_FLOAT_LITERAL);
980fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
981fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (scalarType == TYPE_INT || scalarType == TYPE_UINT)
982fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
983fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			int signMult = 1;
984fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (m_curToken == TOKEN_MINUS)
985fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
986fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				signMult = -1;
987fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				advanceToken();
988fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
989fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
990fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			assumeToken(TOKEN_INT_LITERAL);
991fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			elems[scalarNdx].int32 = signMult * parseIntLiteral(m_curTokenStr.c_str());
992fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken(TOKEN_INT_LITERAL);
993fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
994fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
995fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
996fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			DE_ASSERT(scalarType == TYPE_BOOL);
997fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			elems[scalarNdx].bool32 = (m_curToken == TOKEN_TRUE);
998fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (m_curToken != TOKEN_TRUE && m_curToken != TOKEN_FALSE)
999fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				parseError(string("unexpected token, expecting bool: " + m_curTokenStr));
1000fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken(); // true/false
1001fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1002fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1003fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (scalarNdx != (scalarSize - 1))
1004fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken(TOKEN_COMMA);
1005fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1006fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1007fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (scalarSize > 1)
1008fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken(TOKEN_RIGHT_PAREN);
1009fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1010fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Store results.
1011fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1012fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		result.elements.push_back(elems[scalarNdx]);
1013fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1014fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1015fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseValue (ValueBlock& valueBlock)
1016fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1017fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	PARSE_DBG(("      parseValue()\n"));
1018fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1019fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parsed results.
1020fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<Value>*	dstBlock	= DE_NULL;
1021fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	DataType		basicType	= TYPE_LAST;
1022fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::string		valueName;
1023fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1024fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse storage.
1025fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curToken == TOKEN_UNIFORM)
1026fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		dstBlock = &valueBlock.uniforms;
1027fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curToken == TOKEN_INPUT)
1028fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		dstBlock = &valueBlock.inputs;
1029fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curToken == TOKEN_OUTPUT)
1030fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		dstBlock = &valueBlock.outputs;
1031fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1032fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError(string("unexpected token encountered when parsing value classifier"));
1033fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1034fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1035fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse data type.
1036fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	basicType = mapDataTypeToken(m_curToken);
1037fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (basicType == TYPE_INVALID)
1038fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError(string("unexpected token when parsing value data type: " + m_curTokenStr));
1039fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1040fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1041fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse value name.
1042fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curToken == TOKEN_IDENTIFIER || m_curToken == TOKEN_STRING)
1043fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1044fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_IDENTIFIER)
1045fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			valueName = m_curTokenStr;
1046fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1047fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			valueName = parseStringLiteral(m_curTokenStr.c_str());
1048fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1049fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1050fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError(string("unexpected token when parsing value name: " + m_curTokenStr));
1051fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1052fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1053fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse assignment operator.
1054fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_ASSIGN);
1055fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1056fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1057fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		Value value;
1058fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		value.name	= valueName;
1059fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		value.type	= VarType(basicType, PRECISION_LAST);
1060fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		dstBlock->push_back(value);
1061fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1062fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1063fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse actual value.
1064fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curToken == TOKEN_LEFT_BRACKET) // value list
1065fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1066fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		int	arrayLength	= 0; // \todo [2015-08-03 pyry] Currently unused
1067fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1068fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken(TOKEN_LEFT_BRACKET);
1069fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1070fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (;;)
1071fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1072fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseValueElement(basicType, dstBlock->back());
1073fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			arrayLength++;
1074fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1075fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (m_curToken == TOKEN_RIGHT_BRACKET)
1076fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				break;
1077fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else if (m_curToken == TOKEN_VERTICAL_BAR)
1078fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
1079fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				advanceToken();
1080fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				continue;
1081fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
1082fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else
1083fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				parseError(string("unexpected token in value element array: " + m_curTokenStr));
1084fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1085fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1086fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken(TOKEN_RIGHT_BRACKET);
1087fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1088fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else //  single elements
1089fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1090fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseValueElement(basicType, dstBlock->back());
1091fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1092fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1093fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_SEMI_COLON); // end of declaration
1094fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1095fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1096fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseValueBlock (ValueBlock& valueBlock)
1097fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1098fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	PARSE_DBG(("    parseValueBlock()\n"));
1099fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_VALUES);
1100fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_LEFT_BRACE);
1101fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1102fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
1103fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1104fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_UNIFORM || m_curToken == TOKEN_INPUT || m_curToken == TOKEN_OUTPUT)
1105fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseValue(valueBlock);
1106fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_RIGHT_BRACE)
1107fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
1108fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1109fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(string("unexpected token when parsing a value block: " + m_curTokenStr));
1110fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1111fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1112fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_RIGHT_BRACE);
1113fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1114fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1115fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry HaulosdeUint32 ShaderParser::parseShaderStageList (void)
1116fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1117fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	deUint32 mask = 0;
1118fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1119fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_LEFT_BRACE);
1120fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1121fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// don't allow 0-sized lists
1122fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1123fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	mask |= getShaderStageLiteralFlag();
1124fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1125fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1126fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
1127fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1128fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_RIGHT_BRACE)
1129fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
1130fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_COMMA)
1131fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1132fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			deUint32 stageFlag;
1133fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1134fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1135fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			stageFlag = getShaderStageLiteralFlag();
1136fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (stageFlag & mask)
1137fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				parseError(string("stage already set in the shader stage set: " + m_curTokenStr));
1138fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1139fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			mask |= stageFlag;
1140fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1141fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1142fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1143fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(string("invalid shader stage set token: " + m_curTokenStr));
1144fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1145fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_RIGHT_BRACE);
1146fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1147fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return mask;
1148fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1149fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1150fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseRequirement (CaseRequirement& valueBlock)
1151fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1152fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	PARSE_DBG(("    parseRequirement()\n"));
1153fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1154fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1155fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_IDENTIFIER);
1156fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1157fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curTokenStr == "extension")
1158fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1159fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		std::vector<std::string>	anyExtensionStringList;
1160fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		deUint32					affectedCasesFlags		= -1; // by default all stages
1161fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1162fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1163fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		assumeToken(TOKEN_LEFT_BRACE);
1164fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1165fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1166fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		assumeToken(TOKEN_STRING);
1167fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1168fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
1169fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1170fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1171fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (;;)
1172fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1173fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (m_curToken == TOKEN_RIGHT_BRACE)
1174fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				break;
1175fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else if (m_curToken == TOKEN_VERTICAL_BAR)
1176fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
1177fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				advanceToken();
1178fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				assumeToken(TOKEN_STRING);
1179fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1180fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				anyExtensionStringList.push_back(parseStringLiteral(m_curTokenStr.c_str()));
1181fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				advanceToken();
1182fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
1183fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else
1184fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				parseError(string("invalid extension list token: " + m_curTokenStr));
1185fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1186fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken(TOKEN_RIGHT_BRACE);
1187fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1188fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_IN)
1189fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1190fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1191fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			affectedCasesFlags = parseShaderStageList();
1192fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1193fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1194fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		valueBlock = CaseRequirement::createAnyExtensionRequirement(anyExtensionStringList, affectedCasesFlags);
1195fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1196fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "limit")
1197fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1198fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		deUint32	limitEnum;
1199fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		int			limitValue;
1200fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1201fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1202fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1203fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		assumeToken(TOKEN_STRING);
1204fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		limitEnum = getGLEnumFromName(parseStringLiteral(m_curTokenStr.c_str()));
1205fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1206fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1207fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		assumeToken(TOKEN_GREATER);
1208fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1209fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1210fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		assumeToken(TOKEN_INT_LITERAL);
1211fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		limitValue = parseIntLiteral(m_curTokenStr.c_str());
1212fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1213fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1214fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		valueBlock = CaseRequirement::createLimitRequirement(limitEnum, limitValue);
1215fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1216fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "full_glsl_es_100_support")
1217fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1218fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1219fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1220fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		valueBlock = CaseRequirement::createFullGLSLES100SpecificationRequirement();
1221fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1222fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1223fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError(string("invalid requirement value: " + m_curTokenStr));
1224fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1225fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1226fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseExpectResult (ExpectResult& expectResult)
1227fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1228fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_IDENTIFIER);
1229fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1230fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curTokenStr == "pass")
1231fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		expectResult = EXPECT_PASS;
1232fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "compile_fail")
1233fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		expectResult = EXPECT_COMPILE_FAIL;
1234fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "link_fail")
1235fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		expectResult = EXPECT_LINK_FAIL;
1236fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "compile_or_link_fail")
1237fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		expectResult = EXPECT_COMPILE_LINK_FAIL;
1238fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "validation_fail")
1239fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		expectResult = EXPECT_VALIDATION_FAIL;
1240fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (m_curTokenStr == "build_successful")
1241fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		expectResult = EXPECT_BUILD_SUCCESSFUL;
1242fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1243fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError(string("invalid expected result value: " + m_curTokenStr));
1244fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1245fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1246fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1247fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1248fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseGLSLVersion (glu::GLSLVersion& version)
1249fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1250fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	int			versionNum		= 0;
1251fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::string	postfix			= "";
1252fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1253fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_INT_LITERAL);
1254fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	versionNum = parseIntLiteral(m_curTokenStr.c_str());
1255fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1256fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1257fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (m_curToken == TOKEN_IDENTIFIER)
1258fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1259fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		postfix = m_curTokenStr;
1260fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		advanceToken();
1261fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1262fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
12635e30a0c40b29675e3503ce94018e53bd4cf705bfPiotr Byszewski	DE_STATIC_ASSERT(glu::GLSL_VERSION_LAST == 15);
1264fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1265fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if		(versionNum == 100 && postfix == "es")	version = glu::GLSL_VERSION_100_ES;
1266fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 300 && postfix == "es")	version = glu::GLSL_VERSION_300_ES;
1267fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 310 && postfix == "es")	version = glu::GLSL_VERSION_310_ES;
1268fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 320 && postfix == "es")	version = glu::GLSL_VERSION_320_ES;
1269fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 130)						version = glu::GLSL_VERSION_130;
1270fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 140)						version = glu::GLSL_VERSION_140;
1271fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 150)						version = glu::GLSL_VERSION_150;
1272fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 330)						version = glu::GLSL_VERSION_330;
1273fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 400)						version = glu::GLSL_VERSION_400;
1274fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 410)						version = glu::GLSL_VERSION_410;
1275fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 420)						version = glu::GLSL_VERSION_420;
1276fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 430)						version = glu::GLSL_VERSION_430;
1277fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 440)						version = glu::GLSL_VERSION_440;
1278fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (versionNum == 450)						version = glu::GLSL_VERSION_450;
12795e30a0c40b29675e3503ce94018e53bd4cf705bfPiotr Byszewski	else if (versionNum == 460)						version = glu::GLSL_VERSION_460;
1280fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1281fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError("Unknown GLSL version");
1282fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1283fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1284fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parsePipelineProgram (ProgramSpecification& program)
1285fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1286fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_PIPELINE_PROGRAM);
1287fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1288fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
1289fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1290fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_END)
1291fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
1292fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_ACTIVE_STAGES)
1293fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1294fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1295fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			program.activeStages = parseShaderStageList();
1296fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1297fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_REQUIRE)
1298fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1299fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			CaseRequirement requirement;
1300fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseRequirement(requirement);
1301fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1302fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (requirement.type == CaseRequirement::TYPE_EXTENSION)
1303fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				program.requiredExtensions.push_back(requirement.extension);
1304fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else
1305fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				parseError("only extension requirements are allowed inside pipeline program");
1306fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1307fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_VERTEX						||
1308fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_FRAGMENT					||
1309fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_TESSELLATION_CONTROL		||
1310fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_TESSELLATION_EVALUATION	||
1311fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_GEOMETRY)
1312fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1313fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			const Token	token = m_curToken;
1314fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			string		source;
1315fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1316fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1317fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			assumeToken(TOKEN_SHADER_SOURCE);
1318fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			source = parseShaderSource(m_curTokenStr.c_str());
1319fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1320fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1321fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			switch (token)
1322fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
1323fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_VERTEX:					program.sources.sources[SHADERTYPE_VERTEX].push_back(source);					break;
1324fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_FRAGMENT:				program.sources.sources[SHADERTYPE_FRAGMENT].push_back(source);					break;
1325fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_TESSELLATION_CONTROL:	program.sources.sources[SHADERTYPE_TESSELLATION_CONTROL].push_back(source);		break;
1326fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_TESSELLATION_EVALUATION:	program.sources.sources[SHADERTYPE_TESSELLATION_EVALUATION].push_back(source);	break;
1327fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_GEOMETRY:				program.sources.sources[SHADERTYPE_GEOMETRY].push_back(source);					break;
1328fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				default:
1329fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					parseError(DE_FALSE);
1330fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
1331fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1332fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1333fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(string("invalid pipeline program value: " + m_curTokenStr));
1334fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1335fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_END);
1336fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1337fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (program.activeStages == 0)
1338fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		parseError("program pipeline object must have active stages");
1339fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1340fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1341fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseShaderCase (vector<tcu::TestNode*>& shaderNodeList)
1342fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1343fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse 'case'.
1344fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	PARSE_DBG(("  parseShaderCase()\n"));
1345fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_CASE);
1346fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1347fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse case name.
1348fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string caseName = m_curTokenStr;
1349fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(); // \note [pyry] All token types are allowed here.
1350fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1351fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// \todo [pyry] Optimize by parsing most stuff directly to ShaderCaseSpecification
1352fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1353fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Setup case.
1354fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	GLSLVersion						version			= DEFAULT_GLSL_VERSION;
1355fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ExpectResult					expectResult	= EXPECT_PASS;
1356fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string							description;
1357fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string							bothSource;
1358fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<string>					vertexSources;
1359fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<string>					fragmentSources;
1360fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<string>					tessellationCtrlSources;
1361fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<string>					tessellationEvalSources;
1362fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<string>					geometrySources;
1363fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ValueBlock						valueBlock;
1364fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	bool							valueBlockSeen	= false;
1365fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<CaseRequirement>			requirements;
1366fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<ProgramSpecification>	pipelinePrograms;
1367fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1368fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
1369fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1370fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_END)
1371fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
1372fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_DESC)
1373fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1374fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1375fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			assumeToken(TOKEN_STRING);
1376fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			description = parseStringLiteral(m_curTokenStr.c_str());
1377fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1378fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1379fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_EXPECT)
1380fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1381fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1382fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseExpectResult(expectResult);
1383fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1384fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_VALUES)
1385fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1386fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (valueBlockSeen)
1387fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				parseError("multiple value blocks");
1388fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseValueBlock(valueBlock);
1389fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			valueBlockSeen = true;
1390fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1391fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_BOTH						||
1392fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_VERTEX						||
1393fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_FRAGMENT					||
1394fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_TESSELLATION_CONTROL		||
1395fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_TESSELLATION_EVALUATION	||
1396fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				 m_curToken == TOKEN_GEOMETRY)
1397fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1398fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			const Token	token = m_curToken;
1399fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			string		source;
1400fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1401fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1402fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			assumeToken(TOKEN_SHADER_SOURCE);
1403fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			source = parseShaderSource(m_curTokenStr.c_str());
1404fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1405fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1406fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			switch (token)
1407fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
1408fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_VERTEX:					vertexSources.push_back(source);			break;
1409fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_FRAGMENT:				fragmentSources.push_back(source);			break;
1410fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_TESSELLATION_CONTROL:	tessellationCtrlSources.push_back(source);	break;
1411fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_TESSELLATION_EVALUATION:	tessellationEvalSources.push_back(source);	break;
1412fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_GEOMETRY:				geometrySources.push_back(source);			break;
1413fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				case TOKEN_BOTH:
1414fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				{
1415fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					if (!bothSource.empty())
1416fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos						parseError("multiple 'both' blocks");
1417fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					bothSource = source;
1418fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					break;
1419fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				}
1420fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1421fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				default:
1422fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos					parseError(DE_FALSE);
1423fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
1424fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1425fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_VERSION)
1426fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1427fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			advanceToken();
1428fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseGLSLVersion(version);
1429fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1430fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_REQUIRE)
1431fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1432fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			CaseRequirement requirement;
1433fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseRequirement(requirement);
1434fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			requirements.push_back(requirement);
1435fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1436fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_PIPELINE_PROGRAM)
1437fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1438fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			ProgramSpecification pipelineProgram;
1439fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parsePipelineProgram(pipelineProgram);
1440677e4644b77c36b99a8959561730c9a519cc37c0Pyry Haulos			pipelineProgram.sources.separable = true;
1441fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			pipelinePrograms.push_back(pipelineProgram);
1442fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1443fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1444fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(string("unexpected token while parsing shader case: " + m_curTokenStr));
1445fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1446fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1447fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_END); // case end
1448fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1449fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// \todo [pyry] Clean up
1450fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<RequiredCapability>	requiredCaps;
1451fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<RequiredExtension>	requiredExts;
1452fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	bool						fullGLSLES100Required	= false;
1453fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1454fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (size_t reqNdx = 0; reqNdx < requirements.size(); ++reqNdx)
1455fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1456fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const CaseRequirement&	requirement	= requirements[reqNdx];
1457fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1458fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (requirement.type == CaseRequirement::TYPE_EXTENSION)
1459fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			requiredExts.push_back(requirement.extension);
1460fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (requirement.type == CaseRequirement::TYPE_IMPLEMENTATION_LIMIT)
1461fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			requiredCaps.push_back(requirement.requiredCap);
1462fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (requirement.type == CaseRequirement::TYPE_FULL_GLSL_ES_100_SUPPORT)
1463fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			fullGLSLES100Required = true;
1464fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1465fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			DE_ASSERT(false);
1466fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1467fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1468fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (!bothSource.empty())
1469fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1470fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (!vertexSources.empty()				||
1471fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!fragmentSources.empty()			||
1472fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!tessellationCtrlSources.empty()	||
1473fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!tessellationEvalSources.empty()	||
1474fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!geometrySources.empty()			||
1475fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!pipelinePrograms.empty())
1476fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1477fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError("'both' cannot be mixed with other shader stages");
1478fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1479fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1480fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// vertex
1481fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1482fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			ShaderCaseSpecification	spec;
1483fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.caseType				= CASETYPE_VERTEX_ONLY;
1484fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.expectResult			= expectResult;
1485fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.targetVersion			= version;
1486fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.fullGLSLES100Required	= fullGLSLES100Required;
1487fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.requiredCaps			= requiredCaps;
1488fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.values					= valueBlock;
1489fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1490fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs.resize(1);
1491fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs[0].sources << VertexSource(bothSource);
1492fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs[0].requiredExtensions	= requiredExts;
1493fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1494fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			shaderNodeList.push_back(m_caseFactory->createCase(caseName + "_vertex", description, ShaderCaseSpecification(spec)));
1495fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1496fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1497fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// fragment
1498fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1499fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			ShaderCaseSpecification	spec;
1500fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.caseType				= CASETYPE_FRAGMENT_ONLY;
1501fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.expectResult			= expectResult;
1502fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.targetVersion			= version;
1503fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.fullGLSLES100Required	= fullGLSLES100Required;
1504fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.requiredCaps			= requiredCaps;
1505fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.values					= valueBlock;
1506fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1507fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs.resize(1);
1508fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs[0].sources << FragmentSource(bothSource);
1509fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs[0].requiredExtensions	= requiredExts;
1510fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1511fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			shaderNodeList.push_back(m_caseFactory->createCase(caseName + "_fragment", description, ShaderCaseSpecification(spec)));
1512fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1513fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1514fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (pipelinePrograms.empty())
1515fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1516fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		ShaderCaseSpecification	spec;
1517fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.caseType				= CASETYPE_COMPLETE;
1518fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.expectResult			= expectResult;
1519fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.targetVersion			= version;
1520fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.fullGLSLES100Required	= fullGLSLES100Required;
1521fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.requiredCaps			= requiredCaps;
1522fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.values					= valueBlock;
1523fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1524fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs.resize(1);
1525fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs[0].sources.sources[SHADERTYPE_VERTEX].swap(vertexSources);
1526fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs[0].sources.sources[SHADERTYPE_FRAGMENT].swap(fragmentSources);
1527fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs[0].sources.sources[SHADERTYPE_TESSELLATION_CONTROL].swap(tessellationCtrlSources);
1528fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs[0].sources.sources[SHADERTYPE_TESSELLATION_EVALUATION].swap(tessellationEvalSources);
1529fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs[0].sources.sources[SHADERTYPE_GEOMETRY].swap(geometrySources);
1530fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		spec.programs[0].requiredExtensions.swap(requiredExts);
1531fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1532fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		shaderNodeList.push_back(m_caseFactory->createCase(caseName, description, ShaderCaseSpecification(spec)));
1533fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1534fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1535fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1536fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (!vertexSources.empty()				||
1537fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!fragmentSources.empty()			||
1538fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!tessellationCtrlSources.empty()	||
1539fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!tessellationEvalSources.empty()	||
1540fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			!geometrySources.empty())
1541fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1542fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError("pipeline programs cannot be mixed with complete programs");
1543fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1544fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1545fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (!requiredExts.empty())
1546fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError("global extension requirements cannot be mixed with pipeline programs");
1547fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1548fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// Pipeline case, multiple programs
1549fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1550fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			ShaderCaseSpecification	spec;
1551fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.caseType				= CASETYPE_COMPLETE;
1552fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.expectResult			= expectResult;
1553fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.targetVersion			= version;
1554fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.fullGLSLES100Required	= fullGLSLES100Required;
1555fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.requiredCaps			= requiredCaps;
1556fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.values					= valueBlock;
1557fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1558fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			spec.programs.swap(pipelinePrograms);
1559fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1560fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			shaderNodeList.push_back(m_caseFactory->createCase(caseName, description, ShaderCaseSpecification(spec)));
1561fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1562fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1563fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1564fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1565fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseShaderGroup (vector<tcu::TestNode*>& shaderNodeList)
1566fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1567fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse 'case'.
1568fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	PARSE_DBG(("  parseShaderGroup()\n"));
1569fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_GROUP);
1570fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1571fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse case name.
1572fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string name = m_curTokenStr;
1573fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(); // \note [pyry] We don't want to check token type here (for instance to allow "uniform") group.
1574fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1575fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse description.
1576fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_STRING);
1577fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	string description = parseStringLiteral(m_curTokenStr.c_str());
1578fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_STRING);
1579fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1580fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::vector<tcu::TestNode*> children;
1581fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1582fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse group children.
1583fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
1584fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1585fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_END)
1586fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
1587fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_GROUP)
1588fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseShaderGroup(children);
1589fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_CASE)
1590fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseShaderCase(children);
1591fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_IMPORT)
1592fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseImport(children);
1593fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1594fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(string("unexpected token while parsing shader group: " + m_curTokenStr));
1595fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1596fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1597fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_END); // group end
1598fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1599fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Create group node.
1600fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	tcu::TestCaseGroup* groupNode = m_caseFactory->createGroup(name, description, children);
1601fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	shaderNodeList.push_back(groupNode);
1602fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1603fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1604fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid ShaderParser::parseImport (vector<tcu::TestNode*>& shaderNodeList)
1605fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1606fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::string	importFileName;
1607fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1608fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_IMPORT);
1609fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1610fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_STRING);
1611fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	importFileName = parseStringLiteral(m_curTokenStr.c_str());
1612fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken(TOKEN_STRING);
1613fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1614fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1615fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		ShaderParser					subParser		(m_archive, de::FilePath::join(de::FilePath(m_filename).getDirName(), importFileName).getPath(), m_caseFactory);
1616fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const vector<tcu::TestNode*>	importedCases = subParser.parse();
1617fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1618fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// \todo [2015-08-03 pyry] Not exception safe
1619fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		shaderNodeList.insert(shaderNodeList.end(), importedCases.begin(), importedCases.end());
1620fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1621fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1622fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1623fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvector<tcu::TestNode*> ShaderParser::parse (void)
1624fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1625fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const int	dataLen		= m_resource->getSize();
1626fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1627fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_input.resize(dataLen+1);
1628fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_resource->setPosition(0);
1629fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_resource->read((deUint8*)&m_input[0], dataLen);
1630fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_input[dataLen] = '\0';
1631fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1632fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Initialize parser.
1633fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_curPtr		= &m_input[0];
1634fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_curToken		= TOKEN_INVALID;
1635fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	m_curTokenStr	= "";
1636fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	advanceToken();
1637fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1638fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	vector<tcu::TestNode*> nodeList;
1639fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1640fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// Parse all cases.
1641fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	PARSE_DBG(("parse()\n"));
1642fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (;;)
1643fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1644fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (m_curToken == TOKEN_CASE)
1645fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseShaderCase(nodeList);
1646fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_GROUP)
1647fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseShaderGroup(nodeList);
1648fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_IMPORT)
1649fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseImport(nodeList);
1650fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else if (m_curToken == TOKEN_EOF)
1651fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			break;
1652fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		else
1653fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			parseError(string("invalid token encountered at main level: '") + m_curTokenStr + "'");
1654fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1655fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1656fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	assumeToken(TOKEN_EOF);
1657fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos//	printf("  parsed %d test cases.\n", caseList.size());
1658fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return nodeList;
1659fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1660fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1661fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstd::vector<tcu::TestNode*> parseFile (const tcu::Archive& archive, const std::string& filename, ShaderCaseFactory* caseFactory)
1662fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1663fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	sl::ShaderParser	parser	(archive, filename, caseFactory);
1664fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1665fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return parser.parse();
1666fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1667fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1668fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos// Execution utilities
1669fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1670fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstatic void dumpValue (tcu::TestLog& log, const Value& val, const char* storageName, int arrayNdx)
1671fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1672fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const char* const	valueName		= val.name.c_str();
1673fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	const DataType		dataType		= val.type.getBasicType();
1674fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	int					scalarSize		= getDataTypeScalarSize(dataType);
1675fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	ostringstream		result;
1676fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1677fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	result << "    " << storageName << " ";
1678fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1679fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	result << getDataTypeName(dataType) << " " << valueName << ":";
1680fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1681fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (isDataTypeScalar(dataType))
1682fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		result << " ";
1683fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (isDataTypeVector(dataType))
1684fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		result << " [ ";
1685fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (isDataTypeMatrix(dataType))
1686fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		result << "\n";
1687fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1688fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (isDataTypeScalarOrVector(dataType))
1689fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1690fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
1691fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1692fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			int						elemNdx	= arrayNdx;
1693fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			const Value::Element&	e		= val.elements[elemNdx*scalarSize + scalarNdx];
1694fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			result << ((scalarNdx != 0) ? ", " : "");
1695fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1696fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			if (isDataTypeFloatOrVec(dataType))
1697fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				result << e.float32;
1698fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else if (isDataTypeIntOrIVec(dataType))
1699fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				result << e.int32;
1700fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else if (isDataTypeUintOrUVec(dataType))
1701fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				result << (deUint32)e.int32;
1702fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			else if (isDataTypeBoolOrBVec(dataType))
1703fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				result << (e.bool32 ? "true" : "false");
1704fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1705fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1706fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (isDataTypeMatrix(dataType))
1707fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1708fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		int numRows = getDataTypeMatrixNumRows(dataType);
1709fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		int numCols = getDataTypeMatrixNumColumns(dataType);
1710fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
1711fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1712fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			result << "       [ ";
1713fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			for (int colNdx = 0; colNdx < numCols; colNdx++)
1714fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			{
1715fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				int		elemNdx = arrayNdx;
1716fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				float	v		= val.elements[elemNdx*scalarSize + rowNdx*numCols + colNdx].float32;
1717fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				result << ((colNdx==0) ? "" : ", ") << v;
1718fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			}
1719fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			result << " ]\n";
1720fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1721fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1722fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1723fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (isDataTypeScalar(dataType))
1724fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		result << "\n";
1725fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else if (isDataTypeVector(dataType))
1726fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		result << " ]\n";
1727fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1728fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	log << TestLog::Message << result.str() << TestLog::EndMessage;
1729fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1730fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1731fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstatic void dumpValues (tcu::TestLog& log, const vector<Value>& values, const char* storageName, int arrayNdx)
1732fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1733fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (size_t valNdx = 0; valNdx < values.size(); valNdx++)
1734fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		dumpValue(log, values[valNdx], storageName, arrayNdx);
1735fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1736fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1737fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid dumpValues (tcu::TestLog& log, const ValueBlock& values, int arrayNdx)
1738fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1739fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	dumpValues(log, values.inputs,		"input",	arrayNdx);
1740fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	dumpValues(log, values.outputs,		"expected",	arrayNdx);
1741fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	dumpValues(log, values.uniforms,	"uniform",	arrayNdx);
1742fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1743fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1744fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstatic void generateExtensionStatements (std::ostringstream& buf, const std::vector<RequiredExtension>& extensions, glu::ShaderType type)
1745fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1746fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (size_t ndx = 0; ndx < extensions.size(); ++ndx)
1747fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1748fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		DE_ASSERT(extensions[ndx].effectiveStages != 0u &&
1749fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos				  extensions[ndx].alternatives.size() == 1);
1750fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1751fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if ((extensions[ndx].effectiveStages & (1u << (deUint32)type)) != 0)
1752fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			buf << "#extension " << extensions[ndx].alternatives[0] << " : require\n";
1753fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1754fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1755fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1756fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos// Injects #extension XXX : require lines after the last preprocessor directive in the shader code. Does not support line continuations
1757fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosstd::string injectExtensionRequirements (const std::string& baseCode, const std::vector<RequiredExtension>& extensions, glu::ShaderType shaderType)
1758fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1759fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::istringstream	baseCodeBuf					(baseCode);
1760fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::ostringstream	resultBuf;
1761fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::string			line;
1762fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	bool				firstNonPreprocessorLine	= true;
1763fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	std::ostringstream	extStr;
1764fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1765fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	generateExtensionStatements(extStr, extensions, shaderType);
1766fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1767fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	// skip if no requirements
1768fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (extStr.str().empty())
1769fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		return baseCode;
1770fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1771fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	while (std::getline(baseCodeBuf, line))
1772fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1773fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// begins with '#'?
1774fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const std::string::size_type	firstNonWhitespace		= line.find_first_not_of("\t ");
1775fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const bool						isPreprocessorDirective	= (firstNonWhitespace != std::string::npos && line.at(firstNonWhitespace) == '#');
1776fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1777fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		// Inject #extensions
1778fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (!isPreprocessorDirective && firstNonPreprocessorLine)
1779fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		{
1780fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			firstNonPreprocessorLine = false;
1781fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos			resultBuf << extStr.str();
1782fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		}
1783fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1784fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		resultBuf << line << "\n";
1785fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1786fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1787fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	return resultBuf.str();
1788fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1789fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1790fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulosvoid genCompareFunctions (ostringstream& stream, const ValueBlock& valueBlock, bool useFloatTypes)
1791fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos{
1792fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	bool cmpTypeFound[TYPE_LAST];
1793fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (int i = 0; i < TYPE_LAST; i++)
1794fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		cmpTypeFound[i] = false;
1795fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1796fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	for (size_t valueNdx = 0; valueNdx < valueBlock.outputs.size(); valueNdx++)
1797fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1798fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		const Value& val = valueBlock.outputs[valueNdx];
1799fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		cmpTypeFound[(size_t)val.type.getBasicType()] = true;
1800fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1801fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1802fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (useFloatTypes)
1803fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1804fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL])		stream << "bool isOk (float a, bool b) { return ((a > 0.5) == b); }\n";
1805fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL_VEC2])	stream << "bool isOk (vec2 a, bvec2 b) { return (greaterThan(a, vec2(0.5)) == b); }\n";
1806fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL_VEC3])	stream << "bool isOk (vec3 a, bvec3 b) { return (greaterThan(a, vec3(0.5)) == b); }\n";
1807fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL_VEC4])	stream << "bool isOk (vec4 a, bvec4 b) { return (greaterThan(a, vec4(0.5)) == b); }\n";
1808fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT])			stream << "bool isOk (float a, int b)  { float atemp = a+0.5; return (float(b) <= atemp && atemp <= float(b+1)); }\n";
1809fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT_VEC2])	stream << "bool isOk (vec2 a, ivec2 b) { return (ivec2(floor(a + 0.5)) == b); }\n";
1810fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT_VEC3])	stream << "bool isOk (vec3 a, ivec3 b) { return (ivec3(floor(a + 0.5)) == b); }\n";
1811fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT_VEC4])	stream << "bool isOk (vec4 a, ivec4 b) { return (ivec4(floor(a + 0.5)) == b); }\n";
1812fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT])		stream << "bool isOk (float a, uint b) { float atemp = a+0.5; return (float(b) <= atemp && atemp <= float(b+1u)); }\n";
1813fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT_VEC2])	stream << "bool isOk (vec2 a, uvec2 b) { return (uvec2(floor(a + 0.5)) == b); }\n";
1814fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT_VEC3])	stream << "bool isOk (vec3 a, uvec3 b) { return (uvec3(floor(a + 0.5)) == b); }\n";
1815fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT_VEC4])	stream << "bool isOk (vec4 a, uvec4 b) { return (uvec4(floor(a + 0.5)) == b); }\n";
1816fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1817fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	else
1818fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	{
1819fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL])		stream << "bool isOk (bool a, bool b)   { return (a == b); }\n";
1820fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL_VEC2])	stream << "bool isOk (bvec2 a, bvec2 b) { return (a == b); }\n";
1821fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL_VEC3])	stream << "bool isOk (bvec3 a, bvec3 b) { return (a == b); }\n";
1822fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_BOOL_VEC4])	stream << "bool isOk (bvec4 a, bvec4 b) { return (a == b); }\n";
1823fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT])			stream << "bool isOk (int a, int b)     { return (a == b); }\n";
1824fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT_VEC2])	stream << "bool isOk (ivec2 a, ivec2 b) { return (a == b); }\n";
1825fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT_VEC3])	stream << "bool isOk (ivec3 a, ivec3 b) { return (a == b); }\n";
1826fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_INT_VEC4])	stream << "bool isOk (ivec4 a, ivec4 b) { return (a == b); }\n";
1827fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT])		stream << "bool isOk (uint a, uint b)   { return (a == b); }\n";
1828fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT_VEC2])	stream << "bool isOk (uvec2 a, uvec2 b) { return (a == b); }\n";
1829fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT_VEC3])	stream << "bool isOk (uvec3 a, uvec3 b) { return (a == b); }\n";
1830fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos		if (cmpTypeFound[TYPE_UINT_VEC4])	stream << "bool isOk (uvec4 a, uvec4 b) { return (a == b); }\n";
1831fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	}
1832fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1833fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT])		stream << "bool isOk (float a, float b, float eps) { return (abs(a-b) <= (eps*abs(b) + eps)); }\n";
1834fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_VEC2])	stream << "bool isOk (vec2 a, vec2 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n";
1835fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_VEC3])	stream << "bool isOk (vec3 a, vec3 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n";
1836fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_VEC4])	stream << "bool isOk (vec4 a, vec4 b, float eps) { return all(lessThanEqual(abs(a-b), (eps*abs(b) + eps))); }\n";
1837fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1838fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT2])		stream << "bool isOk (mat2 a, mat2 b, float eps) { vec2 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec2(eps))); }\n";
1839fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT2X3])	stream << "bool isOk (mat2x3 a, mat2x3 b, float eps) { vec3 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec3(eps))); }\n";
1840fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT2X4])	stream << "bool isOk (mat2x4 a, mat2x4 b, float eps) { vec4 diff = max(abs(a[0]-b[0]), abs(a[1]-b[1])); return all(lessThanEqual(diff, vec4(eps))); }\n";
1841fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT3X2])	stream << "bool isOk (mat3x2 a, mat3x2 b, float eps) { vec2 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec2(eps))); }\n";
1842fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT3])		stream << "bool isOk (mat3 a, mat3 b, float eps) { vec3 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec3(eps))); }\n";
1843fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT3X4])	stream << "bool isOk (mat3x4 a, mat3x4 b, float eps) { vec4 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), abs(a[2]-b[2])); return all(lessThanEqual(diff, vec4(eps))); }\n";
1844fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT4X2])	stream << "bool isOk (mat4x2 a, mat4x2 b, float eps) { vec2 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec2(eps))); }\n";
1845fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT4X3])	stream << "bool isOk (mat4x3 a, mat4x3 b, float eps) { vec3 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec3(eps))); }\n";
1846fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos	if (cmpTypeFound[TYPE_FLOAT_MAT4])		stream << "bool isOk (mat4 a, mat4 b, float eps) { vec4 diff = max(max(abs(a[0]-b[0]), abs(a[1]-b[1])), max(abs(a[2]-b[2]), abs(a[3]-b[3]))); return all(lessThanEqual(diff, vec4(eps))); }\n";
1847fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos}
1848fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos
1849fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos} // sl
1850fb19324168dd35ccbb7fca74e5426f1a3fbc03a2Pyry Haulos} // glu
1851