1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
3  * ------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Shader variable type.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "gluVarType.hpp"
25 #include "deStringUtil.hpp"
26 #include "deArrayUtil.hpp"
27 
28 namespace glu
29 {
30 
VarType(void)31 VarType::VarType (void)
32 	: m_type(VARTYPE_LAST)
33 {
34 }
35 
VarType(const VarType & other)36 VarType::VarType (const VarType& other)
37 	: m_type(VARTYPE_LAST)
38 {
39 	*this = other;
40 }
41 
VarType(DataType basicType,Precision precision)42 VarType::VarType (DataType basicType, Precision precision)
43 	: m_type(VARTYPE_BASIC)
44 {
45 	m_data.basic.type		= basicType;
46 	m_data.basic.precision	= precision;
47 }
48 
VarType(const VarType & elementType,int arraySize)49 VarType::VarType (const VarType& elementType, int arraySize)
50 	: m_type(VARTYPE_ARRAY)
51 {
52 	DE_ASSERT(arraySize >= 0 || arraySize == UNSIZED_ARRAY);
53 	m_data.array.size			= arraySize;
54 	m_data.array.elementType	= new VarType(elementType);
55 }
56 
VarType(const StructType * structPtr)57 VarType::VarType (const StructType* structPtr)
58 	: m_type(VARTYPE_STRUCT)
59 {
60 	m_data.structPtr = structPtr;
61 }
62 
~VarType(void)63 VarType::~VarType (void)
64 {
65 	if (m_type == VARTYPE_ARRAY)
66 		delete m_data.array.elementType;
67 }
68 
operator =(const VarType & other)69 VarType& VarType::operator= (const VarType& other)
70 {
71 	if (this == &other)
72 		return *this; // Self-assignment.
73 
74 	VarType *oldElementType = m_type == VARTYPE_ARRAY ? m_data.array.elementType : DE_NULL;
75 
76 	m_type	= other.m_type;
77 	m_data	= Data();
78 
79 	if (m_type == VARTYPE_ARRAY)
80 	{
81 		m_data.array.elementType	= new VarType(*other.m_data.array.elementType);
82 		m_data.array.size			= other.m_data.array.size;
83 	}
84 	else
85 		m_data = other.m_data;
86 
87 	delete oldElementType;
88 
89 	return *this;
90 }
91 
getScalarSize(void) const92 int VarType::getScalarSize (void) const
93 {
94 	switch (m_type)
95 	{
96 		case VARTYPE_BASIC:	return glu::getDataTypeScalarSize(m_data.basic.type);
97 		case VARTYPE_ARRAY:	return m_data.array.elementType->getScalarSize()*m_data.array.size;
98 
99 		case VARTYPE_STRUCT:
100 		{
101 			int size = 0;
102 			for (StructType::ConstIterator iter = m_data.structPtr->begin(); iter != m_data.structPtr->end(); iter++)
103 				size += iter->getType().getScalarSize();
104 			return size;
105 		}
106 
107 		default:
108 			DE_ASSERT(false);
109 			return 0;
110 	}
111 }
112 
operator ==(const VarType & other) const113 bool VarType::operator== (const VarType& other) const
114 {
115 	if (m_type != other.m_type)
116 		return false;
117 
118 	switch (m_type)
119 	{
120 		case VARTYPE_BASIC:
121 			return	m_data.basic.type == other.m_data.basic.type &&
122 					m_data.basic.precision == other.m_data.basic.precision;
123 
124 		case VARTYPE_ARRAY:
125 			return	*m_data.array.elementType == *other.m_data.array.elementType &&
126 					m_data.array.size == other.m_data.array.size;
127 
128 		case VARTYPE_STRUCT:
129 			return m_data.structPtr == other.m_data.structPtr;
130 
131 		default:
132 			DE_ASSERT(false);
133 			return 0;
134 	}
135 }
136 
operator !=(const VarType & other) const137 bool VarType::operator!= (const VarType& other) const
138 {
139 	return !(*this == other);
140 }
141 
142 // StructMember implementation
143 
operator ==(const StructMember & other) const144 bool StructMember::operator== (const StructMember& other) const
145 {
146 	return (m_name == other.m_name) && (m_type == other.m_type);
147 }
148 
operator !=(const StructMember & other) const149 bool StructMember::operator!= (const StructMember& other) const
150 {
151 	return !(*this == other);
152 }
153 
154 // StructType implementation.
155 
addMember(const char * name,const VarType & type)156 void StructType::addMember (const char* name, const VarType& type)
157 {
158 	m_members.push_back(StructMember(name, type));
159 }
160 
operator ==(const StructType & other) const161 bool StructType::operator== (const StructType& other) const
162 {
163 	return (m_typeName == other.m_typeName) && (m_members == other.m_members);
164 }
165 
operator !=(const StructType & other) const166 bool StructType::operator!= (const StructType& other) const
167 {
168 	return !(*this == other);
169 }
170 
getStorageName(Storage storage)171 const char* getStorageName (Storage storage)
172 {
173 	static const char* const s_names[] = { "in", "out", "const", "uniform", "buffer", "patch in", "patch out" };
174 
175 	return de::getSizedArrayElement<STORAGE_LAST>(s_names, storage);
176 }
177 
getInterpolationName(Interpolation interpolation)178 const char* getInterpolationName (Interpolation interpolation)
179 {
180 	static const char* const s_names[] = { "smooth", "flat", "centroid" };
181 
182 	return de::getSizedArrayElement<INTERPOLATION_LAST>(s_names, interpolation);
183 }
184 
getFormatLayoutName(FormatLayout layout)185 const char* getFormatLayoutName (FormatLayout layout)
186 {
187 	static const char* s_names[] =
188 	{
189 		"rgba32f",			// FORMATLAYOUT_RGBA32F
190 		"rgba16f",			// FORMATLAYOUT_RGBA16F
191 		"r32f",				// FORMATLAYOUT_R32F
192 		"rgba8",			// FORMATLAYOUT_RGBA8
193 		"rgba8_snorm",		// FORMATLAYOUT_RGBA8_SNORM
194 		"rgba32i",			// FORMATLAYOUT_RGBA32I
195 		"rgba16i",			// FORMATLAYOUT_RGBA16I
196 		"rgba8i",			// FORMATLAYOUT_RGBA8I
197 		"r32i",				// FORMATLAYOUT_R32I
198 		"rgba32ui",			// FORMATLAYOUT_RGBA32UI
199 		"rgba16ui",			// FORMATLAYOUT_RGBA16UI
200 		"rgba8ui",			// FORMATLAYOUT_RGBA8UI
201 		"r32ui",			// FORMATLAYOUT_R32UI
202 	};
203 
204 	return de::getSizedArrayElement<FORMATLAYOUT_LAST>(s_names, layout);
205 }
206 
getMemoryAccessQualifierName(MemoryAccessQualifier qualifier)207 const char* getMemoryAccessQualifierName (MemoryAccessQualifier qualifier)
208 {
209 	switch (qualifier)
210 	{
211 		case MEMORYACCESSQUALIFIER_COHERENT_BIT:	return "coherent";
212 		case MEMORYACCESSQUALIFIER_VOLATILE_BIT:	return "volatile";
213 		case MEMORYACCESSQUALIFIER_RESTRICT_BIT:	return "restrict";
214 		case MEMORYACCESSQUALIFIER_READONLY_BIT:	return "readonly";
215 		case MEMORYACCESSQUALIFIER_WRITEONLY_BIT:	return "writeonly";
216 		default:
217 			DE_ASSERT(false);
218 			return DE_NULL;
219 	}
220 }
221 
getMatrixOrderName(MatrixOrder qualifier)222 const char* getMatrixOrderName (MatrixOrder qualifier)
223 {
224 	static const char* s_names[] =
225 	{
226 		"column_major",	// MATRIXORDER_COLUMN_MAJOR
227 		"row_major",	// MATRIXORDER_ROW_MAJOR
228 	};
229 
230 	return de::getSizedArrayElement<MATRIXORDER_LAST>(s_names, qualifier);
231 }
232 
233 // Layout Implementation
234 
Layout(int location_,int binding_,int offset_,FormatLayout format_,MatrixOrder matrixOrder_)235 Layout::Layout (int location_, int binding_, int offset_, FormatLayout format_, MatrixOrder matrixOrder_)
236 	: location			(location_)
237 	, binding			(binding_)
238 	, offset			(offset_)
239 	, format			(format_)
240 	, matrixOrder		(matrixOrder_)
241 {
242 }
243 
operator ==(const Layout & other) const244 bool Layout::operator== (const Layout& other) const
245 {
246 	return	location == other.location &&
247 			binding == other.binding &&
248 			offset == other.offset &&
249 			format == other.format &&
250 			matrixOrder == other.matrixOrder;
251 }
252 
operator !=(const Layout & other) const253 bool Layout::operator!= (const Layout& other) const
254 {
255 	return !(*this == other);
256 }
257 
258 // VariableDeclaration Implementation
259 
VariableDeclaration(const VarType & varType_,const std::string & name_,Storage storage_,Interpolation interpolation_,const Layout & layout_,deUint32 memoryAccessQualifierBits_)260 VariableDeclaration::VariableDeclaration (const VarType& varType_, const std::string& name_, Storage storage_, Interpolation interpolation_, const Layout& layout_, deUint32 memoryAccessQualifierBits_)
261 	: layout						(layout_)
262 	, interpolation					(interpolation_)
263 	, storage						(storage_)
264 	, varType						(varType_)
265 	, memoryAccessQualifierBits		(memoryAccessQualifierBits_)
266 	, name							(name_)
267 {
268 }
269 
operator ==(const VariableDeclaration & other) const270 bool VariableDeclaration::operator== (const VariableDeclaration& other) const
271 {
272 	return	layout == other.layout &&
273 			interpolation == other.interpolation &&
274 			storage == other.storage &&
275 			varType == other.varType &&
276 			memoryAccessQualifierBits == other.memoryAccessQualifierBits &&
277 			name == other.name;
278 }
279 
operator !=(const VariableDeclaration & other) const280 bool VariableDeclaration::operator!= (const VariableDeclaration& other) const
281 {
282 	return !(*this == other);
283 }
284 
285 // InterfaceBlock Implementation
286 
InterfaceBlock(void)287 InterfaceBlock::InterfaceBlock (void)
288 	: layout						(Layout())
289 	, storage						(glu::STORAGE_LAST)
290 	, memoryAccessQualifierFlags	(0)
291 {
292 }
293 
294 // Declaration utilties.
295 
operator <<(std::ostream & str,const Layout & layout)296 std::ostream& operator<< (std::ostream& str, const Layout& layout)
297 {
298 	std::vector<std::string> layoutDeclarationList;
299 
300 	if (layout.location != -1)
301 		layoutDeclarationList.push_back("location=" + de::toString(layout.location));
302 
303 	if (layout.binding != -1)
304 		layoutDeclarationList.push_back("binding=" + de::toString(layout.binding));
305 
306 	if (layout.offset != -1)
307 		layoutDeclarationList.push_back("offset=" + de::toString(layout.offset));
308 
309 	if (layout.format != FORMATLAYOUT_LAST)
310 		layoutDeclarationList.push_back(getFormatLayoutName(layout.format));
311 
312 	if (layout.matrixOrder != MATRIXORDER_LAST)
313 		layoutDeclarationList.push_back(getMatrixOrderName(layout.matrixOrder));
314 
315 	if (!layoutDeclarationList.empty())
316 	{
317 		str << "layout(" << layoutDeclarationList[0];
318 
319 		for (int layoutNdx = 1; layoutNdx < (int)layoutDeclarationList.size(); ++layoutNdx)
320 			str << ", " << layoutDeclarationList[layoutNdx];
321 
322 		str << ")";
323 	}
324 
325 	return str;
326 }
327 
operator <<(std::ostream & str,const VariableDeclaration & decl)328 std::ostream& operator<< (std::ostream& str, const VariableDeclaration& decl)
329 {
330 	if (decl.layout != Layout())
331 		str << decl.layout << " ";
332 
333 	for (int bitNdx = 0; (1 << bitNdx) & MEMORYACCESSQUALIFIER_MASK; ++bitNdx)
334 		if (decl.memoryAccessQualifierBits & (1 << bitNdx))
335 			str << getMemoryAccessQualifierName((glu::MemoryAccessQualifier)(1 << bitNdx)) << " ";
336 
337 	if (decl.interpolation != INTERPOLATION_LAST)
338 		str << getInterpolationName(decl.interpolation) << " ";
339 
340 	if (decl.storage != STORAGE_LAST)
341 		str << getStorageName(decl.storage) << " ";
342 
343 	str << declare(decl.varType, decl.name);
344 
345 	return str;
346 }
347 
348 namespace decl
349 {
350 
operator <<(std::ostream & str,const Indent & indent)351 std::ostream& operator<< (std::ostream& str, const Indent& indent)
352 {
353 	for (int i = 0; i < indent.level; i++)
354 		str << "\t";
355 	return str;
356 }
357 
operator <<(std::ostream & str,const DeclareVariable & decl)358 std::ostream& operator<< (std::ostream& str, const DeclareVariable& decl)
359 {
360 	const VarType&		type	= decl.varType;
361 	const VarType*		curType	= &type;
362 	std::vector<int>	arraySizes;
363 
364 	// Handle arrays.
365 	while (curType->isArrayType())
366 	{
367 		arraySizes.push_back(curType->getArraySize());
368 		curType = &curType->getElementType();
369 	}
370 
371 	if (curType->isBasicType())
372 	{
373 		if (curType->getPrecision() != PRECISION_LAST && !glu::isDataTypeFloat16OrVec(curType->getBasicType()))
374 				str << glu::getPrecisionName(curType->getPrecision()) << " ";
375 		str << glu::getDataTypeName(curType->getBasicType());
376 	}
377 	else if (curType->isStructType())
378 	{
379 		const StructType* structPtr = curType->getStructPtr();
380 
381 		if (structPtr->hasTypeName())
382 			str << structPtr->getTypeName();
383 		else
384 			str << declare(structPtr, decl.indentLevel); // Generate inline declaration.
385 	}
386 	else
387 		DE_ASSERT(false);
388 
389 	str << " " << decl.name;
390 
391 	// Print array sizes.
392 	for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
393 	{
394 		const int arrSize = *sizeIter;
395 		if (arrSize == VarType::UNSIZED_ARRAY)
396 			str << "[]";
397 		else
398 			str << "[" << arrSize << "]";
399 	}
400 
401 	return str;
402 }
403 
operator <<(std::ostream & str,const DeclareStructTypePtr & decl)404 std::ostream& operator<< (std::ostream& str, const DeclareStructTypePtr& decl)
405 {
406 	str << "struct";
407 
408 	// Type name is optional.
409 	if (decl.structPtr->hasTypeName())
410 		str << " " << decl.structPtr->getTypeName();
411 
412 	str << "\n" << indent(decl.indentLevel) << "{\n";
413 
414 	for (StructType::ConstIterator memberIter = decl.structPtr->begin(); memberIter != decl.structPtr->end(); memberIter++)
415 	{
416 		str << indent(decl.indentLevel+1);
417 		str << declare(memberIter->getType(), memberIter->getName(), decl.indentLevel+1) << ";\n";
418 	}
419 
420 	str << indent(decl.indentLevel) << "}";
421 
422 	return str;
423 }
424 
operator <<(std::ostream & str,const DeclareStructType & decl)425 std::ostream& operator<< (std::ostream& str, const DeclareStructType& decl)
426 {
427 	return str << declare(&decl.structType, decl.indentLevel);
428 }
429 
430 } // decl
431 } // glu
432