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(TYPE_LAST)
33 {
34 }
35
VarType(const VarType & other)36 VarType::VarType (const VarType& other)
37 : m_type(TYPE_LAST)
38 {
39 *this = other;
40 }
41
VarType(DataType basicType,Precision precision)42 VarType::VarType (DataType basicType, Precision precision)
43 : m_type(TYPE_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(TYPE_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(TYPE_STRUCT)
59 {
60 m_data.structPtr = structPtr;
61 }
62
~VarType(void)63 VarType::~VarType (void)
64 {
65 if (m_type == TYPE_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 if (m_type == TYPE_ARRAY)
75 delete m_data.array.elementType;
76
77 m_type = other.m_type;
78 m_data = Data();
79
80 if (m_type == TYPE_ARRAY)
81 {
82 m_data.array.elementType = new VarType(*other.m_data.array.elementType);
83 m_data.array.size = other.m_data.array.size;
84 }
85 else
86 m_data = other.m_data;
87
88 return *this;
89 }
90
getScalarSize(void) const91 int VarType::getScalarSize (void) const
92 {
93 switch (m_type)
94 {
95 case TYPE_BASIC: return glu::getDataTypeScalarSize(m_data.basic.type);
96 case TYPE_ARRAY: return m_data.array.elementType->getScalarSize()*m_data.array.size;
97
98 case TYPE_STRUCT:
99 {
100 int size = 0;
101 for (StructType::ConstIterator iter = m_data.structPtr->begin(); iter != m_data.structPtr->end(); iter++)
102 size += iter->getType().getScalarSize();
103 return size;
104 }
105
106 default:
107 DE_ASSERT(false);
108 return 0;
109 }
110 }
111
operator ==(const VarType & other) const112 bool VarType::operator== (const VarType& other) const
113 {
114 if (m_type != other.m_type)
115 return false;
116
117 switch (m_type)
118 {
119 case TYPE_BASIC:
120 return m_data.basic.type == other.m_data.basic.type &&
121 m_data.basic.precision == other.m_data.basic.precision;
122
123 case TYPE_ARRAY:
124 return *m_data.array.elementType == *other.m_data.array.elementType &&
125 m_data.array.size == other.m_data.array.size;
126
127 case TYPE_STRUCT:
128 return m_data.structPtr == other.m_data.structPtr;
129
130 default:
131 DE_ASSERT(false);
132 return 0;
133 }
134 }
135
operator !=(const VarType & other) const136 bool VarType::operator!= (const VarType& other) const
137 {
138 return !(*this == other);
139 }
140
141 // StructMember implementation
142
operator ==(const StructMember & other) const143 bool StructMember::operator== (const StructMember& other) const
144 {
145 return (m_name == other.m_name) && (m_type == other.m_type);
146 }
147
operator !=(const StructMember & other) const148 bool StructMember::operator!= (const StructMember& other) const
149 {
150 return !(*this == other);
151 }
152
153 // StructType implementation.
154
addMember(const char * name,const VarType & type)155 void StructType::addMember (const char* name, const VarType& type)
156 {
157 m_members.push_back(StructMember(name, type));
158 }
159
operator ==(const StructType & other) const160 bool StructType::operator== (const StructType& other) const
161 {
162 return (m_typeName == other.m_typeName) && (m_members == other.m_members);
163 }
164
operator !=(const StructType & other) const165 bool StructType::operator!= (const StructType& other) const
166 {
167 return !(*this == other);
168 }
169
getStorageName(Storage storage)170 const char* getStorageName (Storage storage)
171 {
172 static const char* const s_names[] = { "in", "out", "const", "uniform", "buffer", "patch in", "patch out" };
173
174 return de::getSizedArrayElement<STORAGE_LAST>(s_names, storage);
175 }
176
getInterpolationName(Interpolation interpolation)177 const char* getInterpolationName (Interpolation interpolation)
178 {
179 static const char* const s_names[] = { "smooth", "flat", "centroid" };
180
181 return de::getSizedArrayElement<INTERPOLATION_LAST>(s_names, interpolation);
182 }
183
getFormatLayoutName(FormatLayout layout)184 const char* getFormatLayoutName (FormatLayout layout)
185 {
186 static const char* s_names[] =
187 {
188 "rgba32f", // FORMATLAYOUT_RGBA32F
189 "rgba16f", // FORMATLAYOUT_RGBA16F
190 "r32f", // FORMATLAYOUT_R32F
191 "rgba8", // FORMATLAYOUT_RGBA8
192 "rgba8_snorm", // FORMATLAYOUT_RGBA8_SNORM
193 "rgba32i", // FORMATLAYOUT_RGBA32I
194 "rgba16i", // FORMATLAYOUT_RGBA16I
195 "rgba8i", // FORMATLAYOUT_RGBA8I
196 "r32i", // FORMATLAYOUT_R32I
197 "rgba32ui", // FORMATLAYOUT_RGBA32UI
198 "rgba16ui", // FORMATLAYOUT_RGBA16UI
199 "rgba8ui", // FORMATLAYOUT_RGBA8UI
200 "r32ui", // FORMATLAYOUT_R32UI
201 };
202
203 return de::getSizedArrayElement<FORMATLAYOUT_LAST>(s_names, layout);
204 }
205
getMemoryAccessQualifierName(MemoryAccessQualifier qualifier)206 const char* getMemoryAccessQualifierName (MemoryAccessQualifier qualifier)
207 {
208 switch (qualifier)
209 {
210 case MEMORYACCESSQUALIFIER_COHERENT_BIT: return "coherent";
211 case MEMORYACCESSQUALIFIER_VOLATILE_BIT: return "volatile";
212 case MEMORYACCESSQUALIFIER_RESTRICT_BIT: return "restrict";
213 case MEMORYACCESSQUALIFIER_READONLY_BIT: return "readonly";
214 case MEMORYACCESSQUALIFIER_WRITEONLY_BIT: return "writeonly";
215 default:
216 DE_ASSERT(false);
217 return DE_NULL;
218 }
219 }
220
getMatrixOrderName(MatrixOrder qualifier)221 const char* getMatrixOrderName (MatrixOrder qualifier)
222 {
223 static const char* s_names[] =
224 {
225 "column_major", // MATRIXORDER_COLUMN_MAJOR
226 "row_major", // MATRIXORDER_ROW_MAJOR
227 };
228
229 return de::getSizedArrayElement<MATRIXORDER_LAST>(s_names, qualifier);
230 }
231
232 // Layout Implementation
233
Layout(int location_,int binding_,int offset_,FormatLayout format_,MatrixOrder matrixOrder_)234 Layout::Layout (int location_, int binding_, int offset_, FormatLayout format_, MatrixOrder matrixOrder_)
235 : location (location_)
236 , binding (binding_)
237 , offset (offset_)
238 , format (format_)
239 , matrixOrder (matrixOrder_)
240 {
241 }
242
operator ==(const Layout & other) const243 bool Layout::operator== (const Layout& other) const
244 {
245 return location == other.location &&
246 binding == other.binding &&
247 offset == other.offset &&
248 format == other.format &&
249 matrixOrder == other.matrixOrder;
250 }
251
operator !=(const Layout & other) const252 bool Layout::operator!= (const Layout& other) const
253 {
254 return !(*this == other);
255 }
256
257 // VariableDeclaration Implementation
258
VariableDeclaration(const VarType & varType_,const std::string & name_,Storage storage_,Interpolation interpolation_,const Layout & layout_,deUint32 memoryAccessQualifierBits_)259 VariableDeclaration::VariableDeclaration (const VarType& varType_, const std::string& name_, Storage storage_, Interpolation interpolation_, const Layout& layout_, deUint32 memoryAccessQualifierBits_)
260 : layout (layout_)
261 , interpolation (interpolation_)
262 , storage (storage_)
263 , varType (varType_)
264 , memoryAccessQualifierBits (memoryAccessQualifierBits_)
265 , name (name_)
266 {
267 }
268
operator ==(const VariableDeclaration & other) const269 bool VariableDeclaration::operator== (const VariableDeclaration& other) const
270 {
271 return layout == other.layout &&
272 interpolation == other.interpolation &&
273 storage == other.storage &&
274 varType == other.varType &&
275 memoryAccessQualifierBits == other.memoryAccessQualifierBits &&
276 name == other.name;
277 }
278
operator !=(const VariableDeclaration & other) const279 bool VariableDeclaration::operator!= (const VariableDeclaration& other) const
280 {
281 return !(*this == other);
282 }
283
284 // InterfaceBlock Implementation
285
InterfaceBlock(void)286 InterfaceBlock::InterfaceBlock (void)
287 : layout (Layout())
288 , storage (glu::STORAGE_LAST)
289 , memoryAccessQualifierFlags (0)
290 {
291 }
292
293 // Declaration utilties.
294
operator <<(std::ostream & str,const Layout & layout)295 std::ostream& operator<< (std::ostream& str, const Layout& layout)
296 {
297 std::vector<std::string> layoutDeclarationList;
298
299 if (layout.location != -1)
300 layoutDeclarationList.push_back("location=" + de::toString(layout.location));
301
302 if (layout.binding != -1)
303 layoutDeclarationList.push_back("binding=" + de::toString(layout.binding));
304
305 if (layout.offset != -1)
306 layoutDeclarationList.push_back("offset=" + de::toString(layout.offset));
307
308 if (layout.format != FORMATLAYOUT_LAST)
309 layoutDeclarationList.push_back(getFormatLayoutName(layout.format));
310
311 if (layout.matrixOrder != MATRIXORDER_LAST)
312 layoutDeclarationList.push_back(getMatrixOrderName(layout.matrixOrder));
313
314 if (!layoutDeclarationList.empty())
315 {
316 str << "layout(" << layoutDeclarationList[0];
317
318 for (int layoutNdx = 1; layoutNdx < (int)layoutDeclarationList.size(); ++layoutNdx)
319 str << ", " << layoutDeclarationList[layoutNdx];
320
321 str << ")";
322 }
323
324 return str;
325 }
326
operator <<(std::ostream & str,const VariableDeclaration & decl)327 std::ostream& operator<< (std::ostream& str, const VariableDeclaration& decl)
328 {
329 if (decl.layout != Layout())
330 str << decl.layout << " ";
331
332 for (int bitNdx = 0; (1 << bitNdx) & MEMORYACCESSQUALIFIER_MASK; ++bitNdx)
333 if (decl.memoryAccessQualifierBits & (1 << bitNdx))
334 str << getMemoryAccessQualifierName((glu::MemoryAccessQualifier)(1 << bitNdx)) << " ";
335
336 if (decl.interpolation != INTERPOLATION_LAST)
337 str << getInterpolationName(decl.interpolation) << " ";
338
339 if (decl.storage != STORAGE_LAST)
340 str << getStorageName(decl.storage) << " ";
341
342 str << declare(decl.varType, decl.name);
343
344 return str;
345 }
346
347 namespace decl
348 {
349
operator <<(std::ostream & str,const Indent & indent)350 std::ostream& operator<< (std::ostream& str, const Indent& indent)
351 {
352 for (int i = 0; i < indent.level; i++)
353 str << "\t";
354 return str;
355 }
356
operator <<(std::ostream & str,const DeclareVariable & decl)357 std::ostream& operator<< (std::ostream& str, const DeclareVariable& decl)
358 {
359 const VarType& type = decl.varType;
360 const VarType* curType = &type;
361 std::vector<int> arraySizes;
362
363 // Handle arrays.
364 while (curType->isArrayType())
365 {
366 arraySizes.push_back(curType->getArraySize());
367 curType = &curType->getElementType();
368 }
369
370 if (curType->isBasicType())
371 {
372 if (curType->getPrecision() != PRECISION_LAST)
373 str << glu::getPrecisionName(curType->getPrecision()) << " ";
374 str << glu::getDataTypeName(curType->getBasicType());
375 }
376 else if (curType->isStructType())
377 {
378 const StructType* structPtr = curType->getStructPtr();
379
380 if (structPtr->hasTypeName())
381 str << structPtr->getTypeName();
382 else
383 str << declare(structPtr, decl.indentLevel); // Generate inline declaration.
384 }
385 else
386 DE_ASSERT(false);
387
388 str << " " << decl.name;
389
390 // Print array sizes.
391 for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++)
392 {
393 const int arrSize = *sizeIter;
394 if (arrSize == VarType::UNSIZED_ARRAY)
395 str << "[]";
396 else
397 str << "[" << arrSize << "]";
398 }
399
400 return str;
401 }
402
operator <<(std::ostream & str,const DeclareStructTypePtr & decl)403 std::ostream& operator<< (std::ostream& str, const DeclareStructTypePtr& decl)
404 {
405 str << "struct";
406
407 // Type name is optional.
408 if (decl.structPtr->hasTypeName())
409 str << " " << decl.structPtr->getTypeName();
410
411 str << "\n" << indent(decl.indentLevel) << "{\n";
412
413 for (StructType::ConstIterator memberIter = decl.structPtr->begin(); memberIter != decl.structPtr->end(); memberIter++)
414 {
415 str << indent(decl.indentLevel+1);
416 str << declare(memberIter->getType(), memberIter->getName(), decl.indentLevel+1) << ";\n";
417 }
418
419 str << indent(decl.indentLevel) << "}";
420
421 return str;
422 }
423
operator <<(std::ostream & str,const DeclareStructType & decl)424 std::ostream& operator<< (std::ostream& str, const DeclareStructType& decl)
425 {
426 return str << declare(&decl.structType, decl.indentLevel);
427 }
428
429 } // decl
430 } // glu
431