1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.1 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Program interface utilities
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinitionUtil.hpp"
25e5c31af7Sopenharmony_ci#include "es31fProgramInterfaceDefinition.hpp"
26e5c31af7Sopenharmony_ci#include "gluVarType.hpp"
27e5c31af7Sopenharmony_ci#include "gluVarTypeUtil.hpp"
28e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
29e5c31af7Sopenharmony_ci#include "deString.h"
30e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
31e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ci#include <set>
34e5c31af7Sopenharmony_ci#include <map>
35e5c31af7Sopenharmony_ci#include <sstream>
36e5c31af7Sopenharmony_ci#include <vector>
37e5c31af7Sopenharmony_ci#include <algorithm>
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_cinamespace deqp
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_cinamespace gles31
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_cinamespace Functional
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_cinamespace ProgramInterfaceDefinition
46e5c31af7Sopenharmony_ci{
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_ciVariableSearchFilter::VariableSearchFilter (void)
49e5c31af7Sopenharmony_ci	: m_shaderTypeBits	(0xFFFFFFFFul)
50e5c31af7Sopenharmony_ci	, m_storageBits		(0xFFFFFFFFul)
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_ci}
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::createShaderTypeFilter (glu::ShaderType type)
55e5c31af7Sopenharmony_ci{
56e5c31af7Sopenharmony_ci	DE_ASSERT(type < glu::SHADERTYPE_LAST);
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci	VariableSearchFilter filter;
59e5c31af7Sopenharmony_ci	filter.m_shaderTypeBits = (1u << type);
60e5c31af7Sopenharmony_ci	return filter;
61e5c31af7Sopenharmony_ci}
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::createStorageFilter (glu::Storage storage)
64e5c31af7Sopenharmony_ci{
65e5c31af7Sopenharmony_ci	DE_ASSERT(storage < glu::STORAGE_LAST);
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	VariableSearchFilter filter;
68e5c31af7Sopenharmony_ci	filter.m_storageBits = (1u << storage);
69e5c31af7Sopenharmony_ci	return filter;
70e5c31af7Sopenharmony_ci}
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::createShaderTypeStorageFilter (glu::ShaderType type, glu::Storage storage)
73e5c31af7Sopenharmony_ci{
74e5c31af7Sopenharmony_ci	return logicalAnd(createShaderTypeFilter(type), createStorageFilter(storage));
75e5c31af7Sopenharmony_ci}
76e5c31af7Sopenharmony_ci
77e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::logicalOr (const VariableSearchFilter& a, const VariableSearchFilter& b)
78e5c31af7Sopenharmony_ci{
79e5c31af7Sopenharmony_ci	VariableSearchFilter filter;
80e5c31af7Sopenharmony_ci	filter.m_shaderTypeBits	= a.m_shaderTypeBits | b.m_shaderTypeBits;
81e5c31af7Sopenharmony_ci	filter.m_storageBits	= a.m_storageBits | b.m_storageBits;
82e5c31af7Sopenharmony_ci	return filter;
83e5c31af7Sopenharmony_ci}
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ciVariableSearchFilter VariableSearchFilter::logicalAnd (const VariableSearchFilter& a, const VariableSearchFilter& b)
86e5c31af7Sopenharmony_ci{
87e5c31af7Sopenharmony_ci	VariableSearchFilter filter;
88e5c31af7Sopenharmony_ci	filter.m_shaderTypeBits	= a.m_shaderTypeBits & b.m_shaderTypeBits;
89e5c31af7Sopenharmony_ci	filter.m_storageBits	= a.m_storageBits & b.m_storageBits;
90e5c31af7Sopenharmony_ci	return filter;
91e5c31af7Sopenharmony_ci}
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_cibool VariableSearchFilter::matchesFilter (const ProgramInterfaceDefinition::Shader* shader) const
94e5c31af7Sopenharmony_ci{
95e5c31af7Sopenharmony_ci	DE_ASSERT(shader->getType() < glu::SHADERTYPE_LAST);
96e5c31af7Sopenharmony_ci	return (m_shaderTypeBits & (1u << shader->getType())) != 0;
97e5c31af7Sopenharmony_ci}
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_cibool VariableSearchFilter::matchesFilter (const glu::VariableDeclaration& variable) const
100e5c31af7Sopenharmony_ci{
101e5c31af7Sopenharmony_ci	DE_ASSERT(variable.storage < glu::STORAGE_LAST);
102e5c31af7Sopenharmony_ci	return (m_storageBits & (1u << variable.storage)) != 0;
103e5c31af7Sopenharmony_ci}
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_cibool VariableSearchFilter::matchesFilter (const glu::InterfaceBlock& block) const
106e5c31af7Sopenharmony_ci{
107e5c31af7Sopenharmony_ci	DE_ASSERT(block.storage < glu::STORAGE_LAST);
108e5c31af7Sopenharmony_ci	return (m_storageBits & (1u << block.storage)) != 0;
109e5c31af7Sopenharmony_ci}
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_ci} // ProgramInterfaceDefinition
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_cistatic bool incrementMultiDimensionIndex (std::vector<int>& index, const std::vector<int>& dimensions)
114e5c31af7Sopenharmony_ci{
115e5c31af7Sopenharmony_ci	int incrementDimensionNdx = (int)(index.size() - 1);
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci	while (incrementDimensionNdx >= 0)
118e5c31af7Sopenharmony_ci	{
119e5c31af7Sopenharmony_ci		if (++index[incrementDimensionNdx] == dimensions[incrementDimensionNdx])
120e5c31af7Sopenharmony_ci			index[incrementDimensionNdx--] = 0;
121e5c31af7Sopenharmony_ci		else
122e5c31af7Sopenharmony_ci			break;
123e5c31af7Sopenharmony_ci	}
124e5c31af7Sopenharmony_ci
125e5c31af7Sopenharmony_ci	return (incrementDimensionNdx != -1);
126e5c31af7Sopenharmony_ci}
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_cibool programContainsIOBlocks (const ProgramInterfaceDefinition::Program* program)
129e5c31af7Sopenharmony_ci{
130e5c31af7Sopenharmony_ci	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
131e5c31af7Sopenharmony_ci	{
132e5c31af7Sopenharmony_ci		if (shaderContainsIOBlocks(program->getShaders()[shaderNdx]))
133e5c31af7Sopenharmony_ci			return true;
134e5c31af7Sopenharmony_ci	}
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_ci	return false;
137e5c31af7Sopenharmony_ci}
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_cibool shaderContainsIOBlocks (const ProgramInterfaceDefinition::Shader* shader)
140e5c31af7Sopenharmony_ci{
141e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
142e5c31af7Sopenharmony_ci	{
143e5c31af7Sopenharmony_ci		const glu::Storage storage = shader->getDefaultBlock().interfaceBlocks[ndx].storage;
144e5c31af7Sopenharmony_ci		if (storage == glu::STORAGE_IN			||
145e5c31af7Sopenharmony_ci			storage == glu::STORAGE_OUT			||
146e5c31af7Sopenharmony_ci			storage == glu::STORAGE_PATCH_IN	||
147e5c31af7Sopenharmony_ci			storage == glu::STORAGE_PATCH_OUT)
148e5c31af7Sopenharmony_ci		{
149e5c31af7Sopenharmony_ci			return true;
150e5c31af7Sopenharmony_ci		}
151e5c31af7Sopenharmony_ci	}
152e5c31af7Sopenharmony_ci	return false;
153e5c31af7Sopenharmony_ci}
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ciglu::ShaderType getProgramTransformFeedbackStage (const ProgramInterfaceDefinition::Program* program)
156e5c31af7Sopenharmony_ci{
157e5c31af7Sopenharmony_ci	if (program->hasStage(glu::SHADERTYPE_GEOMETRY))
158e5c31af7Sopenharmony_ci		return glu::SHADERTYPE_GEOMETRY;
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci	if (program->hasStage(glu::SHADERTYPE_TESSELLATION_EVALUATION))
161e5c31af7Sopenharmony_ci		return glu::SHADERTYPE_TESSELLATION_EVALUATION;
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci	if (program->hasStage(glu::SHADERTYPE_VERTEX))
164e5c31af7Sopenharmony_ci		return glu::SHADERTYPE_VERTEX;
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci	DE_ASSERT(false);
167e5c31af7Sopenharmony_ci	return glu::SHADERTYPE_LAST;
168e5c31af7Sopenharmony_ci}
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_civoid generateVariableTypeResourceNames (std::vector<std::string>& resources, const std::string& name, const glu::VarType& type, deUint32 resourceNameGenerationFlags)
171e5c31af7Sopenharmony_ci{
172e5c31af7Sopenharmony_ci	DE_ASSERT((resourceNameGenerationFlags & (~RESOURCE_NAME_GENERATION_FLAG_MASK)) == 0);
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci	// remove top-level flag from children
175e5c31af7Sopenharmony_ci	const deUint32 childFlags = resourceNameGenerationFlags & ~((deUint32)RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE);
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci	if (type.isBasicType())
178e5c31af7Sopenharmony_ci		resources.push_back(name);
179e5c31af7Sopenharmony_ci	else if (type.isStructType())
180e5c31af7Sopenharmony_ci	{
181e5c31af7Sopenharmony_ci		const glu::StructType* structType = type.getStructPtr();
182e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < structType->getNumMembers(); ++ndx)
183e5c31af7Sopenharmony_ci			generateVariableTypeResourceNames(resources, name + "." + structType->getMember(ndx).getName(), structType->getMember(ndx).getType(), childFlags);
184e5c31af7Sopenharmony_ci	}
185e5c31af7Sopenharmony_ci	else if (type.isArrayType())
186e5c31af7Sopenharmony_ci	{
187e5c31af7Sopenharmony_ci		// Bottom-level arrays of basic types of a transform feedback variable will produce only the first
188e5c31af7Sopenharmony_ci		// element but without the trailing "[0]"
189e5c31af7Sopenharmony_ci		if (type.getElementType().isBasicType() &&
190e5c31af7Sopenharmony_ci			(resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE) != 0)
191e5c31af7Sopenharmony_ci		{
192e5c31af7Sopenharmony_ci			resources.push_back(name);
193e5c31af7Sopenharmony_ci		}
194e5c31af7Sopenharmony_ci		// Bottom-level arrays of basic types and SSBO top-level arrays of any type procude only first element
195e5c31af7Sopenharmony_ci		else if (type.getElementType().isBasicType() ||
196e5c31af7Sopenharmony_ci				 (resourceNameGenerationFlags & RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) != 0)
197e5c31af7Sopenharmony_ci		{
198e5c31af7Sopenharmony_ci			generateVariableTypeResourceNames(resources, name + "[0]", type.getElementType(), childFlags);
199e5c31af7Sopenharmony_ci		}
200e5c31af7Sopenharmony_ci		// Other arrays of aggregate types are expanded
201e5c31af7Sopenharmony_ci		else
202e5c31af7Sopenharmony_ci		{
203e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx < type.getArraySize(); ++ndx)
204e5c31af7Sopenharmony_ci				generateVariableTypeResourceNames(resources, name + "[" + de::toString(ndx) + "]", type.getElementType(), childFlags);
205e5c31af7Sopenharmony_ci		}
206e5c31af7Sopenharmony_ci	}
207e5c31af7Sopenharmony_ci	else
208e5c31af7Sopenharmony_ci		DE_ASSERT(false);
209e5c31af7Sopenharmony_ci}
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci// Program source generation
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_cinamespace
214e5c31af7Sopenharmony_ci{
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ciusing ProgramInterfaceDefinition::VariablePathComponent;
217e5c31af7Sopenharmony_ciusing ProgramInterfaceDefinition::VariableSearchFilter;
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_cistatic std::string getShaderExtensionDeclarations (const ProgramInterfaceDefinition::Shader* shader)
220e5c31af7Sopenharmony_ci{
221e5c31af7Sopenharmony_ci	if (shader->getVersion() > glu::GLSL_VERSION_440)
222e5c31af7Sopenharmony_ci		return "";
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_ci	std::vector<std::string>	extensions;
225e5c31af7Sopenharmony_ci	std::ostringstream			buf;
226e5c31af7Sopenharmony_ci
227e5c31af7Sopenharmony_ci	if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
228e5c31af7Sopenharmony_ci	{
229e5c31af7Sopenharmony_ci		extensions.push_back("GL_EXT_geometry_shader");
230e5c31af7Sopenharmony_ci	}
231e5c31af7Sopenharmony_ci	else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL ||
232e5c31af7Sopenharmony_ci			 shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
233e5c31af7Sopenharmony_ci	{
234e5c31af7Sopenharmony_ci		extensions.push_back("GL_EXT_tessellation_shader");
235e5c31af7Sopenharmony_ci	}
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci	if (shaderContainsIOBlocks(shader))
238e5c31af7Sopenharmony_ci		extensions.push_back("GL_EXT_shader_io_blocks");
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)extensions.size(); ++ndx)
241e5c31af7Sopenharmony_ci		buf << "#extension " << extensions[ndx] << " : require\n";
242e5c31af7Sopenharmony_ci	return buf.str();
243e5c31af7Sopenharmony_ci}
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_cistatic std::string getShaderTypeDeclarations (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader)
246e5c31af7Sopenharmony_ci{
247e5c31af7Sopenharmony_ci	glu::ShaderType type = shader->getType();
248e5c31af7Sopenharmony_ci	auto isCoreGL = (shader->getVersion() > glu::GLSL_VERSION_440);
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci	switch (type)
251e5c31af7Sopenharmony_ci	{
252e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_VERTEX:
253e5c31af7Sopenharmony_ci			if (isCoreGL)
254e5c31af7Sopenharmony_ci				return "out gl_PerVertex { vec4 gl_Position; };\n";
255e5c31af7Sopenharmony_ci			return "";
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_FRAGMENT:
258e5c31af7Sopenharmony_ci			return "";
259e5c31af7Sopenharmony_ci
260e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_GEOMETRY:
261e5c31af7Sopenharmony_ci		{
262e5c31af7Sopenharmony_ci			std::ostringstream buf;
263e5c31af7Sopenharmony_ci			buf <<	"layout(points) in;\n"
264e5c31af7Sopenharmony_ci					"layout(points, max_vertices=" << program->getGeometryNumOutputVertices() << ") out;\n";
265e5c31af7Sopenharmony_ci			if (isCoreGL)
266e5c31af7Sopenharmony_ci			{
267e5c31af7Sopenharmony_ci				buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
268e5c31af7Sopenharmony_ci					   "out gl_PerVertex { vec4 gl_Position; };\n";
269e5c31af7Sopenharmony_ci			}
270e5c31af7Sopenharmony_ci			return buf.str();
271e5c31af7Sopenharmony_ci		}
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_TESSELLATION_CONTROL:
274e5c31af7Sopenharmony_ci		{
275e5c31af7Sopenharmony_ci			std::ostringstream buf;
276e5c31af7Sopenharmony_ci			buf << "layout(vertices=" << program->getTessellationNumOutputPatchVertices() << ") out;\n";
277e5c31af7Sopenharmony_ci			if (isCoreGL)
278e5c31af7Sopenharmony_ci			{
279e5c31af7Sopenharmony_ci				buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
280e5c31af7Sopenharmony_ci					   "out gl_PerVertex { vec4 gl_Position; } gl_out[];\n";
281e5c31af7Sopenharmony_ci			}
282e5c31af7Sopenharmony_ci			return buf.str();
283e5c31af7Sopenharmony_ci		}
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
286e5c31af7Sopenharmony_ci		{
287e5c31af7Sopenharmony_ci			std::ostringstream buf;
288e5c31af7Sopenharmony_ci			if (isCoreGL)
289e5c31af7Sopenharmony_ci			{
290e5c31af7Sopenharmony_ci				buf << "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
291e5c31af7Sopenharmony_ci					   "out gl_PerVertex { vec4 gl_Position; };\n";
292e5c31af7Sopenharmony_ci			}
293e5c31af7Sopenharmony_ci			buf << "layout(triangles, point_mode) in;\n";
294e5c31af7Sopenharmony_ci			return buf.str();
295e5c31af7Sopenharmony_ci		}
296e5c31af7Sopenharmony_ci
297e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_COMPUTE:
298e5c31af7Sopenharmony_ci			return "layout(local_size_x=1) in;\n";
299e5c31af7Sopenharmony_ci
300e5c31af7Sopenharmony_ci		default:
301e5c31af7Sopenharmony_ci			DE_ASSERT(false);
302e5c31af7Sopenharmony_ci			return "";
303e5c31af7Sopenharmony_ci	}
304e5c31af7Sopenharmony_ci}
305e5c31af7Sopenharmony_ci
306e5c31af7Sopenharmony_ciclass StructNameEqualPredicate
307e5c31af7Sopenharmony_ci{
308e5c31af7Sopenharmony_cipublic:
309e5c31af7Sopenharmony_ci				StructNameEqualPredicate	(const char* name) : m_name(name) { }
310e5c31af7Sopenharmony_ci	bool		operator()					(const glu::StructType* type) { return type->hasTypeName() && (deStringEqual(m_name, type->getTypeName()) == DE_TRUE); }
311e5c31af7Sopenharmony_ciprivate:
312e5c31af7Sopenharmony_ci	const char*	m_name;
313e5c31af7Sopenharmony_ci};
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_cistatic void collectNamedStructureDefinitions (std::vector<const glu::StructType*>& dst, const glu::VarType& type)
316e5c31af7Sopenharmony_ci{
317e5c31af7Sopenharmony_ci	if (type.isBasicType())
318e5c31af7Sopenharmony_ci		return;
319e5c31af7Sopenharmony_ci	else if (type.isArrayType())
320e5c31af7Sopenharmony_ci		return collectNamedStructureDefinitions(dst, type.getElementType());
321e5c31af7Sopenharmony_ci	else if (type.isStructType())
322e5c31af7Sopenharmony_ci	{
323e5c31af7Sopenharmony_ci		if (type.getStructPtr()->hasTypeName())
324e5c31af7Sopenharmony_ci		{
325e5c31af7Sopenharmony_ci			// must be unique (may share the the same struct)
326e5c31af7Sopenharmony_ci			std::vector<const glu::StructType*>::iterator where = std::find_if(dst.begin(), dst.end(), StructNameEqualPredicate(type.getStructPtr()->getTypeName()));
327e5c31af7Sopenharmony_ci			if (where != dst.end())
328e5c31af7Sopenharmony_ci			{
329e5c31af7Sopenharmony_ci				DE_ASSERT(**where == *type.getStructPtr());
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_ci				// identical type has been added already, types of members must be added too
332e5c31af7Sopenharmony_ci				return;
333e5c31af7Sopenharmony_ci			}
334e5c31af7Sopenharmony_ci		}
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci		// Add types of members first
337e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
338e5c31af7Sopenharmony_ci			collectNamedStructureDefinitions(dst, type.getStructPtr()->getMember(ndx).getType());
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ci		dst.push_back(type.getStructPtr());
341e5c31af7Sopenharmony_ci	}
342e5c31af7Sopenharmony_ci	else
343e5c31af7Sopenharmony_ci		DE_ASSERT(false);
344e5c31af7Sopenharmony_ci}
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_cistatic void writeStructureDefinitions (std::ostringstream& buf, const ProgramInterfaceDefinition::DefaultBlock& defaultBlock)
347e5c31af7Sopenharmony_ci{
348e5c31af7Sopenharmony_ci	std::vector<const glu::StructType*> namedStructs;
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci	// Collect all structs in post order
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)defaultBlock.variables.size(); ++ndx)
353e5c31af7Sopenharmony_ci		collectNamedStructureDefinitions(namedStructs, defaultBlock.variables[ndx].varType);
354e5c31af7Sopenharmony_ci
355e5c31af7Sopenharmony_ci	for (int blockNdx = 0; blockNdx < (int)defaultBlock.interfaceBlocks.size(); ++blockNdx)
356e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)defaultBlock.interfaceBlocks[blockNdx].variables.size(); ++ndx)
357e5c31af7Sopenharmony_ci			collectNamedStructureDefinitions(namedStructs, defaultBlock.interfaceBlocks[blockNdx].variables[ndx].varType);
358e5c31af7Sopenharmony_ci
359e5c31af7Sopenharmony_ci	// Write
360e5c31af7Sopenharmony_ci
361e5c31af7Sopenharmony_ci	for (int structNdx = 0; structNdx < (int)namedStructs.size(); ++structNdx)
362e5c31af7Sopenharmony_ci	{
363e5c31af7Sopenharmony_ci		buf <<	"struct " << namedStructs[structNdx]->getTypeName() << "\n"
364e5c31af7Sopenharmony_ci				"{\n";
365e5c31af7Sopenharmony_ci
366e5c31af7Sopenharmony_ci		for (int memberNdx = 0; memberNdx < namedStructs[structNdx]->getNumMembers(); ++memberNdx)
367e5c31af7Sopenharmony_ci			buf << glu::indent(1) << glu::declare(namedStructs[structNdx]->getMember(memberNdx).getType(), namedStructs[structNdx]->getMember(memberNdx).getName(), 1) << ";\n";
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_ci		buf <<	"};\n";
370e5c31af7Sopenharmony_ci	}
371e5c31af7Sopenharmony_ci
372e5c31af7Sopenharmony_ci	if (!namedStructs.empty())
373e5c31af7Sopenharmony_ci		buf << "\n";
374e5c31af7Sopenharmony_ci}
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_cistatic void writeInterfaceBlock (std::ostringstream& buf, const glu::InterfaceBlock& interfaceBlock)
377e5c31af7Sopenharmony_ci{
378e5c31af7Sopenharmony_ci	buf << interfaceBlock.layout;
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci	if (interfaceBlock.layout != glu::Layout())
381e5c31af7Sopenharmony_ci		buf << " ";
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci	buf	<< glu::getStorageName(interfaceBlock.storage) << " " << interfaceBlock.interfaceName << "\n"
384e5c31af7Sopenharmony_ci		<< "{\n";
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)interfaceBlock.variables.size(); ++ndx)
387e5c31af7Sopenharmony_ci		buf << glu::indent(1) << interfaceBlock.variables[ndx] << ";\n";
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci	buf << "}";
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci	if (!interfaceBlock.instanceName.empty())
392e5c31af7Sopenharmony_ci		buf << " " << interfaceBlock.instanceName;
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
395e5c31af7Sopenharmony_ci		buf << "[" << interfaceBlock.dimensions[dimensionNdx] << "]";
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	buf << ";\n\n";
398e5c31af7Sopenharmony_ci}
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_cistatic bool isReadableInterface (const glu::InterfaceBlock& interface)
401e5c31af7Sopenharmony_ci{
402e5c31af7Sopenharmony_ci	return	interface.storage == glu::STORAGE_UNIFORM	||
403e5c31af7Sopenharmony_ci			interface.storage == glu::STORAGE_IN		||
404e5c31af7Sopenharmony_ci			interface.storage == glu::STORAGE_PATCH_IN	||
405e5c31af7Sopenharmony_ci			(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_WRITEONLY_BIT) == 0);
406e5c31af7Sopenharmony_ci}
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_cistatic bool isWritableInterface (const glu::InterfaceBlock& interface)
409e5c31af7Sopenharmony_ci{
410e5c31af7Sopenharmony_ci	return	interface.storage == glu::STORAGE_OUT		||
411e5c31af7Sopenharmony_ci			interface.storage == glu::STORAGE_PATCH_OUT	||
412e5c31af7Sopenharmony_ci			(interface.storage == glu::STORAGE_BUFFER && (interface.memoryAccessQualifierFlags & glu::MEMORYACCESSQUALIFIER_READONLY_BIT) == 0);
413e5c31af7Sopenharmony_ci}
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_cistatic void writeVariableReadAccumulateExpression (std::ostringstream&							buf,
417e5c31af7Sopenharmony_ci												   const std::string&							accumulatorName,
418e5c31af7Sopenharmony_ci												   const std::string&							name,
419e5c31af7Sopenharmony_ci												   glu::ShaderType								shaderType,
420e5c31af7Sopenharmony_ci												   glu::Storage									storage,
421e5c31af7Sopenharmony_ci												   const ProgramInterfaceDefinition::Program*	program,
422e5c31af7Sopenharmony_ci												   const glu::VarType&							varType)
423e5c31af7Sopenharmony_ci{
424e5c31af7Sopenharmony_ci	if (varType.isBasicType())
425e5c31af7Sopenharmony_ci	{
426e5c31af7Sopenharmony_ci		buf << "\t" << accumulatorName << " += ";
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci		if (glu::isDataTypeScalar(varType.getBasicType()))
429e5c31af7Sopenharmony_ci			buf << "vec4(float(" << name << "))";
430e5c31af7Sopenharmony_ci		else if (glu::isDataTypeVector(varType.getBasicType()))
431e5c31af7Sopenharmony_ci			buf << "vec4(" << name << ".xyxy)";
432e5c31af7Sopenharmony_ci		else if (glu::isDataTypeMatrix(varType.getBasicType()))
433e5c31af7Sopenharmony_ci			buf << "vec4(float(" << name << "[0][0]))";
434e5c31af7Sopenharmony_ci		else if (glu::isDataTypeSamplerMultisample(varType.getBasicType()))
435e5c31af7Sopenharmony_ci			buf << "vec4(float(textureSize(" << name << ").x))";
436e5c31af7Sopenharmony_ci		else if (glu::isDataTypeSampler(varType.getBasicType()))
437e5c31af7Sopenharmony_ci			buf << "vec4(float(textureSize(" << name << ", 0).x))";
438e5c31af7Sopenharmony_ci		else if (glu::isDataTypeImage(varType.getBasicType()))
439e5c31af7Sopenharmony_ci			buf << "vec4(float(imageSize(" << name << ").x))";
440e5c31af7Sopenharmony_ci		else if (varType.getBasicType() == glu::TYPE_UINT_ATOMIC_COUNTER)
441e5c31af7Sopenharmony_ci			buf << "vec4(float(atomicCounterIncrement(" << name << ")))";
442e5c31af7Sopenharmony_ci		else
443e5c31af7Sopenharmony_ci			DE_ASSERT(false);
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ci		buf << ";\n";
446e5c31af7Sopenharmony_ci	}
447e5c31af7Sopenharmony_ci	else if (varType.isStructType())
448e5c31af7Sopenharmony_ci	{
449e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
450e5c31af7Sopenharmony_ci			writeVariableReadAccumulateExpression(buf,
451e5c31af7Sopenharmony_ci												  accumulatorName,
452e5c31af7Sopenharmony_ci												  name + "." + varType.getStructPtr()->getMember(ndx).getName(),
453e5c31af7Sopenharmony_ci												  shaderType,
454e5c31af7Sopenharmony_ci												  storage,
455e5c31af7Sopenharmony_ci												  program,
456e5c31af7Sopenharmony_ci												  varType.getStructPtr()->getMember(ndx).getType());
457e5c31af7Sopenharmony_ci	}
458e5c31af7Sopenharmony_ci	else if (varType.isArrayType())
459e5c31af7Sopenharmony_ci	{
460e5c31af7Sopenharmony_ci		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
461e5c31af7Sopenharmony_ci		{
462e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
463e5c31af7Sopenharmony_ci				writeVariableReadAccumulateExpression(buf,
464e5c31af7Sopenharmony_ci													  accumulatorName,
465e5c31af7Sopenharmony_ci													  name + "[" + de::toString(ndx) + "]",
466e5c31af7Sopenharmony_ci													  shaderType,
467e5c31af7Sopenharmony_ci													  storage,
468e5c31af7Sopenharmony_ci													  program,
469e5c31af7Sopenharmony_ci													  varType.getElementType());
470e5c31af7Sopenharmony_ci		}
471e5c31af7Sopenharmony_ci		else if (storage == glu::STORAGE_BUFFER)
472e5c31af7Sopenharmony_ci		{
473e5c31af7Sopenharmony_ci			// run-time sized array, read arbitrary
474e5c31af7Sopenharmony_ci			writeVariableReadAccumulateExpression(buf,
475e5c31af7Sopenharmony_ci												  accumulatorName,
476e5c31af7Sopenharmony_ci												  name + "[8]",
477e5c31af7Sopenharmony_ci												  shaderType,
478e5c31af7Sopenharmony_ci												  storage,
479e5c31af7Sopenharmony_ci												  program,
480e5c31af7Sopenharmony_ci												  varType.getElementType());
481e5c31af7Sopenharmony_ci		}
482e5c31af7Sopenharmony_ci		else
483e5c31af7Sopenharmony_ci		{
484e5c31af7Sopenharmony_ci			DE_ASSERT(storage == glu::STORAGE_IN);
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci			if (shaderType == glu::SHADERTYPE_GEOMETRY)
487e5c31af7Sopenharmony_ci			{
488e5c31af7Sopenharmony_ci				// implicit sized geometry input array, size = primitive size. Just reading first is enough
489e5c31af7Sopenharmony_ci				writeVariableReadAccumulateExpression(buf,
490e5c31af7Sopenharmony_ci													  accumulatorName,
491e5c31af7Sopenharmony_ci													  name + "[0]",
492e5c31af7Sopenharmony_ci													  shaderType,
493e5c31af7Sopenharmony_ci													  storage,
494e5c31af7Sopenharmony_ci													  program,
495e5c31af7Sopenharmony_ci													  varType.getElementType());
496e5c31af7Sopenharmony_ci			}
497e5c31af7Sopenharmony_ci			else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
498e5c31af7Sopenharmony_ci			{
499e5c31af7Sopenharmony_ci				// implicit sized tessellation input array, size = input patch max size. Just reading current is enough
500e5c31af7Sopenharmony_ci				writeVariableReadAccumulateExpression(buf,
501e5c31af7Sopenharmony_ci													  accumulatorName,
502e5c31af7Sopenharmony_ci													  name + "[gl_InvocationID]",
503e5c31af7Sopenharmony_ci													  shaderType,
504e5c31af7Sopenharmony_ci													  storage,
505e5c31af7Sopenharmony_ci													  program,
506e5c31af7Sopenharmony_ci													  varType.getElementType());
507e5c31af7Sopenharmony_ci			}
508e5c31af7Sopenharmony_ci			else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
509e5c31af7Sopenharmony_ci			{
510e5c31af7Sopenharmony_ci				// implicit sized tessellation input array, size = output patch max size. Read all to prevent optimizations
511e5c31af7Sopenharmony_ci				DE_ASSERT(program->getTessellationNumOutputPatchVertices() > 0);
512e5c31af7Sopenharmony_ci				for (int ndx = 0; ndx < (int)program->getTessellationNumOutputPatchVertices(); ++ndx)
513e5c31af7Sopenharmony_ci				{
514e5c31af7Sopenharmony_ci					writeVariableReadAccumulateExpression(buf,
515e5c31af7Sopenharmony_ci														  accumulatorName,
516e5c31af7Sopenharmony_ci														  name + "[" + de::toString(ndx) + "]",
517e5c31af7Sopenharmony_ci														  shaderType,
518e5c31af7Sopenharmony_ci														  storage,
519e5c31af7Sopenharmony_ci														  program,
520e5c31af7Sopenharmony_ci														  varType.getElementType());
521e5c31af7Sopenharmony_ci				}
522e5c31af7Sopenharmony_ci			}
523e5c31af7Sopenharmony_ci			else
524e5c31af7Sopenharmony_ci				DE_ASSERT(false);
525e5c31af7Sopenharmony_ci		}
526e5c31af7Sopenharmony_ci	}
527e5c31af7Sopenharmony_ci	else
528e5c31af7Sopenharmony_ci		DE_ASSERT(false);
529e5c31af7Sopenharmony_ci}
530e5c31af7Sopenharmony_ci
531e5c31af7Sopenharmony_cistatic void writeInterfaceReadAccumulateExpression (std::ostringstream&							buf,
532e5c31af7Sopenharmony_ci													const std::string&							accumulatorName,
533e5c31af7Sopenharmony_ci													const glu::InterfaceBlock&					block,
534e5c31af7Sopenharmony_ci													glu::ShaderType								shaderType,
535e5c31af7Sopenharmony_ci													const ProgramInterfaceDefinition::Program*	program)
536e5c31af7Sopenharmony_ci{
537e5c31af7Sopenharmony_ci	if (block.dimensions.empty())
538e5c31af7Sopenharmony_ci	{
539e5c31af7Sopenharmony_ci		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
542e5c31af7Sopenharmony_ci		{
543e5c31af7Sopenharmony_ci			writeVariableReadAccumulateExpression(buf,
544e5c31af7Sopenharmony_ci												  accumulatorName,
545e5c31af7Sopenharmony_ci												  prefix + block.variables[ndx].name,
546e5c31af7Sopenharmony_ci												  shaderType,
547e5c31af7Sopenharmony_ci												  block.storage,
548e5c31af7Sopenharmony_ci												  program,
549e5c31af7Sopenharmony_ci												  block.variables[ndx].varType);
550e5c31af7Sopenharmony_ci		}
551e5c31af7Sopenharmony_ci	}
552e5c31af7Sopenharmony_ci	else
553e5c31af7Sopenharmony_ci	{
554e5c31af7Sopenharmony_ci		std::vector<int> index(block.dimensions.size(), 0);
555e5c31af7Sopenharmony_ci
556e5c31af7Sopenharmony_ci		for (;;)
557e5c31af7Sopenharmony_ci		{
558e5c31af7Sopenharmony_ci			// access element
559e5c31af7Sopenharmony_ci			{
560e5c31af7Sopenharmony_ci				std::ostringstream name;
561e5c31af7Sopenharmony_ci				name << block.instanceName;
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
564e5c31af7Sopenharmony_ci					name << "[" << index[dimensionNdx] << "]";
565e5c31af7Sopenharmony_ci
566e5c31af7Sopenharmony_ci				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
567e5c31af7Sopenharmony_ci				{
568e5c31af7Sopenharmony_ci					writeVariableReadAccumulateExpression(buf,
569e5c31af7Sopenharmony_ci														  accumulatorName,
570e5c31af7Sopenharmony_ci														  name.str() + "." + block.variables[ndx].name,
571e5c31af7Sopenharmony_ci														  shaderType,
572e5c31af7Sopenharmony_ci														  block.storage,
573e5c31af7Sopenharmony_ci														  program,
574e5c31af7Sopenharmony_ci														  block.variables[ndx].varType);
575e5c31af7Sopenharmony_ci				}
576e5c31af7Sopenharmony_ci			}
577e5c31af7Sopenharmony_ci
578e5c31af7Sopenharmony_ci			// increment index
579e5c31af7Sopenharmony_ci			if (!incrementMultiDimensionIndex(index, block.dimensions))
580e5c31af7Sopenharmony_ci				break;
581e5c31af7Sopenharmony_ci		}
582e5c31af7Sopenharmony_ci	}
583e5c31af7Sopenharmony_ci}
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_cistatic void writeVariableWriteExpression (std::ostringstream&							buf,
586e5c31af7Sopenharmony_ci										  const std::string&							sourceVec4Name,
587e5c31af7Sopenharmony_ci										  const std::string&							name,
588e5c31af7Sopenharmony_ci										  glu::ShaderType								shaderType,
589e5c31af7Sopenharmony_ci										  glu::Storage									storage,
590e5c31af7Sopenharmony_ci										  const ProgramInterfaceDefinition::Program*	program,
591e5c31af7Sopenharmony_ci										  const glu::VarType&							varType)
592e5c31af7Sopenharmony_ci{
593e5c31af7Sopenharmony_ci	if (varType.isBasicType())
594e5c31af7Sopenharmony_ci	{
595e5c31af7Sopenharmony_ci		buf << "\t" << name << " = ";
596e5c31af7Sopenharmony_ci
597e5c31af7Sopenharmony_ci		if (glu::isDataTypeScalar(varType.getBasicType()))
598e5c31af7Sopenharmony_ci			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << sourceVec4Name << ".y)";
599e5c31af7Sopenharmony_ci		else if (glu::isDataTypeVector(varType.getBasicType()) || glu::isDataTypeMatrix(varType.getBasicType()))
600e5c31af7Sopenharmony_ci			buf << glu::getDataTypeName(varType.getBasicType()) << "(" << glu::getDataTypeName(glu::getDataTypeScalarType(varType.getBasicType())) << "(" << sourceVec4Name << ".y))";
601e5c31af7Sopenharmony_ci		else
602e5c31af7Sopenharmony_ci			DE_ASSERT(false);
603e5c31af7Sopenharmony_ci
604e5c31af7Sopenharmony_ci		buf << ";\n";
605e5c31af7Sopenharmony_ci	}
606e5c31af7Sopenharmony_ci	else if (varType.isStructType())
607e5c31af7Sopenharmony_ci	{
608e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < varType.getStructPtr()->getNumMembers(); ++ndx)
609e5c31af7Sopenharmony_ci			writeVariableWriteExpression(buf,
610e5c31af7Sopenharmony_ci										 sourceVec4Name,
611e5c31af7Sopenharmony_ci										 name + "." + varType.getStructPtr()->getMember(ndx).getName(),
612e5c31af7Sopenharmony_ci										 shaderType,
613e5c31af7Sopenharmony_ci										 storage,
614e5c31af7Sopenharmony_ci										 program,
615e5c31af7Sopenharmony_ci										 varType.getStructPtr()->getMember(ndx).getType());
616e5c31af7Sopenharmony_ci	}
617e5c31af7Sopenharmony_ci	else if (varType.isArrayType())
618e5c31af7Sopenharmony_ci	{
619e5c31af7Sopenharmony_ci		if (varType.getArraySize() != glu::VarType::UNSIZED_ARRAY)
620e5c31af7Sopenharmony_ci		{
621e5c31af7Sopenharmony_ci			for (int ndx = 0; ndx < varType.getArraySize(); ++ndx)
622e5c31af7Sopenharmony_ci				writeVariableWriteExpression(buf,
623e5c31af7Sopenharmony_ci											 sourceVec4Name,
624e5c31af7Sopenharmony_ci											 name + "[" + de::toString(ndx) + "]",
625e5c31af7Sopenharmony_ci											 shaderType,
626e5c31af7Sopenharmony_ci											 storage,
627e5c31af7Sopenharmony_ci											 program,
628e5c31af7Sopenharmony_ci											 varType.getElementType());
629e5c31af7Sopenharmony_ci		}
630e5c31af7Sopenharmony_ci		else if (storage == glu::STORAGE_BUFFER)
631e5c31af7Sopenharmony_ci		{
632e5c31af7Sopenharmony_ci			// run-time sized array, write arbitrary
633e5c31af7Sopenharmony_ci			writeVariableWriteExpression(buf,
634e5c31af7Sopenharmony_ci										 sourceVec4Name,
635e5c31af7Sopenharmony_ci										 name + "[9]",
636e5c31af7Sopenharmony_ci										 shaderType,
637e5c31af7Sopenharmony_ci										 storage,
638e5c31af7Sopenharmony_ci										 program,
639e5c31af7Sopenharmony_ci										 varType.getElementType());
640e5c31af7Sopenharmony_ci		}
641e5c31af7Sopenharmony_ci		else
642e5c31af7Sopenharmony_ci		{
643e5c31af7Sopenharmony_ci			DE_ASSERT(storage == glu::STORAGE_OUT);
644e5c31af7Sopenharmony_ci
645e5c31af7Sopenharmony_ci			if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
646e5c31af7Sopenharmony_ci			{
647e5c31af7Sopenharmony_ci				// implicit sized tessellation onput array, size = output patch max size. Can only write to gl_InvocationID
648e5c31af7Sopenharmony_ci				writeVariableWriteExpression(buf,
649e5c31af7Sopenharmony_ci											 sourceVec4Name,
650e5c31af7Sopenharmony_ci											 name + "[gl_InvocationID]",
651e5c31af7Sopenharmony_ci											 shaderType,
652e5c31af7Sopenharmony_ci											 storage,
653e5c31af7Sopenharmony_ci											 program,
654e5c31af7Sopenharmony_ci											 varType.getElementType());
655e5c31af7Sopenharmony_ci			}
656e5c31af7Sopenharmony_ci			else
657e5c31af7Sopenharmony_ci				DE_ASSERT(false);
658e5c31af7Sopenharmony_ci		}
659e5c31af7Sopenharmony_ci	}
660e5c31af7Sopenharmony_ci	else
661e5c31af7Sopenharmony_ci		DE_ASSERT(false);
662e5c31af7Sopenharmony_ci}
663e5c31af7Sopenharmony_ci
664e5c31af7Sopenharmony_cistatic void writeInterfaceWriteExpression (std::ostringstream&							buf,
665e5c31af7Sopenharmony_ci										   const std::string&							sourceVec4Name,
666e5c31af7Sopenharmony_ci										   const glu::InterfaceBlock&					block,
667e5c31af7Sopenharmony_ci										   glu::ShaderType								shaderType,
668e5c31af7Sopenharmony_ci										   const ProgramInterfaceDefinition::Program*	program)
669e5c31af7Sopenharmony_ci{
670e5c31af7Sopenharmony_ci	if (block.dimensions.empty())
671e5c31af7Sopenharmony_ci	{
672e5c31af7Sopenharmony_ci		const std::string prefix = (block.instanceName.empty()) ? ("") : (block.instanceName + ".");
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
675e5c31af7Sopenharmony_ci		{
676e5c31af7Sopenharmony_ci			writeVariableWriteExpression(buf,
677e5c31af7Sopenharmony_ci										 sourceVec4Name,
678e5c31af7Sopenharmony_ci										 prefix + block.variables[ndx].name,
679e5c31af7Sopenharmony_ci										 shaderType,
680e5c31af7Sopenharmony_ci										 block.storage,
681e5c31af7Sopenharmony_ci										 program,
682e5c31af7Sopenharmony_ci										 block.variables[ndx].varType);
683e5c31af7Sopenharmony_ci		}
684e5c31af7Sopenharmony_ci	}
685e5c31af7Sopenharmony_ci	else
686e5c31af7Sopenharmony_ci	{
687e5c31af7Sopenharmony_ci		std::vector<int> index(block.dimensions.size(), 0);
688e5c31af7Sopenharmony_ci
689e5c31af7Sopenharmony_ci		for (;;)
690e5c31af7Sopenharmony_ci		{
691e5c31af7Sopenharmony_ci			// access element
692e5c31af7Sopenharmony_ci			{
693e5c31af7Sopenharmony_ci				std::ostringstream name;
694e5c31af7Sopenharmony_ci				name << block.instanceName;
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci				for (int dimensionNdx = 0; dimensionNdx < (int)block.dimensions.size(); ++dimensionNdx)
697e5c31af7Sopenharmony_ci					name << "[" << index[dimensionNdx] << "]";
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci				for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
700e5c31af7Sopenharmony_ci				{
701e5c31af7Sopenharmony_ci					writeVariableWriteExpression(buf,
702e5c31af7Sopenharmony_ci												 sourceVec4Name,
703e5c31af7Sopenharmony_ci												 name.str() + "." + block.variables[ndx].name,
704e5c31af7Sopenharmony_ci												 shaderType,
705e5c31af7Sopenharmony_ci												 block.storage,
706e5c31af7Sopenharmony_ci												 program,
707e5c31af7Sopenharmony_ci												 block.variables[ndx].varType);
708e5c31af7Sopenharmony_ci				}
709e5c31af7Sopenharmony_ci			}
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci			// increment index
712e5c31af7Sopenharmony_ci			if (!incrementMultiDimensionIndex(index, block.dimensions))
713e5c31af7Sopenharmony_ci				break;
714e5c31af7Sopenharmony_ci		}
715e5c31af7Sopenharmony_ci	}
716e5c31af7Sopenharmony_ci}
717e5c31af7Sopenharmony_ci
718e5c31af7Sopenharmony_cistatic bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const char* subPath, const glu::VarType& type)
719e5c31af7Sopenharmony_ci{
720e5c31af7Sopenharmony_ci	glu::VarTokenizer tokenizer(subPath);
721e5c31af7Sopenharmony_ci
722e5c31af7Sopenharmony_ci	typePath.push_back(VariablePathComponent(&type));
723e5c31af7Sopenharmony_ci
724e5c31af7Sopenharmony_ci	if (tokenizer.getToken() == glu::VarTokenizer::TOKEN_END)
725e5c31af7Sopenharmony_ci		return true;
726e5c31af7Sopenharmony_ci
727e5c31af7Sopenharmony_ci	if (type.isStructType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_PERIOD)
728e5c31af7Sopenharmony_ci	{
729e5c31af7Sopenharmony_ci		tokenizer.advance();
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci		// malformed path
732e5c31af7Sopenharmony_ci		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_IDENTIFIER)
733e5c31af7Sopenharmony_ci			return false;
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci		for (int memberNdx = 0; memberNdx < type.getStructPtr()->getNumMembers(); ++memberNdx)
736e5c31af7Sopenharmony_ci			if (type.getStructPtr()->getMember(memberNdx).getName() == tokenizer.getIdentifier())
737e5c31af7Sopenharmony_ci				return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getStructPtr()->getMember(memberNdx).getType());
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ci		// malformed path, no such member
740e5c31af7Sopenharmony_ci		return false;
741e5c31af7Sopenharmony_ci	}
742e5c31af7Sopenharmony_ci	else if (type.isArrayType() && tokenizer.getToken() == glu::VarTokenizer::TOKEN_LEFT_BRACKET)
743e5c31af7Sopenharmony_ci	{
744e5c31af7Sopenharmony_ci		tokenizer.advance();
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci		// malformed path
747e5c31af7Sopenharmony_ci		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_NUMBER)
748e5c31af7Sopenharmony_ci			return false;
749e5c31af7Sopenharmony_ci
750e5c31af7Sopenharmony_ci		tokenizer.advance();
751e5c31af7Sopenharmony_ci		if (tokenizer.getToken() != glu::VarTokenizer::TOKEN_RIGHT_BRACKET)
752e5c31af7Sopenharmony_ci			return false;
753e5c31af7Sopenharmony_ci
754e5c31af7Sopenharmony_ci		return traverseVariablePath(typePath, subPath + tokenizer.getCurrentTokenEndLocation(), type.getElementType());
755e5c31af7Sopenharmony_ci	}
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci	return false;
758e5c31af7Sopenharmony_ci}
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_cistatic bool traverseVariablePath (std::vector<VariablePathComponent>& typePath, const std::string& path, const glu::VariableDeclaration& var)
761e5c31af7Sopenharmony_ci{
762e5c31af7Sopenharmony_ci	if (glu::parseVariableName(path.c_str()) != var.name)
763e5c31af7Sopenharmony_ci		return false;
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci	typePath.push_back(VariablePathComponent(&var));
766e5c31af7Sopenharmony_ci	return traverseVariablePath(typePath, path.c_str() + var.name.length(), var.varType);
767e5c31af7Sopenharmony_ci}
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_cistatic bool traverseShaderVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Shader* shader, const std::string& path, const VariableSearchFilter& filter)
770e5c31af7Sopenharmony_ci{
771e5c31af7Sopenharmony_ci	// Default block variable?
772e5c31af7Sopenharmony_ci	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
773e5c31af7Sopenharmony_ci		if (filter.matchesFilter(shader->getDefaultBlock().variables[varNdx]))
774e5c31af7Sopenharmony_ci			if (traverseVariablePath(typePath, path, shader->getDefaultBlock().variables[varNdx]))
775e5c31af7Sopenharmony_ci				return true;
776e5c31af7Sopenharmony_ci
777e5c31af7Sopenharmony_ci	// is variable an interface block variable?
778e5c31af7Sopenharmony_ci	{
779e5c31af7Sopenharmony_ci		const std::string blockName = glu::parseVariableName(path.c_str());
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
782e5c31af7Sopenharmony_ci		{
783e5c31af7Sopenharmony_ci			if (!filter.matchesFilter(shader->getDefaultBlock().interfaceBlocks[interfaceNdx]))
784e5c31af7Sopenharmony_ci				continue;
785e5c31af7Sopenharmony_ci
786e5c31af7Sopenharmony_ci			if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].interfaceName == blockName)
787e5c31af7Sopenharmony_ci			{
788e5c31af7Sopenharmony_ci				// resource is a member of a named interface block
789e5c31af7Sopenharmony_ci				// \note there is no array index specifier even if the interface is declared as an array of instances
790e5c31af7Sopenharmony_ci				const std::string blockMemberPath = path.substr(blockName.size() + 1);
791e5c31af7Sopenharmony_ci				const std::string blockMemeberName = glu::parseVariableName(blockMemberPath.c_str());
792e5c31af7Sopenharmony_ci
793e5c31af7Sopenharmony_ci				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
794e5c31af7Sopenharmony_ci				{
795e5c31af7Sopenharmony_ci					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
796e5c31af7Sopenharmony_ci					{
797e5c31af7Sopenharmony_ci						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
798e5c31af7Sopenharmony_ci						return traverseVariablePath(typePath, blockMemberPath, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
799e5c31af7Sopenharmony_ci					}
800e5c31af7Sopenharmony_ci				}
801e5c31af7Sopenharmony_ci
802e5c31af7Sopenharmony_ci				// terminate search
803e5c31af7Sopenharmony_ci				return false;
804e5c31af7Sopenharmony_ci			}
805e5c31af7Sopenharmony_ci			else if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].instanceName.empty())
806e5c31af7Sopenharmony_ci			{
807e5c31af7Sopenharmony_ci				const std::string blockMemeberName = glu::parseVariableName(path.c_str());
808e5c31af7Sopenharmony_ci
809e5c31af7Sopenharmony_ci				// unnamed block contains such variable?
810e5c31af7Sopenharmony_ci				for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables.size(); ++varNdx)
811e5c31af7Sopenharmony_ci				{
812e5c31af7Sopenharmony_ci					if (shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx].name == blockMemeberName)
813e5c31af7Sopenharmony_ci					{
814e5c31af7Sopenharmony_ci						typePath.push_back(VariablePathComponent(&shader->getDefaultBlock().interfaceBlocks[interfaceNdx]));
815e5c31af7Sopenharmony_ci						return traverseVariablePath(typePath, path, shader->getDefaultBlock().interfaceBlocks[interfaceNdx].variables[varNdx]);
816e5c31af7Sopenharmony_ci					}
817e5c31af7Sopenharmony_ci				}
818e5c31af7Sopenharmony_ci
819e5c31af7Sopenharmony_ci				// continue search
820e5c31af7Sopenharmony_ci			}
821e5c31af7Sopenharmony_ci		}
822e5c31af7Sopenharmony_ci	}
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci	return false;
825e5c31af7Sopenharmony_ci}
826e5c31af7Sopenharmony_ci
827e5c31af7Sopenharmony_cistatic bool traverseProgramVariablePath (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& path, const VariableSearchFilter& filter)
828e5c31af7Sopenharmony_ci{
829e5c31af7Sopenharmony_ci	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
830e5c31af7Sopenharmony_ci	{
831e5c31af7Sopenharmony_ci		const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
832e5c31af7Sopenharmony_ci
833e5c31af7Sopenharmony_ci		if (filter.matchesFilter(shader))
834e5c31af7Sopenharmony_ci		{
835e5c31af7Sopenharmony_ci			// \note modifying output variable even when returning false
836e5c31af7Sopenharmony_ci			typePath.clear();
837e5c31af7Sopenharmony_ci			if (traverseShaderVariablePath(typePath, shader, path, filter))
838e5c31af7Sopenharmony_ci				return true;
839e5c31af7Sopenharmony_ci		}
840e5c31af7Sopenharmony_ci	}
841e5c31af7Sopenharmony_ci
842e5c31af7Sopenharmony_ci	return false;
843e5c31af7Sopenharmony_ci}
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_cistatic bool containsSubType (const glu::VarType& complexType, glu::DataType basicType)
846e5c31af7Sopenharmony_ci{
847e5c31af7Sopenharmony_ci	if (complexType.isBasicType())
848e5c31af7Sopenharmony_ci	{
849e5c31af7Sopenharmony_ci		return complexType.getBasicType() == basicType;
850e5c31af7Sopenharmony_ci	}
851e5c31af7Sopenharmony_ci	else if (complexType.isArrayType())
852e5c31af7Sopenharmony_ci	{
853e5c31af7Sopenharmony_ci		return containsSubType(complexType.getElementType(), basicType);
854e5c31af7Sopenharmony_ci	}
855e5c31af7Sopenharmony_ci	else if (complexType.isStructType())
856e5c31af7Sopenharmony_ci	{
857e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
858e5c31af7Sopenharmony_ci			if (containsSubType(complexType.getStructPtr()->getMember(ndx).getType(), basicType))
859e5c31af7Sopenharmony_ci				return true;
860e5c31af7Sopenharmony_ci		return false;
861e5c31af7Sopenharmony_ci	}
862e5c31af7Sopenharmony_ci	else
863e5c31af7Sopenharmony_ci	{
864e5c31af7Sopenharmony_ci		DE_ASSERT(false);
865e5c31af7Sopenharmony_ci		return false;
866e5c31af7Sopenharmony_ci	}
867e5c31af7Sopenharmony_ci}
868e5c31af7Sopenharmony_ci
869e5c31af7Sopenharmony_cistatic int getNumShaderBlocks (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
870e5c31af7Sopenharmony_ci{
871e5c31af7Sopenharmony_ci	int retVal = 0;
872e5c31af7Sopenharmony_ci
873e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
874e5c31af7Sopenharmony_ci	{
875e5c31af7Sopenharmony_ci		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
876e5c31af7Sopenharmony_ci		{
877e5c31af7Sopenharmony_ci			int numInstances = 1;
878e5c31af7Sopenharmony_ci
879e5c31af7Sopenharmony_ci			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
880e5c31af7Sopenharmony_ci				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
881e5c31af7Sopenharmony_ci
882e5c31af7Sopenharmony_ci			retVal += numInstances;
883e5c31af7Sopenharmony_ci		}
884e5c31af7Sopenharmony_ci	}
885e5c31af7Sopenharmony_ci
886e5c31af7Sopenharmony_ci	return retVal;
887e5c31af7Sopenharmony_ci}
888e5c31af7Sopenharmony_ci
889e5c31af7Sopenharmony_cistatic int getNumAtomicCounterBuffers (const ProgramInterfaceDefinition::Shader* shader)
890e5c31af7Sopenharmony_ci{
891e5c31af7Sopenharmony_ci	std::set<int> buffers;
892e5c31af7Sopenharmony_ci
893e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
894e5c31af7Sopenharmony_ci	{
895e5c31af7Sopenharmony_ci		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
896e5c31af7Sopenharmony_ci		{
897e5c31af7Sopenharmony_ci			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
898e5c31af7Sopenharmony_ci			buffers.insert(shader->getDefaultBlock().variables[ndx].layout.binding);
899e5c31af7Sopenharmony_ci		}
900e5c31af7Sopenharmony_ci	}
901e5c31af7Sopenharmony_ci
902e5c31af7Sopenharmony_ci	return (int)buffers.size();
903e5c31af7Sopenharmony_ci}
904e5c31af7Sopenharmony_ci
905e5c31af7Sopenharmony_citemplate <typename DataTypeMap>
906e5c31af7Sopenharmony_cistatic int accumulateComplexType (const glu::VarType& complexType, const DataTypeMap& dTypeMap)
907e5c31af7Sopenharmony_ci{
908e5c31af7Sopenharmony_ci	if (complexType.isBasicType())
909e5c31af7Sopenharmony_ci		return dTypeMap(complexType.getBasicType());
910e5c31af7Sopenharmony_ci	else if (complexType.isArrayType())
911e5c31af7Sopenharmony_ci	{
912e5c31af7Sopenharmony_ci		const int arraySize = (complexType.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (complexType.getArraySize());
913e5c31af7Sopenharmony_ci		return arraySize * accumulateComplexType(complexType.getElementType(), dTypeMap);
914e5c31af7Sopenharmony_ci	}
915e5c31af7Sopenharmony_ci	else if (complexType.isStructType())
916e5c31af7Sopenharmony_ci	{
917e5c31af7Sopenharmony_ci		int sum = 0;
918e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < complexType.getStructPtr()->getNumMembers(); ++ndx)
919e5c31af7Sopenharmony_ci			sum += accumulateComplexType(complexType.getStructPtr()->getMember(ndx).getType(), dTypeMap);
920e5c31af7Sopenharmony_ci		return sum;
921e5c31af7Sopenharmony_ci	}
922e5c31af7Sopenharmony_ci	else
923e5c31af7Sopenharmony_ci	{
924e5c31af7Sopenharmony_ci		DE_ASSERT(false);
925e5c31af7Sopenharmony_ci		return false;
926e5c31af7Sopenharmony_ci	}
927e5c31af7Sopenharmony_ci}
928e5c31af7Sopenharmony_ci
929e5c31af7Sopenharmony_citemplate <typename InterfaceBlockFilter, typename VarDeclFilter, typename DataTypeMap>
930e5c31af7Sopenharmony_cistatic int accumulateShader (const ProgramInterfaceDefinition::Shader* shader,
931e5c31af7Sopenharmony_ci							 const InterfaceBlockFilter& ibFilter,
932e5c31af7Sopenharmony_ci							 const VarDeclFilter& vdFilter,
933e5c31af7Sopenharmony_ci							 const DataTypeMap& dMap)
934e5c31af7Sopenharmony_ci{
935e5c31af7Sopenharmony_ci	int retVal = 0;
936e5c31af7Sopenharmony_ci
937e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
938e5c31af7Sopenharmony_ci	{
939e5c31af7Sopenharmony_ci		if (ibFilter(shader->getDefaultBlock().interfaceBlocks[ndx]))
940e5c31af7Sopenharmony_ci		{
941e5c31af7Sopenharmony_ci			int numInstances = 1;
942e5c31af7Sopenharmony_ci
943e5c31af7Sopenharmony_ci			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
944e5c31af7Sopenharmony_ci				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
945e5c31af7Sopenharmony_ci
946e5c31af7Sopenharmony_ci			for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].variables.size(); ++varNdx)
947e5c31af7Sopenharmony_ci				retVal += numInstances * accumulateComplexType(shader->getDefaultBlock().interfaceBlocks[ndx].variables[varNdx].varType, dMap);
948e5c31af7Sopenharmony_ci		}
949e5c31af7Sopenharmony_ci	}
950e5c31af7Sopenharmony_ci
951e5c31af7Sopenharmony_ci	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
952e5c31af7Sopenharmony_ci		if (vdFilter(shader->getDefaultBlock().variables[varNdx]))
953e5c31af7Sopenharmony_ci			retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, dMap);
954e5c31af7Sopenharmony_ci
955e5c31af7Sopenharmony_ci	return retVal;
956e5c31af7Sopenharmony_ci}
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_cistatic bool unusedTrueConstantTypeFilter (glu::DataType d)
959e5c31af7Sopenharmony_ci{
960e5c31af7Sopenharmony_ci	DE_UNREF(d);
961e5c31af7Sopenharmony_ci	return true;
962e5c31af7Sopenharmony_ci}
963e5c31af7Sopenharmony_ci
964e5c31af7Sopenharmony_ciclass InstanceCounter
965e5c31af7Sopenharmony_ci{
966e5c31af7Sopenharmony_cipublic:
967e5c31af7Sopenharmony_ci	InstanceCounter (bool (*predicate)(glu::DataType))
968e5c31af7Sopenharmony_ci		: m_predicate(predicate)
969e5c31af7Sopenharmony_ci	{
970e5c31af7Sopenharmony_ci	}
971e5c31af7Sopenharmony_ci
972e5c31af7Sopenharmony_ci	int operator() (glu::DataType t) const
973e5c31af7Sopenharmony_ci	{
974e5c31af7Sopenharmony_ci		return (m_predicate(t)) ? (1) : (0);
975e5c31af7Sopenharmony_ci	}
976e5c31af7Sopenharmony_ci
977e5c31af7Sopenharmony_ciprivate:
978e5c31af7Sopenharmony_ci	bool (*const m_predicate)(glu::DataType);
979e5c31af7Sopenharmony_ci};
980e5c31af7Sopenharmony_ci
981e5c31af7Sopenharmony_ciclass InterfaceBlockStorageFilter
982e5c31af7Sopenharmony_ci{
983e5c31af7Sopenharmony_cipublic:
984e5c31af7Sopenharmony_ci	InterfaceBlockStorageFilter (glu::Storage storage)
985e5c31af7Sopenharmony_ci		: m_storage(storage)
986e5c31af7Sopenharmony_ci	{
987e5c31af7Sopenharmony_ci	}
988e5c31af7Sopenharmony_ci
989e5c31af7Sopenharmony_ci	bool operator() (const glu::InterfaceBlock& b) const
990e5c31af7Sopenharmony_ci	{
991e5c31af7Sopenharmony_ci		return m_storage == b.storage;
992e5c31af7Sopenharmony_ci	}
993e5c31af7Sopenharmony_ci
994e5c31af7Sopenharmony_ciprivate:
995e5c31af7Sopenharmony_ci	const glu::Storage m_storage;
996e5c31af7Sopenharmony_ci};
997e5c31af7Sopenharmony_ci
998e5c31af7Sopenharmony_ciclass VariableDeclarationStorageFilter
999e5c31af7Sopenharmony_ci{
1000e5c31af7Sopenharmony_cipublic:
1001e5c31af7Sopenharmony_ci	VariableDeclarationStorageFilter (glu::Storage storage)
1002e5c31af7Sopenharmony_ci		: m_storage(storage)
1003e5c31af7Sopenharmony_ci	{
1004e5c31af7Sopenharmony_ci	}
1005e5c31af7Sopenharmony_ci
1006e5c31af7Sopenharmony_ci	bool operator() (const glu::VariableDeclaration& d) const
1007e5c31af7Sopenharmony_ci	{
1008e5c31af7Sopenharmony_ci		return m_storage == d.storage;
1009e5c31af7Sopenharmony_ci	}
1010e5c31af7Sopenharmony_ci
1011e5c31af7Sopenharmony_ciprivate:
1012e5c31af7Sopenharmony_ci	const glu::Storage m_storage;
1013e5c31af7Sopenharmony_ci};
1014e5c31af7Sopenharmony_ci
1015e5c31af7Sopenharmony_cistatic int getNumTypeInstances (const glu::VarType& complexType, bool (*predicate)(glu::DataType))
1016e5c31af7Sopenharmony_ci{
1017e5c31af7Sopenharmony_ci	return accumulateComplexType(complexType, InstanceCounter(predicate));
1018e5c31af7Sopenharmony_ci}
1019e5c31af7Sopenharmony_ci
1020e5c31af7Sopenharmony_cistatic int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, bool (*predicate)(glu::DataType))
1021e5c31af7Sopenharmony_ci{
1022e5c31af7Sopenharmony_ci	return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), InstanceCounter(predicate));
1023e5c31af7Sopenharmony_ci}
1024e5c31af7Sopenharmony_ci
1025e5c31af7Sopenharmony_cistatic int getNumTypeInstances (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
1026e5c31af7Sopenharmony_ci{
1027e5c31af7Sopenharmony_ci	return getNumTypeInstances(shader, storage, unusedTrueConstantTypeFilter);
1028e5c31af7Sopenharmony_ci}
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_cistatic int accumulateShaderStorage (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage, int (*typeMap)(glu::DataType))
1031e5c31af7Sopenharmony_ci{
1032e5c31af7Sopenharmony_ci	return accumulateShader(shader, InterfaceBlockStorageFilter(storage), VariableDeclarationStorageFilter(storage), typeMap);
1033e5c31af7Sopenharmony_ci}
1034e5c31af7Sopenharmony_ci
1035e5c31af7Sopenharmony_cistatic int getNumDataTypeComponents (glu::DataType type)
1036e5c31af7Sopenharmony_ci{
1037e5c31af7Sopenharmony_ci	if (glu::isDataTypeScalarOrVector(type) || glu::isDataTypeMatrix(type))
1038e5c31af7Sopenharmony_ci		return glu::getDataTypeScalarSize(type);
1039e5c31af7Sopenharmony_ci	else
1040e5c31af7Sopenharmony_ci		return 0;
1041e5c31af7Sopenharmony_ci}
1042e5c31af7Sopenharmony_ci
1043e5c31af7Sopenharmony_cistatic int getNumDataTypeVectors (glu::DataType type)
1044e5c31af7Sopenharmony_ci{
1045e5c31af7Sopenharmony_ci	if (glu::isDataTypeScalar(type))
1046e5c31af7Sopenharmony_ci		return 1;
1047e5c31af7Sopenharmony_ci	else if (glu::isDataTypeVector(type))
1048e5c31af7Sopenharmony_ci		return 1;
1049e5c31af7Sopenharmony_ci	else if (glu::isDataTypeMatrix(type))
1050e5c31af7Sopenharmony_ci		return glu::getDataTypeMatrixNumColumns(type);
1051e5c31af7Sopenharmony_ci	else
1052e5c31af7Sopenharmony_ci		return 0;
1053e5c31af7Sopenharmony_ci}
1054e5c31af7Sopenharmony_ci
1055e5c31af7Sopenharmony_cistatic int getNumComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
1056e5c31af7Sopenharmony_ci{
1057e5c31af7Sopenharmony_ci	return accumulateShaderStorage(shader, storage, getNumDataTypeComponents);
1058e5c31af7Sopenharmony_ci}
1059e5c31af7Sopenharmony_ci
1060e5c31af7Sopenharmony_cistatic int getNumVectors (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
1061e5c31af7Sopenharmony_ci{
1062e5c31af7Sopenharmony_ci	return accumulateShaderStorage(shader, storage, getNumDataTypeVectors);
1063e5c31af7Sopenharmony_ci}
1064e5c31af7Sopenharmony_ci
1065e5c31af7Sopenharmony_cistatic int getNumDefaultBlockComponents (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
1066e5c31af7Sopenharmony_ci{
1067e5c31af7Sopenharmony_ci	int retVal = 0;
1068e5c31af7Sopenharmony_ci
1069e5c31af7Sopenharmony_ci	for (int varNdx = 0; varNdx < (int)shader->getDefaultBlock().variables.size(); ++varNdx)
1070e5c31af7Sopenharmony_ci		if (shader->getDefaultBlock().variables[varNdx].storage == storage)
1071e5c31af7Sopenharmony_ci			retVal += accumulateComplexType(shader->getDefaultBlock().variables[varNdx].varType, getNumDataTypeComponents);
1072e5c31af7Sopenharmony_ci
1073e5c31af7Sopenharmony_ci	return retVal;
1074e5c31af7Sopenharmony_ci}
1075e5c31af7Sopenharmony_ci
1076e5c31af7Sopenharmony_cistatic int getMaxBufferBinding (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
1077e5c31af7Sopenharmony_ci{
1078e5c31af7Sopenharmony_ci	int maxBinding = -1;
1079e5c31af7Sopenharmony_ci
1080e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
1081e5c31af7Sopenharmony_ci	{
1082e5c31af7Sopenharmony_ci		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
1083e5c31af7Sopenharmony_ci		{
1084e5c31af7Sopenharmony_ci			const int	binding			= (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().interfaceBlocks[ndx].layout.binding);
1085e5c31af7Sopenharmony_ci			int			numInstances	= 1;
1086e5c31af7Sopenharmony_ci
1087e5c31af7Sopenharmony_ci			for (int dimensionNdx = 0; dimensionNdx < (int)shader->getDefaultBlock().interfaceBlocks[ndx].dimensions.size(); ++dimensionNdx)
1088e5c31af7Sopenharmony_ci				numInstances *= shader->getDefaultBlock().interfaceBlocks[ndx].dimensions[dimensionNdx];
1089e5c31af7Sopenharmony_ci
1090e5c31af7Sopenharmony_ci			maxBinding = de::max(maxBinding, binding + numInstances - 1);
1091e5c31af7Sopenharmony_ci		}
1092e5c31af7Sopenharmony_ci	}
1093e5c31af7Sopenharmony_ci
1094e5c31af7Sopenharmony_ci	return (int)maxBinding;
1095e5c31af7Sopenharmony_ci}
1096e5c31af7Sopenharmony_ci
1097e5c31af7Sopenharmony_cistatic int getBufferTypeSize (glu::DataType type, glu::MatrixOrder order)
1098e5c31af7Sopenharmony_ci{
1099e5c31af7Sopenharmony_ci	// assume vec4 alignments, should produce values greater than or equal to the actual resource usage
1100e5c31af7Sopenharmony_ci	int numVectors = 0;
1101e5c31af7Sopenharmony_ci
1102e5c31af7Sopenharmony_ci	if (glu::isDataTypeScalarOrVector(type))
1103e5c31af7Sopenharmony_ci		numVectors = 1;
1104e5c31af7Sopenharmony_ci	else if (glu::isDataTypeMatrix(type) && order == glu::MATRIXORDER_ROW_MAJOR)
1105e5c31af7Sopenharmony_ci		numVectors = glu::getDataTypeMatrixNumRows(type);
1106e5c31af7Sopenharmony_ci	else if (glu::isDataTypeMatrix(type) && order != glu::MATRIXORDER_ROW_MAJOR)
1107e5c31af7Sopenharmony_ci		numVectors = glu::getDataTypeMatrixNumColumns(type);
1108e5c31af7Sopenharmony_ci	else
1109e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1110e5c31af7Sopenharmony_ci
1111e5c31af7Sopenharmony_ci	return 4 * numVectors;
1112e5c31af7Sopenharmony_ci}
1113e5c31af7Sopenharmony_ci
1114e5c31af7Sopenharmony_cistatic int getBufferVariableSize (const glu::VarType& type, glu::MatrixOrder order)
1115e5c31af7Sopenharmony_ci{
1116e5c31af7Sopenharmony_ci	if (type.isBasicType())
1117e5c31af7Sopenharmony_ci		return getBufferTypeSize(type.getBasicType(), order);
1118e5c31af7Sopenharmony_ci	else if (type.isArrayType())
1119e5c31af7Sopenharmony_ci	{
1120e5c31af7Sopenharmony_ci		const int arraySize = (type.getArraySize() == glu::VarType::UNSIZED_ARRAY) ? (1) : (type.getArraySize());
1121e5c31af7Sopenharmony_ci		return arraySize * getBufferVariableSize(type.getElementType(), order);
1122e5c31af7Sopenharmony_ci	}
1123e5c31af7Sopenharmony_ci	else if (type.isStructType())
1124e5c31af7Sopenharmony_ci	{
1125e5c31af7Sopenharmony_ci		int sum = 0;
1126e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < type.getStructPtr()->getNumMembers(); ++ndx)
1127e5c31af7Sopenharmony_ci			sum += getBufferVariableSize(type.getStructPtr()->getMember(ndx).getType(), order);
1128e5c31af7Sopenharmony_ci		return sum;
1129e5c31af7Sopenharmony_ci	}
1130e5c31af7Sopenharmony_ci	else
1131e5c31af7Sopenharmony_ci	{
1132e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1133e5c31af7Sopenharmony_ci		return false;
1134e5c31af7Sopenharmony_ci	}
1135e5c31af7Sopenharmony_ci}
1136e5c31af7Sopenharmony_ci
1137e5c31af7Sopenharmony_cistatic int getBufferSize (const glu::InterfaceBlock& block, glu::MatrixOrder blockOrder)
1138e5c31af7Sopenharmony_ci{
1139e5c31af7Sopenharmony_ci	int size = 0;
1140e5c31af7Sopenharmony_ci
1141e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)block.variables.size(); ++ndx)
1142e5c31af7Sopenharmony_ci		size += getBufferVariableSize(block.variables[ndx].varType, (block.variables[ndx].layout.matrixOrder == glu::MATRIXORDER_LAST) ? (blockOrder) : (block.variables[ndx].layout.matrixOrder));
1143e5c31af7Sopenharmony_ci
1144e5c31af7Sopenharmony_ci	return size;
1145e5c31af7Sopenharmony_ci}
1146e5c31af7Sopenharmony_ci
1147e5c31af7Sopenharmony_cistatic int getBufferMaxSize (const ProgramInterfaceDefinition::Shader* shader, glu::Storage storage)
1148e5c31af7Sopenharmony_ci{
1149e5c31af7Sopenharmony_ci	int maxSize = 0;
1150e5c31af7Sopenharmony_ci
1151e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
1152e5c31af7Sopenharmony_ci		if (shader->getDefaultBlock().interfaceBlocks[ndx].storage == storage)
1153e5c31af7Sopenharmony_ci			maxSize = de::max(maxSize, getBufferSize(shader->getDefaultBlock().interfaceBlocks[ndx], shader->getDefaultBlock().interfaceBlocks[ndx].layout.matrixOrder));
1154e5c31af7Sopenharmony_ci
1155e5c31af7Sopenharmony_ci	return (int)maxSize;
1156e5c31af7Sopenharmony_ci}
1157e5c31af7Sopenharmony_ci
1158e5c31af7Sopenharmony_cistatic int getAtomicCounterMaxBinding (const ProgramInterfaceDefinition::Shader* shader)
1159e5c31af7Sopenharmony_ci{
1160e5c31af7Sopenharmony_ci	int maxBinding = -1;
1161e5c31af7Sopenharmony_ci
1162e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1163e5c31af7Sopenharmony_ci	{
1164e5c31af7Sopenharmony_ci		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
1165e5c31af7Sopenharmony_ci		{
1166e5c31af7Sopenharmony_ci			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
1167e5c31af7Sopenharmony_ci			maxBinding = de::max(maxBinding, shader->getDefaultBlock().variables[ndx].layout.binding);
1168e5c31af7Sopenharmony_ci		}
1169e5c31af7Sopenharmony_ci	}
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ci	return (int)maxBinding;
1172e5c31af7Sopenharmony_ci}
1173e5c31af7Sopenharmony_ci
1174e5c31af7Sopenharmony_cistatic int getUniformMaxBinding (const ProgramInterfaceDefinition::Shader* shader, bool (*predicate)(glu::DataType))
1175e5c31af7Sopenharmony_ci{
1176e5c31af7Sopenharmony_ci	int maxBinding = -1;
1177e5c31af7Sopenharmony_ci
1178e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1179e5c31af7Sopenharmony_ci	{
1180e5c31af7Sopenharmony_ci		const int binding		= (shader->getDefaultBlock().variables[ndx].layout.binding == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.binding);
1181e5c31af7Sopenharmony_ci		const int numInstances	= getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, predicate);
1182e5c31af7Sopenharmony_ci
1183e5c31af7Sopenharmony_ci		maxBinding = de::max(maxBinding, binding + numInstances - 1);
1184e5c31af7Sopenharmony_ci	}
1185e5c31af7Sopenharmony_ci
1186e5c31af7Sopenharmony_ci	return maxBinding;
1187e5c31af7Sopenharmony_ci}
1188e5c31af7Sopenharmony_ci
1189e5c31af7Sopenharmony_cistatic int getAtomicCounterMaxBufferSize (const ProgramInterfaceDefinition::Shader* shader)
1190e5c31af7Sopenharmony_ci{
1191e5c31af7Sopenharmony_ci	std::map<int, int>	bufferSizes;
1192e5c31af7Sopenharmony_ci	int					maxSize			= 0;
1193e5c31af7Sopenharmony_ci
1194e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1195e5c31af7Sopenharmony_ci	{
1196e5c31af7Sopenharmony_ci		if (containsSubType(shader->getDefaultBlock().variables[ndx].varType, glu::TYPE_UINT_ATOMIC_COUNTER))
1197e5c31af7Sopenharmony_ci		{
1198e5c31af7Sopenharmony_ci			const int bufferBinding	= shader->getDefaultBlock().variables[ndx].layout.binding;
1199e5c31af7Sopenharmony_ci			const int offset		= (shader->getDefaultBlock().variables[ndx].layout.offset == -1) ? (0) : (shader->getDefaultBlock().variables[ndx].layout.offset);
1200e5c31af7Sopenharmony_ci			const int size			= offset + 4 * getNumTypeInstances(shader->getDefaultBlock().variables[ndx].varType, glu::isDataTypeAtomicCounter);
1201e5c31af7Sopenharmony_ci
1202e5c31af7Sopenharmony_ci			DE_ASSERT(shader->getDefaultBlock().variables[ndx].layout.binding != -1);
1203e5c31af7Sopenharmony_ci
1204e5c31af7Sopenharmony_ci			if (bufferSizes.find(bufferBinding) == bufferSizes.end())
1205e5c31af7Sopenharmony_ci				bufferSizes[bufferBinding] = size;
1206e5c31af7Sopenharmony_ci			else
1207e5c31af7Sopenharmony_ci				bufferSizes[bufferBinding] = de::max<int>(bufferSizes[bufferBinding], size);
1208e5c31af7Sopenharmony_ci		}
1209e5c31af7Sopenharmony_ci	}
1210e5c31af7Sopenharmony_ci
1211e5c31af7Sopenharmony_ci	for (std::map<int, int>::iterator it = bufferSizes.begin(); it != bufferSizes.end(); ++it)
1212e5c31af7Sopenharmony_ci		maxSize = de::max<int>(maxSize, it->second);
1213e5c31af7Sopenharmony_ci
1214e5c31af7Sopenharmony_ci	return maxSize;
1215e5c31af7Sopenharmony_ci}
1216e5c31af7Sopenharmony_ci
1217e5c31af7Sopenharmony_cistatic int getNumFeedbackVaryingComponents (const ProgramInterfaceDefinition::Program* program, const std::string& name)
1218e5c31af7Sopenharmony_ci{
1219e5c31af7Sopenharmony_ci	std::vector<VariablePathComponent> path;
1220e5c31af7Sopenharmony_ci
1221e5c31af7Sopenharmony_ci	if (name == "gl_Position")
1222e5c31af7Sopenharmony_ci		return 4;
1223e5c31af7Sopenharmony_ci
1224e5c31af7Sopenharmony_ci	DE_ASSERT(deStringBeginsWith(name.c_str(), "gl_") == DE_FALSE);
1225e5c31af7Sopenharmony_ci
1226e5c31af7Sopenharmony_ci	if (!traverseProgramVariablePath(path, program, name, VariableSearchFilter::createShaderTypeStorageFilter(getProgramTransformFeedbackStage(program), glu::STORAGE_OUT)))
1227e5c31af7Sopenharmony_ci		DE_ASSERT(false); // Program failed validate, invalid operation
1228e5c31af7Sopenharmony_ci
1229e5c31af7Sopenharmony_ci	return accumulateComplexType(*path.back().getVariableType(), getNumDataTypeComponents);
1230e5c31af7Sopenharmony_ci}
1231e5c31af7Sopenharmony_ci
1232e5c31af7Sopenharmony_cistatic int getNumXFBComponents (const ProgramInterfaceDefinition::Program* program)
1233e5c31af7Sopenharmony_ci{
1234e5c31af7Sopenharmony_ci	int numComponents = 0;
1235e5c31af7Sopenharmony_ci
1236e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
1237e5c31af7Sopenharmony_ci		numComponents += getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]);
1238e5c31af7Sopenharmony_ci
1239e5c31af7Sopenharmony_ci	return numComponents;
1240e5c31af7Sopenharmony_ci}
1241e5c31af7Sopenharmony_ci
1242e5c31af7Sopenharmony_cistatic int getNumMaxXFBOutputComponents (const ProgramInterfaceDefinition::Program* program)
1243e5c31af7Sopenharmony_ci{
1244e5c31af7Sopenharmony_ci	int numComponents = 0;
1245e5c31af7Sopenharmony_ci
1246e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
1247e5c31af7Sopenharmony_ci		numComponents = de::max(numComponents, getNumFeedbackVaryingComponents(program, program->getTransformFeedbackVaryings()[ndx]));
1248e5c31af7Sopenharmony_ci
1249e5c31af7Sopenharmony_ci	return numComponents;
1250e5c31af7Sopenharmony_ci}
1251e5c31af7Sopenharmony_ci
1252e5c31af7Sopenharmony_cistatic int getFragmentOutputMaxLocation (const ProgramInterfaceDefinition::Shader* shader)
1253e5c31af7Sopenharmony_ci{
1254e5c31af7Sopenharmony_ci	DE_ASSERT(shader->getType() == glu::SHADERTYPE_FRAGMENT);
1255e5c31af7Sopenharmony_ci
1256e5c31af7Sopenharmony_ci	int maxOutputLocation = -1;
1257e5c31af7Sopenharmony_ci
1258e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1259e5c31af7Sopenharmony_ci	{
1260e5c31af7Sopenharmony_ci		if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT)
1261e5c31af7Sopenharmony_ci		{
1262e5c31af7Sopenharmony_ci			// missing location qualifier means location == 0
1263e5c31af7Sopenharmony_ci			const int outputLocation		= (shader->getDefaultBlock().variables[ndx].layout.location == -1)
1264e5c31af7Sopenharmony_ci												? (0)
1265e5c31af7Sopenharmony_ci												: (shader->getDefaultBlock().variables[ndx].layout.location);
1266e5c31af7Sopenharmony_ci
1267e5c31af7Sopenharmony_ci			// only basic types or arrays of basic types possible
1268e5c31af7Sopenharmony_ci			DE_ASSERT(!shader->getDefaultBlock().variables[ndx].varType.isStructType());
1269e5c31af7Sopenharmony_ci
1270e5c31af7Sopenharmony_ci			const int locationSlotsTaken	= (shader->getDefaultBlock().variables[ndx].varType.isArrayType())
1271e5c31af7Sopenharmony_ci												? (shader->getDefaultBlock().variables[ndx].varType.getArraySize())
1272e5c31af7Sopenharmony_ci												: (1);
1273e5c31af7Sopenharmony_ci
1274e5c31af7Sopenharmony_ci			maxOutputLocation = de::max(maxOutputLocation, outputLocation + locationSlotsTaken - 1);
1275e5c31af7Sopenharmony_ci		}
1276e5c31af7Sopenharmony_ci	}
1277e5c31af7Sopenharmony_ci
1278e5c31af7Sopenharmony_ci	return maxOutputLocation;
1279e5c31af7Sopenharmony_ci}
1280e5c31af7Sopenharmony_ci
1281e5c31af7Sopenharmony_ci} // anonymous
1282e5c31af7Sopenharmony_ci
1283e5c31af7Sopenharmony_cistd::vector<std::string> getProgramInterfaceBlockMemberResourceList (const glu::InterfaceBlock& interfaceBlock)
1284e5c31af7Sopenharmony_ci{
1285e5c31af7Sopenharmony_ci	const std::string			namePrefix					= (!interfaceBlock.instanceName.empty()) ? (interfaceBlock.interfaceName + ".") : ("");
1286e5c31af7Sopenharmony_ci	const bool					isTopLevelBufferVariable	= (interfaceBlock.storage == glu::STORAGE_BUFFER);
1287e5c31af7Sopenharmony_ci	std::vector<std::string>	resources;
1288e5c31af7Sopenharmony_ci
1289e5c31af7Sopenharmony_ci	// \note this is defined in the GLSL spec, not in the GL spec
1290e5c31af7Sopenharmony_ci	for (int variableNdx = 0; variableNdx < (int)interfaceBlock.variables.size(); ++variableNdx)
1291e5c31af7Sopenharmony_ci		generateVariableTypeResourceNames(resources,
1292e5c31af7Sopenharmony_ci										  namePrefix + interfaceBlock.variables[variableNdx].name,
1293e5c31af7Sopenharmony_ci										  interfaceBlock.variables[variableNdx].varType,
1294e5c31af7Sopenharmony_ci										  (isTopLevelBufferVariable) ?
1295e5c31af7Sopenharmony_ci											(RESOURCE_NAME_GENERATION_FLAG_TOP_LEVEL_BUFFER_VARIABLE) :
1296e5c31af7Sopenharmony_ci											(RESOURCE_NAME_GENERATION_FLAG_DEFAULT));
1297e5c31af7Sopenharmony_ci
1298e5c31af7Sopenharmony_ci	return resources;
1299e5c31af7Sopenharmony_ci}
1300e5c31af7Sopenharmony_ci
1301e5c31af7Sopenharmony_cistd::vector<std::string> getProgramInterfaceResourceList (const ProgramInterfaceDefinition::Program* program, ProgramInterface interface)
1302e5c31af7Sopenharmony_ci{
1303e5c31af7Sopenharmony_ci	// The same {uniform (block), buffer (variable)} can exist in multiple shaders, remove duplicates but keep order
1304e5c31af7Sopenharmony_ci	const bool					removeDuplicated	= (interface == PROGRAMINTERFACE_UNIFORM)			||
1305e5c31af7Sopenharmony_ci													  (interface == PROGRAMINTERFACE_UNIFORM_BLOCK)		||
1306e5c31af7Sopenharmony_ci													  (interface == PROGRAMINTERFACE_BUFFER_VARIABLE)	||
1307e5c31af7Sopenharmony_ci													  (interface == PROGRAMINTERFACE_SHADER_STORAGE_BLOCK);
1308e5c31af7Sopenharmony_ci	std::vector<std::string>	resources;
1309e5c31af7Sopenharmony_ci
1310e5c31af7Sopenharmony_ci	switch (interface)
1311e5c31af7Sopenharmony_ci	{
1312e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_UNIFORM:
1313e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_BUFFER_VARIABLE:
1314e5c31af7Sopenharmony_ci		{
1315e5c31af7Sopenharmony_ci			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
1316e5c31af7Sopenharmony_ci
1317e5c31af7Sopenharmony_ci			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
1318e5c31af7Sopenharmony_ci			{
1319e5c31af7Sopenharmony_ci				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
1320e5c31af7Sopenharmony_ci
1321e5c31af7Sopenharmony_ci				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
1322e5c31af7Sopenharmony_ci					if (shader->getDefaultBlock().variables[variableNdx].storage == storage)
1323e5c31af7Sopenharmony_ci						generateVariableTypeResourceNames(resources,
1324e5c31af7Sopenharmony_ci														  shader->getDefaultBlock().variables[variableNdx].name,
1325e5c31af7Sopenharmony_ci														  shader->getDefaultBlock().variables[variableNdx].varType,
1326e5c31af7Sopenharmony_ci														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
1327e5c31af7Sopenharmony_ci
1328e5c31af7Sopenharmony_ci				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
1329e5c31af7Sopenharmony_ci				{
1330e5c31af7Sopenharmony_ci					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
1331e5c31af7Sopenharmony_ci					if (interfaceBlock.storage == storage)
1332e5c31af7Sopenharmony_ci					{
1333e5c31af7Sopenharmony_ci						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
1334e5c31af7Sopenharmony_ci						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
1335e5c31af7Sopenharmony_ci					}
1336e5c31af7Sopenharmony_ci				}
1337e5c31af7Sopenharmony_ci			}
1338e5c31af7Sopenharmony_ci			break;
1339e5c31af7Sopenharmony_ci		}
1340e5c31af7Sopenharmony_ci
1341e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_UNIFORM_BLOCK:
1342e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_SHADER_STORAGE_BLOCK:
1343e5c31af7Sopenharmony_ci		{
1344e5c31af7Sopenharmony_ci			const glu::Storage storage = (interface == PROGRAMINTERFACE_UNIFORM_BLOCK) ? (glu::STORAGE_UNIFORM) : (glu::STORAGE_BUFFER);
1345e5c31af7Sopenharmony_ci
1346e5c31af7Sopenharmony_ci			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
1347e5c31af7Sopenharmony_ci			{
1348e5c31af7Sopenharmony_ci				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
1349e5c31af7Sopenharmony_ci				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
1350e5c31af7Sopenharmony_ci				{
1351e5c31af7Sopenharmony_ci					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
1352e5c31af7Sopenharmony_ci					if (interfaceBlock.storage == storage)
1353e5c31af7Sopenharmony_ci					{
1354e5c31af7Sopenharmony_ci						std::vector<int> index(interfaceBlock.dimensions.size(), 0);
1355e5c31af7Sopenharmony_ci
1356e5c31af7Sopenharmony_ci						for (;;)
1357e5c31af7Sopenharmony_ci						{
1358e5c31af7Sopenharmony_ci							// add resource string for each element
1359e5c31af7Sopenharmony_ci							{
1360e5c31af7Sopenharmony_ci								std::ostringstream name;
1361e5c31af7Sopenharmony_ci								name << interfaceBlock.interfaceName;
1362e5c31af7Sopenharmony_ci
1363e5c31af7Sopenharmony_ci								for (int dimensionNdx = 0; dimensionNdx < (int)interfaceBlock.dimensions.size(); ++dimensionNdx)
1364e5c31af7Sopenharmony_ci									name << "[" << index[dimensionNdx] << "]";
1365e5c31af7Sopenharmony_ci
1366e5c31af7Sopenharmony_ci								resources.push_back(name.str());
1367e5c31af7Sopenharmony_ci							}
1368e5c31af7Sopenharmony_ci
1369e5c31af7Sopenharmony_ci							// increment index
1370e5c31af7Sopenharmony_ci							if (!incrementMultiDimensionIndex(index, interfaceBlock.dimensions))
1371e5c31af7Sopenharmony_ci								break;
1372e5c31af7Sopenharmony_ci						}
1373e5c31af7Sopenharmony_ci					}
1374e5c31af7Sopenharmony_ci				}
1375e5c31af7Sopenharmony_ci			}
1376e5c31af7Sopenharmony_ci			break;
1377e5c31af7Sopenharmony_ci		}
1378e5c31af7Sopenharmony_ci
1379e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_PROGRAM_INPUT:
1380e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_PROGRAM_OUTPUT:
1381e5c31af7Sopenharmony_ci		{
1382e5c31af7Sopenharmony_ci			const glu::Storage		queryStorage		= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_IN) : (glu::STORAGE_OUT);
1383e5c31af7Sopenharmony_ci			const glu::Storage		queryPatchStorage	= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (glu::STORAGE_PATCH_IN) : (glu::STORAGE_PATCH_OUT);
1384e5c31af7Sopenharmony_ci			const glu::ShaderType	shaderType			= (interface == PROGRAMINTERFACE_PROGRAM_INPUT) ? (program->getFirstStage()) : (program->getLastStage());
1385e5c31af7Sopenharmony_ci
1386e5c31af7Sopenharmony_ci			for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
1387e5c31af7Sopenharmony_ci			{
1388e5c31af7Sopenharmony_ci				const ProgramInterfaceDefinition::Shader* shader = program->getShaders()[shaderNdx];
1389e5c31af7Sopenharmony_ci
1390e5c31af7Sopenharmony_ci				if (shader->getType() != shaderType)
1391e5c31af7Sopenharmony_ci					continue;
1392e5c31af7Sopenharmony_ci
1393e5c31af7Sopenharmony_ci				for (int variableNdx = 0; variableNdx < (int)shader->getDefaultBlock().variables.size(); ++variableNdx)
1394e5c31af7Sopenharmony_ci				{
1395e5c31af7Sopenharmony_ci					const glu::Storage variableStorage = shader->getDefaultBlock().variables[variableNdx].storage;
1396e5c31af7Sopenharmony_ci					if (variableStorage == queryStorage || variableStorage == queryPatchStorage)
1397e5c31af7Sopenharmony_ci						generateVariableTypeResourceNames(resources,
1398e5c31af7Sopenharmony_ci														  shader->getDefaultBlock().variables[variableNdx].name,
1399e5c31af7Sopenharmony_ci														  shader->getDefaultBlock().variables[variableNdx].varType,
1400e5c31af7Sopenharmony_ci														  RESOURCE_NAME_GENERATION_FLAG_DEFAULT);
1401e5c31af7Sopenharmony_ci				}
1402e5c31af7Sopenharmony_ci
1403e5c31af7Sopenharmony_ci				for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
1404e5c31af7Sopenharmony_ci				{
1405e5c31af7Sopenharmony_ci					const glu::InterfaceBlock& interfaceBlock = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
1406e5c31af7Sopenharmony_ci					if (interfaceBlock.storage == queryStorage || interfaceBlock.storage == queryPatchStorage)
1407e5c31af7Sopenharmony_ci					{
1408e5c31af7Sopenharmony_ci						const std::vector<std::string> blockResources = getProgramInterfaceBlockMemberResourceList(interfaceBlock);
1409e5c31af7Sopenharmony_ci						resources.insert(resources.end(), blockResources.begin(), blockResources.end());
1410e5c31af7Sopenharmony_ci					}
1411e5c31af7Sopenharmony_ci				}
1412e5c31af7Sopenharmony_ci			}
1413e5c31af7Sopenharmony_ci
1414e5c31af7Sopenharmony_ci			// built-ins
1415e5c31af7Sopenharmony_ci			if (interface == PROGRAMINTERFACE_PROGRAM_INPUT)
1416e5c31af7Sopenharmony_ci			{
1417e5c31af7Sopenharmony_ci				if (shaderType == glu::SHADERTYPE_VERTEX && resources.empty())
1418e5c31af7Sopenharmony_ci					resources.push_back("gl_VertexID"); // only read from when there are no other inputs
1419e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
1420e5c31af7Sopenharmony_ci					resources.push_back("gl_FragCoord"); // only read from when there are no other inputs
1421e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
1422e5c31af7Sopenharmony_ci					resources.push_back("gl_PerVertex.gl_Position");
1423e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
1424e5c31af7Sopenharmony_ci				{
1425e5c31af7Sopenharmony_ci					resources.push_back("gl_InvocationID");
1426e5c31af7Sopenharmony_ci					resources.push_back("gl_PerVertex.gl_Position");
1427e5c31af7Sopenharmony_ci				}
1428e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
1429e5c31af7Sopenharmony_ci					resources.push_back("gl_PerVertex.gl_Position");
1430e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_COMPUTE && resources.empty())
1431e5c31af7Sopenharmony_ci					resources.push_back("gl_NumWorkGroups"); // only read from when there are no other inputs
1432e5c31af7Sopenharmony_ci			}
1433e5c31af7Sopenharmony_ci			else if (interface == PROGRAMINTERFACE_PROGRAM_OUTPUT)
1434e5c31af7Sopenharmony_ci			{
1435e5c31af7Sopenharmony_ci				if (shaderType == glu::SHADERTYPE_VERTEX)
1436e5c31af7Sopenharmony_ci					resources.push_back("gl_Position");
1437e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_FRAGMENT && resources.empty())
1438e5c31af7Sopenharmony_ci					resources.push_back("gl_FragDepth"); // only written to when there are no other outputs
1439e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_GEOMETRY)
1440e5c31af7Sopenharmony_ci					resources.push_back("gl_Position");
1441e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
1442e5c31af7Sopenharmony_ci				{
1443e5c31af7Sopenharmony_ci					resources.push_back("gl_PerVertex.gl_Position");
1444e5c31af7Sopenharmony_ci					resources.push_back("gl_TessLevelOuter[0]");
1445e5c31af7Sopenharmony_ci					resources.push_back("gl_TessLevelInner[0]");
1446e5c31af7Sopenharmony_ci				}
1447e5c31af7Sopenharmony_ci				else if (shaderType == glu::SHADERTYPE_TESSELLATION_EVALUATION)
1448e5c31af7Sopenharmony_ci					resources.push_back("gl_Position");
1449e5c31af7Sopenharmony_ci			}
1450e5c31af7Sopenharmony_ci
1451e5c31af7Sopenharmony_ci			break;
1452e5c31af7Sopenharmony_ci		}
1453e5c31af7Sopenharmony_ci
1454e5c31af7Sopenharmony_ci		case PROGRAMINTERFACE_TRANSFORM_FEEDBACK_VARYING:
1455e5c31af7Sopenharmony_ci		{
1456e5c31af7Sopenharmony_ci			const glu::ShaderType xfbStage = getProgramTransformFeedbackStage(program);
1457e5c31af7Sopenharmony_ci
1458e5c31af7Sopenharmony_ci			for (int varyingNdx = 0; varyingNdx < (int)program->getTransformFeedbackVaryings().size(); ++varyingNdx)
1459e5c31af7Sopenharmony_ci			{
1460e5c31af7Sopenharmony_ci				const std::string& varyingName = program->getTransformFeedbackVaryings()[varyingNdx];
1461e5c31af7Sopenharmony_ci
1462e5c31af7Sopenharmony_ci				if (deStringBeginsWith(varyingName.c_str(), "gl_"))
1463e5c31af7Sopenharmony_ci					resources.push_back(varyingName); // builtin
1464e5c31af7Sopenharmony_ci				else
1465e5c31af7Sopenharmony_ci				{
1466e5c31af7Sopenharmony_ci					std::vector<VariablePathComponent> path;
1467e5c31af7Sopenharmony_ci
1468e5c31af7Sopenharmony_ci					if (!traverseProgramVariablePath(path, program, varyingName, VariableSearchFilter::createShaderTypeStorageFilter(xfbStage, glu::STORAGE_OUT)))
1469e5c31af7Sopenharmony_ci						DE_ASSERT(false); // Program failed validate, invalid operation
1470e5c31af7Sopenharmony_ci
1471e5c31af7Sopenharmony_ci					generateVariableTypeResourceNames(resources,
1472e5c31af7Sopenharmony_ci													  varyingName,
1473e5c31af7Sopenharmony_ci													  *path.back().getVariableType(),
1474e5c31af7Sopenharmony_ci													  RESOURCE_NAME_GENERATION_FLAG_TRANSFORM_FEEDBACK_VARIABLE);
1475e5c31af7Sopenharmony_ci				}
1476e5c31af7Sopenharmony_ci			}
1477e5c31af7Sopenharmony_ci
1478e5c31af7Sopenharmony_ci			break;
1479e5c31af7Sopenharmony_ci		}
1480e5c31af7Sopenharmony_ci
1481e5c31af7Sopenharmony_ci		default:
1482e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1483e5c31af7Sopenharmony_ci	}
1484e5c31af7Sopenharmony_ci
1485e5c31af7Sopenharmony_ci	if (removeDuplicated)
1486e5c31af7Sopenharmony_ci	{
1487e5c31af7Sopenharmony_ci		std::set<std::string>		addedVariables;
1488e5c31af7Sopenharmony_ci		std::vector<std::string>	uniqueResouces;
1489e5c31af7Sopenharmony_ci
1490e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)resources.size(); ++ndx)
1491e5c31af7Sopenharmony_ci		{
1492e5c31af7Sopenharmony_ci			if (addedVariables.find(resources[ndx]) == addedVariables.end())
1493e5c31af7Sopenharmony_ci			{
1494e5c31af7Sopenharmony_ci				addedVariables.insert(resources[ndx]);
1495e5c31af7Sopenharmony_ci				uniqueResouces.push_back(resources[ndx]);
1496e5c31af7Sopenharmony_ci			}
1497e5c31af7Sopenharmony_ci		}
1498e5c31af7Sopenharmony_ci
1499e5c31af7Sopenharmony_ci		uniqueResouces.swap(resources);
1500e5c31af7Sopenharmony_ci	}
1501e5c31af7Sopenharmony_ci
1502e5c31af7Sopenharmony_ci	return resources;
1503e5c31af7Sopenharmony_ci}
1504e5c31af7Sopenharmony_ci
1505e5c31af7Sopenharmony_ci/**
1506e5c31af7Sopenharmony_ci * Name of the unused uniform added by generateProgramInterfaceProgramSources
1507e5c31af7Sopenharmony_ci *
1508e5c31af7Sopenharmony_ci * A uniform named "unusedZero" is added by
1509e5c31af7Sopenharmony_ci * generateProgramInterfaceProgramSources.  It is used in expressions to
1510e5c31af7Sopenharmony_ci * prevent various program resources from being eliminated by the GLSL
1511e5c31af7Sopenharmony_ci * compiler's optimizer.
1512e5c31af7Sopenharmony_ci *
1513e5c31af7Sopenharmony_ci * \sa deqp::gles31::Functional::ProgramInterfaceDefinition::generateProgramInterfaceProgramSources
1514e5c31af7Sopenharmony_ci */
1515e5c31af7Sopenharmony_ciconst char* getUnusedZeroUniformName()
1516e5c31af7Sopenharmony_ci{
1517e5c31af7Sopenharmony_ci	return "unusedZero";
1518e5c31af7Sopenharmony_ci}
1519e5c31af7Sopenharmony_ci
1520e5c31af7Sopenharmony_ciglu::ProgramSources generateProgramInterfaceProgramSources (const ProgramInterfaceDefinition::Program* program)
1521e5c31af7Sopenharmony_ci{
1522e5c31af7Sopenharmony_ci	glu::ProgramSources sources;
1523e5c31af7Sopenharmony_ci
1524e5c31af7Sopenharmony_ci	DE_ASSERT(program->isValid());
1525e5c31af7Sopenharmony_ci
1526e5c31af7Sopenharmony_ci	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
1527e5c31af7Sopenharmony_ci	{
1528e5c31af7Sopenharmony_ci		const ProgramInterfaceDefinition::Shader*	shader						= program->getShaders()[shaderNdx];
1529e5c31af7Sopenharmony_ci		bool										containsUserDefinedOutputs	= false;
1530e5c31af7Sopenharmony_ci		bool										containsUserDefinedInputs	= false;
1531e5c31af7Sopenharmony_ci		std::ostringstream							sourceBuf;
1532e5c31af7Sopenharmony_ci		std::ostringstream							usageBuf;
1533e5c31af7Sopenharmony_ci
1534e5c31af7Sopenharmony_ci		sourceBuf	<< glu::getGLSLVersionDeclaration(shader->getVersion()) << "\n"
1535e5c31af7Sopenharmony_ci					<< getShaderExtensionDeclarations(shader)
1536e5c31af7Sopenharmony_ci					<< getShaderTypeDeclarations(program, shader)
1537e5c31af7Sopenharmony_ci					<< "\n";
1538e5c31af7Sopenharmony_ci
1539e5c31af7Sopenharmony_ci		// Struct definitions
1540e5c31af7Sopenharmony_ci
1541e5c31af7Sopenharmony_ci		writeStructureDefinitions(sourceBuf, shader->getDefaultBlock());
1542e5c31af7Sopenharmony_ci
1543e5c31af7Sopenharmony_ci		// variables in the default scope
1544e5c31af7Sopenharmony_ci
1545e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1546e5c31af7Sopenharmony_ci			sourceBuf << shader->getDefaultBlock().variables[ndx] << ";\n";
1547e5c31af7Sopenharmony_ci
1548e5c31af7Sopenharmony_ci		if (!shader->getDefaultBlock().variables.empty())
1549e5c31af7Sopenharmony_ci			sourceBuf << "\n";
1550e5c31af7Sopenharmony_ci
1551e5c31af7Sopenharmony_ci		// Interface blocks
1552e5c31af7Sopenharmony_ci
1553e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++ndx)
1554e5c31af7Sopenharmony_ci			writeInterfaceBlock(sourceBuf, shader->getDefaultBlock().interfaceBlocks[ndx]);
1555e5c31af7Sopenharmony_ci
1556e5c31af7Sopenharmony_ci		// Use inputs and outputs so that they won't be removed by the optimizer
1557e5c31af7Sopenharmony_ci
1558e5c31af7Sopenharmony_ci		usageBuf <<	"highp uniform vec4 " << getUnusedZeroUniformName() << "; // Default value is vec4(0.0).\n"
1559e5c31af7Sopenharmony_ci					"highp vec4 readInputs()\n"
1560e5c31af7Sopenharmony_ci					"{\n"
1561e5c31af7Sopenharmony_ci					"	highp vec4 retValue = " << getUnusedZeroUniformName() << ";\n";
1562e5c31af7Sopenharmony_ci
1563e5c31af7Sopenharmony_ci		// User-defined inputs
1564e5c31af7Sopenharmony_ci
1565e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1566e5c31af7Sopenharmony_ci		{
1567e5c31af7Sopenharmony_ci			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_IN			||
1568e5c31af7Sopenharmony_ci				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_IN	||
1569e5c31af7Sopenharmony_ci				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_UNIFORM)
1570e5c31af7Sopenharmony_ci			{
1571e5c31af7Sopenharmony_ci				writeVariableReadAccumulateExpression(usageBuf,
1572e5c31af7Sopenharmony_ci													  "retValue",
1573e5c31af7Sopenharmony_ci													  shader->getDefaultBlock().variables[ndx].name,
1574e5c31af7Sopenharmony_ci													  shader->getType(),
1575e5c31af7Sopenharmony_ci													  shader->getDefaultBlock().variables[ndx].storage,
1576e5c31af7Sopenharmony_ci													  program,
1577e5c31af7Sopenharmony_ci													  shader->getDefaultBlock().variables[ndx].varType);
1578e5c31af7Sopenharmony_ci				containsUserDefinedInputs = true;
1579e5c31af7Sopenharmony_ci			}
1580e5c31af7Sopenharmony_ci		}
1581e5c31af7Sopenharmony_ci
1582e5c31af7Sopenharmony_ci		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
1583e5c31af7Sopenharmony_ci		{
1584e5c31af7Sopenharmony_ci			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
1585e5c31af7Sopenharmony_ci			if (isReadableInterface(interface))
1586e5c31af7Sopenharmony_ci			{
1587e5c31af7Sopenharmony_ci				writeInterfaceReadAccumulateExpression(usageBuf,
1588e5c31af7Sopenharmony_ci													   "retValue",
1589e5c31af7Sopenharmony_ci													   interface,
1590e5c31af7Sopenharmony_ci													   shader->getType(),
1591e5c31af7Sopenharmony_ci													   program);
1592e5c31af7Sopenharmony_ci				containsUserDefinedInputs = true;
1593e5c31af7Sopenharmony_ci			}
1594e5c31af7Sopenharmony_ci		}
1595e5c31af7Sopenharmony_ci
1596e5c31af7Sopenharmony_ci		// Built-in-inputs
1597e5c31af7Sopenharmony_ci
1598e5c31af7Sopenharmony_ci		switch (shader->getType())
1599e5c31af7Sopenharmony_ci		{
1600e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_VERTEX:
1601e5c31af7Sopenharmony_ci				// make readInputs to never be compile time constant
1602e5c31af7Sopenharmony_ci				if (!containsUserDefinedInputs)
1603e5c31af7Sopenharmony_ci					usageBuf << "	retValue += vec4(float(gl_VertexID));\n";
1604e5c31af7Sopenharmony_ci				break;
1605e5c31af7Sopenharmony_ci
1606e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_FRAGMENT:
1607e5c31af7Sopenharmony_ci				// make readInputs to never be compile time constant
1608e5c31af7Sopenharmony_ci				if (!containsUserDefinedInputs)
1609e5c31af7Sopenharmony_ci					usageBuf << "	retValue += gl_FragCoord;\n";
1610e5c31af7Sopenharmony_ci				break;
1611e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_GEOMETRY:
1612e5c31af7Sopenharmony_ci				// always use previous stage's output values so that previous stage won't be optimized out
1613e5c31af7Sopenharmony_ci				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
1614e5c31af7Sopenharmony_ci				break;
1615e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_TESSELLATION_CONTROL:
1616e5c31af7Sopenharmony_ci				// always use previous stage's output values so that previous stage won't be optimized out
1617e5c31af7Sopenharmony_ci				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
1618e5c31af7Sopenharmony_ci				break;
1619e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_TESSELLATION_EVALUATION:
1620e5c31af7Sopenharmony_ci				// always use previous stage's output values so that previous stage won't be optimized out
1621e5c31af7Sopenharmony_ci				usageBuf << "	retValue += gl_in[0].gl_Position;\n";
1622e5c31af7Sopenharmony_ci				break;
1623e5c31af7Sopenharmony_ci
1624e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_COMPUTE:
1625e5c31af7Sopenharmony_ci				// make readInputs to never be compile time constant
1626e5c31af7Sopenharmony_ci				if (!containsUserDefinedInputs)
1627e5c31af7Sopenharmony_ci					usageBuf << "	retValue += vec4(float(gl_NumWorkGroups.x));\n";
1628e5c31af7Sopenharmony_ci				break;
1629e5c31af7Sopenharmony_ci			default:
1630e5c31af7Sopenharmony_ci				DE_ASSERT(false);
1631e5c31af7Sopenharmony_ci		}
1632e5c31af7Sopenharmony_ci
1633e5c31af7Sopenharmony_ci		usageBuf <<	"	return retValue;\n"
1634e5c31af7Sopenharmony_ci					"}\n\n";
1635e5c31af7Sopenharmony_ci
1636e5c31af7Sopenharmony_ci		usageBuf <<	"void writeOutputs(in highp vec4 unusedValue)\n"
1637e5c31af7Sopenharmony_ci					"{\n";
1638e5c31af7Sopenharmony_ci
1639e5c31af7Sopenharmony_ci		// User-defined outputs
1640e5c31af7Sopenharmony_ci
1641e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)shader->getDefaultBlock().variables.size(); ++ndx)
1642e5c31af7Sopenharmony_ci		{
1643e5c31af7Sopenharmony_ci			if (shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_OUT ||
1644e5c31af7Sopenharmony_ci				shader->getDefaultBlock().variables[ndx].storage == glu::STORAGE_PATCH_OUT)
1645e5c31af7Sopenharmony_ci			{
1646e5c31af7Sopenharmony_ci				writeVariableWriteExpression(usageBuf,
1647e5c31af7Sopenharmony_ci											 "unusedValue",
1648e5c31af7Sopenharmony_ci											 shader->getDefaultBlock().variables[ndx].name,
1649e5c31af7Sopenharmony_ci											 shader->getType(),
1650e5c31af7Sopenharmony_ci											 shader->getDefaultBlock().variables[ndx].storage,
1651e5c31af7Sopenharmony_ci											 program,
1652e5c31af7Sopenharmony_ci											 shader->getDefaultBlock().variables[ndx].varType);
1653e5c31af7Sopenharmony_ci				containsUserDefinedOutputs = true;
1654e5c31af7Sopenharmony_ci			}
1655e5c31af7Sopenharmony_ci		}
1656e5c31af7Sopenharmony_ci
1657e5c31af7Sopenharmony_ci		for (int interfaceNdx = 0; interfaceNdx < (int)shader->getDefaultBlock().interfaceBlocks.size(); ++interfaceNdx)
1658e5c31af7Sopenharmony_ci		{
1659e5c31af7Sopenharmony_ci			const glu::InterfaceBlock& interface = shader->getDefaultBlock().interfaceBlocks[interfaceNdx];
1660e5c31af7Sopenharmony_ci			if (isWritableInterface(interface))
1661e5c31af7Sopenharmony_ci			{
1662e5c31af7Sopenharmony_ci				writeInterfaceWriteExpression(usageBuf, "unusedValue", interface, shader->getType(), program);
1663e5c31af7Sopenharmony_ci				containsUserDefinedOutputs = true;
1664e5c31af7Sopenharmony_ci			}
1665e5c31af7Sopenharmony_ci		}
1666e5c31af7Sopenharmony_ci
1667e5c31af7Sopenharmony_ci		// Builtin-outputs that must be written to
1668e5c31af7Sopenharmony_ci
1669e5c31af7Sopenharmony_ci		if (shader->getType() == glu::SHADERTYPE_VERTEX)
1670e5c31af7Sopenharmony_ci			usageBuf << "	gl_Position = unusedValue;\n";
1671e5c31af7Sopenharmony_ci		else if (shader->getType() == glu::SHADERTYPE_GEOMETRY)
1672e5c31af7Sopenharmony_ci			usageBuf << "	gl_Position = unusedValue;\n"
1673e5c31af7Sopenharmony_ci						 "	EmitVertex();\n";
1674e5c31af7Sopenharmony_ci		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_CONTROL)
1675e5c31af7Sopenharmony_ci			usageBuf << "	gl_out[gl_InvocationID].gl_Position = unusedValue;\n"
1676e5c31af7Sopenharmony_ci						"	gl_TessLevelOuter[0] = 2.8;\n"
1677e5c31af7Sopenharmony_ci						"	gl_TessLevelOuter[1] = 2.8;\n"
1678e5c31af7Sopenharmony_ci						"	gl_TessLevelOuter[2] = 2.8;\n"
1679e5c31af7Sopenharmony_ci						"	gl_TessLevelOuter[3] = 2.8;\n"
1680e5c31af7Sopenharmony_ci						"	gl_TessLevelInner[0] = 2.8;\n"
1681e5c31af7Sopenharmony_ci						"	gl_TessLevelInner[1] = 2.8;\n";
1682e5c31af7Sopenharmony_ci		else if (shader->getType() == glu::SHADERTYPE_TESSELLATION_EVALUATION)
1683e5c31af7Sopenharmony_ci			usageBuf << "	gl_Position = unusedValue;\n";
1684e5c31af7Sopenharmony_ci
1685e5c31af7Sopenharmony_ci		// Output to sink input data to
1686e5c31af7Sopenharmony_ci
1687e5c31af7Sopenharmony_ci		if (!containsUserDefinedOutputs)
1688e5c31af7Sopenharmony_ci		{
1689e5c31af7Sopenharmony_ci			if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
1690e5c31af7Sopenharmony_ci				usageBuf << "	gl_FragDepth = dot(unusedValue.xy, unusedValue.xw);\n";
1691e5c31af7Sopenharmony_ci			else if (shader->getType() == glu::SHADERTYPE_COMPUTE)
1692e5c31af7Sopenharmony_ci				usageBuf << "	unusedOutputBlock.unusedValue = unusedValue;\n";
1693e5c31af7Sopenharmony_ci		}
1694e5c31af7Sopenharmony_ci
1695e5c31af7Sopenharmony_ci		usageBuf <<	"}\n\n"
1696e5c31af7Sopenharmony_ci					"void main()\n"
1697e5c31af7Sopenharmony_ci					"{\n"
1698e5c31af7Sopenharmony_ci					"	writeOutputs(readInputs());\n"
1699e5c31af7Sopenharmony_ci					"}\n";
1700e5c31af7Sopenharmony_ci
1701e5c31af7Sopenharmony_ci		// Interface for unused output
1702e5c31af7Sopenharmony_ci
1703e5c31af7Sopenharmony_ci		if (shader->getType() == glu::SHADERTYPE_COMPUTE && !containsUserDefinedOutputs)
1704e5c31af7Sopenharmony_ci		{
1705e5c31af7Sopenharmony_ci			sourceBuf	<< "writeonly buffer UnusedOutputInterface\n"
1706e5c31af7Sopenharmony_ci						<< "{\n"
1707e5c31af7Sopenharmony_ci						<< "	highp vec4 unusedValue;\n"
1708e5c31af7Sopenharmony_ci						<< "} unusedOutputBlock;\n\n";
1709e5c31af7Sopenharmony_ci		}
1710e5c31af7Sopenharmony_ci
1711e5c31af7Sopenharmony_ci		sources << glu::ShaderSource(shader->getType(), sourceBuf.str() + usageBuf.str());
1712e5c31af7Sopenharmony_ci	}
1713e5c31af7Sopenharmony_ci
1714e5c31af7Sopenharmony_ci	if (program->isSeparable())
1715e5c31af7Sopenharmony_ci		sources << glu::ProgramSeparable(true);
1716e5c31af7Sopenharmony_ci
1717e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)program->getTransformFeedbackVaryings().size(); ++ndx)
1718e5c31af7Sopenharmony_ci		sources << glu::TransformFeedbackVarying(program->getTransformFeedbackVaryings()[ndx]);
1719e5c31af7Sopenharmony_ci
1720e5c31af7Sopenharmony_ci	if (program->getTransformFeedbackMode())
1721e5c31af7Sopenharmony_ci		sources << glu::TransformFeedbackMode(program->getTransformFeedbackMode());
1722e5c31af7Sopenharmony_ci
1723e5c31af7Sopenharmony_ci	return sources;
1724e5c31af7Sopenharmony_ci}
1725e5c31af7Sopenharmony_ci
1726e5c31af7Sopenharmony_cibool findProgramVariablePathByPathName (std::vector<VariablePathComponent>& typePath, const ProgramInterfaceDefinition::Program* program, const std::string& pathName, const VariableSearchFilter& filter)
1727e5c31af7Sopenharmony_ci{
1728e5c31af7Sopenharmony_ci	std::vector<VariablePathComponent> modifiedPath;
1729e5c31af7Sopenharmony_ci
1730e5c31af7Sopenharmony_ci	if (!traverseProgramVariablePath(modifiedPath, program, pathName, filter))
1731e5c31af7Sopenharmony_ci		return false;
1732e5c31af7Sopenharmony_ci
1733e5c31af7Sopenharmony_ci	// modify param only on success
1734e5c31af7Sopenharmony_ci	typePath.swap(modifiedPath);
1735e5c31af7Sopenharmony_ci	return true;
1736e5c31af7Sopenharmony_ci}
1737e5c31af7Sopenharmony_ci
1738e5c31af7Sopenharmony_ciProgramInterfaceDefinition::ShaderResourceUsage getShaderResourceUsage (const ProgramInterfaceDefinition::Program* program, const ProgramInterfaceDefinition::Shader* shader)
1739e5c31af7Sopenharmony_ci{
1740e5c31af7Sopenharmony_ci	ProgramInterfaceDefinition::ShaderResourceUsage retVal;
1741e5c31af7Sopenharmony_ci
1742e5c31af7Sopenharmony_ci	retVal.numInputs						= getNumTypeInstances(shader, glu::STORAGE_IN);
1743e5c31af7Sopenharmony_ci	retVal.numInputVectors					= getNumVectors(shader, glu::STORAGE_IN);
1744e5c31af7Sopenharmony_ci	retVal.numInputComponents				= getNumComponents(shader, glu::STORAGE_IN);
1745e5c31af7Sopenharmony_ci
1746e5c31af7Sopenharmony_ci	retVal.numOutputs						= getNumTypeInstances(shader, glu::STORAGE_OUT);
1747e5c31af7Sopenharmony_ci	retVal.numOutputVectors					= getNumVectors(shader, glu::STORAGE_OUT);
1748e5c31af7Sopenharmony_ci	retVal.numOutputComponents				= getNumComponents(shader, glu::STORAGE_OUT);
1749e5c31af7Sopenharmony_ci
1750e5c31af7Sopenharmony_ci	retVal.numPatchInputComponents			= getNumComponents(shader, glu::STORAGE_PATCH_IN);
1751e5c31af7Sopenharmony_ci	retVal.numPatchOutputComponents			= getNumComponents(shader, glu::STORAGE_PATCH_OUT);
1752e5c31af7Sopenharmony_ci
1753e5c31af7Sopenharmony_ci	retVal.numDefaultBlockUniformComponents	= getNumDefaultBlockComponents(shader, glu::STORAGE_UNIFORM);
1754e5c31af7Sopenharmony_ci	retVal.numCombinedUniformComponents		= getNumComponents(shader, glu::STORAGE_UNIFORM);
1755e5c31af7Sopenharmony_ci	retVal.numUniformVectors				= getNumVectors(shader, glu::STORAGE_UNIFORM);
1756e5c31af7Sopenharmony_ci
1757e5c31af7Sopenharmony_ci	retVal.numSamplers						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
1758e5c31af7Sopenharmony_ci	retVal.numImages						= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
1759e5c31af7Sopenharmony_ci
1760e5c31af7Sopenharmony_ci	retVal.numAtomicCounterBuffers			= getNumAtomicCounterBuffers(shader);
1761e5c31af7Sopenharmony_ci	retVal.numAtomicCounters				= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
1762e5c31af7Sopenharmony_ci
1763e5c31af7Sopenharmony_ci	retVal.numUniformBlocks					= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
1764e5c31af7Sopenharmony_ci	retVal.numShaderStorageBlocks			= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ci	// add builtins
1767e5c31af7Sopenharmony_ci	switch (shader->getType())
1768e5c31af7Sopenharmony_ci	{
1769e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_VERTEX:
1770e5c31af7Sopenharmony_ci			// gl_Position is not counted
1771e5c31af7Sopenharmony_ci			break;
1772e5c31af7Sopenharmony_ci
1773e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_FRAGMENT:
1774e5c31af7Sopenharmony_ci			// nada
1775e5c31af7Sopenharmony_ci			break;
1776e5c31af7Sopenharmony_ci
1777e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_GEOMETRY:
1778e5c31af7Sopenharmony_ci			// gl_Position in (point mode => size 1)
1779e5c31af7Sopenharmony_ci			retVal.numInputs			+= 1;
1780e5c31af7Sopenharmony_ci			retVal.numInputVectors		+= 1;
1781e5c31af7Sopenharmony_ci			retVal.numInputComponents	+= 4;
1782e5c31af7Sopenharmony_ci
1783e5c31af7Sopenharmony_ci			// gl_Position out
1784e5c31af7Sopenharmony_ci			retVal.numOutputs			+= 1;
1785e5c31af7Sopenharmony_ci			retVal.numOutputVectors		+= 1;
1786e5c31af7Sopenharmony_ci			retVal.numOutputComponents	+= 4;
1787e5c31af7Sopenharmony_ci			break;
1788e5c31af7Sopenharmony_ci
1789e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_TESSELLATION_CONTROL:
1790e5c31af7Sopenharmony_ci			// gl_Position in is read up to gl_InstanceID
1791e5c31af7Sopenharmony_ci			retVal.numInputs			+= 1 * program->getTessellationNumOutputPatchVertices();
1792e5c31af7Sopenharmony_ci			retVal.numInputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
1793e5c31af7Sopenharmony_ci			retVal.numInputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
1794e5c31af7Sopenharmony_ci
1795e5c31af7Sopenharmony_ci			// gl_Position out, size = num patch out vertices
1796e5c31af7Sopenharmony_ci			retVal.numOutputs			+= 1 * program->getTessellationNumOutputPatchVertices();
1797e5c31af7Sopenharmony_ci			retVal.numOutputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
1798e5c31af7Sopenharmony_ci			retVal.numOutputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
1799e5c31af7Sopenharmony_ci			break;
1800e5c31af7Sopenharmony_ci
1801e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_TESSELLATION_EVALUATION:
1802e5c31af7Sopenharmony_ci			// gl_Position in is read up to gl_InstanceID
1803e5c31af7Sopenharmony_ci			retVal.numInputs			+= 1 * program->getTessellationNumOutputPatchVertices();
1804e5c31af7Sopenharmony_ci			retVal.numInputVectors		+= 1 * program->getTessellationNumOutputPatchVertices();
1805e5c31af7Sopenharmony_ci			retVal.numInputComponents	+= 4 * program->getTessellationNumOutputPatchVertices();
1806e5c31af7Sopenharmony_ci
1807e5c31af7Sopenharmony_ci			// gl_Position out
1808e5c31af7Sopenharmony_ci			retVal.numOutputs			+= 1;
1809e5c31af7Sopenharmony_ci			retVal.numOutputVectors		+= 1;
1810e5c31af7Sopenharmony_ci			retVal.numOutputComponents	+= 4;
1811e5c31af7Sopenharmony_ci			break;
1812e5c31af7Sopenharmony_ci
1813e5c31af7Sopenharmony_ci		case glu::SHADERTYPE_COMPUTE:
1814e5c31af7Sopenharmony_ci			// nada
1815e5c31af7Sopenharmony_ci			break;
1816e5c31af7Sopenharmony_ci
1817e5c31af7Sopenharmony_ci		default:
1818e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1819e5c31af7Sopenharmony_ci			break;
1820e5c31af7Sopenharmony_ci	}
1821e5c31af7Sopenharmony_ci	return retVal;
1822e5c31af7Sopenharmony_ci}
1823e5c31af7Sopenharmony_ci
1824e5c31af7Sopenharmony_ciProgramInterfaceDefinition::ProgramResourceUsage getCombinedProgramResourceUsage (const ProgramInterfaceDefinition::Program* program)
1825e5c31af7Sopenharmony_ci{
1826e5c31af7Sopenharmony_ci	ProgramInterfaceDefinition::ProgramResourceUsage	retVal;
1827e5c31af7Sopenharmony_ci	int													numVertexOutputComponents	= 0;
1828e5c31af7Sopenharmony_ci	int													numFragmentInputComponents	= 0;
1829e5c31af7Sopenharmony_ci	int													numVertexOutputVectors		= 0;
1830e5c31af7Sopenharmony_ci	int													numFragmentInputVectors		= 0;
1831e5c31af7Sopenharmony_ci
1832e5c31af7Sopenharmony_ci	retVal.uniformBufferMaxBinding					= -1; // max binding is inclusive upper bound. Allow 0 bindings by using negative value
1833e5c31af7Sopenharmony_ci	retVal.uniformBufferMaxSize						= 0;
1834e5c31af7Sopenharmony_ci	retVal.numUniformBlocks							= 0;
1835e5c31af7Sopenharmony_ci	retVal.numCombinedVertexUniformComponents		= 0;
1836e5c31af7Sopenharmony_ci	retVal.numCombinedFragmentUniformComponents		= 0;
1837e5c31af7Sopenharmony_ci	retVal.numCombinedGeometryUniformComponents		= 0;
1838e5c31af7Sopenharmony_ci	retVal.numCombinedTessControlUniformComponents	= 0;
1839e5c31af7Sopenharmony_ci	retVal.numCombinedTessEvalUniformComponents		= 0;
1840e5c31af7Sopenharmony_ci	retVal.shaderStorageBufferMaxBinding			= -1; // see above
1841e5c31af7Sopenharmony_ci	retVal.shaderStorageBufferMaxSize				= 0;
1842e5c31af7Sopenharmony_ci	retVal.numShaderStorageBlocks					= 0;
1843e5c31af7Sopenharmony_ci	retVal.numVaryingComponents						= 0;
1844e5c31af7Sopenharmony_ci	retVal.numVaryingVectors						= 0;
1845e5c31af7Sopenharmony_ci	retVal.numCombinedSamplers						= 0;
1846e5c31af7Sopenharmony_ci	retVal.atomicCounterBufferMaxBinding			= -1; // see above
1847e5c31af7Sopenharmony_ci	retVal.atomicCounterBufferMaxSize				= 0;
1848e5c31af7Sopenharmony_ci	retVal.numAtomicCounterBuffers					= 0;
1849e5c31af7Sopenharmony_ci	retVal.numAtomicCounters						= 0;
1850e5c31af7Sopenharmony_ci	retVal.maxImageBinding							= -1; // see above
1851e5c31af7Sopenharmony_ci	retVal.numCombinedImages						= 0;
1852e5c31af7Sopenharmony_ci	retVal.numCombinedOutputResources				= 0;
1853e5c31af7Sopenharmony_ci	retVal.numXFBInterleavedComponents				= 0;
1854e5c31af7Sopenharmony_ci	retVal.numXFBSeparateAttribs					= 0;
1855e5c31af7Sopenharmony_ci	retVal.numXFBSeparateComponents					= 0;
1856e5c31af7Sopenharmony_ci	retVal.fragmentOutputMaxBinding					= -1; // see above
1857e5c31af7Sopenharmony_ci
1858e5c31af7Sopenharmony_ci	for (int shaderNdx = 0; shaderNdx < (int)program->getShaders().size(); ++shaderNdx)
1859e5c31af7Sopenharmony_ci	{
1860e5c31af7Sopenharmony_ci		const ProgramInterfaceDefinition::Shader* const shader = program->getShaders()[shaderNdx];
1861e5c31af7Sopenharmony_ci
1862e5c31af7Sopenharmony_ci		retVal.uniformBufferMaxBinding		= de::max(retVal.uniformBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_UNIFORM));
1863e5c31af7Sopenharmony_ci		retVal.uniformBufferMaxSize			= de::max(retVal.uniformBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_UNIFORM));
1864e5c31af7Sopenharmony_ci		retVal.numUniformBlocks				+= getNumShaderBlocks(shader, glu::STORAGE_UNIFORM);
1865e5c31af7Sopenharmony_ci
1866e5c31af7Sopenharmony_ci		switch (shader->getType())
1867e5c31af7Sopenharmony_ci		{
1868e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_VERTEX:					retVal.numCombinedVertexUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
1869e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_FRAGMENT:					retVal.numCombinedFragmentUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
1870e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_GEOMETRY:					retVal.numCombinedGeometryUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
1871e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_TESSELLATION_CONTROL:		retVal.numCombinedTessControlUniformComponents	+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
1872e5c31af7Sopenharmony_ci			case glu::SHADERTYPE_TESSELLATION_EVALUATION:	retVal.numCombinedTessEvalUniformComponents		+= getNumComponents(shader, glu::STORAGE_UNIFORM); break;
1873e5c31af7Sopenharmony_ci			default: break;
1874e5c31af7Sopenharmony_ci		}
1875e5c31af7Sopenharmony_ci
1876e5c31af7Sopenharmony_ci		retVal.shaderStorageBufferMaxBinding	= de::max(retVal.shaderStorageBufferMaxBinding, getMaxBufferBinding(shader, glu::STORAGE_BUFFER));
1877e5c31af7Sopenharmony_ci		retVal.shaderStorageBufferMaxSize		= de::max(retVal.shaderStorageBufferMaxSize, getBufferMaxSize(shader, glu::STORAGE_BUFFER));
1878e5c31af7Sopenharmony_ci		retVal.numShaderStorageBlocks			+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
1879e5c31af7Sopenharmony_ci
1880e5c31af7Sopenharmony_ci		if (shader->getType() == glu::SHADERTYPE_VERTEX)
1881e5c31af7Sopenharmony_ci		{
1882e5c31af7Sopenharmony_ci			numVertexOutputComponents	+= getNumComponents(shader, glu::STORAGE_OUT);
1883e5c31af7Sopenharmony_ci			numVertexOutputVectors		+= getNumVectors(shader, glu::STORAGE_OUT);
1884e5c31af7Sopenharmony_ci		}
1885e5c31af7Sopenharmony_ci		else if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
1886e5c31af7Sopenharmony_ci		{
1887e5c31af7Sopenharmony_ci			numFragmentInputComponents	+= getNumComponents(shader, glu::STORAGE_IN);
1888e5c31af7Sopenharmony_ci			numFragmentInputVectors		+= getNumVectors(shader, glu::STORAGE_IN);
1889e5c31af7Sopenharmony_ci		}
1890e5c31af7Sopenharmony_ci
1891e5c31af7Sopenharmony_ci		retVal.numCombinedSamplers	+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeSampler);
1892e5c31af7Sopenharmony_ci
1893e5c31af7Sopenharmony_ci		retVal.atomicCounterBufferMaxBinding	= de::max(retVal.atomicCounterBufferMaxBinding, getAtomicCounterMaxBinding(shader));
1894e5c31af7Sopenharmony_ci		retVal.atomicCounterBufferMaxSize		= de::max(retVal.atomicCounterBufferMaxSize, getAtomicCounterMaxBufferSize(shader));
1895e5c31af7Sopenharmony_ci		retVal.numAtomicCounterBuffers			+= getNumAtomicCounterBuffers(shader);
1896e5c31af7Sopenharmony_ci		retVal.numAtomicCounters				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeAtomicCounter);
1897e5c31af7Sopenharmony_ci		retVal.maxImageBinding					= de::max(retVal.maxImageBinding, getUniformMaxBinding(shader, glu::isDataTypeImage));
1898e5c31af7Sopenharmony_ci		retVal.numCombinedImages				+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
1899e5c31af7Sopenharmony_ci
1900e5c31af7Sopenharmony_ci		retVal.numCombinedOutputResources		+= getNumTypeInstances(shader, glu::STORAGE_UNIFORM, glu::isDataTypeImage);
1901e5c31af7Sopenharmony_ci		retVal.numCombinedOutputResources		+= getNumShaderBlocks(shader, glu::STORAGE_BUFFER);
1902e5c31af7Sopenharmony_ci
1903e5c31af7Sopenharmony_ci		if (shader->getType() == glu::SHADERTYPE_FRAGMENT)
1904e5c31af7Sopenharmony_ci		{
1905e5c31af7Sopenharmony_ci			retVal.numCombinedOutputResources += getNumVectors(shader, glu::STORAGE_OUT);
1906e5c31af7Sopenharmony_ci			retVal.fragmentOutputMaxBinding = de::max(retVal.fragmentOutputMaxBinding, getFragmentOutputMaxLocation(shader));
1907e5c31af7Sopenharmony_ci		}
1908e5c31af7Sopenharmony_ci	}
1909e5c31af7Sopenharmony_ci
1910e5c31af7Sopenharmony_ci	if (program->getTransformFeedbackMode() == GL_INTERLEAVED_ATTRIBS)
1911e5c31af7Sopenharmony_ci		retVal.numXFBInterleavedComponents = getNumXFBComponents(program);
1912e5c31af7Sopenharmony_ci	else if (program->getTransformFeedbackMode() == GL_SEPARATE_ATTRIBS)
1913e5c31af7Sopenharmony_ci	{
1914e5c31af7Sopenharmony_ci		retVal.numXFBSeparateAttribs	= (int)program->getTransformFeedbackVaryings().size();
1915e5c31af7Sopenharmony_ci		retVal.numXFBSeparateComponents	= getNumMaxXFBOutputComponents(program);
1916e5c31af7Sopenharmony_ci	}
1917e5c31af7Sopenharmony_ci
1918e5c31af7Sopenharmony_ci	// legacy limits
1919e5c31af7Sopenharmony_ci	retVal.numVaryingComponents	= de::max(numVertexOutputComponents, numFragmentInputComponents);
1920e5c31af7Sopenharmony_ci	retVal.numVaryingVectors	= de::max(numVertexOutputVectors, numFragmentInputVectors);
1921e5c31af7Sopenharmony_ci
1922e5c31af7Sopenharmony_ci	return retVal;
1923e5c31af7Sopenharmony_ci}
1924e5c31af7Sopenharmony_ci
1925e5c31af7Sopenharmony_ci} // Functional
1926e5c31af7Sopenharmony_ci} // gles31
1927e5c31af7Sopenharmony_ci} // deqp
1928