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